Really basic question on example script

Okay, so I’ve done a bit of coding in Unity so far and am working through different types of code to get a basic understanding of it. At the moment I’m trying to implement a code that’s attached to a gameobject that once it spawns will attempt to find a table from the environment.

The example code I’m attempting to utilise for this is the following:

// Find the name of the closest enemy

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    public GameObject FindClosestEnemy()
    {
        GameObject[] gos;
        gos = GameObject.FindGameObjectsWithTag("Enemy");
        GameObject closest = null;
        float distance = Mathf.Infinity;
        Vector3 position = transform.position;
        foreach (GameObject go in gos)
        {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if (curDistance < distance)
            {
                closest = go;
                distance = curDistance;
            }
        }
        return closest;
    }
}

I can understand roughly how the code is working, but I’m getting thrown by the foreach loop, namely the element, “go”. What is “go”? Is it a declared variable? An existing gameobject? I know it’s probably really simple but I’d really appreciate anyone taking the time to explain this to me, thanks.

It’s a temporary variable that does always contain the current element of the IEnumerable specified after the ‘in’ keyword, it’s similar to the current element when you use a standard for-loop with an index that’s always incremented by 1 (e.g. myGameObject[index]).

Differences to a normal for-loop with regards to the temporary variable:

  • for-each takes the elements sequentially until you break, return or an exception is thrown (and not caught)

  • the previous fact implies it’s equal to having a for-loop with an index always incremented by 1

  • you cannot run out of bounds with that temporary variable

  • you cannot re-assign the temporary variable

  • breaking change with C#5: capturing of the temporary variable in a lambda expression has changed

I might have missed something. Feel free to add.

Nope that was pretty much spot on sir. C# once it compiles that code actually just magically does this…

Old code →

foreach (GameObject go in gos)
        {
            Vector3 diff = go.transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if (curDistance < distance)
            {
                closest = go;
                distance = curDistance;
            }
        }

C# turns it into this and compiles just like it always did

for(int i=0; i <- goDoIt; i++)
        {
            Vector3 diff = gos[i].transform.position - position;
            float curDistance = diff.sqrMagnitude;
            if (curDistance < distance)
            {
                closest = gos[i];
                distance = curDistance;
            }
        }

@Suddoha is correct though. Even though they do exactly the same thing, this older method has a potential to mess up. If you use just = instead of <= you have a potential off by 1 error.

Bah I tried to explain it but just google off by 1 error, fence post error. Best way.

1 Like

@Xype , what’s up with you today. :eyes:
That’s exactly off by 1, i.e. out of bounds at the end and it skips the first element.

Therefore, I cannot completely follow your thoughts here:

Actually, it’s the other way around. The zero-based version is cleaner and adds no confusion for anyone who has learned for-loops and zero-based indexing (which is used in most common programming languages).
A loop starting with i = 1 and i<= count or length is highly alarming. One should consider to use the zero-based version.

i KNOW I been up all night lol I was on a roll but my magic is spent man. I kept catching my own mistakes there so I gave up lol.

I KNOW its why I gave up and just said google. I would be asleep right now if I didn’t have an appointment shortly.

Sadly I deleted my best advice. Just stick to foreach cause it does the same thing and sleepyness wont make you goof it.

You’ve got the choice: coffee or sleep! :smile:

1 Like

Thanks guys! This really helped, Suddoha, your explanation went a little over my head in all honesty, but I got a good overview from it of what is happening in the code.

And Xype, despite your fatigue you helped tie it all together for me,

This was my “penny drop” moment.

Thanks a lot guys!

Feel free to ask about any particular detail that I’ve mentioned. :slight_smile: