Wondering why its happend .. please take a look on my script.

Hi Everyone,

In they scrip down - I build turret which finds the Instantiated enemy objects, and then rotate to the closest turret in it range.

The script is work fine but I wonder about something wierd, I really sure that Im missing something Important.

when i set the var
shortestDistance = Mathf.Infinity;
inside Start() {
Instead of Update()

The turret find and rotate only to the first enemy, and then stop working,

Please help.

Thank you.

public class Turret : MonoBehaviour
{
    public Transform target;
    public float range = 20f;
    public string enemyTag = "Enemy";
    public Transform partToRotate;
    public  float distanceToEnemy;
    public float shortestDistance;


    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("UpdateTarget", 0f, 0.5f);
       
       
    }

    void UpdateTarget()
    {
        shortestDistance = Mathf.Infinity;
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        GameObject nearestEnemy = null;
        foreach (GameObject enemy in enemies)
        {
            distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
             // Here the distance to enemy change every enemy is spawn.
            if (distanceToEnemy < shortestDistance)
            {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;
                Debug.Log(shortestDistance);
            }
        }   

        if (nearestEnemy != null && shortestDistance <= range) // distance to enemy
        {
            target = nearestEnemy.transform; // here the turret action start.
        }
        else
        {
            target = null;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (target == null)
            return;

        Vector3 dir = target.position - transform.position;
        Quaternion lookRotation = Quaternion.LookRotation(dir);
        Vector3 rotation = lookRotation.eulerAngles;
        partToRotate.rotation = Quaternion.Euler(0f, rotation.y, 0f);

    }


    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, range);

    }
}

What did you think would happen? Why did you want to set it in Start instead of Update?

UpdateTarget() only looks for targets that are closer than shortestDistance. If you don’t reset shortestDistance between searches, then once it finds an enemy at a distance of (say) 2, then all enemies farther than 2 will be ignored forever.

If all enemies are walking along the same path, then none of them will get closer than the first enemy got at its closest point, so no enemies other than the first will be targeted. (With a little bit of uncertainty due to where exactly the frame boundaries fall.)

1 Like

Hello ,
Thanks for your reply,

Im sorry, I read what you write over and over and still not get it.

I translated what I understand;
Please tell me what am I missing.

If distanceToEnemy < Infinity
shotestDistance will be Equal to the enemy.transform.position is found.
and
set gameObject nearestEnemy to the enemy was found.

What I dont understand is: Every enemy is instantiated the distanceToEnemy get the new value with the larger distance
Means that, becuase shortestDistance is Equal to distanceToEnemy it should raise every once enemy is instantiated and the nearestEnemy will set to the farther one.

… Please help… Im Confused.

 void UpdateTarget()
    {
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        float shortestDistance = Mathf.Infinity;
        GameObject nearestEnemy = null;
        foreach (GameObject enemy in enemies)
        {
            float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
         
            if (distanceToEnemy < shortestDistance)
            {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;

            }
        }

Nope. You are checking if (distanceToEnemy < shortestDistance) before reassigning shortestDistance. So, for first enemy you find, you have this setup:
shortestDistance = Math.Infinity;
distanceToEnemy = 1; (for example)
So distanceToEnemy < shortestDistance is true.

For next enemy, this is the setup:
shortestDistance = 1; (since you are not resetting it)
distanceToEnemy = 2 (again, for example)
With this values, distanceToEnemy < shortestDistance is false, and thats is what causing your stuck

Hope it helps :smile:

Stop. Where in the code do you see that?

Line 28 checks if distanceToEnemy < shortestDistance
But I don’t see any line that checks if distanceToEnemy < infinity

Remember: computers do exactly what you tell them, and nothing else.

He means on first iteration I guess, since at the beginning shortestDistance = Mathf.Infinity

Thank you for your reply,

“float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);”
this line runs on foreach , should make the distanceToEnemy updated every enemy is instantiated no?

Lets check if I understand it correctly , in first iteration shortestDistance = Mathf.Infinity;

In second iteration and etc… it check if distanceToEnemy is < the last enemy distance (shortestDistance has set before)
If you.
nearestEnemy = enemy found in loop.

Am I right?

if yes.
2 question:

  1. The condition if distanceToEnemy < shortestDitannce is kinda set to be false when we say shortestDistance = distanceToEnemy, why the condition keep running?

  2. If the “value” Infinty set to be only to the first iteration, why should it update every 0.5 seconds , and not set only in Start()?

NO. That line has no clue when an enemy is instantiated and does not take that into account in any way.

It updates the variable whenever that line of code is executed. Computers do exactly what you tell them. It doesn’t know what your goal is, it just follows your instructions and hopes they’re right. So it updates the variable when it sees an instruction to update it, and not at any other time.

That line of code runs whenever the function containing it is called. (Actually several times each call, because of the loop.)

The function is called once every 0.5 seconds (because of the “InvokeRepeating” command you put in Start).

So every 0.5 seconds, this code looks at “every single enemy in the entire game at this exact moment”, and checks how far away they are, and compares that distance to whatever is stored in the variable “shortestDistance”.

If you reset “shortestDistance” at the beginning of the function, then that’s the initial point of comparison. If you don’t reset it, then it remembers whatever value it had the last time the function ran, 0.5 seconds ago. Since the rest of the function only every makes “shortestDistance” smaller, then if you stop resetting it every time, then there is no way for it to ever get bigger under any circumstances.

That’s only true as long as you set shortestDistance to infinity right before the first iteration. You are asking what happens if you stop doing that, and the answer is that the computer compares against whatever value was most recently stored in “shortestDistance”, because that’s what the instruction says.

It will still use infinity the very first time it runs (at 0.5 seconds). But then at 1.0 seconds, it doesn’t use infinity, it uses “whatever number you last assigned to this variable”. And it continues doing that at 1.5 seconds, at 2.0 seconds, at 2.5 seconds, etc.

Hi,

Thanks alot for the detailed answer.

Impressing that what made me confused is Information storage hierarchy.
Now , after I understand it. It very make sense.

Thanks for saving my sleep.