Search Unity

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

Discussion in 'Scripting' started by condition6d5489, Aug 28, 2022.

  1. condition6d5489

    condition6d5489

    Joined:
    Jul 17, 2014
    Posts:
    11
    In my level I have a Prefab that has scripts in the child objects that depend on the Start() function. Something like this:
    upload_2022-8-27_22-12-21.png

    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):
    Code (CSharp):
    1. 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!
     
    Last edited: Aug 29, 2022
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    What are you using to determine it's not running?
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    By the time Instantiate<T>() returns, ONLY the OnEnable() and Awake() methods will be called.

    Is that your problem?

    If you Instantiate<T>() 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
     
  4. condition6d5489

    condition6d5489

    Joined:
    Jul 17, 2014
    Posts:
    11
    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.
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    Might be helpful to show a bit more of your code.
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    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.
     
    Kurt-Dekker likes this.
  7. condition6d5489

    condition6d5489

    Joined:
    Jul 17, 2014
    Posts:
    11
    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:

    Code (CSharp):
    1.     void HandlePlayerTap(Vector2 screenPos, float atTime)
    2.     {
    3.         if (IsPointerOverUIObject())
    4.             return;
    5.        
    6.         if (prefab == null)
    7.             prefab = Instantiate(_prefabRef, transform).GetComponent<PrefabTest>();
    8.  
    9.     }
    upload_2022-8-28_17-55-17.png

    Code (CSharp):
    1. public class PrefabTest : MonoBehaviour
    2. {
    3.     // Start is called before the first frame update
    4.     void Start()
    5.     {
    6.         //This works on Android and PC.
    7.         Debug.Log("Prefab Test Start is called.");
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.      
    14.     }
    15. }
    upload_2022-8-28_17-55-33.png

    Code (CSharp):
    1. public class TestParent : MonoBehaviour
    2. {
    3.     public TestChildA childA;
    4.     public TestChildB childB;
    5.  
    6.     public GameObject goChildA;
    7.     public GameObject goChildB;
    8.  
    9.     public Transform tChildA;
    10.     public Transform tChildB;
    11.  
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.         //This runs as expected on PC
    16.         //This runs as expected on android ONLY IF I manually added "Prefab" to the scene before building the .apk file
    17.         //This NEVER runs if I instantiate "Prefab" via script.
    18.         Debug.Log("Test Parent Start is called.");
    19.  
    20.  
    21.         //just a bunch of null checks below.
    22.         //These checks are here because originally I thought I was chasing a different null error.
    23.         if (childA == null)
    24.         {
    25.             Debug.Log("child A is null.");
    26.         }
    27.         else
    28.         {
    29.             Debug.Log("child A is not null.");
    30.         }
    31.  
    32.         if(childB == null)
    33.         {
    34.             Debug.Log("child B is null.");
    35.         }
    36.         else
    37.         {
    38.             Debug.Log("child B is not null.");
    39.         }
    40.  
    41.         if (goChildA == null)
    42.         {
    43.             Debug.Log("gochild A is null.");
    44.         }
    45.         else
    46.         {
    47.             Debug.Log("gochild A is not null.");
    48.         }
    49.  
    50.         if (goChildB == null)
    51.         {
    52.             Debug.Log("gochild B is null.");
    53.         }
    54.         else
    55.         {
    56.             Debug.Log("gochild B is not null.");
    57.         }
    58.  
    59.         if (tChildA == null)
    60.         {
    61.             Debug.Log("tchild A is null.");
    62.         }
    63.         else
    64.         {
    65.             Debug.Log("tchild A is not null.");
    66.         }
    67.  
    68.         if (tChildB == null)
    69.         {
    70.             Debug.Log("tchild B is null.");
    71.         }
    72.         else
    73.         {
    74.             Debug.Log("tchild B is not null.");
    75.         }
    76.     }
    77.  
    78.     // Update is called once per frame
    79.     void Update()
    80.     {
    81.      
    82.     }
    83. }
    TestChildA and TestChildB are both empty:

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

    Code (CSharp):
    1. public class TestChildA : MonoBehaviour
    2. {
    3.     // Start is called before the first frame update
    4.     void Start()
    5.     {
    6.         //This runs as expected on PC
    7.         //This runs as expected on android ONLY IF I manually added "Prefab" to the scene before building the .apk file
    8.         //This NEVER runs if I instantiate "Prefab" via script.
    9.         Debug.Log("Test Child A Start is called.");
    10.     }
    11.  
    12.     // Update is called once per frame
    13.     void Update()
    14.     {
    15.      
    16.     }
    17. }
     
  8. Pharan

    Pharan

    Joined:
    Oct 28, 2013
    Posts:
    102
    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
     
    Last edited: Feb 13, 2023
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,992
    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.
     
    Pharan likes this.
  10. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    720
    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.