Unity核心概念⑦:Transform
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);
一、Transform的主要作用
游戏对象(GameObject)位移、旋转、缩放、父子关系、坐标转换等相关操作都由Transform来处理。它是Unity提供的重要的类。
二、Vector3
1.主要作用
用来表示三维坐标系中的一个点或者一个向量。
2.申明方法
方法一:
// 声明并初始化一个Vector3结构体变量v
// new Vector3() 使用默认构造函数,创建零向量(0, 0, 0)
Vector3 v = new Vector3();// 设置向量v的X分量为10(通常控制左右方向)
v.x = 10;// 设置向量v的Y分量为10(通常控制上下方向)
v.y = 10;// 设置向量v的Z分量为10(通常控制前后方向)
v.z = 10;// 此时向量v的值为(10, 10, 10),表示一个三维空间中的点或方向
方法二:
Vector3 v = new Vector3(10, 10, 10);//x , y , zVector3 v = new Vector3(10, 10);//不赋值z默认z为0
3.基本计算
①加减乘除:
// 创建第一个三维向量 v1,值为 (1, 1, 1)
Vector3 v1 = new Vector3(1, 1, 1);// 创建第二个三维向量 v2,值为 (2, 2, 2)
Vector3 v2 = new Vector3(2, 2, 2);// 向量加法:对应分量相加,结果为 (1+2, 1+2, 1+2) = (3, 3, 3)
// 几何意义:两个向量的合成向量
print(v1 + v2);// 向量减法:对应分量相减,结果为 (1-2, 1-2, 1-2) = (-1, -1, -1)
// 几何意义:从v2指向v1的向量
print(v1 - v2);// 向量乘法:对应分量相乘,结果为 (1*2, 1*2, 1*2) = (2, 2, 2)
// 注意:这不是点积或叉积,而是分量乘法
print(v1 * v2);// 向量除法:对应分量相除,结果为 (1/2, 1/2, 1/2) = (0.5, 0.5, 0.5)
// 注意:除数分量不能为0,否则会得到无限大(Infinity)
print(v1 / v2);
②常用方法:
// 打印零向量,表示三维空间原点 (0, 0, 0)
// 常用于初始化或重置位置
print(Vector3.zero);// 打印右方向单位向量,表示X轴正方向 (1, 0, 0)
// 常用于表示物体的右侧移动或方向
print(Vector3.right);// 打印前方向单位向量,表示Z轴正方向 (0, 0, 1)
// 在Unity中,Z轴通常代表前后方向(3D空间)
print(Vector3.forward);// 打印后方向单位向量,表示Z轴负方向 (0, 0, -1)
// 与前方向相反
print(Vector3.back);// 打印上方向单位向量,表示Y轴正方向 (0, 1, 0)
// 常用于表示跳跃、上升方向
print(Vector3.up);// 打印下方向单位向量,表示Y轴负方向 (0, -1, 0)
// 与上方向相反,常用于表示重力方向
print(Vector3.down);
③计算两个点之间的距离:
print(Vector3.Distance(v1,v2));
三、位置
1.相对世界坐标系
print(this.transform.position);
通过position得到的位置是相对于世界坐标系的原点的为止,可能和面板显示的位置不一样,因为如果对象有父子关系,并且父对象位置不在原点,那么和面板上的位置信息肯定就是不一样的。
2.相对父对象
print(this.transform.localPosition);
注意:
①以上两个坐标很重要,如果你想以面板坐标为准来进行位置设置,那一定是通过localPosition来进行设置的。他们两个可能会出现是一样的情况:父对象坐标就是世界坐标系原点(0,0,0);对象没有父对象。
②位置的赋值不能改变x,y,z,只能整体改变。不能改变x,y,z的某一个值。
如果只想改变一个值,那么另外两个值要保持原有坐标一致。可以通过以下方法:
直接赋值
this.transform.position = new Vector3(2,this.transform.position.y,this.transform.position.z);
// 修改当前物体在世界空间中的位置
// 只改变X坐标,保持Y和Z坐标不变
虽然不能直接改transform的x,y,z,但是Vector3可以直接改。所以可以先将坐标取出来,再重新赋值。
// 获取当前物体相对于父物体的局部坐标位置
// 如果物体没有父物体,则localPosition与position(世界坐标)相同
Vector3 v = this.transform.localPosition;// 修改局部坐标的X分量为10
// 这里修改的是临时变量v的值,尚未应用到物体上
v.x = 10;// 将修改后的局部坐标赋值回物体
// 物体将相对于其父物体在X轴上移动到位移10的位置
this.transform.localPosition = v;
四、位移
1.坐标系下位移的计算公式
路程=方向*速度*时间
计算方法一:自己计算
this.transform.position = this.transform.position + this.transform.forward* 1 *Time.deltaTime;
//当前的位置+位移的距离=所在的位置
方向决定了前进方向。
计算方法二:API
一般使用AP来进行位移。默认参数是相对于自己坐标系的。
①相对于世界坐标系的Z轴移动并且始终是朝世界坐标系的Z轴正方向移动。
this.transform.Translate(Vectors.forward * 1 * Time.deltaTime, Space.World);
②相对于世界坐标系,自己的面朝向去动并且始终朝自己的面朝向移动。
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);
③相对于自己坐标系下的自己面朝向进行向量移动(一定不会这样让物体移动)
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.Self);
④相对于自己的坐标系下的Z轴正方向移动并且始终朝自己的面朝向移动。
this.transform.Translate(Vectors.forward * 1 * Time.deltaTime, Space.Self);
五、角度和旋转
1.角度
①输出相对世界坐标角度
print(this.transform.eulerAngles);
②输出相对父对象角度
print(this.transform.localEulerAngles);
注意
设置角度和设置位置一样,不能单独设置x,y,z,需要一起设置。
如果希望改变的角度是面板上显示的内容,那一定是改变相对父对象的角度。
this.transform.localEulerAngles = new Vector(10,10,10);
// 设置物体相对于父物体的旋转角度为(10, 10, 10)度
// X轴旋转10度,Y轴旋转10度,Z轴旋转10度
2.旋转
①自己计算
方法跟位移是一样的,在此省略不讲,一般使用API。
②API
自转:
// 每帧调用,使物体持续旋转
// Rotate方法:相对于当前朝向施加一个旋转
// new Vector3(0, 10, 0):表示绕Y轴旋转10度
// Time.deltaTime:乘以帧时间,使旋转速度与帧率无关
// 效果:物体每秒绕自身Y轴旋转10度,平滑流畅
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime);
// 使物体每帧绕世界坐标系的Y轴旋转
// 参数1:旋转的角度和轴 (0, 10, 0) * Time.deltaTime - 绕Y轴每秒10度
// 参数2:Space.World - 使用世界坐标系(全局坐标)作为旋转参考系
// 效果:物体将围绕固定的世界Y轴旋转,不受自身朝向影响
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime, Space.World);
相对某个轴转多少度:
// 让当前物体持续旋转
// 每帧绕自身的上方向(Y轴)旋转一定角度
//参数一:相对哪个轴进行转动
//参数二:转动的角度是多少
//参数三:默认不填相对自己的坐标系进行旋转
this.transform.Rotate(Vector3.up, 10 * Time.deltaTime);
this.transform.Rotate(Vector3.up, 10 * Time.deltaTime,Space.World);
相对某个点转:
// 让当前物体围绕世界空间中的某个点进行公转
// 每帧围绕指定点和指定轴旋转一定角度
this.transform.RotateAround(Vector3.zero, Vector3.up, 10 * Time.deltaTime);
//参数一:相对于哪一个点旋转
//参数二:相对于那一个点旋转的哪一个轴旋转
//参数三:旋转的度数:旋转速度*时间
六、缩放和看向
1.缩放
相对世界坐标系:
print(this.transform.lossyScale);
相对本地坐标系(父对象):
print(this.transform.localScale);
注意:
①缩放不能只改x,y,z,只能一起改(相对于世界坐标系的缩放大小只能获得,不能更改)。所以我们一般修改缩放大小都是更改相对于父对象的缩放大小“localScale”。
this.transform.localScale = new Vector(3,3,3);
②Unity没有提供关于缩放的API。如果想要让缩放发生变化只能自己写。
// 让当前物体持续均匀放大
// 每帧在所有维度上增加缩放值
this.transform.localScale += Vector3.one * Time.deltaTime;
2.看向
让一个对象的面朝向一直向着某一点或者某一个对象。写在Update函数里才能一直看向。
看向一个点:
// 让当前物体立即旋转,使其正面(Z轴正方向)指向世界坐标原点(0,0,0)
this.transform.LookAt(Vector3.zero);
看向一个对象:看向一个对象就传入一个对象的transform信息。
this.transform.LookAt(对象名);
七、父子关系
1.获取和设置父对象
①获取父对象名字:
print(this.transform.parent.name);
②设置父对象:
断绝父子关系:
this.transform.parent = null;
建立父子关系:
this.transform.parent = GameObject.Find("要建立父子关系的父对象名").transform;
③通过API来设置父子关系:
this.transform.SetParent = null;//断绝父子关系
this.transform.SetParent( GameObject.Find("要建立父子关系的父对象名").transform);
//建立父子关系
this.transform.SetParent( GameObject.Find("要建立父子关系的父对象名").transform,false);
//参数一:父对象名
//参数二:是否保留世界坐标的位置、角度、缩放信息
//true:会保留世界坐标下的信息和父对象进行计算,得到本地坐标系的信息
//false:不会保留世界坐标下的信息,直接赋值到本地坐标系下
2.抛弃子对象
和自己的所有子对象断绝父子关系,不会断绝孙子关系。
this.transform.DetachChildren();
3.获取子对象
得到子对象的transform信息。
①按名字查找儿子
只能查找子对象,不能查找孙子对象。
注意:Find查找能够找到失活对象,GameObject相关的查找不能找到失活对象。
this.transform.Find("子对象名");
②遍历子对象
输出有多少个子对象,失活的子对象算数,孙子对象不算数。
print(this.transform.childCount);
通过索引号去得到对应的子对象,如果编号超出了子对象数量的范围会报错。返回值transform可以得到对应子对象的位置相关信息。
Transform firstChild = this.transform.GetChild(0);// 循环遍历当前物体的所有子物体
// childCount:获取子物体总数,作为循环条件
for(int i = 0; i < this.transform.childCount; i++)
{// 正确:通过索引i获取每个子物体,并打印其名称// GetChild(i) 返回第i个子物体的Transform组件print("子对象名:" + this.transform.GetChild(i).name);
}
4.子对象的操作
①判断父子关系
// 检查 son 变换是否是当前物体变换的子级(包括间接子级)
if(son.IsChildOf(this.transform))
{// 如果 son 是当前物体的子对象、孙对象等任何后代对象,条件成立print("是我的子对象");
}
②得到自己作为子对象的编号
print(son.GetSiblingIndex());
③把自己设置为第一个子对象
son.SetAsFirstSibling();
④把自己设置为最后一个子对象
son.SetAsLastSibling();
⑤把自己设置为第几个子对象
son.SetSiblingIndex(3);//把自己设置为第3个子对象
如果括号内所填数字范围超过子对象数量,默认会设置为第一个或最后一个子对象。
八、坐标转换
1.世界坐标系转本地坐标系
帮助我们大概判断一个相对位置。
①世界坐标系的点转换为相对本地坐标系的点(受缩放影响)
// 世界坐标系的前方向向量,值为 (0, 0, 1)
// 表示世界空间Z轴正方向
Vector3.forward;// 将世界坐标系中的一个点(或方向)转换到当前物体的局部坐标系中
// 参数:世界空间中的点(这里用的是世界前方点 (0, 0, 1))
// 返回值:该点在当前物体局部坐标系中的位置
this.transform.InverseTransformPoint(Vector3.forward);
②世界坐标系的方向转换为相对本地坐标系的方向
不受缩放影响:
this.transform.InverseTransformDirection(Vector3.forward);
受缩放影响:
this.transform.InverseTransformVector(Vector3.forward);
2.本地坐标系转世界坐标系
①本地坐标系的点转换为相对世界坐标系的点(受缩放影响)
this.transform.TransformPoint(Vector3.forward);
②本地坐标系的方向转换为相对世界坐标系的方向
不受缩放影响:
this.transform.TransformDirection(Vector3.forward);
受缩放影响:
this.transform.TransformVector(Vector3.forward);