Home > Software engineering >  Why cant I modify Transform.position?
Why cant I modify Transform.position?

Time:01-18

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class MoveAbleButtonSystem : MonoBehaviour
{
    public Transform ObjectToMove;
    public bool moveLeft = true;
    public bool moveRight = false;
    public float SpeedToMove = 1f;

    private bool pressed = false;
    public float minZ = 0f;
    public float maxZ = 0f;

    void onm ouseDown()
    {
        pressed = true;
    }

    void onm ouseUp()
    {
        pressed = false;
    }

    void Update()
    {
        Transform T = ObjectToMove.transform;

        if (pressed && moveLeft)
        {
            T.Translate(Vector3.forward * SpeedToMove * Time.deltaTime, Space.World);
        }else
        if(pressed && moveRight)
        {
            T.Translate(Vector3.back * SpeedToMove * Time.deltaTime, Space.World);
        }

        if(T.position.z > maxZ)
        {
            T.position.z = maxZ;
        }

    }
}

Assets\Scripts\MainMenu\MoveAbleButtonSystem.cs(42,13): error CS1612: Cannot modify the return value of 'Transform.position' because it is not a variable

I dont get why I cannot change the position. All I want to do is for the ObjectToMove to move until it passes a certain point, after what it is not supposed to move anymore. Using Clamp provides the same error.

CodePudding user response:

The following simplified example demonstrates the same compile error:

public class Program
{
    public static void Main()
    {
        var container = new Container();
        container.Property.Value = 1; // Error CS1612 - Cannot modify the return value of 'Container.Property' because it is not a variable
    }
}

public struct Item
{
    public int Value;
}

public class Container
{
    public Item Property { get; set; }
}

This is the issue you're seeing. It's happening because the Container.Property property is returning a copy of a value type, in this case struct Item.

Because this is a copy of the item stored in Container and not the item itself, changing the copy's properties cannot have any visible effect because the value returned from the property is not stored anywhere - no variable is assigned from it.

Therefore the compiler gives an error, to avoid misleading and useless code.

The documentation for Error CS1612 explains all this in detail.

CodePudding user response:

Others - and the error documentation - already explained the issue and the why in detail.

But in terms of a solution for your issue you would go e.g.

// Get copy of current position
var position = T.position;

if(position.z > maxZ)
{
    // modify the copy
    position.z = maxZ;
}

// assign back / apply modified value
T.position = position;

You could even combine and simplify it a lot by doing e.g.

public enum MoveDirection
{    
    Left,
    Right
}

public MoveDirection direction;

void Update()
{
    if(pressed)
    {
        var T = ObjectToMove.transform;
        var position = T.position;

        var multiplier = direction == MoveDirection.Left ? 1 : -1;
        position.z = Mathf.Clamp(position.z   SpeedToMove * Time.deltaTime * multiplier);
 
        T.position = position;
    }
}
    

CodePudding user response:

As pointed in the comments from Mathieu and Matthew, position is a struct field of the calss Transform and due to this reason you can not change its fields like this. If you want to understand why this is not working imagine that Unity's Transform and position look something like this:

struct Position
{
    public int x;
    public int y;
    public int z;
}

class Transform
{
    public Position _position;
    public Position position 
    {
        get
        {
            return _position;
        }
        set
        {
            _position = value;
        }
    }
}

When you write T.position.z the position part is actually a value copy of the original T's position variable. So by changing the copy of position you will not get the desired effect of updating the T.position's z field. Due to this reason C# it trying to help you by throwing an error.

CodePudding user response:

You can not change the individual components of a Vector3. To do this, you will have to change all the components. i.e :

if (T.position.z > maxZ)
{
    T.position = new Vector3(T.position.x, T.position.y, maxZ)
}
  • Related