Unity基础-数学向量
二、向量相关用法
概述
向量在Unity游戏开发中扮演着重要角色,用于表示位置、方向、速度等。Unity提供了Vector2、Vector3等结构体来处理向量运算。
1. 向量基础操作
1.1 向量创建和访问
// 创建向量
Vector3 position = new Vector3(1, 2, 3);
Vector2 position2D = new Vector2(1, 2);
// 访问向量分量
float x = position.x;
float y = position.y;
float z = position.z;
1.2 向量运算
// 向量加减
Vector3 v1 = new Vector3(1, 2, 3);
Vector3 v2 = new Vector3(4, 5, 6);
Vector3 sum = v1 + v2; // 结果:(5, 7, 9)
Vector3 diff = v2 - v1; // 结果:(3, 3, 3)
// 向量数乘
Vector3 scaled = v1 * 2; // 结果:(2, 4, 6)
2. 向量重要方法
2.1 向量点乘(Dot Product)
// 点乘用于计算两个向量的夹角
float dot = Vector3.Dot(v1, v2);
// 实际应用:判断物体相对位置
// 如果点乘结果 > 0,表示物体在前方
// 如果点乘结果 < 0,表示物体在后方
if(Vector3.Dot(transform.forward, target.position - transform.position) > 0)
{
print("目标在前方");
}
2.2 向量叉乘(Cross Product)
// 叉乘用于获取垂直于两个向量的向量
Vector3 cross = Vector3.Cross(v1, v2);
// 实际应用:判断左右方向
// 如果叉乘结果的y分量 > 0,表示在右侧
// 如果叉乘结果的y分量 < 0,表示在左侧
if(Vector3.Cross(transform.forward, target.position - transform.position).y > 0)
{
print("目标在右侧");
}
2.3 向量夹角计算
// 方法1:使用点乘和反三角函数
float dot = Vector3.Dot(v1.normalized, v2.normalized);
float angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
// 方法2:直接使用Vector3.Angle
float angle = Vector3.Angle(v1, v2);
3. 向量插值
3.1 线性插值(Lerp)
// 在两个向量之间进行线性插值
Vector3 result = Vector3.Lerp(start, end, t); // t的范围是[0,1]
3.2 球形插值(Slerp)
// 在两个向量之间进行球形插值,保持匀速旋转
Vector3 result = Vector3.Slerp(start, end, t);
4. 向量常用属性
Vector3 v = new Vector3(3, 4, 0);
// 向量长度
float magnitude = v.magnitude; // 结果:5
// 向量平方长度(性能更好)
float sqrMagnitude = v.sqrMagnitude; // 结果:25
// 单位向量
Vector3 normalized = v.normalized; // 结果:(0.6, 0.8, 0)
// 零向量
Vector3 zero = Vector3.zero; // 结果:(0, 0, 0)
// 单位向量
Vector3 one = Vector3.one; // 结果:(1, 1, 1)
5. 实际应用示例
5.1 物体跟随
// 使用Vector3.Lerp实现平滑跟随
transform.position = Vector3.Lerp(transform.position, target.position, Time.deltaTime * speed);
5.2 方向检测
// 检测目标是否在视野范围内
Vector3 directionToTarget = target.position - transform.position;
float angle = Vector3.Angle(transform.forward, directionToTarget);
if(angle < viewAngle && directionToTarget.magnitude < viewDistance)
{
print("目标在视野范围内");
}
5.3 巡逻检测
// 检测目标是否在特定区域内
if(Vector3.Dot(transform.forward, target.position - transform.position) > 0)
{
if(Vector3.Cross(transform.forward, target.position - transform.position).y > 0)
{
if(Vector3.Angle(transform.forward, target.position - transform.position) < 30 &&
Vector3.Distance(transform.position, target.position) < 5)
{
print("发现目标");
}
}
}
6. 调试工具
// 绘制线段
Debug.DrawLine(start, end, Color.red);
// 绘制射线
Debug.DrawRay(origin, direction, Color.blue);
7. 使用建议
-
性能优化:
- 优先使用sqrMagnitude代替magnitude
- 避免频繁创建新的Vector3实例
- 合理使用向量缓存
-
精度控制:
- 使用Mathf.Approximately比较浮点数
- 注意向量运算的精度损失
-
常见陷阱:
- 注意向量归一化时的零向量情况
- 注意叉乘的方向性
- 注意角度计算的范围限制