本帖最后由 RaymondChan 于 2018-2-6 21:15 编辑 注:本文属于基础系列,高手可以略过哦 1. 写在前面 你有没有过类似这样子的疑惑? 1.明明我只拖动了一个物体z轴,为何检视面板上其余两个轴的值也发生变化了?检视面板上显示的不就是本地坐标嘛,总不会是世界坐标?那也不对呀! 2.使用transform.localPosition移动一个物体,我们只是想让一个物体往它的z轴方向移动,为何实际运行时却不是,而是不知道往哪个方向移动了,这是什么鬼? 如果你已经想明白这些疑惑,那么请设想以下情形: 新建一个Cube,将其Rotation的Y值改为300,为其添加脚本,在Update中分别执行以下语句时,先想一想各自会怎么移动?然后对比一下后面的结果(可以注意下上方的Global与Local的切换)。如果你依然有疑惑,我觉得咱们可以继续往下看。
实际结果如下: 1 transform.Translate(Vector3.forward * Time.deltaTime); ![]() 2 transform.Translate(transform.forward * Time.deltaTime); ![]() 3 transform.position += Vector3.forward * Time.deltaTime; ![]() 4 transform.localPosition += Vector3.forward * Time.deltaTime; ![]() 5 transform.position += transform.forward * Time.deltaTime; ![]() 6 transform.localPosition += transform.forward * Time.deltaTime; ![]() 7 Vector3 objVector3=transform.InverseTransformDirection(Vector3.forward); transform.Translate(objVector3*Time.deltaTime); ![]() 2. Unity坐标系基础 如果对上面的内容有疑惑,我们可能先需要重新了解一下Unity的坐标系。在Unity中常用的坐标系有全局坐标系、局部坐标系、相机坐标系、屏幕坐标系,我们今天主要涉及的是全局坐标系与局部坐标系。 全局坐标系 全局坐标系是用来描述游戏场景内所有物体位置和方向的基准,我们一般也叫它世界坐标系。在Unity场景中创建的物体都是以全局坐标系中的坐标原点来确定各自位置的。所以,全局坐标系是基准,我们可以使用世界坐标来保存一个物体的确切位置。 局部坐标系 每个物体都有其独立的物体坐标系,并且随物体进行相同的移动或者旋转,也可以叫做模型坐标系或物体坐标系。模型Mesh保存的顶点坐标均为局部坐标系下的坐标。Unity工具栏上的Global/Local按钮可以切换显示全局坐标系和局部坐标系。这里要注意了,当切换到Local的时候,显示的是物体自身的坐标系,是自身的坐标系,是自身的坐标系,是自身的坐标系,重要的事多说几遍。 3. Transform中容易混淆的几个问题 transform.position与transform.localPostion(rotation同理) transform.position 是物体的世界坐标,也就是相对世界坐标系原点的位置; transform.localPosition 这个大家一般理解为本地坐标,而一般问题也就出在“本地”这两个字的理解上,这个“本地”不是物体的自身的坐标系(这个local不是工具栏上Global/Local中的Local),而是指父物体的坐标系,当没有父物体时,就是世界坐标系,换句话说如果这个物体有父物体,那么localPosition就是该物体的相对父物体的自身坐标系原点的位置,如果没有父物体,那么localPosition就会等于position。 给大家画个图方便大家理解一下。为了便于观察,我们使用二维坐标系来演示,如下图,A物体的position为(2,3),B物体的position为(5,4),如果A物体是B物体的父物体,那么B物体的localPosition就是以A点为原点的相对坐标(5-2,4-3)即(3,1) ![]() vector3.forward与transform.forward(up、right同理) vector3.forward 这个值大家看到forward很容易将它与世界坐标联系起来,但它就只是一个三维向量,forward只是一个记法而已,官方表述是shorthand,它的值永远都是(0, 0, 1),与世界坐标没有任何关系,你将它用在世界坐标(position)里,它就代表着世界坐标的(0,0,1),你将它用在本地坐标上(localPosition),那么它就代表着本地坐标中的(0,0,1),这一点要记住,否则很容易搞错; transform.forward 这也是一个三维向量,方向是该物体的自身坐标系的z轴方向,长度是世界坐标系中的1,由于这个向量的方向是该物体自身z轴方向,所以这个三维向量的值是会变化的,是基于世界坐标系计算得到的值。 Transform在检视面板上的显示的值 ![]() 这里的Position是localPosition的值,是在父物体的坐标系下的值,也就是相对父物体原点的位置。这与工具栏上的Local是不一样的。所以才会出现直接拖拽物体的z轴,而检视面板中不一定是z的值在变化。 Translate是指定坐标系的 public void Translate(Vector3 translation, Space relativeTo = Space.Self); public void Translate(Vector3 translation, Transform relativeTo); Translate方法具有多个重载方法,当我们不指定坐标系时,默认是按自身坐标系进行位移,我们也可以指定为世界坐标系,当然也可以指定为其他任意物体自身的坐标系。所以当我们使用默认坐标系时,要记住这是物体自身的坐标系。 4. 对1中7种移动的分析
5. 再次思考 我们加点改变,在上述的Cube下新建一个子物体cube,与父物体拉开一段距离,进行一点任意旋转,只对子物体同样执行以上语句,子物体cube都会怎么移动? 这里我就不再赘述啦,大家可以自己尝试哦。如果这个依然可以想明白,那么到这里基本上就OK啦。 ![]() 6. 小结 带着大家回顾了下Unity中的全局坐标系与局部坐标系,分析了几种容易混淆的问题以及几种移动的方式,希望可以给大家带来一点帮助。 工程文件(Unity 2017.3.0f3): 链接:https://pan.baidu.com/s/1bqiT9FL 密码:xd11 |
|