0

Is there any fundamental difference between assigning a value to a variable before or inside the Start() method?

For clarity, I'm not talking about declaring variables but really just giving them values like, in this simple example:

public class test : MonoBehaviour
{
    private float exampleFloat = 12.34f;

    private void Start()
    {
        // do stuff with exampleFloat
    }
}

versus this :

public class test : MonoBehaviour
{
    private float exampleFloat;

    private void Start()
    {
       exampleFloat = 12.34f;
       // do stuff with exampleFloat
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MathMith
  • 39
  • 7
  • 8
    There is a difference if you try to use the value before Start has been called. – luk2302 Nov 26 '22 at 21:57
  • well in my example I would use it in the Start method. Should I always attribute values before everything then? It seems cleaner when everything is at the same place but I was worried since I've seen a lot of people doing it in Start(). – MathMith Nov 26 '22 at 22:05
  • @MathMith - Now that's a different question: Where should I initialize variables for better code maintainability? – Enigmativity Nov 26 '22 at 22:16
  • For what I read online, they should be initialized where they're used. So it would be the same rule for filling them then? – MathMith Nov 26 '22 at 22:51
  • @MathMith - That'll be opinion-based. I would try to write code that is easier to maintain. That's my opinion. – Enigmativity Nov 27 '22 at 01:10

4 Answers4

3

Just to add, because we ARE talking about Unity, let's discuss your question with some examples.

Object Lifecycle

Let's consider the object lifecycle and when Unity events are called:

public class test : MonoBehaviour
{
    private float exampleFloat = 12.34f;

    private void Awake ()
    {
        Debug.Log($"Example 1: exampleFloat = {exampleFloat}");
    }

    private void Start()
    {
        //do stuff with exampleFloat
    }
}

and:

public class test : MonoBehaviour
{
    private float exampleFloat;

    private void Awake ()
    {
        Debug.Log($"Example 2: exampleFloat = {exampleFloat}");
    }

    private void Start()
    {
       exampleFloat = 12.34f;
       //do stuff with exampleFloat
    }
}

In the above examples, the results would be:

Example 1: exampleFloat = 12.34
Example 2: exampleFloat = 0

Serialisation

Now, let's throw serialisation into the mix!

public class test : MonoBehaviour
{
    [SerializeField] private float exampleFloat = 12.34f;

    private void Start()
    {
        //do stuff with exampleFloat
        Debug.Log($"Example 3: exampleFloat = {exampleFloat}");
    }
}

and:

public class test : MonoBehaviour
{
    [SerializeField] private float exampleFloat;

    private void Start()
    {
       exampleFloat = 12.34f;
       Debug.Log($"Example 4: exampleFloat = {exampleFloat}");
       //do stuff with exampleFloat
    }
}

In the above examples, the results would be:

Example 3: exampleFloat = 12.34 // OR whatever is serialised in the Inspector!
Example 4: exampleFloat = 12.34 // always 12.34.

So, it turns out that it does matter where you apply your values, as Unity is very much dependent on the component lifecycle. Awake will always be called before Start. Serialisation occurs after the object is created, but before Awake. And you're not supposed to call a Component constructor, so declaring values in there isn't an option.

Milan Egon Votrubec
  • 3,696
  • 2
  • 10
  • 24
2

I don't know if Unity changes this at all, but at least in the pure C# world, the only difference can be shown with the question:

Do you intend to read from exampleFloat before calling Start()?

In the second example, where you just declare the variable, the variable will get assigned a value of 0 by default. If you try to read the variable before calling Start(), you won't see the value as 12.34.


There is a similar problem of "do I initialize variables inside or outside constructors?", but at least with using a constructor, you know the variable will have the target value before the object (class) is initialized.

gunr2171
  • 16,104
  • 25
  • 61
  • 88
1

The Start() method is called before the first frame, but after many other scripts begin to execute code. If you set the value of 'exampleFloat' within the Start() method, it is possible an outside script will attempt to use this variable before 'exampleFloat' has been set within the Start() method.

For this reason, it is generally considered better practice to set the value of 'exampleFloat' when declaring the variable (if possible):

public class test : MonoBehaviour
{
    private float exampleFloat = 12.34f;
}
Sek
  • 11
  • 2
0
private float exampleFloat;

...declares the variable, and as it's a primitive type, sets it to its default value, in this case 0.

Therefore, if you access the variable before the Start method has run, it will be 0. If you access it inside Start, or after that has run, it will have the value 12.34.

By the way, this is a C# question, nothing to do with Unity.

Avrohom Yisroel
  • 8,555
  • 8
  • 50
  • 106
  • 2
    It certainly could be something to do with Unity if the OP is expecting to know about any behaviour difference for this code running under Unity. Now we have to wonder when does Unity call `Start`. – Enigmativity Nov 26 '22 at 22:03
  • I'm pretty novice man I don't know if Start() even exists outside of Unity, that's why I put the tag Unity. – MathMith Nov 26 '22 at 22:08