unity中3D数学相关类、属性、方法、用途总结+超级综合的案例

这篇内容将与unity中移动旋转的控制密切相关,有关移动旋转

主要涉及到的类:Vector3,Mathf,Quaternion,Transform。

1.三角函数

其实关于三角函数的使用并不会很常见,因为unity已经给我们提供了很多方便计算向量夹角、角度范围的方法,可以直接调用,除非我们想自己去封装一些特殊的需求,否则用unity提供给我们的方法就很简便了。但是只有理解了原理才能够明白何时怎么用,所以还是要看看其中的数学原理。

(1).角度的度量方式

  • 角度:弧长等于圆周长1/360时对应的角度为1°;
  • 弧度:弧长等于半径时为1弧度,比如π就是半圈,周长为2πr;
  • 角度和弧度之间的转换:
    在这里插入图片描述

(2).三角函数:

在这里插入图片描述

(3).反三角函数:

在这里插入图片描述

2.向量

(1).向量常用属性:

  • Vector3.magnitude 向量长度 Vector3.sqrMagnitude向量的平方长度
    向量 v 的大小以Mathf.Sqrt(Vector3.Dot(v, v)) 方式进行计算。 但是,Sqrt 计算相当复杂, 执行时间比普通算术运算要长。计算平方数代替使用 magnitude 属性要快得多 - 计算基本相同,只是消除了执行缓慢的 Sqrt 调用。如果您只将大小用于比较距离的目的,则也可以将平方数与距离的平方进行比较, 因为这种比较也会给出相同的结果。
  • Vector3.normalized 标准化向量(单位向量)

(2).点乘: Vector3.Dot

public static float Dot (Vector3 lhs, Vector3 rhs);

在这里插入图片描述
应用:

在这里插入图片描述

(3).叉乘:Vector3.Cross

public static Vector3 Cross (Vector3 lhs, Vector3 rhs);

在这里插入图片描述
应用:
a.创建垂直于lhs和rhs构成的平面的向量=>自己创建坐标系。
b.判断lhs和rhs的相对位置=>根据正负判断顺逆时针关系。

(4).Vector3.Angle 计算向量间夹角

public static float Angle (Vector3 from, Vector3 to);
返回的角度为两个向量之间的无符号角度。也就是说,使用两个向量之间的两个可能角度中的较小者。结果永远不会超过 180 度。
这要比我们自己用点乘和三角函数求夹角快多了。

3.欧拉角transform.eulerAngles

欧拉角在航空领域叫做导航角,就像下图这个飞机,可以抬头低头(绕x轴),左右摇摆(绕z轴),改变前进方向(绕y轴),非常便于理解。
在这里插入图片描述

(1).优点:

• 仅使用三个数字表达方位,占用空间小。
• 沿坐标轴旋转的单位为角度,符合人的思考方式。
•任意三个数字都是合法的,不存在不合法的欧拉角。

(2).缺点:

a.方位的表达方式不维一:

• 对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角位移是否相同。正如官方描述的这样:

以欧拉角表示的旋转(以度为单位)。 x、y 和 z 角表示一个围绕 Z 轴旋转 z 度、围绕 X 轴旋转 x 度、围绕 Y 轴旋转 y度的旋转。 仅使用该变量读取角度和将角度设置为绝对值。不要增大角度,因为当角度超过 360 度时,操作将失败。 请改用Transform.Rotate。

• 例如:

角度0,5,0与角度0,365,0
角度0,-5,0与角度0,355,0
角度250,0,0与角度290,180,180

b.万向节死锁:

• 物体沿X轴旋转±90度,自身坐标系Z轴与世界坐标系Y轴将重合,此时再沿Y或Z轴旋转时,将失去一个自由度。
• 在万向节死锁情况下,规定沿Y轴完成绕竖直轴的全部旋转,即此时Z轴旋转为0。
在这里插入图片描述

4.四元数:Quaternion qt = transform.rotation;

在这里插入图片描述

(1).优点:

避免万向节死锁
• this.transform.rotation *= Quaternion.Euler(0, 1, 0); 可使物体沿自身坐标Y轴旋转
• this.transform.Rotate(Vector3 eulerAngles)内部就是使用四元数相乘实现

(2).缺点:

• 难于使用,不建议单独修改某个数值。
• 存在不合法的四元数。

(3).基本使用和运算:

a.从四元数中读取欧拉角:Quaternion.eulerAngles
b.四元数左乘向量,表示将该向量按照四元数表示的角度旋转:

Quaternion.Euler : public static Quaternion Euler (float x, float y, float z);
返回一个围绕 Z 轴旋转 z 度、围绕 X 轴旋转 x 度、围绕 Y 轴旋转 y 度的旋转。
eg:

// A rotation 30 degrees around the y-axis
Quaternion rotation = Quaternion.Euler(0, 30, 0);

在这里插入图片描述

c.四元数之间相乘

• 两个四元数相乘可以组合旋转效果。
• 例如:

Quaternion rotation01 =Quaternion.Euler(0, 30, 0) * Quaternion.Euler(0, 20, 0);
Quaternion rotation02 = Quaternion.Euler(0, 50, 0);

rotation01 与 rotation02 相同。

5.重要应用实例:

在吃鸡、CS中手雷都是致命武器,但是我们会发现不同情况下手雷的伤害却不同,可能会和爆炸点距离、掩体、装备好坏有关,这里我们就以处理掩体和手雷爆炸造成伤害的方式,我们研究的当然是最尴尬的情况:
在这里插入图片描述
也就是要判断玩家是否完全躲在了掩体后面,显然这就和切点c的位置密切相关了,如果c和炸弹的连线会经过掩体,那么玩家就完全躲了进去。

那么问题就变成了如何计算切点c的位置:
a.我们已知的:玩家坐标,炸弹坐标,玩家半径
b.可以通过向量运算求出来的:

//向量a:玩家指向炸弹的向量
Vector3 a = 炸弹.tranform.position - 玩家.tranform.position;
//向量b :向量a在玩家部分的向量
Vector3 b = a.normalized * 玩家半径;
//图中的夹角:利用反余弦(这时可就用不了Vector3.angle了!!!)
float angle = Mathf.Acos( 玩家半径 / a.magnitude ) * Mathf.Red2Deg;

c.最精髓的一步来了:
切点C的坐标:就是向量b旋转到圆心和切点方向时加上玩家坐标(向量是从玩家指向外界的)。

Vector3 c = 玩家.tranform.position + Quaternion.Euler(0,-angle,0) * b;

当然这只是图示的情况,如果露出的在下面那就是:

Vector3 c = 玩家.tranform.position + Quaternion.Euler(0,angle,0) * b;
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值