unity3d 为什么我不能修改变换位置?

s3fp2yjn  于 2023-01-21  发布在  其他
关注(0)|答案(4)|浏览(535)
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 OnMouseDown()
    {
        pressed = true;
    }

    void OnMouseUp()
    {
        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;
        }

    }
}

资源\脚本\主菜单\可移动按钮系统.cs(42,13):错误CS1612:无法修改“Transform.position”的返回值,因为它不是变量
我不明白为什么我不能改变位置。我所要做的就是让ObjectToMove移动,直到它通过某个点,在它不应该再移动之后。使用Clamp也会产生同样的错误。

yks3o0rb

yks3o0rb1#

下面的简化示例演示了相同的编译错误:

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; }
}

这就是你所看到的问题,因为Container.Property属性返回了一个值类型的副本,在本例中是struct Item
因为这是存储在Container中的项的 * 副本 *,而不是项本身,所以更改副本的属性不会有任何可见的效果,因为从属性返回的值没有存储在任何地方-没有从中分配变量。
因此,编译器会给出一个错误,以避免误导和无用的代码。
The documentation for Error CS1612详细解释了这一切。

watbbzwu

watbbzwu2#

其他人--以及error documentation--已经详细解释了这个问题和原因
但就你的问题的解决方案而言,你会说,

// 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;

你甚至可以通过以下方式将其合并并简化。

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;
    }
}
pxiryf3j

pxiryf3j3#

正如Mathieu和Matthew在评论中指出的,position是calss Transform的一个结构域,因此你不能像这样修改它的域。如果你想理解为什么这不起作用,想象Unity的Transformposition对象看起来像这样:

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;
        }
    }
}

当你写T.position.z时,position部分实际上是getter属性返回的position变量的值副本。因此,通过改变position的副本,你不会得到更新T.positionz字段的预期效果。由于这个原因,C#它试图通过抛出一个错误来帮助您,以防止一个非常难以识别的bug。

s71maibg

s71maibg4#

您不能更改Vector3的单个组件。为此,您必须更改所有组件。例如:

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

相关问题