When do I initialize variables as new when declaring them

Basically, when do I use the top format vs when do I use the bottom one?

Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

Vector2 mousePos = new Vector2 (Camera.main.ScreenToWorldPoint(Input.mousePosition));

Doesn’t matter.

The method ScreenToWorldPoint returns a Vector3.

You’re basically trying to cast it to Vector2.

This cast is implicit and just happens automatically (hence why the 1st works). The 2nd, or alternatively this:

Vector2 mousePos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);

Are just explicit ways of doing it.

…

[edit]
scratch that… sorry. Your 2nd example doesn’t actually make sense since Vector2 only has 1 constructor other than the default and it’s the one that take x,y. So yeah, your 2nd one doesn’t even compile. Though my alternate example will and my statements basically stand for that.

…

Now if this was just some random example and you’re actually asking about the “new” operator in general terms. Well… when you use that depends on when you need it. There’s 2 main types that can use it. Ref types and Value types. Ref types you use the “new” operator when you need a new instance of that object. Value types don’t necessarily need the “new” operator but rather the new operator is only used when you explicitly want to use that specific constructor and the parameters it accepts.

1 Like

So yea this was more of a random example, thanks for the response, but I still dont get it.

As a ref type, why would I need a new instance if I just defined this new variable just now, why wouldn’t my original variable just be in effect?

Because a variable and an instance are 2 different things in regards to a ref type.

Say you have a list:

List<int> lst;

Here you have a List variable named ‘lst’. It points to nothing, and therefore would evaluate null. (note if this variable is scoped in a short context like a function the compiler may even warn you that you never assigned it)

lst = new List<int>();

Now ‘lst’ points to a List, it is no longer null.

lst.Add(1);
lst.Add(5);
lst.Add(100);

Now the list contains 3 elements.

var lst2 = lst;

Now a second variable of type List named ‘lst2’ (the compiler infers the type of var by the assignement). ‘lst’ and ‘lst2’ are the same list.

lst2.Add(452);

foreach(var entry in lst)
{
    Debug.Log(entry);
}

Even though I loop ‘lst’, it’ll contain all 4 elements including the 452 that I added to ‘lst2’.

lst = new List<int>();

Now I’ve created a “new” List. ‘lst’ no longer points to the same List that ‘lst2’ does.

lst.Add(-5);
lst2.Add(1000);

foreach(var entry in lst)
{
    Debug.Log(entry);
}

Now looping over every entry in ‘lst’ will only result in “5” being logged. Because this list only contains a single element.

…

SO

I used “new” to create a “new” instance of a List distinct from the old instance of List that I was using previously.

I use “new” when I need a “new” instance.

Why might I need a new instance? Depends on the scenario. Maybe I want a new empty list, maybe I want a 2nd GameObject, maybe I want 2 different web requests.

var go = new GameObject("Obj1");
go.AddComponent<BoxCollider>();
go = new GameObject("Obj2");
go.AddComponent<SphereCollider>();

See, I can reuse the variable for 2 different objects. Once you reach the 2nd assignment any modification of ‘go’ modifies the “new” GameObject, not the previous one.

Awesome ELI5 explanation!

Why wouldn’t I just define the variable as a list without the new?

 lst = List<int>();

And,

So basically, Obj1 is stuck with a box collider and there is no way for you to edit it from the variable ‘go’ anymore, and all changes will be applied to Obj2?

Why would I use this approach instead of making 2 different variables from the get go? Does this perform better?

Because that’s not how C# is written. When creating instances you use the “new” operator. It’s just like how in english you start sentences with a capital letter. It’s just how it is done syntactically.

There’s also vagueness to not have the ‘new’ operator. Lets use a class that doesn’t have generics (the generics just add complexity not specific to this discussion). Say for the regular List from System.Collections (no <…>).

lst = List();

How do we know that List is a construction of a new object and not say calling a method/function that happens to be named “List”?

With common names like “List” this may be more obvious but imagine if it was some more complex name:

obj = LevelFactory();

This is less readable as it requires me to think about what “LevelFactory” is. Is it a method/function, a class, what’s going on here? I need more context to know. Therefore, less readable.

For this specific example there’s not really a huge difference (I mean technically there is in that wherever this code is scoped there may be some minor allocation requirements such as in the stack frame needing a slightly large frame to fit the variables… but it’s mostly negligible in the grand scheme of things performance wide).

Really it’s more about intent. What is it you’re attempting to accomplish at the moment.

This very basic example does not really impress the choice of intent, it’s really just showing it’s possible. Furthermore you may want to just use 1 variable if you don’t need to configure “Obj1” anymore… you’re done, moved on, it’s spawned and out there. What if we had 30 GameObject’s to spawn with distinct configs for each? Do we really want 30 variables? What about 100? What about 1000? (though as we get to large numbers I’d argue you’d start going towards some sort of factory that would do this. Similar to how unity has scene files that it can build a scene from).

But here’s a situation of intent:

Transform nearest = null;
float dist = float.PositiveInfinity;
foreach(var coll in Physics.OverlapSphere(this.transform.position, 100f))
{
    float d = Vector3.Distance(this.transform.position, coll.transform.position);
    if (d < dist)
    {
        nearest = coll.transform;
        dist = d;
    }
}

if(nearest != null)
{
    this.transform.position = Vector3.Lerp(this.transform.position, nearest.position, 0.5f);
}

Here the intent is that we don’t need a bunch of “nearest” variables. We just want the one, the nearest. So as I loop over all the colliders near me, I update ‘nearest’ with the one that calculates as a shorter distance.

My intent requires a single variable. But over the life of the variable what object it points potentially changes several times.

I should point out that this conversation suggests you’re very early in your learning of C#.

You should probably sit down with some texts/books on the topic of learning C#. Work through them, learn the language, get more familiar with it. As you use it more these things become more obvious as to “why” they’re that way.

But in the end at this stage of your learning you can take it as “because that’s the way it’s done”.

1 Like

This example is perfect. Thanks a lot for helping out with this.

I think my question to this example is why didn’t you use the operator ‘new’ when defining the Vector3.Distance…?

Yea I am still new to coding and Unity and this is something basic that I felt I needed to understand before I move on and you’ve been tremendous help, and if you have anything to recommend then I am all ears.

I’m learning as I go and try and stop at any point that I don’t get and put effort to understand it properly so that I build my knowledge the best I can from the ground up.

Thanks again :slight_smile: