- Home /
GameObject position.Set() not working
I'm trying to instantiate a clone of an object at position X, then move the original object to position Y; however, the Position.Set() doesn't seem to do anything. Both objects stay at the position X, even though setting gravity and velocity work fine.
The pieces of my code in question:
(The script function Update() on the original object)
void Update()
{
if (isFree == true && isActive == true)
{
if (Input.GetMouseButtonDown(0))
{
GameObject.Find("LaunchPoint").GetComponent<Loader>().Load();
transform.position.Set(Anchor.transform.position.x, Anchor.transform.position.y, Anchor.transform.position.z);
rigidbody.velocity.Set(0, 0, 0);
rigidbody.useGravity = false;
isFree = false;
GameObject.Find("Main Camera").GetComponent<FollowObject>().MoveToPos(transform.position);
}
}
}
Anchor is another gameobject in the scene that doesn't move.
(The code on the object that does the 'reloading' (the copy bit)):
public class Loader : MonoBehaviour {
public GameObject target;
public void Load()
{
GameObject newTarget = (GameObject)Instantiate(target);
newTarget.transform.rotation.Set(target.transform.rotation.x, target.transform.rotation.y, target.transform.rotation.z, target.transform.rotation.w);
newTarget.rigidbody.velocity.Set(target.rigidbody.velocity.x, target.rigidbody.velocity.y, target.rigidbody.velocity.z);
newTarget.GetComponent<FollowMouse>().enabled = false;
}
// Update is called once per frame
void Update()
{
target = GameObject.Find(target.name);
}
}
I can't understand why the position of the original object (first bit of code) doesn't move the object. I've also tried it with number values (0,0,0) and it doesn't do anything either, when everything else appears to work properly.
Answer by lynchem · Mar 12, 2012 at 03:45 PM
I've encountered this issue as well and whilst I can't explain why exactly I can tell you how to work around it. Do this:
Vector3 newPos = new Vector3(Anchor.transform.position.x, Anchor.transform.position.y, Anchor.transform.position.z); transform.position = newPos;
Hope that helps
Edit: transform.position returns a copy , that's why Set() doesn't work. You'd think the compiler would issue a warning.
As far as I can tell, this happens because when you use 'transform.position', it returns a new vector3, rather than giving you a reference to the actual position. Then, when you use Vector3.Set(), it modifies the returned Vector3, without actually changing the original! This is why you have to be careful about exactly how the values are passed around internally. Transform.position and Rigidbody.velocity are not simply direct references to the values that they represent- there is at least one layer of indirection that we can't exactly see from the outside.
In C#, structs are passed by value, and classes are passed by reference. The fundamental difference between passing by pointer and passing by value is an important thing that you need to be aware of if you don't want to get caught up like this. There are almost no languages in which primitives (int, long, char) are passed by reference by default.
No, you can't access them directly, because there are no references. That's the important point.
@rad1c - This is not a issue. Is works 100% as intended. Let me try to clarify the discussion above with a little illustration:
Step 1: Your script gets the value of the "transform" property. It returns a REFERENCE to the transform component. A reference is basically a direct access to it. Why is it a reference? Because classes are always references, and "Transform" is a CLASS.
Step 2: We call the "position" property on our reference to the Transform component. This will return a COPY of the position of the transform. A copy has NO $$anonymous$$ORE RELATION to whatever or wherever it was previously stored. Basically this new value has no idea that it used to be the position of a transform, since it, well, is a copy. Why is it a copy? Since "Vector3" is a STRUCT, and structs are always being copied(Unless explicitly specified, but that I'll not go into detail on that).
Step 3: We call the "Set" method on the COPY of our position. The values are now set. But why aren't they applied to the to transform? Since we only set the position values in the COPY of the position. And not in the actual Vector3 inside the transform, thus we must explicitly set the value of transform.position, not simply change the value of the return value of transform.position.
Did this clarify it a bit? If not ask and I'll try my bets to explain it, or simply google a bit around for the differences between classes and structs in C#, I'm certain that there are a bunch of good explanations.
Answer by brocksmedley · Jan 03, 2014 at 10:25 PM
In your gameobject, you should have a script that inherits from MonoBehavior. In there, (in a function; update or start or whatever) you can access the transform subclass with this code:
transform.position = new Vector3 (x, y, z);
You can also access the individual values (x, y, z) like this:
transform.position.x
I'm not sure if you can directly modify those, but the best way to learn is to try it out for yourself.
I know this is a super old question, but I figure this might help someone else.
The values (`x`, y
, z
) of the Vector3
are read-only. So they can't be edited directly, but the whole position (a Vector3
) can be replaced (like you descriped).
@Vadammt: That conclusion you came to is not true. The components of a Vector3 are not read only. The problem arises from the combination when using a property of a struct like a Vector3, which is a value-type.
transform.position is a property (not a simple field) of a Vector3. When "reading" a Vector3-property you get a copy of the struct. You can set the components of that struct, but it won't influence the original, underlying value.
Example:
// C#
public class $$anonymous$$yTestClass
{
public Vector3 internalValue = Vector3.zero;
public Vector3 position
{
get { return internalValue; }
set { internalValue = value; }
}
}
$$anonymous$$yTestClass inst = new $$anonymous$$yTestClass();
inst.internalValue.x = 5; // works just fine
inst.position.x = 10; // Doesn't work.
The second example line doesn't work since you call the getter of the "position" property and then changing x of the copy the get method returned. That won't change the internalValue. Properties of structs can only be changed by invoking the "set" method which only happens when you assign something to the property itself. Like:
inst.position = new Vector3(10,0,0);
//or
inst.position += Vector3.right*10; // this calls the getter first, add (10,0,0) to the copy and assigns it back to position.
Your answer
Follow this Question
Related Questions
[CODE]Keep Gameobject position exactly at mouse cursor when cast float position to int 1 Answer
Best way to detect if an object is near? 1 Answer
Simultaneously moving GameObjects using C# script. 3 Answers
Slide GUITexture/GameObject into view? 1 Answer
postion scale and rotation greyed out and not working 1 Answer