I want to copy a GameObject into a separate GameObject in order to keep track of it’s transform/position.
Basically
GameObject oldObj = GameObject currentObj;
and then compare
if (oldObj.transform.position == currentObj.transform.position) { //do sth }
and see whether it moved (you can move currentObj around).
However it appears as though oldObj isn’t a copy, but merely a pointer/reference, hence they are always the same position and you never detect any change.
My current workaround is to pull out the transform into separate variables:
So my question is basically whether there is a specific reason that “=” doesn’t copy GameObjects, but points instead? I assume there must be some sort of GameObject.clone/copy, but is it very inefficient to do compared to my current workaround? (Speed/Performance is very important due to device limitations)
For reference types (all objects - eg. things defined as a class), variables are pointers. If you do a = b for a pointer, you copy the pointer, so now b is pointing at the same object.
For value types (numbers like int, float, structs like Vector3, Quaternion), you get a copy of the value.
To illustrate, call this with a Transform and Vector3:
using UnityEngine;
using UnityEngine.Assertions;
public static class Test
{
public static void Foo(Transform t, Vector3 v)
{
/*
* copies the value of the variable v into vCopy. Since Vector3 is a struct, the variable is just the struct,
* so changing vCopy will not change v.
*/
var vCopy = v;
/*
* Copies the value of the variable t into tRef. Since Transform is a class, the variable is a pointer to the
* object, so tCopy points to the same object as t.
*/
var tCopy = t;
t.position = Vector3.zero;
tCopy.position = Vector3.right;
//They have the same position!
Assert.AreEqual(Vector3.right, t.position);
//ReferenceEquals means that they reference the same object!
Assert.IsTrue(object.ReferenceEquals(t, tCopy));
v.x = 5;
vCopy.x = 10;
//They are different values!
Assert.AreEqual(5, v.x);
//Note that all of this is why you can't do this:
//t.position.x = 15; //WONT COMPILE!
/*
* t.position returns a copy of t's position, so changing the x-value of that would do nothing. The compiler's guarding you against writing a line of
* code that doesn't do anything.
* If you do it over 2 lines, it's more obvious that it won't work:
*/
t.position = Vector3.zero;
var pos = t.position;
pos.x = 15;
//t's position didn't change from changing the pos variable
Assert.AreEqual(t.position.x, 0);
//For objects, though, you can do this:
var rigidbody = t.GetComponent<Rigidbody>();
rigidbody.velocity = Vector3.right;
//Works since Rigidbody is an object, not a struct
Assert.AreEqual(Vector3.right, t.GetComponent<Rigidbody>().velocity);
}
}