"new" keyword question

Seem a bit too late to question this, and i know what it does, I’ve spent some months studying C# and usually constructors and instantiating those with the “new” keyword to initialize them is very common, but i just struggle to understand when it is the case to use it and especially in Unity scripts, where monobehaviours seems do not need most of the time.
For example here, in the code from Gary lecture:

    TextMeshPro label;
    Vector2Int coordinates = new Vector2Int();

    void Awake() 
        label = GetComponent<TextMeshPro>();

    void Update()
    void DisplayCoordinates()
        coordinates.x = Mathf.RoundToInt(transform.parent.position.x / UnityEditor.EditorSnapSettings.move.x);
        coordinates.y = Mathf.RoundToInt(transform.parent.position.z / UnityEditor.EditorSnapSettings.move.z);
        label.text = $"{coordinates.x},{coordinates.y}";
    void UpdateObjectName()
        transform.parent.name = coordinates.ToString();

I would never guessed that we need to initialize coordinates as a new Vector2Int.

Anyone have a simple explanation to help me understand better when you have to do it and when you don’t? Thanks in advance

When you want a new object, you use the new keyword. Gary wants a new Vector2Int so he uses the new keyword - he’s initialising the coordinates. You always need it. Without it, there is no object.

When you say int a = 2;, the compiler is really writing int a = new int(2); - there’s an implicit conversion happening

MonoBehaviours do need it, but we don’t use it ourselves because the behaviour is being instantiated by Unity - Unity is calling the ‘new’.

Basically, anything that is Unity - MonoBehaviours and ScriptableObjects will be handled by Unity, any other ‘normal’ classes we’ll need to do ourselves

What Gary did with Vector2Int could be also be done with just:

Vector2Int coordinates;

because Unity does the “new” keyword conversion under the hood?

P.S the script was a monobehaviour, i did not included the Class in the code i postetd previously because usually it’s not important

Vector2Int is a struct. Vector2Int coordinates; is not the same. It is ‘uninitialised’. If Vector2Int was a class, it would be null. Structs cannot be null, so Vector2Int will be all the default values it could have. Yes, it’s the same as new Vector2Int(), but the compiler likes to complain that you are trying to use an ‘uninitialised variable’. Gary initialises it, and the compiler stops complaining - even though it has the same value - in this case.

Assume you have your own struct - let’s call it V2I (a copy of Vector2Int). We want our copy to default to (1,1). It may look something like this

public struct V2I
    public int X { get; set; }
    public int Y { get; set; }

    public V2I()
        X = 1;
        Y = 1;

Now V2I coordinates; and V2I coordinates = new V2I(); is no longer the same thing. This is because the ‘uninitialised’ version will have both X and Y = 0 - their default values - while the constructor sets them to 1. When it is ‘uninitialised’, no constructors were called.

So to do it myself i need to check a type of a variable and if it’s happens to be a struct i need to initialise it, otherwise i can leave it as most of the others…hope it is like this xD
Mhhh there are other types like struct that i need to keep an eye to initialise when i’m creating variables?

No, always initialise variables. Unless they’re MonoBehaviours or ScriptableObjects. Then you need to set them to something. Usually using the inspector, or GetComponent (for MonoBehaviours)

Yes i was referring in case of a monobehaviour script…there are other type that i need to initialize them like if it’s a struct or the compiler get angry?

Yes. All other types must be initialised. Gary could have written Vector2Int coordinates; like you suggested, but then - before he set the x and y values, he would’ve had to initialise it. This would’ve caused the coordinates to be re-initialised every time DisplayCoordinates is run which is not necessary, so he initialised it once - at the beginning

Sorry about that, i’m getting very confused and i’m feeling dumber even more…

For a monobehaviour, when i say initialise like a struct i mean like Gary did using the new keyword on the variable declaration.

But usually with other kind of types you can do just like this :

public class RandomClass : MonoBehaviour
  int a;

  void Start()
  void RandomMethod()
     a = 1;

and usually even without giving a value to the variable, It will became a default zero , except for string that must assign them a value if i did recall well…

You probably are in pain right know… and i’m really sorry about it…

My brain need to find the things that clicks it before i fully understand the concept, and by now i just know that when i see a struct in a type in a monobehaviour i must put the new keyword in the variable declaration.

Like I said in my first post; the compiler does an implicit conversion from a = 1; to a = new int(1); - so it’s being initialised here. But not all structs and classes have implicit conversions. So, Gary needs to explicitly initialise the Vector2Int.

This is it’s default - its uninitialised value. Like my demonstration with the V2I, if it’s uninitialised the constructor isn’t executed, so the X and Y will be the default values; 0. Defaults are valid, but the compiler will complain about using uninitialised variables. We generally don’t want to use the default values as-is because we are skipping anything that may need to be set up in the constructor so, while int a will print 0, if anything was being set up in the constructor it would have been skipped, possibly leaving our value in a unstable state.

Mhhh, ok, i need to check what are the classes and struct without implicit conversion…even thou i start thinking that it is more a good habit to have, especially if you are not dealing with just monobehaviours classes and need to go back using constructors and the classics C# stuff.

You shouldn’t have to worry too much about it.

All classes must be initialised with ‘new’. In Unity, this is not necessary for MonoBehaviours and ScriptableObjects. For every other class, use ‘new’.

The built-in intrinsic types have implicit conversions; int a = 1;, float f = 1.2f;, string name = "John";. All the basic stuff.

And then any other struct (like Vector2, Vector3, Vector2Int) you just handle like you would a class; use the ‘new’ keyword

thanks got it

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms