0
\$\begingroup\$

I'm making a 2D game with Unity that's based on avoiding/evading enemies. The problem i'm facing right now is i can't get the enemies to move towards the target/player, but instead they follow it. So they never actually "attack" because they only follow it around and don't even come close to it. Also if the target/player stops moving, they stop moving.

I'm wondering if it could be something in my scene, since i've asked this question on multiple forum threads in the unity forums section and everyone seems to answer with the same lines of code.

Extra information:

My enemy has a box collider on it with no rigidbody 2D. My player has a box collider on it with a rigidbody 2D.

Kind regards.

using UnityEngine;
using System.Collections;

public class BeeBehaviour : MonoBehaviour {

  public Transform target;
  public float moveSpeed = 3;

  void Start () {
    target = GameObject.Find("MainObject").transform;
  }

  void Update () {
    Chase();
  }

  void Chase () {
        Vector3 targetDirection = target.position - transform.position;
        transform.position += targetDirection * moveSpeed * Time.deltaTime;
  }
}
\$\endgroup\$
  • \$\begingroup\$ Are you trying to predict where the target will be so the enemy heads toward the future position as opposed to the current position? \$\endgroup\$ – Savlon Apr 11 '15 at 12:28
  • \$\begingroup\$ No, i want the enemy to chase/attack the player. if it touches the player, the player dies. \$\endgroup\$ – Michael Apr 11 '15 at 12:36
2
\$\begingroup\$

You have:

void Chase () {
    Vector3 targetDirection = target.position - transform.position;
    transform.position += targetDirection * moveSpeed * Time.deltaTime;
}

One problem is that your targetDirection is not normalized but rather has magnitude equal to the distance between the objects. By multiplying this unnormalized vector to determine the frame's movement you are producing movement that proportional to the distance between objects i.e. the following GameObject will slow down as it get closer and depending on the value of moveSpeed may never reach the target.

You could fix this with:

void Chase () {
    Vector3 vectorToTarget = target.position - transform.position;
    transform.position += vectorToTarget.normalized * moveSpeed * Time.deltaTime;
}

This still leaves the problem of overshooting if the frame's movement is greater than our distance from the target. For this we can check the distance to the target and if it is less than the usual movement for that frame set the our position equal to the target.

void Chase () {
    Vector3 vectorToTarget = target.position - transform.position;
    float moveDistance = moveSpeed * Time.deltaTime;
    if (vectorToTarget.magnitude > moveDistance ) {
        transform.position += vectorToTarget.normalized * moveDistance;
    }
    else {
        transform.position = target.position;
    }
}

However stepping the values of a vector towards another is a common problem and unity has provided a convenience method Vector3.MoveTowards() to help us with the heavy lifting:

 void Chase () {
    float movementDistance = moveSpeed * Time.deltaTime;
    transform.position = Vector3.MoveTowards(transform.position, target.position, movementDistance);
}
\$\endgroup\$
0
\$\begingroup\$

I use this simple script I whipped up to get mobs to follow on the X axis (but you could easily add a couple of lines to include Y axis as well because it already calculates that distance I just don't use it because I'm building a side scroller) I just created these functions in a MobAIMovement script and then called TotDistance from the Update function.

void TotDistance (){
    var testX = transform.position.x;
    var testY = transform.position.y;

    var pTestX = target.transform.position.x;
    var pTestY = target.transform.position.y;

    var xDistance = testX - pTestX;
    var yDistance = testY - pTestY;

    var totDistance = Mathf.Pow (xDistance, 2) + Mathf.Pow (yDistance, 2);
    totDistance = Mathf.Sqrt (totDistance);


    Debug.Log ("Total Distance: " + totDistance);

    FacePlayer (xDistance, totDistance);


}

void FacePlayer(float xDistunce, float tutDistunce){
    if (xDistunce < -0.5) {
        transform.localScale = new Vector3(-1, 1, 1);
        if (tutDistunce > mobRange){
            transform.Translate(1 * Time.deltaTime, 0, 0, Space.World);
            anim.SetBool ("isMoving",true);
        }
        else{
            anim.SetBool ("isMoving",false);
        }

    }
    if (xDistunce > 0.5) {
        transform.localScale = new Vector3(1, 1, 1);
        if(tutDistunce > mobRange){
            transform.Translate(-1 * Time.deltaTime, 0, 0, Space.World);
            anim.SetBool ("isMoving",true);
        }
        else{
            anim.SetBool("isMoving",false);
        }
    }
}

Very simple. It basically follows it on X, but stops once it is within range.(easily changed or removed.) It also flips the sprite to face and move left or right. The "isMoving" bool is just there to trigger the moving animation state and can be removed as well.

If I were you, I would change the (1 * Time.deltatime to 1 * mSpeed * Time.deltatime) and then set an mSpeed variable for the mob. That way if it isn't catching you, then you can speed up the mob by changing that variable.

If you want death to come from contact use OnCollisionEnter2D(collision2D coll) to detect collisions with player and destroy. If you want attack, then modify the script a bit. In the section where it stops within range you can change it to attack when it's within a totDistance instead of stop completely (which is all mine does at this second.)

One more thing, I'm pretty sure transform.forward won't work they you want in the 2D engine. You'll need transform.up or transform.right etc.

I'm no professional and still new to this all myself. Maybe this will help out. (I know my programming is probably archaic and not very efficient. Just figuring it out as I go along.)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.