waveConfig.GetWaypoints()[0].transform.position - [0] [1] [3] etc

16_ld_cud
2d
#1

In lecture 100 in EnemySpawner.cs, I am really confused with the index number to access the list of waypoints on this line:
waveConfig.GetWaypoints()[0].transform.position

Can anyone explain what the [0] is accessing and why changing the value (as long as the value you give it is less than the number of waypoints in your path) still works?!?

If I put a value higher than the total number of waypoints then nothing spawns.

I guess [0] is a ‘safe’ value as there must always be at least 1 waypoint in a path but still so confused as to why it works exactly the same if I increase the value?!?

#2

Hi Paulo,

Do you know what an array or a List is? If not, take a look at this.

Assuming we have a List of type Waypoint. Here is the C# way of initialising that List. I’m initialising the List with a length of 4: Waypoint[] waypoints = new List(4);

Unity does the initialisation automatically for us when increase the size value of our List in the Inspector. Don’t worry about this detail.

The new keyword creates a new List object. The [] indicate that this is a collection, e.g. a List or an array. How can we access the single positions, e.g. element 1?

waypoints[0] ---> first element
waypoints[1] ---> second element
waypoints[2] ---> third element
waypoints[3] ---> forth element

Since the index starts at 0, our first element is at index 0.

My List does not have any objects assigned. If you logged an element into your Console, the message would say null. Array items can accessed via variableName[index], too.

And while we are on it: If you tried to access waypoints[4], you would get an IndexOutOfRangeException error because I initialised the List with a length of 4. waypoints[4] is the fifth element.

Did this clear it up for you?


See also:

#3

Hi Nina,

I understand lists and arrays and the main differences.

What I don’t understand is why I get the same result i.e the enemy follows the same path in the same order regardless of what number I put here [0], [1], [3] etc. (up to the total number if waypoints).

Surely if I am addressing a higher element it should miss out the elements below?

So if I tell it to start at [1], how is it still able to access the waypoint at [0]?

#4

Could it be that you asked the same question on Udemy, too? If so, I’ve replied to you there. I’m pasting my answer here.


Are you referring to this method?

private IEnumerator SpawnAllEnemiesInWave(WaveConfig waveConfig)
{
    for (int enemyCount = 0; enemyCount < waveConfig.GetNumberOfEnemies(); enemyCount++)
    {
        var newEnemy = Instantiate(
            waveConfig.GetEnemyPrefab(),
            waveConfig.GetWaypoints()[0].transform.position,
            Quaternion.identity);
        newEnemy.GetComponent<EnemyPathing>().SetWaveConfig(waveConfig);

        yield return new WaitForSeconds(waveConfig.GetTimeBetweenSpawns());
    }
}

If so, we instantiate all our enemies at the position of the first waypoint in our List. The first element in a List or an array is at index 0.

If you instantiate the enemy at index 1, 2 or 3 and the enemy appears at the same position as index 0, that’s very likely due to the EnemyPathing object. Our waypointIndex value is initialised with 0. And in Start, we assign the position of the first element to the transform.position.

int waypointIndex = 0;
 
void Start ()
{
    waypoints = waveConfig.GetWaypoints();
    transform.position = waypoints[waypointIndex].transform.position;
}

This means that we could instantiate our enemy at other positions and will always get the same result. For example:

var newEnemy = Instantiate(
    waveConfig.GetEnemyPrefab(),
    new Vector3(1000f, 1000f, 1000f),
    Quaternion.identity);
1 Like
#5

Yes that makes more sense, thank you.

Still a bit confused about why we are passing the [0] in this line and declaring waypointIndex = 0:
var newEnemy = Instantiate(
waveConfig.GetEnemyPrefab(),
waveConfig.GetWaypoints()[0].transform.position,
Quaternion.identity);

I will have another look when I get home but without having all the code in front on me I think I will look at referencing waypointIndex in EnemyPathing.cs to avoid confusion and duplication eg.
var newEnemy = Instantiate(
waveConfig.GetEnemyPrefab(),
waveConfig.GetWaypoints()[waveConfig.GetWaypointIndex].transform.position,
Quaternion.identity);

Thanks for your help on here and for the same question on udemy.

#6

waveConfig.GetWaypoints()[waveConfig.GetWaypointIndex].transform.position would also be possible. It’s probably a better solution than the hard-coded value.

However, as aforementioned, it actually does not matter what you pass on for the position. My last example has the same result because the EnemyPathing instance will override the position.

I think Rick’s idea was to instantiate the enemy at the position of the first waypoint. This would have made sense if the EnemyPathing didn’t set the position in Start().

If you comment out the line, you could set the waypointIndex to 1 or 2, and the enemy would move from GetWaypoints()[0] to that waypoint. Test that in your code.

1 Like
#7

I have removed Rick’s line in EnemyPathing.cs Start as it does nothing!:
transform.position = waypoints[waypointIndex].transform.position;

I now have waypointIndex in WaveConfig.cs:

[SerializeField] int waypointIndex = 0;
public int GetWaypointIndex() { return waypointIndex; }
public void SetWaypointIndex(int waypointIndex) { this.waypointIndex = waypointIndex; }

And can call it from EnemySpawner.cs

private IEnumerator SpawnAllEnemiesInWave(WaveConfig waveConfig)
    {
        for (int enemyCount = 0; enemyCount < waveConfig.GetNumberOfEnemies(); enemyCount++)
        {
            var newEnemy = Instantiate(
                waveConfig.GetEnemyPrefab(),
                waveConfig.GetWaypoints()[waveConfig.GetWaypointIndex()].transform.position,
                Quaternion.identity); //this means we dont need rotation - just use the objects current rotation

            newEnemy.GetComponent<EnemyPathing>().SetWaveConfig(waveConfig);

            yield return new WaitForSeconds(waveConfig.GetTimeBetweenSpawns());

        }
    }

Now everything is working, plus I have control over which waypoint on a path an enemy will spawn from, might be useful later for some added randomness!

Thanks again for your help on this, this level of support has surpassed my expectations for an online course :smiley:

#8

You’re welcome. Enjoy the course, and keep up the good work! :slight_smile:

closed #9

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.