Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Null reference in builds

Discussion in 'Scripting' started by EddieCam, Aug 14, 2012.

  1. EddieCam

    EddieCam

    Joined:
    Oct 28, 2009
    Posts:
    26
    I'm having a really odd problem, where a public Camera reference works fine in editor, but throws a null reference in builds.
    Code (csharp):
    1. public Camera mainCam;
    2. void Awake()
    3. {
    4. Debug.Log( mainCam.name );
    5. }
    6.  
    mainCam isn't referenced from any other scripts, there is only one copy of this script in the scene, and yes, mainCam is assigned in the inspector. I was using Camera.main to assign before, but this also wasn't working. So I'm assuming there's something up with that camera specifically.
    But, unless the camera is deleting and then respawning itself on launch (since it renders fine) I have no idea what could be happening....
     
  2. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    That is probably related to script execution order. If you execute it in the editor, first the camera gets deleted and respawned and the mainCam variable is initialized, before Awake of the shown script is called. So I expect this camera deletion and creation happens in an Awake as well. You can't know which Awake is executed first. There are two solutions:
    - Script execution order
    - Change the shown script and use Start instead of Awake. Because Start is called after all Awakes. So make sure that the mainCam variable is initialized in an Awake, to safely access it in Start.
     
  3. EddieCam

    EddieCam

    Joined:
    Oct 28, 2009
    Posts:
    26
    Turned out that a demo scene in the FingerGesture package had an error when I tried to load it. Unity didn't load the scene (none of the loaded gameobjects changed, and the menubar stayed the same) but internally, all the changes I was making and changing were saved to the demo scene, rather than the one I was loading on build. I only found out when I accidentally clicked 'Add current scene' in the build settings and it put the FingerGestures scene in.

    The moral is, check your scenes and don't trust the titlebar!
     
  4. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    393
    Still relevant 6 years later:

    1) Check that the referenced
    gameObject.tag
    is not "EditorOnly". Check that none of the parent-gameObjects have that tag either.

    2) Check that the object was actually constructed before you queried it. For example, this problem might arise when trying to access member variables during Awake(), especially any member variables of children-components. That's because children are not yet Awoken (not yet constructed by unity)

    3) Recall that Awake() is called immediately after you instantiate the component. It pauses your current function until the component's Awake() completes. In other words, Awake is not called on the next frame, but is called immediately.

    4) Check that unity hasn't stripped-away the code when it was producing a Build. For that, inside the c# file, write a
    [Preserve]
    attribute on top of the problematic class, and above any member-variable which actually references such a class. You will need to include
    UnityEngine.Scripting
    namespace

    5) Look into Script compilation order. For example, you may have a singleton that initialises itself during Awake(). For any other class that compiles earlier than your singleton, accessing the singleton's instance during its Awake() won't work.

    6) forget about Monobehavior::Start() function. It's bugged and not guaranteed to be called after all other objects have finished doing Awake(). This bugged Start() function can be called anytime it wants, even immediately after the object's Awake().

    To guarantee it doesn't happen - make your own Start() function that is called before the first update. For that, instead of inheritting from Monobehaviour, inherit from its extended version. From a custom class (I am using
    MyCustomMonobehavior.cs
    ) that issues a
    Start_DuringFirstUpdate()
    callback right before the
    UpdateCallback()


    Code (CSharp):
    1.  public class MyCustomMonobehavior{
    2.         bool _startInvoked = false;
    3.    
    4.         protected virtual void Awake(){}
    5.  
    6.         void Update(){
    7.             if(_startInvoked == false){
    8.                 _startInvoked = true;
    9.                 Start_FirstUpdate();
    10.             }
    11.             Update_callback();
    12.         }
    13.  
    14.         protected abstract void Update_callback();
    15.     }
     
    Last edited: Jan 17, 2019
    Lorellaro likes this.
  5. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,586
    I've never had any problem with "Start", can you point us to the bug-report?

    In my experience, "Start" just behaves as it's documented:
    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  6. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    393
    Last edited: Jan 20, 2019