Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved using DOTween to fade a CanvasGroup, getting a MissingReferenceException when reloading scene

Discussion in 'Scripting' started by pawelpietryka, Nov 30, 2022.

  1. pawelpietryka

    pawelpietryka

    Joined:
    Aug 18, 2022
    Posts:
    12
    So I need a quick way to just reload the current scene with


    void onReloadScene(InputAction.CallbackContext context)
    {
    Scene scene = SceneManager.GetActiveScene();
    SceneManager.LoadScene(scene.name);
    }


    I get this error message


    MissingReferenceException: The object of type 'CanvasGroup' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object.



    I'm super new to programming but I'm assuming DOTween tries to animate the fading even tho all element havent been loaded yet? Is there a quick fix? I tried using the singlton pattern 'DontDestroy' on the UI gameobject (that has the canvas group) but it didn't work. Could I potentially trigger DOTween slightly later?

    Thanks for the help in advance!


    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using DG.Tweening;
    6. using TMPro;
    7. using UnityEngine.UI;
    8.  
    9. public class DistanceCalculation : MonoBehaviour
    10. {
    11.  
    12.     [SerializeField] GameObject closestPainting;
    13.     [SerializeField] float distanceToPainting;
    14.  
    15.     [SerializeField] TextMeshProUGUI titleText;
    16.     [SerializeField] TextMeshProUGUI descriptionText;
    17.  
    18.     [SerializeField] CanvasGroup fadingDescriptionText;
    19.     [SerializeField] CanvasGroup fadingTitleText;
    20.     [SerializeField] CanvasGroup fadingScrim;
    21.     [SerializeField] CanvasGroup fadingRawImageForQRCode;
    22.  
    23.      [SerializeField] RawImage RawImageReferenceForQRCode;
    24.      [SerializeField] string[] paintingTitle =
    25.     {
    26.         "The Family",
    27.         "Nu au Voile",
    28.         "The Dance Class"
    29.     };
    30.     [SerializeField] string[] paintingDescription =
    31.     {
    32.         "The Kiss ...",
    33.         "Albert Aublet was a pupil ...",
    34.         "This work and its ..."
    35.     };
    36.    
    37.     [SerializeField] Texture[] paintingQRCodes;
    38.  
    39.     // Update is called once per frame
    40.     void Update()
    41.     {
    42.    
    43.         FindClosestPainting();
    44.  
    45.         if (distanceToPainting < 20f)
    46.         {
    47.        
    48.             switch (closestPainting.name)
    49.             {
    50.                 case "Klimt":
    51.                     titleText.SetText(paintingTitle[0]);
    52.                     descriptionText.SetText(paintingDescription[0]);
    53.                                      
    54.                     RawImageReferenceForQRCode.texture = paintingQRCodes[0];
    55.  
    56.                     FadeIn();
    57.                     // Debug.Log("The Familiy");
    58.                     break;
    59.  
    60.                 case "Lady":
    61.                     titleText.SetText(paintingTitle[1]);
    62.                     descriptionText.SetText(paintingDescription[1]);
    63.                     RawImageReferenceForQRCode.texture = paintingQRCodes[1];
    64.                     FadeIn();
    65.                     // Debug.Log("Lady");
    66.                     break;
    67.  
    68.                 case "Dance Class":
    69.                     titleText.SetText(paintingTitle[2]);
    70.                     descriptionText.SetText(paintingDescription[2]);
    71.                     RawImageReferenceForQRCode.texture = paintingQRCodes[2];
    72.                     FadeIn();
    73.                     // Debug.Log("Dance Class");
    74.                     break;
    75.  
    76.                 case null:
    77.                     Debug.Log("Something went wrong");
    78.                     break;
    79.             }
    80.  
    81.         }
    82.         else
    83.         {
    84.             FadeOut();
    85.         }
    86.  
    87.        
    88.     }
    89.  
    90.     public GameObject FindClosestPainting()
    91.     {
    92.         GameObject[] paintings;
    93.         paintings = GameObject.FindGameObjectsWithTag("Painting");
    94.         GameObject closest = null;
    95.         float distance = Mathf.Infinity;
    96.         Vector3 position = transform.position;
    97.         foreach (GameObject painting in paintings)
    98.         {
    99.             Vector3 diff = painting.transform.position - position;
    100.             float curDistance = diff.sqrMagnitude;
    101.             if (curDistance < distance)
    102.             {
    103.                 closest = painting;
    104.                 distance = curDistance;
    105.  
    106.                
    107.             }
    108.         }
    109.         closestPainting = closest;
    110.         distanceToPainting = distance;
    111.         return closest;
    112.     }
    113.    
    114.     void FadeIn()
    115.     {
    116.         fadingScrim.DOFade(1,1);
    117.         fadingTitleText.DOFade(1,2);
    118.         fadingDescriptionText.DOFade(1,2);
    119.         fadingRawImageForQRCode.DOFade(1,2);
    120.     }
    121.  
    122.     void FadeOut()
    123.     {
    124.         fadingScrim.DOFade(0,1);
    125.         fadingDescriptionText.DOFade(0,1);
    126.         fadingTitleText.DOFade(0,1);
    127.         fadingRawImageForQRCode.DOFade(0,1);
    128.     }  
    129. }
    130.  
     
  2. pawelpietryka

    pawelpietryka

    Joined:
    Aug 18, 2022
    Posts:
    12
    this is what i had on the UI gameobject that has all the text/canvasgroups as children


    public class DontDestroy : MonoBehaviour
    {

    public static DontDestroy Instance { get; private set; }

    void Awake()
    {
    // If there is an instance, and it's not me, delete myself.

    if (Instance != null && Instance != this)
    {
    Destroy(this);
    }
    else
    {
    Instance = this;
    }

    }
    }
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,005
    It really doesn't matter what you're doing. The answer is always the same:

    How to fix a NullReferenceException error

    https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

    Three steps to success:
    - Identify what is null <-- any other action taken before this step is WASTED TIME
    - Identify why it is null
    - Fix that

    Isolate, isolate, isolate, find the null, fix it.

    That code looks like a partial yet defective implementation of something singleton-ish.

    To understand why, here is some timing diagram help:

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

    If you ACTUALLY need a singleton-ish construct, here is a correct way to do it:

    Simple Singleton (UnitySingleton):


    (if you don't actually need it, don't do it!)

    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!

    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.
    , and only while it exists.
     
  4. pawelpietryka

    pawelpietryka

    Joined:
    Aug 18, 2022
    Posts:
    12
    Thank you so much, Kurt-Dekker for taking all this time to write up a very comprehensive response. I do really appreciate it.

    I will try to understand it now and read through the links you included. I'll report if I solve it (or if I'm still stuck)!

    Cheers
     
    Kurt-Dekker likes this.
  5. pawelpietryka

    pawelpietryka

    Joined:
    Aug 18, 2022
    Posts:
    12
    Petricevic and Kurt-Dekker like this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,005
    Oh thanks, great find, thanks also for coming back to post here... making the forum a better place!
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,576
    Please stop spamming the forums recommending your product. Whist recommending your product isn't bad, making many, many such posts as you've done today (necroing in a lot of cases) isn't welcome.

    Thanks.
     
    Kurt-Dekker likes this.