Android Build Isn't Calling Start() On Instantiated Prefab's Children

In my level I have a Prefab that has scripts in the child objects that depend on the Start() function. Something like this:

my script Test Parent runs just fine on PC (Start() fires)
If I drag this prefab into my scene, and run in on Android it works, every script fires the start function.

When I instantiate my prefab in script (only on android, Windows works just fine):

prefab = Instantiate(_prefabRef, transform).GetComponent<PrefabTest>();

Only Start() in the Prefab is run and not in the TestParent.cs script. Why isn’t the Start() running on Android?

Thanks for any help!

What are you using to determine it’s not running?

By the time Instantiate() returns, ONLY the OnEnable() and Awake() methods will be called.

Is that your problem?

If you Instantiate() things at runtime you need to give them time to do their thing before you start whapping on them as if they’re fully-operational and ready for business.

Here is some timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

I have a debug.log statement in my start function. I’d just like to say that without any changes, the build runs as expected on PC, but only fails to call Start() on an Android device.

I could be wrong, but I don’t think this matters. I’m not “whapping” on my test prefab ever and it still never gets to Start(). For the actual prefab, it’s instantiated during the state machine’s ‘Enter’ state, and should have plenty of time (3-5 IRL seconds) before the player will actually interact with the object.

Might be helpful to show a bit more of your code.

Thinking on this a bit more, it’s probably an order of operation error. Remember that just because some scripts run first before other scripts in editor, doesn’t mean that will be the case in a build (unless you specifically set it that way.) So, if your Start methods run in the wrong order and you get an error, it’s possible they are running in the wrong order, so your code stops at an error.

For example, if you have 3 scripts all with a Start and in editor or a windows build they run

Script 1
Script 2
Script 3

On Android they could run
Script 2
Script 1
Script 3

Thus, that could explain the difference you are seeing.

1 Like

FYI

  • There are no errors
  • My code doesn’t crash
  • My project runs as expected in all other areas except PrefabTest doesn’t call start… ever.
  • I’ve deleted my .apk and rebuilt the whole project, uninstalled the app and reloaded it… nothing helps.

I tried my best to eliminate all code from the problem to isolate the issue. So the following code is what I have that recreates the issue described above:

From my Manager class:

    void HandlePlayerTap(Vector2 screenPos, float atTime)
    {
        if (IsPointerOverUIObject())
            return;
       
        if (prefab == null)
            prefab = Instantiate(_prefabRef, transform).GetComponent<PrefabTest>();

    }

8397993--1108578--upload_2022-8-28_17-55-17.png

public class PrefabTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //This works on Android and PC.
        Debug.Log("Prefab Test Start is called.");
    }

    // Update is called once per frame
    void Update()
    {
      
    }
}

8397993--1108581--upload_2022-8-28_17-55-33.png

public class TestParent : MonoBehaviour
{
    public TestChildA childA;
    public TestChildB childB;

    public GameObject goChildA;
    public GameObject goChildB;

    public Transform tChildA;
    public Transform tChildB;

    // Start is called before the first frame update
    void Start()
    {
        //This runs as expected on PC
        //This runs as expected on android ONLY IF I manually added "Prefab" to the scene before building the .apk file
        //This NEVER runs if I instantiate "Prefab" via script.
        Debug.Log("Test Parent Start is called.");


        //just a bunch of null checks below.
        //These checks are here because originally I thought I was chasing a different null error.
        if (childA == null)
        {
            Debug.Log("child A is null.");
        }
        else
        {
            Debug.Log("child A is not null.");
        }

        if(childB == null)
        {
            Debug.Log("child B is null.");
        }
        else
        {
            Debug.Log("child B is not null.");
        }

        if (goChildA == null)
        {
            Debug.Log("gochild A is null.");
        }
        else
        {
            Debug.Log("gochild A is not null.");
        }

        if (goChildB == null)
        {
            Debug.Log("gochild B is null.");
        }
        else
        {
            Debug.Log("gochild B is not null.");
        }

        if (tChildA == null)
        {
            Debug.Log("tchild A is null.");
        }
        else
        {
            Debug.Log("tchild A is not null.");
        }

        if (tChildB == null)
        {
            Debug.Log("tchild B is null.");
        }
        else
        {
            Debug.Log("tchild B is not null.");
        }
    }

    // Update is called once per frame
    void Update()
    {
      
    }
}

TestChildA and TestChildB are both empty:

8397993--1108584--upload_2022-8-28_18-4-29.png

public class TestChildA : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //This runs as expected on PC
        //This runs as expected on android ONLY IF I manually added "Prefab" to the scene before building the .apk file
        //This NEVER runs if I instantiate "Prefab" via script.
        Debug.Log("Test Child A Start is called.");
    }

    // Update is called once per frame
    void Update()
    {
      
    }
}

I’m also running into this problem, except it’s also happening while testing the project in Unity Editor Play mode.

I’m instantiating a prefab via script and at least one of my scripts’ Start() isn’t being called. I put a debug log in it and it’s not logging.

It’s not an order of operation problem. It just not called at all.

Running Unity 2022.2.5f1

Since the question got bumped already: Start would not be called when

  • The GameObject or any parent object the script is attached to is deactivated before at least one frame has passed.
  • The script itself is / gets disabled before the first frame has passed.
  • The script or complete gameobject got destroyed before the first frame has passed.

So in order to investigate, I would recommend to add log statements to OnEnable / OnDisable and Awake / OnDestroy to see if the object is actually enabled and active. You probably want to include the Time.frameCount in the message to properly distinguish when the event actually happens.

We used way more complex prefab structures with nested objects and scripts and each is working as expected. So it has to be something in your code, somewhere. Common pitfalls can be hidden stuff like an animation that contains an animation curve that disables the object.

2 Likes

Don’t forget that the object will deactivate itself if it throws an exception in Awake – although you’d probably notice if that was happening, since it’d blow up whoever instantiated it.