Antoine
Antoine

Reputation: 141

Have enemy accelerate towards player in Unity

I have a script that has the enemy move towards the player at the same speed, but I am trying to make the enemy slow down then accelerate when he is switching directions. The enemy currently just moves left and write towards the player's position. Here is my code from the script that my boss is attached to in the update function:

Vector2 targetPosition = new Vector2 (player.transform.position.x, transform.position.y); 
transform.position = Vector2.MoveTowards (transform.position, targetPosition, moveSpeed * Time.deltaTime);

I have also tried using Lerp and using the transform.position as the first parameter, but the boss goes slower when the player is closer, and faster when the player is faster away.

transform.position = Vector2.Lerp (transform.position, targetPosition, moveSpeed * Time.deltaTime);

Does anyone know how to make the enemy slow down, then gradually increase his speed as he change direction, then return to normal speed after he has finished changing directions

**EDIT: ** full script below

using UnityEngine;

public class Roll : StateMachineBehaviour
{
    [SerializeField] private float moveSpeed = 2.4f; 
    [SerializeField] private float rotateSpeed = 100f; 

    [SerializeField] private float minRollTime = 6f;
    [SerializeField] private float maxRollTime = 8f;
    private float rollTimer = 0f; 

    [SerializeField] private float rightBoundary = 5f;
    [SerializeField] private float leftBoundary = -5f;

    private Transform playerTransform = null;
    private BossHealth bossHealth = null;     
    private Transform bossTransform = null;
    private Transform bodyTransform = null;
    private Transform earsTransform = null; 

    private Vector2 targetPosition = Vector2.zero; 

    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        playerTransform = GameObject.FindWithTag("Player").transform; 

        bossHealth = animator.GetComponent<BossHealth>(); 

        Boss01 boss = FindObjectOfType<Boss01>(); 
        bossTransform = boss.bossTransform;  
        bodyTransform = boss.bodyTransform; 
        earsTransform = boss.earsTransform; 

        rollTimer = Random.Range (minRollTime, maxRollTime); 
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        if (bossTransform.position.x >= leftBoundary && bossTransform.position.x <= rightBoundary)
        {
            targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
            bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);

            if (playerTransform.position.x > 0)
                bodyTransform.Rotate(0f, 0f, -rotateSpeed * Time.deltaTime); 
            else
                bodyTransform.Rotate(0f, 0f, rotateSpeed * Time.deltaTime); 
        }
        else if (bossTransform.position.x < leftBoundary) 
        {
            if (playerTransform.position.x > bossTransform.position.x) 
            {
                targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
                bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);
            }
        }
        else
        {
            if (playerTransform.position.x < bossTransform.position.x) 
            {
                targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
                bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);
            }
        }

        if (rollTimer <= 0f)
            animator.SetTrigger ("aim"); 
        else
            rollTimer -= Time.deltaTime; 

        if (bossHealth.CheckHealth())
            animator.SetTrigger ("transition"); 

        if (earsTransform.rotation != Quaternion.Euler (0f, 0f, 0f))
            earsTransform.rotation = Quaternion.Slerp(earsTransform.rotation, Quaternion.Euler(0f, 0f, 0f), 1f * Time.deltaTime); 
    }

    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        animator.ResetTrigger ("aim"); 
        animator.ResetTrigger ("transition"); 
    }
}

Upvotes: 0

Views: 1549

Answers (1)

rustyBucketBay
rustyBucketBay

Reputation: 4561

To achieve the position (meters/second) you multiply the speed * Time.deltatime, so you achieve the meters. To handle acceleration, you need to handle variable speed. Acceleration is m/s2, multiplied * Time.deltatime you will have the instant speed, and that speed * Time.deltaTime will give you the position.

Here some pseudocode (step and speed should be class varibles and this modifieed in the update. accel is the constant acceleration, that should be constans for the simplicity's sake, I guess that you need uniformingly accelerated movement):

speed += accel * Time.deltaTime; // instant speed
step =  speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);

With the sign of the accel + or - you will determine if the entities speed is increasing (accelerating) or decreasing (decelerating).

Hope that helps

Edit:

Full script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveTowards : MonoBehaviour
{
  public Transform target;
  private float step = 0f;
  private float speed = 0f;
  public float accel = 0f;
  // Start is called before the first frame update
  void Start()
  {

  }

  // Update is called once per frame
  void Update()
  {
    speed += accel * Time.deltaTime; // instant speed
    step = speed * Time.deltaTime; // calculate distance to move
    transform.position = Vector3.MoveTowards(transform.position, target.position, step);
  }
}

Screenshot of script attached in editor:

enter image description here

Attached the script to the game object you want to move, and attach the transform of the target in the public fielld. The choose your acceleration, positive to accelerate towards an negative to accelerate backwars, and there you got it.

Upvotes: 1

Related Questions