数学与unity

坐标系

世界坐标系

unity的世界坐标系是左手系,左手手掌向上为y轴,4根手指为x轴,大拇指为z轴

局部坐标系

1
2
3
4
5
6
7
8
//坐标
Vector3 worldPos =transform.position;//获取当前物品的世界坐标系
Vector3 localPos =transform.loaclPosition;//获取当前物品相对父物品的位置
//旋转 用到四元数(Quaternion)
Quaternion worldRotation = transform.rotation;
Quaternion localRotation = transform.localRotation;
//父物体局部坐标系下的缩放。无法直接获得世界坐标系的缩放
Vector3 localScale = transform.localScale;

区别

任何坐标数值在不同坐标系用不同的解释。

屏幕坐标系

1
2
3
Vector2 mousePos = Input.mousePostion;//鼠标在屏幕上的位置
Vector3 viewPoint = Camera.main.ScreenToViewportPoint(Input.mousePosition);
//将鼠标指针位置转化为视图坐标系要用摄像机计算

向量

标准化

1
2
3
4
5
6
7
8
9
//Vector3为一个三维向量,下面是它的标准化
Vector3 a=new Vector3(2,1,0);
Vector3 na=a/a.magnitude;

Vector3 na2=a.normalized;

Vector3 na2=Vector3.Normalized(a);

Vector3 na4=(1/a.magnitude)*a;

点积

1
2
3
4
5
//计算向量a在向量b方向上的投影长度
Vector3 a=new Vector(2,1,0);
Vector3 b=new Vector(3,0,0);
Vector3 dir_b=b.nomalized;
float pa=Vector3.dot(a,dir_b);//点积操作

叉积

unity的叉积是左手系

1
2
3
4
5
//计算两向量平面上的法线
Vector3 a=new Vector3(2,1,1);
Vector3 b=new Vector3(3,0,2);
Vector3 n=Vector3.Cross(a,b);//叉乘操作
n=n.normalized;

Vector3常用方法

方法 说明
Cross() 叉乘
Dot() 点乘
Project() 计算向量在另一个向量上的投影
Angle() 返回两个向量的夹角
Distance() 返回两个向量的距离

向量坐标系的转换

对于同一个常数,在不同的方法中有不同的含义

1
2
3
4
//transform.Translate()默认是以局部坐标系为基准
//因此如果想要以世界坐标系为准,Translate函数的参数是要从世界坐标系向量转化成等价的局部坐标系向量
//转化通过InverseTransformDirection()完成
//其他转换函数
方法名 作用
transform.TransformPoint() 局部坐标转换为世界坐标
transform.InverseTransformPoint() 世界坐标转换为局部坐标
transform.TransformDirection() 局部坐标系向量转换为世界坐标系向量
transform.InverseTransformDirection() 世界坐标系向量转换为局部坐标系向量

四元数

概念

四元数包含一个标量分量和一个三维向量分量,四元数Q可以记作 \[ Q=[w,(x,y,z)] \] 矩阵和欧拉角也可以不同程度表示旋转和朝向,但各有优劣,这里不进行赘述。

结构体

四元数的属性

Quaternion属性 说明
x 四元数的x分量,不应直接修改
y 四元数的y分量,不应直接修改
z 四元数的z分量,不应直接修改
w 四元数的w分量,不应直接修改
this[int index] 允许通过下标运算符访问x、y、z、w分量。例如[1]可以访问y
eulerAngles 获得对应的欧拉角
identity 获得无旋转的四元数

四元数的方法和运算符

Quaternion方法 说明
ToAngleAxis 将旋转转换为一个轴和一个角度的性事
SetFromToRotation 与FromToRotation类似,但是直接修改当前四元数对象
SetLookRotation 与LookRotation类似,但是直接修改当前四元数对象
* 四元数相乘,代表依次旋转的操作
== 判断四元数是否相等
!= 判断四元数是否不相等
Dot 两个旋转点乘
AngleAxis 根据一个轴和一个角度获得一个四元数
FromToRotation 获得一个四元数代表从from到to向量的旋转
LookRotation 给定前方和上方向量,获得一个旋转
Slerp 插值,根据比例在两个四元数之间进行球面插值
Lerp 插值,根据比例在两个四元数之间进行插值并将结果规范化
RotateTowards 将旋转from变到旋转to
Inverse 返回四元数的逆
Angle 返回两个旋转之间的夹角
Euler 转换为对应的欧拉角

理解和运用四元数

四元数可以表示朝向和旋转。旋转可以用四元数乘法进行。

旋转和朝向的关系

元素1 运算符 元素2 一般意义
朝向 * 朝向 错误操作,意义不明
朝向 * 旋转 从某个朝向开始,旋转一个角,得到新的朝向
旋转 * 旋转 组合两次旋转,得到合并的结果

要注意的是,四元数相乘不满足交换律。

更有意思的是,四元数乘法可以直接作用于向量,这样就可以直接旋转向量。

用四元数旋转向量的方法

元素1 运算符 元素2 一般意义
朝向 * 向量 错误操作
旋转 * 向量 将向量旋转一个角,得到新的向量

注意四元数乘以向量时,必须四元数在前,向量在后。

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QuatTest : MonoBehaviour
{
void Update()
{
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");
//将横向输入转化为左右旋转,将纵向输入转换为俯仰旋转,得到一个很小的旋转四元数
Quaternion smallRotate = Quaternion.Euler(v, h, 0);
if (Input.GetButton("Fire1"))
{
//按住crtrl键时,沿世界坐标轴旋转
transform.rotation = smallRotate * transform.rotation;
}
else
{
//不按时,沿局部坐标轴旋转
transform.rotation = transform.rotation * smallRotate;
}
}
}


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!