Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Calling method before an Object is fully initialized in Start()

Discussion in 'Scripting' started by Presidio, Sep 13, 2020.

  1. Presidio

    Presidio

    Joined:
    Nov 15, 2016
    Posts:
    2
    Hi everyone,
    I'm having an issue structuring my code so that objects get a chance to initialize before a method is called on them. In the code below, I Instantiate a "ProceduralSystem" by pressing the spacebar for now, from the GalaxySystem class. The ProceduralSystem holds an array of "planets" that are created when in the Start() method.

    The ProceduralSystem is Instantiated, but when I call GetSolarSystemWidth() on it, it comes back with 0. I've looked through the de-bugger, and I know that it comes back with 0 because Start() in ProceduralSystem hasn't ran yet before that get method is called and returned.

    I found I could get around this by calling the SpawnPlanets() method in the Awake() instead of Start() of ProceduralSystem, since it runs and returns back to GalaxySystem before Start() does. But is this the right way of getting around this issue? Is it okay to initialize those planet objects, and other variables from the Awake() method rather than Start()?

    What other practice could I use to make sure the object is initialized before calling methods on it?


    Code (CSharp):
    1. public class GalaxySystem : MonoBehaviour
    2. {
    3.     public GameObject solarSystemsPrefab;
    4.     public List<ProceduralSystem> solarSystems;
    5.     void Start() {
    6.         solarSystems = new List<ProceduralSystem>();
    7.     }
    8.     void Update() {
    9.         if (Input.GetKeyDown(KeyCode.Space)) {
    10.             CreateNextRandomSystem();
    11.         }
    12.     }
    13.  
    14.     public void CreateNextRandomSystem() {
    15.         GameObject system = Instantiate(solarSystemsPrefab, new Vector3(0f, 0f, 0f), Quaternion.identity, transform);
    16.         system.gameObject.transform.position = new Vector3(0f, 0f, system.GetComponent<ProceduralSystem>().GetSolarSystemWidth());
    17.     }
    18. }
    Code (CSharp):
    1. public class ProceduralSystem : MonoBehaviour
    2. {
    3.     public List<Planet> planets;
    4.     public GameObject planetPrefab;
    5.     void Start() {
    6.         SpawnPlanets(numberOfPlanets);
    7.     }
    8.     void SpawnPlanets(int numOfPlanets) {
    9. //Spawns a number of planetPrefabs with <Planet> component
    10.     }
    11.     public float  GetSolarSystemWidth() {
    12.         return systemWidth;
    13.     }
    14.  
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    5,506
    Awake is good to initialize stuff on the same script and start is good for when you need scripts to access other scripts. There are other options though. One is to setup the script execution order inside Unity. The other is to have another script that will manage initializing any script that you need it to in the order you want it in.

    I've done both. The first method is straight forward. The second is just making a manager script for example and then adding an init() method to my other scripts that I can call in the order I want, so I know each script that is relied on has set stuff up before the next script runs.
     
unityunity