1

I want to create a Vector3 type object referring to my player's position so that I can use a shorter name in my script.But I failed to do it. It seems that the new object pointing at other address.

I wrote some code like this:

//PlayerController.cs
vector3 playerPos = transform.position;
Debug.Log(System.Object.ReferenceEquals(playerPos,transform.position)); 

The output was

false

What caused this and how can I refer to my player's position correctly?

1 Answer 1

5

What caused this

Below is a simple explanation.

transform.position is Vector3.

Vector3 is a struct.

Struct is a value type.

It's always good look in the Unity's Documentation to see which type Unity API is. This really matter when working in Unity.

enter image description here

When you do:

vector3 playerPos = transform.position;

New struct is created and values from transform.position; is copied to playerPos variable. Since the variable is value type and copied, performing System.Object.ReferenceEquals on it should return false.


I want to create a vector3-type object referring to my player's position so that I can use a shorter

In this case, you have to change the Vector3 to Transform.

Transform myPos = null;
void Start()
{
    myPos = transform;
}

then you can do:

myPos.position = newPos; 

The reason you have to declare the position as Transform instead of Vector3 is because Transform is a class and a class stores the reference of the object.

class is a reference type.

enter image description here

Debug.Log(System.Object.ReferenceEquals(myPos, transform)); should return true because myPos and transform are both classes and the myPos variable is referencing the transform variable.

So, whenever you access your position with myPos.position;, it will give you the newest position of your GameObject which is also (transform.position) since the myPos variable is a class that has a reference of transform which is also a class.

Assuming that myPos is struct or declared as vector3 myPos instead of Transform myPos, then the myPos variable would hold the copy value of transform.position when it was assigned and will never return the latest position of your GameObject since it is a copy.

You can learn more about class vs struct here.

Finally System.Object.ReferenceEquals says "ReferenceEquals" not "ValueEquals" so this is even self-explanatory. You use it on a class/referece types not on structs or value types.

Sign up to request clarification or add additional context in comments.

9 Comments

Does this mean that in the case of Vector3 structs and transform class in Unity, the == is overridden by Equals and not the default ReferenceEquals? Since if we use playerPos == transform.position Unity returns true.
A struct is not a reference type. It's values are accessed directly. Therefore, when you compare a Vector3 with a Vector3, you are comparing value types, (Equals), not their reference types (ReferenceEquals).
@Galandil ReferenceEquals compares the reference. playerPos == transform.position compares the value of the Vector3 such as x, y, and z, values which are all floats.
Sorry, I explained myself poorly. My question is this: by default, == makes a reference comparison by using ReferenceEquals. So, when we compare two objects with ==, and at least one of them is a value type, we override to Equals instead of ReferenceEquals, right?
@Galandil "by default, == makes a reference comparison" Not really. It depends on the API. For Vector3, Unity has an overload of == that compares the SqrMagnitude of both Vectors. It does not compare the reference of a Vector3 with ==. On the other hand, you are right. You can override the Equals function but you should't override ReferenceEquals for Vector3 since it is a struct.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.