Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Why can I modify transform.position but not transform.position.y?

Discussion in 'Scripting' started by tomtomeow, Nov 14, 2017.

  1. tomtomeow

    tomtomeow

    Joined:
    Jul 5, 2017
    Posts:
    14
    I am trying to write this:
    Code (csharp):
    1.  
    2.         transform.position = distanceBetweenCamAndPlayer + player.transform.position;
    3.         transform.position.y = cameraY;
    4.  
    the first line works fine, but the second one displays the error: "cannot modify the return value of transform.position because it is not a variable".
    How come I can change the transform.position with a vector3 but I can't change only the Y component?
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Because of value types!

    A Vector3 is a value type, which means that it's passed by value. So whenever you grab a Vector3 from somewhere, you're grabbing a copy:

    Code (csharp):
    1. Vector3 a = new Vector3(1, 2, 3);
    2. Vector3 b = a;
    3. b.x = 15;
    4. Debug.Log(a.x); //still 1!
    Since Transform.position is implemented as a getter, you're getting a copy whenever you're retrieving it. So when you do:

    Code (csharp):
    1. transform.position.x = ...
    You're trying to set the x-value on a copy of the transform's position. The compiler disallows it, since you'd otherwise have code that does nothing that looks like it does something.


    You'll either have to get a copy, modify that, and pass it back in:

    Code (csharp):
    1. var pos = transform.position;
    2. pos.y = cameraY;
    3. transform.position = pos;
    Or make an extension method for Transform that allows you to do what you want:

    Code (csharp):
    1. public static class TransformExtensions {
    2.     public static void SetYPos(this Transform t, float newYPos) {
    3.         var pos = t.position;
    4.         pos.y = newYPos;
    5.         t.position = pos;
    6.     }
    7. }
    8.  
    9. //your code above can now be:
    10.  
    11. transform.position = distanceBetweenCamAndPlayer + player.transform.position;
    12. transform.SetYPos(cameraY);
     
    jq911, hessex, fabiobh and 3 others like this.
  3. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    I used to assign Vector.3 parameters of other classes so I think that example doesn't quite fit. If position would not be a property then transform.position.x = 2 will not create a new position but assign x directly.

    So getter is the reason for that here, but thanks for that explanation.
     
  4. sergienko88

    sergienko88

    Joined:
    Jul 22, 2013
    Posts:
    22
    Plz,read about difference between class and structure
     
  5. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    You can change the value, but you have to change all of them because it's a vector3.
    transform.position = new Vector3(transform.position.x, cameraY,transform.position.z);
     
  6. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    Take a look at the source code for Transform:

    Code (csharp):
    1.  
    2. public Vector3 position
    3. {
    4.    get
    5.    {
    6.      Vector3 result;
    7.      this.INTERNAL_get_position(out result);
    8.      return result;
    9.    }
    10.   set
    11.   {
    12.      this.INTERNAL_set_position(ref value);
    13.   }
    14. }
    15.  
    transform.position gives you a copy of the position. Writing to transform.position.x would do nothing useful.
     
    insominx likes this.