0
\$\begingroup\$

I am following a tutorial for Unity. I don't know C# but I know other similar languages.

I got the tutorial to work. Here is the script I used.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour {

    private Rigidbody rb;
    public float speed;

    // Use this for initialization
    void Start () {
        speed = 3.5f;
        rb = GetComponent <Rigidbody> ();
    }

    // Update is called once per frame
    void Update () {

        float fx = Input.GetAxis ("Horizontal");
        float fz = Input.GetAxis ("Vertical");

        rb.AddForce (new Vector3 (fx, 0, fz) * speed);
    }
}

This goes slightly against my C++ instincts, which are to put initialization values in a constructor.

    public PlayerMove ()
    {
        speed = 3.5f;
    }

    void Start () {    
        rb = GetComponent <Rigidbody> ();
    }

This doesn't work. In Unity, the speed field has an initial value of 0.

Why does setting the initial value in a constructor not work?

\$\endgroup\$
3
  • \$\begingroup\$ Is this an object that you've placed somewhere in your scene, or spawned from a prefab? Or are you creating a bespoke instance via script? (Also: I don't see you using the static keyword anywhere in this code - are you referring to something else when you say "static" in your title?) \$\endgroup\$
    – DMGregory
    Commented Oct 1, 2018 at 21:40
  • \$\begingroup\$ I don't really know what your question means, but this script is a "component" of a sphere. \$\endgroup\$
    – spraff
    Commented Oct 1, 2018 at 21:41
  • \$\begingroup\$ And that sphere is something you placed in your scene in the editor before running the game? Or are you creating it at runtime via another script? \$\endgroup\$
    – DMGregory
    Commented Oct 1, 2018 at 21:50

1 Answer 1

0
\$\begingroup\$

When you attach a component to an object in a Unity scene, or to a saved prefab object, unity serializes the values of its public (or serializable) members into the scene / prefab file.

When you next open or run that scene or spawn an instance of that prefab, Unity creates an instance of the component with the default constructor, then overwrites its members with those serialized values.

Normally this is a good thing: I set speed to 5 in the inspector when editing my scene / assets, I still see the value of 5 the next time I open the editor, and I get a value of 5 at runtime in the game.

But since this deserialization happens after the constructor has run, it can stomp or override values set by the constructor. In this case, you may have created the object in the editor with the initial default value of 0, which got saved into your scene file, before adding the 3.5 value to your constructor. The constructor value can't override what's saved in the scene.

For reasons like this, it's recommended not to use constructors for MonoBehaviours. Instead, use the Awake, OnEnable, or Start methods if you want to do additional initialization after the component has been deserialized.

If you want to set up a default value that the developer can override in the Unity editor's inspector, a field initializer suffices, eg..

 public float speed = 3.5f;
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .