发布时间:2023-08-09 18:30
任何游戏对象在创建的时候都会附带Transform组件,用于储存并操控物体的位置、旋转和缩放。 并且该组件是无法删除的。
Transform面板一共包含3个属性:
Position:位置
Rotation:旋转
Scale:(缩放)
可修改对象的位置、旋转方式、缩放数值
void Start () {
//在控制台上打印绑定此脚本游戏对象的位置信息
Debug.Log(transform.position);
//对绑定此脚本的游戏对象重新设置位置
transform.position = new Vector3(2,2,2);
Debug.Log(transform.position);
}
localPosition
transform.localPosition是一个可读可写的属性。transform.localPosition是利用局部坐标系来展示坐标的,即把父节点作为原点,自身位置就是相对于父节点的在三个轴向上的距离
两者的区别
在场景中创建一个Cube1,并创建Cube1的子物体Cube2.设置Cube1的坐标为(5,6,7),同时设置Cube2为(0,0,2).
将脚本挂载到Cube2的游戏物体上,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TransformDemo : MonoBehaviour {
// Use this for initialization
void Start () {
//在控制台上打印绑定此脚本游戏对象的位置信息
//在控制台上打印的内容是(5.0,6.0,9.0) 表示的是Cube2在世界坐标系下表示的位置 参考的坐标是是世界的原点
Debug.Log(transform.position);
//在控制台上打印的内容是(0.0,0.0,2.0) 表示的是Cube2在局部坐标系下表示的位置 参考的坐标系是Cube1
Debug.Log(transform.localPosition);
}
}
欧拉角
优点:
很容易理解,形象直观;
表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;
缺点:
之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。这里有个视频可以直观的理解下;
由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
欧拉旋转是怎么运作的
在Unity里,欧拉旋转的旋转顺序是Z、X、Y,这在相关的API文档中都有说明,例如Transform.Rotate。其实文档中说得不是非常详细,还有一个细节我们需要明白。如果你仔细想想,就会发现有一个非常重要的东西我们没有说明白,那就是旋转时使用的坐标系。给定一个旋转顺序(例如这里的Z、X、Y),以及它们对应的旋转角度(α,β,r),有两种坐标系可以选择:
绕坐标系E下的Z轴旋转α,绕坐标系E下的Y轴旋转β,绕坐标系E下的X轴旋转r,即进行一次旋转时不一起旋转当前坐标系;
绕坐标系E下的Z轴旋转α,绕坐标系E在绕Z轴旋转α后的新坐标系E’下的Y轴旋转β,绕坐标系E’在绕Y轴旋转β后的新坐标系E”下的X轴旋转r, 即在旋转时,把坐标系一起转动;
很容易知道,这两种选择的结果是不一样的。但如果把它们的旋转顺序颠倒一下,其实结果就会一样。说得明白点,在第一种情况下、按ZXY顺序旋转和在第二种情况下、按YXZ顺序旋转是一样的。证明方法可以看下这篇文章。而Unity文档中说明的旋转顺序指的是在第一种情况下的顺序。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TransformDemo : MonoBehaviour {
// Use this for initialization
void Start () {
//第一种情况
//transform.Rotate(new Vector3(45, 30, 90));
//第二种情况分步骤做效果是一样的
transform.Rotate(new Vector3(0, 30, 0));
transform.Rotate(new Vector3(45, 0, 0));
transform.Rotate(new Vector3(0, 0, 90));
}
}
在了解了上述知识后,我们就不需要那么惧怕四元数了,实际上它和矩阵类似,不同的只是它的表示方式以及运算方式。那么在Unity里如何利用四元数进行旋转呢?Unity里提供了非常多的方式来创建一个四元数。例如Quaternion.AngleAxis(float angle, Vector3 axis),它可以返回一个绕轴线axis旋转angle角度的四元数变换。我们可以一个Vector3和它进行左乘,就将得到旋转后的Vector3。在Unity里只需要用一个“ * ”操作符就可以进行四元数对向量的变换操作,相当于我们上述讲到的p′=qpq−1操作。如果我们想要进行多个旋转变换,只需要左乘其他四元数变换即可。例如下面这样:
Vector3 newVector = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.LookRotation(someDirection) * someVector;
尽管欧拉角更容易我们理解,但四元数比欧拉角要强大很多。Unity提供了这两种方式供我们选择,我们可以选择最合适的变换。
例如,如果我们需要对旋转进行插值,我们可以首先使用Quaternion.eulerAngles来得到欧拉角度,然后使用Mathf.Clamp对其进行插值运算。
最后更新Quaternion.eulerAngles或者使用Quaternion.Euler(yourAngles)来创建一个新的四元数。
又例如,如果你想要组合旋转,比如让人物的脑袋向下看或者旋转身体,两种方法其实都可以,但一旦这些旋转不是以世界坐标轴为旋转轴,比如人物扭动脖子向下看等,那么四元数是一个更合适的选择。Unity还提供了transform.forward, transform.right and transform.up 这些非常有用的轴,这些轴可以和Quaternion.AngleAxis组合起来,来创建非常有用的旋转组合。例如,下面的代码让物体执行低头的动作:
transform.rotation = Quaternion.AngleAxis(degrees, transform.right) * transform.rotation;
//通过这种方式得到的缩放比例是参照父物体计算出来的,也就是说把父物体的的缩放作为标准。也可以通过游戏对象在三个轴上的实际尺寸/父物体对应的三个轴向上的尺寸得到的
Debug.Log(transform.localScale);
//表示的是游戏对象实际的缩放尺寸
Debug.Log(transform.lossyScale);
【注】部分参考于此博客http://blog.csdn.net/candycat1992/article/details/41254799
http://blog.csdn.net/yy763496668
http://blog.csdn.net/yy763496668/article/details/75690180