Unity入门学习(三)3D数学(3)之Vector3类的介绍
目录
一、什么是向量
二、向量的模长和单位向量
三、向量的加减乘除
四、向量的点乘
扇形视野检测
五、向量的叉乘
六、插值运算
七、总结
一、什么是向量
几何意义
1、向量是具有方向和长度的数学对象,常用于表示位移、速度、力等方向性物理量。
2、点是位置,向量是方向+长度,两者在 Unity 中都可用 Vector3 表示,但语义不同。
代码中的 Vector3
Unity 的 Vector3 结构体表示三维向量,包含 x, y, z 三个分量。
例如:
Vector3 position = new Vector3(1, 2, 3); // 表示点的位置
Vector3 direction = new Vector3(0, 1, 0); // 表示方向(例如:向上)
//A和B此时 几何意义是两个点
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(4, 5, 6);
//求向量
Vector3 AB = B - A;
print(AB);
Vector3 BA = A - B;
print(BA);
//零向量和负向量Vector3 zero = Vector3.zero;Vector3 neg = -A;
二、向量的模长和单位向量
模长(Magnitude)
模长是向量的长度,计算公式:
|v| = sqrt(x² + y² + z²)
Vector3 v = new Vector3(3, 4, 0);
float length = v.magnitude; // 结果为5(勾股定理)
两个点之间的距离:
print(Vector3.Distance(A, B));
单位向量(Normalized)
方向相同但长度为1的向量,用于仅关注方向时。
归一化方法:
Vector3 normalizedV = v.normalized; // 返回新单位向量
v.Normalize(); // 将原向量归一化(直接修改v)
常用的单位向量 :
Vector3.zero // (0, 0, 0) → 原点
Vector3.one // (1, 1, 1) → 单位缩放
Vector3.forward // (0, 0, 1) → Z轴正方向(物体前方)
Vector3.back // (0, 0, -1)
Vector3.up // (0, 1, 0) → Y轴正方向(物体上方)
Vector3.down // (0, -1, 0)
Vector3.right // (1, 0, 0) → X轴正方向(物体右侧)
Vector3.left // (-1, 0, 0)
三、向量的加减乘除
向量的基本运算http://1.2 向量的基本运算(加减、数乘) - 白鲸的文章 - 知乎 https://zhuanlan.zhihu.com/p/615940607
加减法
几何意义:向量的合成与分解。矢量相加减,三角形法则或者平行四边形法则,加法就是减法。
Vector3 a = new Vector3(1, 2, 3);
Vector3 b = new Vector3(4, 5, 6);
Vector3 sum = a + b; // (5,7,9)
Vector3 diff = a - b; // (-3,-3,-3)
标量乘除
几何意义:缩放向量长度。
Vector3 v = new Vector3(1, 0, 0);
Vector3 doubled = v * 2; // (2,0,0) 长度变为2
Vector3 half = v / 2; // (0.5,0,0)
四、向量的点乘
公式与几何意义
公式:a·b = |a||b|cosθ,结果为标量。
用途:
计算两向量夹角:θ = arccos(a·b / (|a||b|))
判断方向关系(同向/垂直/反向)。
1. a·b > 0(正数)
几何意义:两向量夹角为锐角(0° ≤ θ < 90°)。
方向关系:两向量大致同方向。
例如:
Vector3 forward = Vector3.forward; // (0,0,1)
Vector3 dir1 = new Vector3(0, 0, 0.5f);
Vector3 dir2 = new Vector3(0, 0, -1f); float dot1 = Vector3.Dot(forward, dir1); // 0.5 > 0 → 同向
float dot2 = Vector3.Dot(forward, dir2); // -1 < 0 → 反向
2. a·b = 0
几何意义:两向量垂直(θ = 90°)。
应用场景:检测物体是否在侧面方向。
例如:
// 判断敌人是否在玩家正左侧/右侧
Vector3 playerRight = transform.right; // 玩家的右侧方向
Vector3 enemyDir = enemy.position - transform.position;
float dot = Vector3.Dot(playerRight, enemyDir);if (Mathf.Approximately(dot, 0)) {//无限逼近0Debug.Log("敌人在正侧方!");
}
3. a·b < 0(负数)
几何意义:两向量夹角为钝角(90° < θ ≤ 180°)。
方向关系:两向量大致反方向。
例如:
Vector3 playerForward = transform.forward;
Vector3 enemyBehindDir = transform.position - enemy.position;if (Vector3.Dot(playerForward, enemyBehindDir) < 0) {Debug.Log("敌人在后方!");
}
点加减向量等同于将点朝着向量的方向移动向量的长度那么远。
例如:
Vector3 a = new Vector3(1, 0, 0);
Vector3 b = new Vector3(0, 1, 0);
float dot = Vector3.Dot(a, b); // 0(垂直)// 判断敌人是否在玩家前方
Vector3 playerForward = transform.forward;
Vector3 enemyDirection = enemy.position - player.position;
if (Vector3.Dot(playerForward, enemyDirection) > 0) {Debug.Log("敌人在前方!");
}
点乘与投影:轴偏移距离分析
点乘可以用来计算一个向量在另一个向量方向上的投影长度,从而判断“距某个轴向偏移了多远”。
公式
向量 a 在向量 b 方向上的投影长度为:
投影长度 = |a| * cosθ = (a·b) / |b|
// 计算物体在玩家正前方(z轴)的偏移距离
Vector3 playerForward = transform.forward; // 假设已归一化(长度=1)
Vector3 objectOffset = object.position - transform.position;// 投影长度 = (objectOffset · playerForward) / |playerForward|
// 因为 playerForward 是单位向量,分母为1,直接取点乘结果
float forwardDistance = Vector3.Dot(objectOffset, playerForward);if (forwardDistance > 5) {Debug.Log("物体在玩家前方5米外");
} else if (forwardDistance < -3) {Debug.Log("物体在玩家后方3米外");
}
扇形视野检测
// 判断目标是否在玩家60度视野内
Vector3 toTarget = target.position - transform.position;
float dot = Vector3.Dot(transform.forward, toTarget.normalized);
float cosThreshold = Mathf.Cos(60 * Mathf.Deg2Rad); // 60度对应的cos值≈0.5if (dot > cosThreshold) {Debug.Log("目标在视野内!");
}
五、向量的叉乘
公式与几何意义
公式:a × b 结果是一个新的向量,方向垂直于 a 和 b 所在平面,遵循右手法则。如图
用途:
计算平面法线(例如:地形法线)。
计算旋转轴(例如:绕轴旋转)。
例如判断叉乘后的向量和原先向量的相对位置:假设AB都是xz平面的线
Vector3 C= Vector3.Cross(A.position, B.position);if (C.y > 0){print("B在A的右侧");}else{print("B在A的左侧");}
六、插值运算
线性插值(Lerp)
作用:在两个向量之间按比例插值,实现平滑过渡。
数学原理
公式:
result=a+t×(b−a)
即直接沿直线从 a 到 b 按比例 t 插值。
特性:
t=0 时返回 a,t=1 时返回 b。
t 超出 [0,1] 时,结果会超出 a 到 b 的直线范围(如 t=2 会得到 b + (b-a))。
例如:
Vector3 start = Vector3.zero;
Vector3 end = new Vector3(10, 0, 0);
Vector3 result = Vector3.Lerp(start, end, 0.5f); // (5,0,0)
球形插值(Slerp)
作用:保持匀速的弧形插值,适合旋转或相机跟随。
输入参数:起点位置,目标位置,弧线移动过去
Vector3 from = transform.forward;
Vector3 to = target.position - transform.position;
Vector3 direction = Vector3.Slerp(from, to, Time.deltaTime * speed);
特性 | Lerp | Slerp |
---|---|---|
插值路径 | 直线 | 球面弧线 |
输入向量要求 | 任意向量(无需归一化) | 必须为单位向量(归一化) |
匀速性 | 非匀速(线性距离变化) | 匀速(恒定角速度) |
典型场景 | 位置、颜色、缩放等非方向性数据 | 方向、旋转等需要保持路径自然性的场景 |
七、总结
Unity Vector3 类的重要属性及 API 总结表:
属性/API | 输入参数 | 输出结果 | 简单示例 |
---|---|---|---|
Vector3.zero | 无 | 零向量 (0,0,0) | Vector3 zero = Vector3.zero; |
Vector3.one | 无 | 单位向量 (1,1,1) | Vector3 one = Vector3.one; |
Vector3.forward | 无 | 世界坐标系前向单位向量 (0,0,1) | Vector3 dir = Vector3.forward; |
Vector3.up | 无 | 世界坐标系上向单位向量 (0,1,0) | Vector3 upDir = Vector3.up; |
vector.magnitude | 无 | 向量的模长(长度) | float len = new Vector3(3,4,0).magnitude; // 5 |
vector.normalized | 无 | 单位向量(不修改原向量) | Vector3 norm = v.normalized; |
vector.Normalize() | 无 | 将原向量归一化(直接修改) | v.Normalize(); |
Vector3.Dot(a, b) | 两个 Vector3 向量 | 点乘结果(标量) | float dot = Vector3.Dot(a, b); |
Vector3.Cross(a, b) | 两个 Vector3 向量 | 叉乘结果(垂直向量) | Vector3 cross = Vector3.Cross(a, b); |
Vector3.Distance(a, b) | 两个 Vector3 点 | 两点之间的直线距离 | float dist = Vector3.Distance(pointA, pointB); |
Vector3.Lerp(a, b, t) | 起点 a ,终点 b ,比例 t | 线性插值后的向量 | Vector3 pos = Vector3.Lerp(start, end, 0.5f); |
Vector3.Slerp(a, b, t) | 单位向量 a ,单位向量 b ,比例 t | 球面插值后的向量 | Vector3 dir = Vector3.Slerp(from, to, t); |
运算符 + (a, b) | 两个 Vector3 向量 | 向量相加结果 | Vector3 sum = a + b; |
运算符 - (a, b) | 两个 Vector3 向量 | 向量相减结果 | Vector3 diff = a - b; |
运算符 * (v, scalar) | 向量 v ,标量 scalar | 向量缩放后的结果 | Vector3 scaled = v * 2f; |
运算符 / (v, scalar) | 向量 v ,标量 scalar | 向量缩放后的结果 | Vector3 half = v / 2f; |
就这样 再见