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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Author: 半夜逃避自己該做的東西其實自己已經火燒屁股的S🐺
// p.s. 我沒有twitter,去google找的話找到的不是我嘿
// 但是我還真的有用S🐺的名義活動,運氣好的話在世界的某處也許可以捕捉到我吧(ry

public class RelativeVelocityDemo : MonoBehaviour
{
    #region Unity Methods

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
            Translate(Vector3.forward);

        if (Input.GetKeyDown(KeyCode.S))
            Translate(Vector3.back);

        if (Input.GetKeyDown(KeyCode.D))
            Translate(Vector3.right);

        if (Input.GetKeyDown(KeyCode.A))
            Translate(Vector3.left);

        if (Input.GetKeyDown(KeyCode.Space))
            Translate(Vector3.up);

        if (Input.GetKeyDown(KeyCode.LeftShift))
            Translate(Vector3.down);

        if (Input.GetKeyDown(KeyCode.LeftControl))
            Translate(new Vector3(Random.Range(0f, 10f), Random.Range(0f, 10f), Random.Range(0f, 10f)));
    }

    #endregion

    #region Methods

    /// <summary>
    /// 假定上一個frame我進行了某種形式的位移
    /// </summary>
    /// <param name="v">實際的位移量</param>
    void Translate(Vector3 v)
    {
        var lastPos = transform.position;
        var lastRot = transform.rotation;

        transform.Translate(v, Space.Self); //進行位移

        var nowPos = transform.position;
        var nowRot = transform.rotation;

        Debug.LogFormat("Original transform velocity: {0}", v);
        Debug.LogFormat("lastPos: {0}, lastRot: {1}, nowPos:{2}, nowRot:{3}", lastPos, lastRot, nowPos, nowRot);

        Vector4 dv = nowPos - lastPos; //其實是Vector3,但是直接轉成Vector4來用
        Vector4 lastForward = lastRot * Vector3.forward;
        Vector4 lastUp = lastRot * Vector3.up;
        Vector4 lastRight = lastRot * Vector3.right;

        // 最後一個是V4(0, 0, 0, 1)是基於矩陣運算的特性決定的,不這樣的話會什麼都算不出來
        Matrix4x4 matrix = new Matrix4x4(lastRight, lastUp, lastForward, new Vector4(0, 0, 0, 1));

        //這個如果算不出來他會給你0就是了,要小心(但理論上應該不會算不出來就是了)
        //利用矩陣特性Ax = y => A^-1 * y = x來求解的做法
        //為什麼可以這樣做去查反(逆)矩陣的特性吧
        Vector3 relativeVelocity = matrix.inverse * dv; //其實算出來是Vector4,但是轉型回Vector3(因為w沒有用到也沒有意義)

        //Debug.LogFormat("Vr: {0}, Vu: {1}, Vf{2}", lastRight, lastUp, lastForward);
        Debug.LogFormat("dv: {0}", dv);
        //Debug.LogFormat("matrix: \n{0}\ninverse: \n{1}", matrix, matrix.inverse);
        Debug.LogFormat("Relative Velocity {0}", relativeVelocity); //這應該就是你要的東西了
    }

    #endregion
}