引擎:实战API

一、三维数学

1、向量

一个数字列表,表示各个维度上的有向位移;

一个有大小有方向的物理量(大小为模长,方向描述空间中向量的指向);

模长

方向

 点乘

根据三角函数cos$ = x / |A|    所以如上图 x = |A| cos$ 

叉乘

由于

向量减

向量加

向量缩放

2、函数

三角函数

反三角函数

 角度与弧度

3、旋转

欧拉角

四元数

二、Lerp-线性插值-平滑运动

1、减速插值

A到B点的1/3在A';剩余A'到B的1/3在A'',以此类推直到移动到B点的过程叫Lerp线性插值的效果,且这个过程呈现减速趋势。

2、变速插值

物体先向前走,再向后走,最后向前走

三、Quaternion-四元数-旋转

1、Quaternion.identity

归一化的处理,就是把rotation改成 欧拉角表示为(0,0,0)

public class ExampleClass : MonoBehaviour {
    void Example() {
        transform.rotation = Quaternion.identity;
    }
}

2、Quaternion.eulerAngles

把四元数转成欧拉角

public Quaternion rotation = Quaternion.identity;
    void Example() {
        rotation.eulerAngles = new Vector3(0, 30, 0);
        print(rotation.eulerAngles);// 结果是 (0.0, 30.0, 0.0)
    }

3、Quaternion.SetFromToRotation

通过开始位置到终点位置来创建一个rotation

比如做了这些绑定, 每一帧都平滑的设置位移,并且根据当前帧的位移,转一下物体,最后效果是物体转着圈的转到了目标位置

//This is the Transform of the second GameObject
    public Transform m_NextPoint;
    Quaternion m_MyQuaternion;
    float m_Speed = 1.0f;

    void Start()
    {
        m_MyQuaternion = new Quaternion();
    }

    void Update()
    {
        //Set the Quaternion rotation from the GameObject's position to the next GameObject's position
        m_MyQuaternion.SetFromToRotation(transform.position, m_NextPoint.position);
        //Move the GameObject towards the second GameObject
        transform.position = Vector3.Lerp(transform.position, m_NextPoint.position, m_Speed * Time.deltaTime);
        //Rotate the GameObject towards the second GameObject

        transform.rotation = m_MyQuaternion * transform.rotation;

        Debug.Log(transform.rotation.eulerAngles);
    }

4、Quaternion.Angle

两个四元数间的角度

public Transform target;
    void Update() {
        float angle = Quaternion.Angle(transform.rotation, target.rotation);
          Debug.Log(angle);
    }

原角是(0,60,0) target角是 (0,30,0)
输出是 30

5、Quaternion.Euler

应该是比较常用的方式,将欧拉角转化为四元数,然后可以进行旋转。

//将8个红色关节的旋转信息赋值给8个模型骨骼
for (int i = 0; i < point.Length; i++)
{
       bone[i].rotation = Quaternion.Euler(point[i].transform.eulerAngles.x, point[i].transform.eulerAngles.y, point[i].transform.eulerAngles.z);
}

6、Quaternion.FromToRotation

创建一个从开始方向到结束方向的旋转

创建一个从开始方向到结束方向的旋转 (0,0,0)

void Awake() {
        print(transform.forward);
        transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);
        print(transform.rotation.eulerAngles);
}

这个是从 (0,1,0)方向 转到 (0,0,1) 得到的结果是 (90,0,0) 绕x轴转90度的旋转

7、Quaternion.Inverse

返回一个相反的旋转

void Awake() {
transform.rotation = Quaternion.Inverse(transform.rotation);
        print(transform.rotation.eulerAngles);
}

预先转的是 (0,60,0)

inverse之后是 (0,300,0) 也就是 (0,-60,0)

8、Quaternion.Lerp

线性插值( Linear Interpolation)
计算角度ab间的差值,并且之后规范结果,参数t是在0到1之间。
lerp比slerp快 但是如果旋转角度离得远看起来会很糟糕。

9、Quaternion.Slerp

球面线性插值(Spherical linear interpolation,通常简称Slerp),是四元数的一种线性插值运算,主要用于在两个表示旋转的四元数之间平滑插值。

10、Quaternion.LookRotation

将方向转化为旋转角度:传入一个方向将返回一个旋转角,当某个物体被施加这个旋转角后,这个物体的forward方向将指向传入的方向。

在场景中新建一个正方体和球体,用LookRotation方法将正方体“看向”球体,并绘制输出3条射线

本文中所有脚本挂载在正方体

public class Test: MonoBehaviour{
    public Transform sphere;

    void Update(){
        // 正方体指向球体的向量dir = 球体坐标 - 正方体坐标
        Vector3 dir = sphere.position - transform.position;  
        // 创建一个 使正方体“看向”球体的旋转角
        Quaternion ang = Quaternion.LookRotation(dir);  
        transform.rotation = ang;
        // 绘制正方体forward方向
        Debug.DrawRay(transform.position, transform.forward * 100, Color.blue);  
        // 绘制向量dir
        Debug.DrawRay(transform.position, dir, Color.green);  
        // 即:绘制正方体的旋转轴
        Debug.DrawRay(transform.position, ang.eulerAngles, Color.red);  
    }
}

运行场景,第一个参数解析:

Vector3 dir = sphere.position - transform.position;
Quaternion ang = Quaternion.LookRotation(dir);

绿色射线:以向量dir为方向。蓝色射线:以正方体forward为方向,与绿色射线部分重合。红色射线:以四元数ang为方向,直接绘制看似“奇怪”(实则正方体的旋转轴线)。

 
传入一个Vector3方向将返回一个Quaternion旋转角,某个物体被施加这个旋转角后,这个物体的forward方向将对齐至传入的Vector3方向。

场景升级,第二个参数解析
LookRotation的第二个参数upwards影响物体的up和right的方向(即影响Z轴旋转),继上续代码即:
transform.right == Vector3.Cross(sphere.postion - transform.postion, upwards).normalized;
transform.up == Vector3.Cross(sphere.postion - transform.postion, transform.right).normalized;

transform.rotation = Quaternion.LookRotation(sphere.position - transform.position, cone.up);  //第二个参数cone.up将影响正方体的right、up方向

调节圆锥的Rotation属性正方体的right、up方向受到了影响,核心代码如上。
圆锥起点绿色射线:方向为圆锥的+Y轴,即cone.up方向。圆锥起点红色射线:方向为Vector3.Cross(transform.forward, cone.up)。
仔细看上图,无论怎么旋转圆锥,圆锥起点红色射线和正方体红色箭头(right方向)始终方向相同、保持平行。
 
若指定第二个参数upwards,则物体的right方向将对齐至‘第一个参数’与‘第二个参数’的叉乘方向。

补充:代码实现LookRotation()

    public Quaternion LookRotation(Vector3 forward)
    {
        float x = Mathf.Acos(Mathf.Sqrt((forward.x * forward.x + forward.z * forward.z) / (forward.x * forward.x + forward.y * forward.y + forward.z * forward.z))) * Mathf.Rad2Deg;
        if (forward.y > 0) x = 360f - x;

        float y = Mathf.Atan2(forward.x, forward.z) * Mathf.Rad2Deg;
        if (y < 0 || forward.x < 0) y += 180f;

        return Quaternion.Euler(x, y, 0f);
    }

这样一个简单LookRotation就实现了,如果还需要实现带第二个参数的方法,只需求出transform.up与LookRotation()返回值之间的夹角就行了。已知两向量求其夹角的公式:


但可惜LookRotation()方法内部没法直接拿到transform.up的值,所以我们只能通过数学方式间接的求出transform.up。
初始时,transform.up、LookRotation()返回值、Y轴一定是共面的,且transform.up ⊥ LookRotation()返回值,根据这两个条件联立方程我们就可以准确求出transform.up的值。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不努力谁会可怜你?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值