用C#实现的代码中,transform.positon的分量不能单独赋值修改,必须对position进行整体修改。这算是个常识,但是至于为什么却从来没有考虑过。
有人说是因为xyz分量是只读的。这样的解释纯属瞎猜。进入vector3里面看一下就知道了,并不是只读的。
并且Js实现的代码中是允许单独修改transform.position的分量的。
做一组对照试验
PositionTest.cs
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public struct MyVector
- {
- public float x, y, z;
- }
- public class ClassVector
- {
- public float x, y, z;
- }
- public class PositionTest : MonoBehaviour {
- //-----------------对照1
- Vector3 _posVector;
- public Vector3 position_1
- {
- get
- {
- return _posVector;
- }
- set
- {
- _posVector = value;
- }
- }
- public Vector3 GetPosition_1()
- {
- return _posVector;
- }
- //------------------对照1 end
- //------------------对照2
- MyVector _posMyVector;
- public MyVector position_2
- {
- get
- {
- return _posMyVector;
- }
- set
- {
- _posMyVector = value;
- }
- }
- public MyVector GetPosition_2()
- {
- return _posMyVector;
- }
- //------------------对照2 end
- //------------------对照3 & 4
- public Vector3 position_3;
- public MyVector position_4;
- //------------------对照3 & 4 end
- //------------------对照5
- private ClassVector _posClassVector = new ClassVector();
- public ClassVector positon_5
- {
- get
- {
- return _posClassVector;
- }
- set
- {
- _posClassVector = value;
- }
- }
- public ClassVector GetPosition_5()
- {
- return _posClassVector;
- }
- //------------------对照5 end
- }
Test.cs
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class Test : MonoBehaviour {
- // Use this for initialization
- void Start () {
- PositionTest posTest = gameObject.AddComponent<PositionTest>();
- posTest.position_1.x = 1;//error
- posTest.GetPosition_1().x = 1;//error
- posTest.position_2.x = 1;//error
- posTest.GetPosition_2().x = 1;//error
- posTest.position_3.x = 1;
- posTest.position_4.x = 1;
- posTest.positon_5.x = 1;
- posTest.GetPosition_5().x = 1;
- }
- }
错误类型都是一样的:
通过对比,可以发现,
1:用属性和方法返回的结构体是不能修改其字段的
2:直接访问公有的结构体是可以修改其字段的
3:用属性和方法返回的类的实例,是可以修改其字段的。
那么基本可以锁定,问题的原因在于结构体Struct。
Struct的赋值是值类型的,也就是
Struct A=new Struct();
Struct B=A;
A跟B并不是同一段内存空间,对B的修改,不会对A产生影响。
测试代码如下:
- <span style="white-space:pre;"> </span>MyVector A = new MyVector();
- MyVector B = A;
- A.x = 1;
- B.x = 2;
- Debug.Log(A.x);
所以,用属性或者方法返回一个Struct类型的数据时,返回的其实是一个旧数据的值拷贝,而不是引用。那么修改这个新的Struct的字段,就不会改变我们的目标字段。
就像在刚才的测试中,我们想要修改的是A的x,我们通过属性和方法获取到的实际上是B。
再来一个实验:
- Debug.Log(transform.position);
- Vector3 posTemp = transform.position;
- posTemp.x += 10;
- Debug.Log(transform.position);
两次打印结果是一样的。
所以这个问题就可以这么理解:代码transform.positon.get返回的只是position字段的一个拷贝,而你要修改这个拷贝是没有意义的。
到这里理解起来很简单,只是刚开始理解的时候没有锁定问题就会很绕。
总结一下导致这个问题的原因:
1,Transform中的position是属性(property)(换成方法也一样,因为属性的实现本质上还是方法)而不是公有字段(fiel)
2,position的类型是Vector3的,而Vector3是Struct类型
3,Struct之间的赋值是拷贝而不是引用
如果有哪里理解的不对的,欢迎指正^_^