(exercise 112, Lists) GameObject converted to Waypoint?

So each of the parent of the cube has an instance of Waypoint.cs. And the Enemy empty has the EnemyMover.cs, to wich we pass instances of the cube’s parent, all of them gameObjets.

This code does work, but i dont unsderstand the Waypoint reference

using System.Collections.Generic;
using UnityEngine;

public class EnemyMover : MonoBehaviour
{
    [SerializeField] List<Waypoint> path = new List<Waypoint>();

    void Start()
    {
        PrintWayPointName();
    }

    void PrintWayPointName() {
        foreach(Waypoint waypoint in path) {
            Debug.Log("waypoint: " + waypoint.name);
        }
    }
}

So in

[SerializeField] List<Waypoint> path = new List<Waypoint>();

// how come those objects passed to [SerializeField] are Waypoint instances, and not GameObjects?
// shoudn't this be

[SerializeField] List<GameObject> path = new List<GameObject>();

thanks

Hi @Luis_Aguiar,
We are passing through a reference to the waypoint script, which is attached to a GameObject in the hierarchy.

You could store a list of GameObjects instead but this has several drawbacks, including:

  • A gameoject that is not a waypoint could pollute your list and potentially cause problems later on.
  • If you want to use a function from the waypoint class, you’d have to get the component from the parent GameObject and also check that it exists before using it.
  • GetComponent can start to get expensive if you’re using it a lot, so storing a list of waypoints will also help with performance.

As an example, this is what the class would probably look like if you were to store a list of GameObjects instead of Waypoints. Note the additional two lines of code that would be required to make things work:

using System.Collections.Generic;
using UnityEngine;

public class EnemyMover : MonoBehaviour {
    [SerializeField] List<GameObject> path = new List<GameObject>();

    void Start() {
        PrintWayPointName();
    }

    void PrintWayPointName() {
        foreach(GameObject go in path) {
            Waypoint waypoint = go.GetComponent<Waypoint>()
            if(waypoint == null) { continue; }
            Debug.Log("waypoint: " + waypoint.name);
        }
    }
}

So, as a general rule of thumb, if you know the type of component you want to store, it’s better to be as specific as possible.
This will; help you improve performance, save you having to type extra lines of code, and make your program more resilient.

I hope that explanation helps.

Thanks for the repply. So because one of the components is an instance of Waypoint, it automatically gets mapped to that datatype, right?

Just as a test, i removed that script component from the first Empy, the “(0, 0)”, and this happned:

NullReferenceException: Object reference not set to an instance of an object
EnemyMover.PrintWayPointName () (at Assets/Enemy/EnemyMover.cs:18)
EnemyMover.Start () (at Assets/Enemy/EnemyMover.cs:13)

thanks for the explanation!

Hi Luis,

Waypoint inherits from MonoBehaviour. When checking the API, you can see that the MonoBehaviour class contains properties such as gameObject, which automatically references the game object to which your script component is attached to. It also adds the GetComponent method to your object.

NullReferenceException means that a reference (“link”) to an instance is missing. Double click on the error message to see to which line in your code it is referring.

1 Like

thanks for the aditional explanation. very cool!

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

Privacy & Terms