Find closest enemy and follow him - Unity2d

In my game there is a player team consisting of several units and an enemy team. I want my units to find the nearest enemy and approach him to attack. I searched for a way on the Internet, but did not find it.
Here is my code for finding the nearest enemy, but I can’t figure out how to make my units go to the nearest enemy.

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

public class Player : MonoBehaviour {

    GameObject [] enemy;
    GameObject closest;
    GameObject target;

    public float speed = 5f;

    public string nearest;

    void Start() {
        enemy = GameObject.FindGameObjectsWithTag("Enemy");
    }

    GameObject FindClosestEnemy() {
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in enemy) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if(curDistance< distance) {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }

    void FixedUpdate() {
        nearest = FindClosestEnemy().name;

    }
}

I just can’t figure out how to make my units attack the nearest enemy.

Just have it MoveTowards the nearest enemy’s position.

I finally figured out how to do this, but when my unit destroys one of the enemies, it does not go to the other.

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

public class Player : MonoBehaviour {

    GameObject [] enemy;
    GameObject closest;
    Vector2 target;
   

    public float speed = 5f;
    public float step;

    public string nearest;

    void Start() {
        enemy = GameObject.FindGameObjectsWithTag("Enemy");
        step = speed * Time.deltaTime;
    }

    GameObject FindClosestEnemy() {
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in enemy) {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if(curDistance< distance)
            {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }

    void FixedUpdate() {
        nearest = FindClosestEnemy().name;
        target = FindClosestEnemy().transform.position;
        transform.position = Vector2.MoveTowards(transform.position, target, step);

    }
}

You probably have an error that says you’re trying to access a destroyed object or something in your console. You need to remove the destroyed object from the stuff you’re searching for.

Why are you doing this in FixedUpdate?

void FixedUpdate() {
        nearest = FindClosestEnemy().name;
        target = FindClosestEnemy().transform.position;
        transform.position = Vector2.MoveTowards(transform.position, target, step);
    }

If this GameObject has physics components, do not ever modify the Transform. Always modify the Rigidbody2D using its API. The above would be a Rigidbody2D set to be Kinematic and you'd do something like:

void FixedUpdate() {
        target = FindClosestEnemy().transform.position;
        var position = Vector2.MoveTowards(myRigidbody.position, target, step);
        myRigidbody.MovePosition(position);
    }

An additional note: You're calculating step which is the per-frame time and using it in the FixedUpdate. This is completely wrong. Calculate it when you use it, it'll then be correct. In the FixedUpdate, Time.deltaTime is temporarily returning Time.fixedDeltaTime.

If you're not using physics then ignore it but also, in that case, don't use "FixedUpdate", use "Update" (per-frame).

I finally got it working, thanks for the help:smile:

1 Like