Search Unity

C# public variables in unity

Discussion in 'Scripting' started by Ap0C552, Feb 21, 2015.

  1. Ap0C552

    Ap0C552

    Joined:
    Feb 7, 2015
    Posts:
    43
    Hello.

    I have noticed that when I declare a public variable in a script, that it is settable in the inspector.

    I am curious how this is implemented? If I do not set my public variable to any value in the start function, will it always take the value set in the inspector? Will setting in the start function override what was set in the inspector?

    How is the value in the inspector assigned to my public var? Like what is happening underneath the hood?
     
  2. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    The value in the inspector will actually override the initialized value in your code, but otherwise will not effect any code you do outside of that initialization, such as in Start() or Awake(). If you do change the value of a serializable public variable in your code after initialization, the inspector will automagically update to reflect the changed value, and you can also change the value in the inspector while the game is playing. Very handy for debugging or just rapidly developing your game without having to start/stop it all the time.

    These changed values are not persistent however, and once your game is stopped, they will revert back to their values that were set before the game was started.
     
  3. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Also if you want it public but not showen in the inspector you can use the
    [HideInInspector] or if you need a private var to show in the inspector you can use the
    [SerializeField] attribute.
     
  4. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    Underneath the hood it's Unity's serialization/deserialization at work. I believe this is how it works:

    When you select your object, Unity's Inspector will read the value of your public variable. So the value you are seeing comes from the instance of your script class. Changing this value in the inspector will cause Unity to update the value in your script instance, meaning it will change the value of your variable.

    Let me try and explain with an example class:


    Code (csharp):
    1. public class CoolThing : MonoBehaviour {
    2.     public int i = 1;
    3.  
    4.     public CoolThing() {
    5.         Debug.Log (i); // Will print 1 (probably, see explanation below)
    6.         // The value we set now will be the value in the Inspector for new objects.
    7.         // If we didn't have this line the value would be from our declaration (1).
    8.         i = 2;
    9.     }
    10.  
    11.     void Start () {
    12.         // Will print value from Inspector (serialization/deserialization),
    13.         // NOT from constructor.
    14.         Debug.Log (i);
    15.     }
    16. }
    Let's say we add this script to a game object. The inspector will show the value 2, because that's the last value our script sets it to in any of the executed methods.

    Then we go ahead and change this value in the inspector to something else, say 3.

    If we now press Play, Unity will serialize the object. This means it will read the value 3 from the public variable i and store it.

    Following this, Unity will create a new instance of CoolThing. This I believe is one reason why components can't have constructors with parameters: Unity needs to be able to create the object and it doesn't know what values to send to the constructor, or if there are multiple constructors, which one to call.
    After this step, the variable has whatever value was set in its declaration or constructor. In our example we overwrite the declared value in the constructor. So when our constructor is called, the value is 1 and then our constructor changes it to 2, which is therefore the value after this step.
    Note: Unity documentation says that deserialization (see next step) is at an undefined state when the constructor is executed! So the value of i isn't guaranteed to be 1 or 2 here, in case deserialization kicks in before our constructor is finished.

    Next Unity will read the data it serialized from our previous object instance, i.e. the stored value of i. It will use this to update the new object so that the variable has this value. So now i is 3. This process is called deserialization.

    Finally, Unity will start to call the standard MonoBehaviour callback methods of our script: Awake, OnEnable, Start, Update, etc. So these will always see the value 3.

    If you want to read up on Unity's serialization process:
    http://blogs.unity3d.com/2014/06/24/serialization-in-unity/
    http://blogs.unity3d.com/2012/10/25/unity-serialization/
    http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.html
     
    Last edited: Feb 22, 2015