How can I make my gameObject find the nearest object with a specific tag and rotate to look at it?

Hi everyone

I'm rather new to Javascript and I've been experimenting with it for the past 3 days and read a lot of tutorials and forum posts - thanks in advance for those.

What I can't figure out is how to have an object look at the nearest other object with a certain tag. I know I need an array for it and I've found some code for similar functions, but they either don't seem to work or do something I don't need to.

Could anyone maybe assist me in how to write this?

What I need is to have the object that code is attached to find the closest object with a specific tag (say "waypoint") and then look at it.

Any help is much appreciated, thank you.

Something along these lines should be what you're after:

(Edit : now tested & working!)

// the tag to search for (set this value in the inspector)
var searchTag = "Respawn";

// the frequency with which to re-scane for new nearest target in seconds 
// (set in inspector)
var scanFrequency = 1.0;

// the current target
private var target : Transform;

function Start() {
    // set up repeating scan for new targets:
    InvokeRepeating("ScanForTarget", 0, scanFrequency );
}

function Update() {
    // we rotate to look at the target every frame (if there is one)
    if (target != null) {
        transform.LookAt(target);
    }
}

function ScanForTarget() {
    // this should be called less often, because it could be an expensive
    // process if there are lots of objects to check against
    target = GetNearestTaggedObject();

}

function GetNearestTaggedObject() : Transform {
    // and finally the actual process for finding the nearest object:

    var nearestDistanceSqr = Mathf.Infinity;
    var taggedGameObjects = GameObject.FindGameObjectsWithTag(searchTag); 
    var nearestObj : Transform = null;

    // loop through each tagged object, remembering nearest one found
    for (var obj : GameObject in taggedGameObjects) {

        var objectPos = obj.transform.position;
        var distanceSqr = (objectPos - transform.position).sqrMagnitude;

        if (distanceSqr < nearestDistanceSqr) {
            nearestObj = obj.transform;
            nearestDistanceSqr = distanceSqr;
        }
    }

    return nearestObj;
}

I was guided to the answer I was looking for, thank you very much! Here is the working code:

function Update () {
    var waypoints: GameObject[] = GameObject.FindGameObjectsWithTag("waypoint"); 
    var closest: GameObject; 
    var closestDist = Mathf.Infinity; 

    for (waypoint in waypoints) { 
        var dist = (transform.position - waypoint.transform.position).sqrMagnitude; 

        if (dist < closestDist) { 
            closestDist = dist; 
            closest = waypoint; 
            } 
    } 
    transform.LookAt(closest.transform); 
}

hey man I noticed that Closest distance never resets and if it does it messes up my targeting here is what I have man see what you think it doesnt use LOOK AT because my code you can slow down the turret so if you wanted a huge battleship cannon you can do that with my code.

var closestDist = Mathf.Infinity; 

var attackRange = 30.0; var shootAngleDistance = 10.0;

var closest: GameObject;

function Update () {

    var waypoints: GameObject[] = GameObject.FindGameObjectsWithTag("waypoint");  </p>
    for(waypoint in waypoints)
    {
    var dist = (transform.position - waypoint.transform.position ).sqrMagnitude;   

    if(dist <= closestDist)
    {
            closestDist = dist;
            closest = waypoint;       
    }else
    {
        closestDist += 100;
    }
    //Debuging ClosestDist
    if(Input.GetKeyDown("t"))
    {
    print("ClosestDist: " + closestDist);
    }

        var targetPoint = closest.transform.position;
        var targetRotation = Quaternion.LookRotation ( targetPoint - transform.position , Vector3.up);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2.0);

        // If we are almost rotated towards target - fire one clip of ammo
        var forward = transform.TransformDirection(Vector3.forward);
        var targetDir = closest.transform.position - transform.position;

        if (Vector3.Angle(forward, targetDir) < shootAngleDistance && closest.gameObject.tag == "waypoint")
            SendMessage("Fire");

    }

}

just add one target transform and ignoring the Y axis and so this script can attached any object and can specify the transform

function GetNearestTaggedObject(searchTag : String,otherTrans: Transform) : Transform
{
// and finally the actual process for finding the nearest object:

    var nearestDistanceSqr : float = Mathf.Infinity;
    var taggedGameObjects : GameObject[] = GameObject.FindGameObjectsWithTag(searchTag); 
    var nearestObj : Transform = null;

    // loop through each tagged object, remembering nearest one found
    for (var obj : GameObject in taggedGameObjects) {

        var objectPos = obj.transform.position;
        var distanceSqr = (objectPos - Vector3(otherTrans.position.x,objectPos.y,otherTrans.position.z)).sqrMagnitude;

        if (distanceSqr < nearestDistanceSqr) {
            nearestObj = obj.transform;
            nearestDistanceSqr = distanceSqr;
        }
    }

    return nearestObj;
}

Here’s a method that I created to do this in C#. It also uses a helper method from my utility class.

    void SelectClosest()
    {
        const int maxSelectionDistance = 2;

        Selected = null;
        var closestDistance = Single.MaxValue;
        foreach (var selectable in GameObject.FindGameObjectsWithTag("Selectable"))
        {
            var distance = gameObject.DistanceSquaredTo(selectable);
            if (distance < closestDistance && distance < maxSelectionDistance * maxSelectionDistance)
            {
                closestDistance = distance;
                Selected = selectable;
            }
        }
    }
    
    public static float DistanceSquaredTo(this GameObject source, GameObject target)
    {
        return Vector3.SqrMagnitude(source.transform.position - target.transform.position);
    }

If you want the turning to be a bit smoother, use this:

    //the tag for how fast the arrow should spin
    var turn  : float = 10.0;
    // the tag to search for (set this value in the inspector)
    var searchTag = "Respawn";
     
    // the frequency with which to re-scane for new nearest target in seconds 
    // (set in inspector)
    var scanFrequency = 1.0;
     
    // the current target
    private var target : Transform;
     
     
    function Start() 
    {
        // set up repeating scan for new targets:
        InvokeRepeating("ScanForTarget", 0, scanFrequency );
    }
     
    function Update() 
    {
        // we rotate to look at the target every frame (if there is one)
        if (target != null) 
        {
        	var targetRotation = Quaternion.LookRotation (target.position - this.transform.position);
            this.transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, turn);
        }
    }
     
    function ScanForTarget() 
    {
        // this should be called less often, because it could be an expensive
        // process if there are lots of objects to check against
        target = GetNearestTaggedObject();
     
    }
     
    function GetNearestTaggedObject() : Transform 
    {
        // and finally the actual process for finding the nearest object:
     
        var nearestDistanceSqr = Mathf.Infinity;
        var taggedGameObjects = GameObject.FindGameObjectsWithTag(searchTag); 
        var nearestObj : Transform = null;
     
        // loop through each tagged object, remembering nearest one found
        for (var obj : GameObject in taggedGameObjects) {
     
            var objectPos = obj.transform.position;
            var distanceSqr = (objectPos - transform.position).sqrMagnitude;
     
            if (distanceSqr < nearestDistanceSqr) {
                nearestObj = obj.transform;
                nearestDistanceSqr = distanceSqr;
            }
        }
     
        return nearestObj;
    }