6
Vector3 v = new Vector3(1, 1, 1);
v.x = 5;

Why can't I do this? I have to do v = new Vector3(5, v.y, v.z);

I assume the reason behind this is for performance. But I can't guess at why this is necessary.


Edit:

I lied, this actually does work. The Vector3 I've been working with transform.position always returns a copy of itself, which is why setting values on it doesn't work. Some kind of Unity magic.

Community
  • 1
  • 1
Farzher
  • 13,934
  • 21
  • 69
  • 100
  • They aren't according to MSDN: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector3_members.aspx. You are lucky though.. generally `struct`'s are tiny immutable objects (like `DateTime`). – Simon Whitehead Sep 11 '13 at 04:56
  • @SimonWhitehead I'm using Unity3D, they support C#. I thought everything was the same, maybe this is just a Unity thing? Can anyone confirm that? – Farzher Sep 11 '13 at 04:57
  • Where is `Vector3` defined? The type linked in the comment above is from XNA. That is most likely not the one you are using. – Brian Rasmussen Sep 11 '13 at 04:58
  • Sorry about the multiple tag edits. The `Vector3` context was unclear. Additionally, the tag `vector` is not relevant to a vector component structure. – Austin Brunkhorst Sep 11 '13 at 05:00
  • As for the actual question, according to the [docs](http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Set.html), you can use `.Set(x, y, z)` to update the values of each component respectively. – Austin Brunkhorst Sep 11 '13 at 05:02

4 Answers4

6

I lied, this actually does work. The Vector3 I've been working with transform.position always returns a copy of itself, which is why setting values on it doesn't work. Some kind of Unity magic.

Actually, the reason is that Vector3 are structs. In C#, structs are value types. So they are always returned by value wereas class can be pass/returned by references. It will be the same behaviour for all properties that wrap struct members (like Rect, Vector2, etc...)

As this is a property, the get method return a copy value of the struct position when you call it. You will always need to assign it to a local ref, modify it and then reassign it:

Vector3 t_Pos = transform.position;
t_Pos.Normalize();
transform.position = t_Pos;
jeerem
  • 111
  • 1
  • 5
2

Unity doesn't allow direct access to Transform.position because position is derived. In other words, internally Unity is storing a transformation matrix, so when you get the position, it's grabbing a copy of it from the transformation matrix.

So it probably looks a little like this for position:

public class Transform
{
    public Vector3 position
    {
        get
        {
            // it would be this if the matrix itself is in world space
            return new Vector3(matrix.m30, matrix.m31, matrix.m32);
        }

        set
        {
            // it probably doesn't use these mono bindings, but
            // I'll use them here for this example
            matrix.SetRow(3, new Vector4(value.x, value.y, value.z));
        }
    }
}
weatx
  • 71
  • 2
1

(Disclaimer: I am not a Unity developer)

Every example I see initialized a new Vector3.. which means the properties are probably readonly in Unity (they aren't in XNA).

But, the documentation shows a Set() method for Vector3's. So you can (apparently) do this:

v.Set(5, v.y, v.z);
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • Doesn't work with the `transform.position` Vector3. "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!" What the heck Unity. – Farzher Sep 11 '13 at 05:13
1

Unity's Vector3s are indeed structs as well - so you are required to create a new instance, even if you are only changing one value. In response to the question itself, as you already mentioned, Vector3's properties aren't readonly.

Source

AquaGeneral
  • 155
  • 1
  • 19