移动
- 适用于既没有物理系统,对移动又没有特殊要求的情况。
- 不易处理障碍物阻挡的问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private float speed = 10f;
float v = Input.GetAxis("Horizontal");
float h = Input.GetAxis("Horizontal");
float vOffset = v * Time.deltaTime * speed;
float hOffset = h * Time.deltaTime * speed;
// 世界坐标系下移动
Vector3 moveDelta = new Vector3(vOffset, 0, hOffset);
transform.position += moveDelta;
transform.Translate(moveDelta, Space.World);
// 朝物体z轴方向移动
transform.position += transform.forward;
transform.Translate(Vector3.forward, Space.Self);
// 朝世界坐标z轴方向移动
transform.position += Vector3.forward;
transform.Translate(Vector3.forward, Space.World);
- 同时设置位置和旋转
1
transform.SetPositionAndRotation();
缩放
旋转
- Unity使用左手坐标系,所以旋转正方向是顺时针方向
- rotation 考虑到了所有父级叠加的旋转量,是世界空间的最终旋转量。
直接设置旋转角度
1
2
// localRotation 是 inspector面板看到的旋转量,相对于父对象。
transform.localRotation = Quaternion.Euler(0, 0, -30);
累计旋转量
- 自身累积(cumulative)旋转量,增量旋转
1 2 3 4 5
void Update() { // 每秒旋转22.5度 transform.Rotate(0f, 22.5f * Time.deltaTime, 0f); }
绕某点累积旋转
- 绕某点累积(cumulative)旋转的方法:
1 2 3 4
// point为世界空间中的点 // axis为旋转轴 // angle为旋转角度 transform.RotateAround(point, axis, angle);
看向某个对象
1
transform.LookAt(attackTarget.transform);
分次应用旋转
- [[四元数]]相乘,应用多次旋转,结合父级的旋转量
1 2 3 4
// 四元数相乘的顺序,先应用自身N,再应用父级... ...321(顶级)。 // 所以乘法顺序为 rotation = 123.....N。 Quaternion rotation = Quaternion.Euler(0, 0, -30); transform.localRotation = grandTrans.localRotation * parentTrans.localRotation * rotation;
坐标变换
本地坐标变换到世界坐标
- 要注意 w 分量的取值, w=0 会忽略 position
1
2
3
4
5
6
7
8
9
10
// 使用 TransformPoint 函数
Vector3 worldPos = transform.parent.TransformPoint(localPosition);
// 使用 localToWorldMatrix 矩阵
// 变换向量 w = 0, 变换坐标 w = 1
worldPos = transform.localToWorldMatrix * new Vector4(localPos.x, localPos.y, localPos.z, 1);
// 使用 Matrix4x4 静态类构建TRS矩阵变换 ( Translation-Rotation-Scale)
Matrix4x4 trs = Matrix4x4.TRS(position, rotation, scale);
worldPos = trs * new Vector4(localPos.x, localPos.y, localPos.z, 1);
世界坐标变换到本地坐标
1
2
3
4
Vector4 worldPos = new Vector4(x, y, z, 1);
localPos = transform.InverseTransformPoint(worldPos);
localPos = transform.worldToLocalMatrix * worldPos;
本地向量变换成世界空间向量
1
transform.TransformDirection();
世界空间向量变换成本地向量
1
transform.InverseTransformDirection();
修改自己的层级
- 修改层级关系的几个函数
1
2
3
transform.SetAsFirstSibling(); // 层级最上(最先渲染)
transform.SetSiblingIndex(i);
transform.SetAsLastSibling(); // 层级最下(最后渲染)
操作子对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 获取子对象的个数
int childCount = transform.childCount;
// 通过名字获取子对象
Transform child = transform.Find("Text");
// 遍历第一层子对象(不包括自身和孙子节点)
foreach(Transform child in transform)
{
Debug.Lod("Child: " + child.name);
}
// 通过名字查找子孙对象
private Transform DeepFindChild(Transform root, string name)
{
Transform result = null;
result = root.Find(name);
if (result == null) {
foreach(Transform transform in root)
{
result = DeepFindChild(transform, name)
{
if (result != null) {
return result;
}
}
}
}
return result;
}
// 遍历所有子孙对象(包括自身和孙子节点)
Transform[] children = GetComponentsInChildren<Transform>();
foreach(Transform child in children)
{
Debug.Log("Child or Self: " + child.name);
}
获取组件
1
2
3
Animator anim = GetComponent<Animator>();
// 获取自身和其所有子孙对象身上的所有组件
Animator[] animators = GetComponentsInChildren<Animator>();
不能直接对 transform.position.y赋值
- transform.position是一个属性,提供了get和set方法,transform.position实际上相当于调用了一个函数,该函数返回了一个Vector3[[CS-值类型]]的拷贝,不是一个变量(variable)直接修改一个这样的临时值是无意义的。
- 归根结底是因为transform.position返回的是一个值类型的临时量,不是因为它是一个属性(其实提供了set方法)