0
\$\begingroup\$

Edit: Here is some important update:

I have found out that the script's Start and Awake voids are called, but AFTER the script is used by some other script. So the problem here is that the gameobject that hosts "OtherScript" is initialized after the gameobject which has a "MainScript" attached and which holds a reference to "OtherScript".

I hope I could explain it well.

If just the one gameobject was initialized before the other, everything would be fine. I will investigate now if I can change the intialization order.

Original post:

I have a complex scenario which I have reduced to the following problem:

I have a Cube in my Unity scene. This cube has the following script on it:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MainScript : MonoBehaviour
{
    public OtherScript TheOtherScript;

    public void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 50, 50), "Load something"))
        {
            this.TheOtherScript.LoadFile();
        }
    }
}

The script "OtherScript" looks like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OtherScript : MonoBehaviour
{
    private string _sPath;

    public bool HasBeenInitialized = false;

    public void Awake()
    {
        _sPath = Application.persistentDataPath + "/somefilename.dat";
        this.HasBeenInitialized = true;//indicator that Awake or Start have occured
    }
    public void Start()
    {
        _sPath = Application.persistentDataPath + "/somefilename.dat";
        this.HasBeenInitialized = true;//indicator that Awake or Start have occured
    }

    public void LoadFile()
    {
        if (_sPath == null)
        {
            Debug.Break();
        }
        //do something with _sPath
    }
}

I have created an empty GameObject to my scene, and I have added such a script to it:

enter image description here

I have then put a reference to empty GameObject to the Cube's "OtherScript" slot:

enter image description here

The problem that I'm experiencing is that "TheOtherScript"'s start / awake has not been called when this button is pressed:

    if (GUI.Button(new Rect(0, 0, 50, 50), "Load something"))
    {
        if (!this.TheOtherScript.HasBeenInitialized)
        {
            Debug.Break();//The script hasn't processed Start or Awake yet. Why???
        }

        this.TheOtherScript.LoadFile();
    }

Neither Awake nor Start is called on this script.

Which event could I react to in this case for initialization?

\$\endgroup\$
  • \$\begingroup\$ You need to instantiate your empty game object. You can't just load the file. Awake and Start are called when you instantiate a game object \$\endgroup\$ – Ben Jul 12 at 3:18
  • \$\begingroup\$ How do you know that Awake and Start are not being called on GameObject? \$\endgroup\$ – Philipp Jul 12 at 11:02
  • \$\begingroup\$ @Philipp I attached the VS debugger to the Unity project. \$\endgroup\$ – tmighty Jul 12 at 14:46
  • 1
    \$\begingroup\$ @Ben Thank you, your comment lead me to the real problem. The script sits on a gameobject in the scene, so it is being initalized. However, I found out that it is initalized AFTER I access it. So I will now investigate if I can change the initialization order. \$\endgroup\$ – tmighty Jul 12 at 15:06
  • \$\begingroup\$ There's some similar issues discussed in this Q&A: Check if Game Component is Ready in Unity \$\endgroup\$ – DMGregory Jul 12 at 15:19
1
\$\begingroup\$

You can change Script Execution Order.

You can use the Script Execution Order settings (menu: Edit > Project Settings, then select the Script Execution Order__ category).

You could also add a safecheck in your code:

public void LoadFile()
{
    if(!HasBeenInitialized) Start();

    if (_sPath == null)
    {
        Debug.Break();
    }
    //do something with _sPath
}

EDIT ----- ANSWER TO PREVIOUS QUESTION BELOW

First of all check that your Unity version is not an Alpha one. In that case anything might happen.

If your unity version is anyone of 2019.1 or previous everything will be working as expected.

Awake

Awake is called after all objects are initialized

Start

However, Awake is called when the script object is initialised, regardless of whether or not the script is enabled. Start may not be called on the same frame as Awake if the script is not enabled at initialisation time.

This means your Awake and Start are called properly (because your game object starts enabled). You may just add a Debug.Log statement to check them.

public void Awake()
{
    Debug.Log("Awake Called");
    _sPath = Application.persistentDataPath + "/somefilename.dat";
}
public void Start()
{
    Debug.Log("Start Called");
    _sPath = Application.persistentDataPath + "/somefilename.dat";
}

public void LoadFile()
{
    if (_sPath == null)
    {
        Debug.Break();
    }
    //do something with _sPath
    Debug.Log(_sPath);
}

The issue relies most likely on MainScript method.

Also:

  • Make sure the scripts are saved before launching play
  • Make sure the scripts are attached to the Game Objects before going in play mode
\$\endgroup\$
  • \$\begingroup\$ Thank you for your answer! I have found out the cause of my problem, I think. I believe that the gameobject isn't initialized early enough, so I will now try to find out if I can change the initialization order. \$\endgroup\$ – tmighty Jul 12 at 15:07
  • \$\begingroup\$ You can change the Script Initialization Order. \$\endgroup\$ – Jack Mariani Jul 12 at 15:20
  • \$\begingroup\$ I also added a way to make sure your script has been initiated before calling load. \$\endgroup\$ – Jack Mariani Jul 12 at 15:26
0
\$\begingroup\$

The problem was "Script Execution Order":

The "OtherScript" is initialized AFTER "MainScript" is initialized". So when "MainScript" access the "OtherScript", it may happen that OtherScript hasn't been initialized yet.

The solution was change the Script Execution Order under "Project Settings..." -> "Script Execution Order".

The script "OtherScript" has to be added with a negative time number, for example -50. It will then be initialized before any other script which are not explicitely listed here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.