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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Null Reference for Slider

Discussion in 'Scripting' started by JosephMGS, May 30, 2020.

  1. JosephMGS

    JosephMGS

    Joined:
    Nov 5, 2019
    Posts:
    20
    I think I've solved this problem by have a check statement but I don't actually get it. I attach below script to slider and adjust sound level. I always get "null reference exception" error if I don't use a null check. How does "if statement" help in this manner? Any brief explanation? Thanks.

    Code (CSharp):
    1. public class SoundSlider : MonoBehaviour
    2. {
    3.     [SerializeField] Slider soundslider;
    4.     AudioManager myaudiomanager;
    5.  
    6.     void Start()
    7.     {
    8.         soundslider.value = PlayerPrefs.GetFloat("audiolevel", 1f);
    9.         myaudiomanager = FindObjectOfType<AudioManager>();
    10.     }
    11.  
    12.     public void ChangeSound() //Called when slider moves
    13.     {
    14.         PlayerPrefs.SetFloat("audiolevel", soundslider.value);
    15.  
    16.         if(myaudiomanager != null)
    17.         {
    18.             myaudiomanager.ChangeSoundActual(soundslider.value);
    19.             //If I put this line out of null check I always get "null reference exception" error
    20.         }
    21.     }
     
    Last edited: May 30, 2020
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    A "null reference exception" means you're trying to use a variable that doesn't have a value. That line is trying to use both the variables "myaudiomanager" and "soundslider", so if either of those variables doesn't have a value, it will cause an exception.

    myaudiomanager could be null if the FindObjectOfType call in Start failed to find anything, or if you somehow call ChangeSound before Start gets a chance to run, or if something else is changing the variable to null after Start.

    soundslider could be null if you forgot to assign a value to it in the inspector for this object.

    But if the "if" statement prevents the error, that means myaudiomanager must have been the variable that was null, not soundslider. And it also means that, in all the times that it would have caused an error, you are skipping that line, not fixing it. In those cases, it won't actually change your volume. (Or at least, this particular script won't.)

    It might be that you're getting errors sometimes and not other times, so you notice the volume changing from the times that it works and the "if" prevents the times when it wouldn't work. In this case, though, that would seem to require that there's some code you haven't posted that's doing something weird to your variable.
     
    JosephMGS and Kurt-Dekker like this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Basically if anyone calls ChangeSound before your Start() function runs, that's how. Since it is public, there's no way to prevent anyone else from calling it at any time, such as during the Awake() function in the Slider, which might indeed be what is happening.

    If you're curious, here's something really awesome: comment out the
    if
    statement and run the code.

    Click once on the nullref error in the log, and look at the bottom "larger" portion of the log. It will be a stack trace of all the functions that were involved leading to your ChangeSound() function getting called. Using that stack trace you might be able to see who is responsible, which I predict will be a function in the Slider class, perhaps called by OnEnable or Awake or somesuch. Looking at stack traces for exceptions can be VERY time-saving as far as figuring out what happened.
     
    Dustin0530 and JosephMGS like this.
  4. JosephMGS

    JosephMGS

    Joined:
    Nov 5, 2019
    Posts:
    20
    Hi All,


    Thanks for the answers. Btw I'm actually a bit familiar with null references. I'm sure that when I include null check the code runs perfect but when I don't I get the below error. I also checked AudioManager in the Editor with [SerializeField] and it is not loaded when I don't use null check. I just want to understand how using a null check helps in this situation. I’ve also included other lines for error reference.


    It's like somehow the Event System (UI.Slider.Set?) is trying to get AudioManager before Start function or it runs when the reference is not null. I assume it is something related to delegates but cant figure out. Any suggestions?


    SoundSlider.ChangeSound () (at Assets/Scripts/SoundSlider.cs:18)

    UnityEngine.Events.InvokableCall.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent/UnityEvent.cs:166)

    UnityEngine.Events.UnityEvent`1[T0].Invoke (T0 arg0) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent/UnityEvent/UnityEvent_1.cs:63)

    UnityEngine.UI.Slider.Set (System.Single input, System.Boolean sendCallback) (at C:/Program Files/Unity/Hub/Editor/2019.2.17f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Slider.cs:518)

    UnityEngine.UI.Slider.set_value (System.Single value) (at C:/Program Files/Unity/Hub/Editor/2019.2.17f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Slider.cs:255)

    SoundSlider.Start () (at Assets/Scripts/SoundSlider.cs:8)
     
  5. JosephMGS

    JosephMGS

    Joined:
    Nov 5, 2019
    Posts:
    20
    Btw I've just checked that if I changed order of line 8 and line 9 it also works without null check. I guess soundslider.value should be set by PlayerPrefs after finding "AudioManager".

    Still cannot get the actual reason however :)
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    I just looked at your code again and you are actually explicitly causing the problem yourself, as verified by your supplying the callstack.

    Look in your Start() function. You SET the slider value first (line 8). That triggers the callback to ChangeSound()

    At that point you have NOT executed line 9, which is what sets audioManager to not be null.

    Reverse those two lines in Start().
     
    JosephMGS likes this.
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    That's also kinda the power and danger of events. No matter how many different things are hooked up to the slider change event, ALL of them are called all as part of your line 8 statement that assigns a value, and all those calls happen before you ever continue from your set-value callsite.
     
    JosephMGS likes this.
  8. JosephMGS

    JosephMGS

    Joined:
    Nov 5, 2019
    Posts:
    20
    Thanks a lot. I guess I need to study on basic principles more :)
     
    Kurt-Dekker likes this.