Gameobject get closest tag? Won't quite work

Hi all,

The script needs to work in relation to a “sprite” which instantiates within the game, so I need to try and use code to find the closest gameobject with the tag. Then the aim is to get the found object with tag and calculate the distance between it and the player. Would you be able to help? This is what I have but it’s not quite working as of yet.

#pragma strict

var distance : int;
var percent : float;
var player : GameObject;
var sprite : GameObject;
var radius : float = 50.0;

function Start(){
}

function Update(){
    sprite == GetClosestObject;
    distance = Vector3.Distance(player.transform.position, sprite.transform.position);
    percent = Mathf.Clamp01(distance / 70f);
    print (percent);
}
function GetClosestObject(tag:String) : GameObject
{
     var objectsWithTag = GameObject.FindGameObjectsWithTag("sprite");
     var closestObject : GameObject;
     for (var obj : GameObject in objectsWithTag)
     {
         if(!closestObject)
         {
            closestObject = obj;
         }
         //compares distances
         if(Vector3.Distance(player.transform.position, obj.transform.position) <= Vector3.Distance(player.transform.position, closestObject.transform.position))
         {
            closestObject = obj;
         }
     }
     return closestObject;
}

line 13 needs () after the function name and you need to pass in the parameter in those brackets… oh and line 20 probably needs to use the parameter not the hardcoded “sprite” value

Yeah, as @LeftyRighty pointed, line 13:

sprite == GetClosestObject;

You should try with:

sprite = GetClosestObject();

Also, using GameObject.FindGameObjectsWithTag() inside a function that is called every frame inside Update() will negatively affect your performance once you start having much more gameObjects in the scene.

You could store your sprites inside a List once you create them, and remove them when they are destroyed. Something like:

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

public class ObjectTracker : MonoBehaviour
{
     static List<GameObject> emptyList = new List<GameObject>();
     static Dictionary<string, List<GameObject>> collection = new Dictionary<string, List<GameObject>>();

     public string tag = "myTag";

     void Awake()
     {
          if (!collection.ContainsKey( tag ))
              collection[tag] = new List<GameObject>();

          collection[tag].Add( gameObject );
     }

     void OnDestroy()
     {
          collection[tag].Remove( gameObject );
     }

     public static List<GameObject> GetObjectsWithTag( string tag )
     {
          return collection.ContainsKey( tag ) ? collection[tag] : emptyList;
     }
    
     public static void Enumerate( string tag, System.Action<GameObject, int> callback)
     {
          if (!collection.ContainsKey( tag ))
               return;

          List<GameObject> list = collections[tag];
          for (int i = 0; i < list.Count; i++)
          {
               if ( callback != null )
                    callback( list[i], i);
          }
     }
}

Now, add this script to all your relevant gameObjects, add via inspector the tag “sprite” and run. You can now fetch all your tagged gameObjects using:

foreach (GameObject obj in ObjectTracker.GetObjectsWithTag( "sprite" ))
{
     // your distance logic goes here
}

ObjectTracker.Enumerate( "sprite", (obj, i) =>
{
     // your distance logic goes here
});

Now you don’t have to worry about destroyed gameObjects since they should clean themselves up from the list. Hope this helps!

When I changed it to just one “=” with the () on the end, this error message came up:

Assets/MyScripts/Pitcheditsprite.js(13,34): BCE0017: The best overload for the method ‘Pitcheditsprite.GetClosestObject(String)’ is not compatible with the argument list ‘()’.

Do you have another solution for this? I’d rather try to steer clear of c# because I’m really not that certain with it and I need to add some other audio accessing stuff to this script when I’ve sorted this out, but if I can’t then I’ll try your listing suggestion.

line 13

sprite = GetClosestObject("sprite");

line 20

var objectsWithTag = GameObject.FindGameObjectsWithTag(tag);

and I’d missed the == :slight_smile:

Your GetClosestObject function takes 1 parameter which needs to be a string, that error is complaining the function is being called without a parameter

It works, eureka!

Thank you so much!

Final thing, this may just need a simple bit of maths but I’m not quite sure which function I need for this. Basically, I want the float of percentage to reflect the pitch of the audiomixer. So when I approach the “sprite”, I want the pitch to go up. The problem with this now is the equation I have out means that the closer I get to the sprite, the smaller the number gets, e.g. from a certain distance the float will be 1, but as I approach it, it will get closer to 0. This is the code I’ve got, any suggestions for how to achieve this number:

#pragma strict
import UnityEngine.Audio;
var distance : int;
var percent : float;
var player : GameObject;
var sprite : GameObject;
var soundpercent : float;
var master : AudioMixer;

function Start(){
}

function Update(){
    distance = Vector3.Distance(player.transform.position, sprite.transform.position);
    percent = Mathf.Clamp01(distance / 90f);
    soundpercent = percent + 1;
    master.SetFloat ("pitch", soundpercent);
    print (percent);
   
}
function GetClosestObject(tag:String) : GameObject
{
     var objectsWithTag = GameObject.FindGameObjectsWithTag("sprite");
     var closestObject : GameObject;
     for (var obj : GameObject in objectsWithTag)
     {
         if(!closestObject)
         {
            closestObject = obj;
         }
    
         if(Vector3.Distance(player.transform.position, obj.transform.position) <= Vector3.Distance(player.transform.position, closestObject.transform.position))
         {
            closestObject = obj;
         }
     }
     return closestObject;
}

Oh, and also the game frame rate is lagging a bit - probably from having to check the other function every Update. Is there a way to maybe only check the update everytime it has to search for a new sprite? Not sure.