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));
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.
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â.
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