Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Loading scene is losing the objects refences

Discussion in 'Scripting' started by bisewski, Sep 9, 2023.

  1. bisewski

    bisewski

    Joined:
    Jan 16, 2014
    Posts:
    120
    Hi.

    I am with problems when loading new scenes and back to the previous scene again. Sure that I am missing something simple here.

    In my project, I have a menu scene where I can load others scenes and back to the menu again.

    I am using a very simple code:
    AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);

    Som when in Menu, I click in a button loadScene1 and ok, works fine.
    In Scene1 I have a button Bavk to Menu and ok, the menu scene is loaded but I am losing all my referenced gameobjects. They still there in my [SerializableField] but the code cant see.

    I receive this error:
    Code (CSharp):
    1. MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
    2. Your script should either check if it is null or you should not destroy the object.
    3. UnityEngine.GameObject.GetComponent[T] () (at <e97d84204f8d4aef92b538c5bab948f1>:0)
    4. touchInteractive.singleTouched_onSingleTouch (singleTouch clicked) (at Assets/Scenes/script/touchInteractive.cs:24)
    5. swipeDetection.SendSingleTouch () (at Assets/Scenes/script/swipeDetection.cs:178)
    6. swipeDetection.Update () (at Assets/Scenes/script/swipeDetection.cs:52)
    This error occours because I hava this line in my code:
    Code (CSharp):
    1.  
    2. [SerializeField]
    3.  private GameObject panelSettings;
    4. ...
    5. Screen.width - panelSettings.GetComponent<RectTransform>().rect.width;
    So the panelSettings lost his reference. Whats happen? I cant understand...
    If I am using SceneManager.LoadSceneAsync is correct to think that the scene will be load from zero again and works fine?

    Thank you.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    You probably have a defective singleton that fails to guard itself.

    Look for DontDestroyOnLoad and NEVER place such an object in a scene file.

    Instead, load it on demand with this approach.

    Simple Singleton (UnitySingleton):

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

    Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

    https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

    These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance

    Alternately you could start one up with a
    RuntimeInitializeOnLoad
    attribute.

    The above solutions can be modified to additively load a scene instead, BUT scenes do not load until end of frame, which means your static factory cannot return the instance that will be in the to-be-loaded scene. This is a minor limitation that is simple to work around.

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }
    There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

    OR just make a custom ScriptableObject that has the shared fields you want for the duration of many scenes, and drag references to that one ScriptableObject instance into everything that needs it. It scales up to a certain point.

    And finally there's always just a simple "static locator" pattern you can use on MonoBehaviour-derived classes, just to give global access to them during their lifecycle.

    WARNING: this does NOT control their uniqueness.

    WARNING: this does NOT control their lifecycle.

    Code (csharp):
    1. public static MyClass Instance { get; private set; }
    2.  
    3. void OnEnable()
    4. {
    5.   Instance = this;
    6. }
    7. void OnDisable()
    8. {
    9.   Instance = null;     // keep everybody honest when we're not around
    10. }
    Anyone can get at it via
    MyClass.Instance.
    , but only while it exists.
     
    bisewski likes this.
  3. bisewski

    bisewski

    Joined:
    Jan 16, 2014
    Posts:
    120
    Its sounds like I have a static event, maybe this is trying to access an gameobject that doesnt exist more. So I dont know what to do.
    I use it to set a swipe event:
    Code (CSharp):
    1.  public static event Action<SwipeData> OnSwipe = delegate { };
    and in other script:
    Code (CSharp):
    1. swipeDetection.OnSwipe += swipeDetection_OnSwipe;
    But I can´t remove the Static...
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    Whatever object subscribes to this delegate also needs to unsubscribe from it when the scene is unloaded. Usually with OnDisable or OnDestroy.
     
    bisewski and Kurt-Dekker like this.
  5. bisewski

    bisewski

    Joined:
    Jan 16, 2014
    Posts:
    120
    OH NOOO.....How I could forget it...I am really need to go to the bed...unbelievable...Shame on me...
    Can I delete this , please?:p
     
  6. bisewski

    bisewski

    Joined:
    Jan 16, 2014
    Posts:
    120
    I
    I will not delete because Kurt send me a new book to read so just because it...
    Thank you Sr...It really help us so much...