2020/08/19 修正範例錯誤。
 
 
在遊戲中,很常會需要兩個座標點間的方向向量,例如玩家與目標點或者 NPC 位置之間的方向向量。
有了方向向量才能夠控制玩家往目標點前進。
 
 
以下教學會用到取兩點距離的算法,這篇文章有詳細說明 "求單一座標點或兩座標點之間的距離長度"。
 
 
取得兩點間的方向向量做法為:
 
// 假如 pos1 為玩家位置, pos2 為目標點位置
Vector2 pos1 = new Vector2( 10.0f, 15.0f );
Vector2 pos2 = new Vector2( 15.0f, 20.0f );

// 移動速度
float speed = 2.0f;

// 目標位置 - 玩家位置 = 玩家到目標點之間的方向向量
// directionVector 結果為 (5, 5)
Vector2 directionVector = pos2 - pos1;

// 取得距離長度, 這邊要將方向向量調整到跟移動速度一樣, 
// 最後的 directionVector 為我們需要的方向向量, 可以直接將該值累加到玩家位置上
float distance = directionVector.magnitude;
directionVector *= (distance == 0.0f ? 0.0f : speed / distance);

// 讓玩家朝著目標位置前進
pos1 += directionVector;
 
Vector3 的做法也一樣,只需要將 Vector2 調整為 Vector3 就可以了。
 
 
以下為詳細解說:
 
方向向量計算公式如下

image01.jpg

 
 
剛開始我們的做法是這樣的
 
// 假如 pos1 為玩家位置, pos2 為目標點位置
Vector2 pos1 = new Vector2( 10.0f, 15.0f );
Vector2 pos2 = new Vector2( 15.0f, 20.0f );

// 目標位置 - 玩家位置 = 玩家到目標點之間的方向向量
// directionVector 結果為 (5, 5)
Vector2 directionVector = pos2 - pos1;
 
但是這樣有個問題,那就是沒辦法控制玩家的移動速度,我們知道了方向向量為 (5, 5)。
所以玩家位置 (10, 15) + 方向向量 (5, 5) = 目標位置 (15, 20)。
結果就是只移動一步就到目標位置了,所以這邊我們繼續做一些改良。
 
 
我們將方向向量的值壓縮在 1 左右,簡單的說就是移動距離為 1。
若方向向量太大超過 1 了,則會被壓縮到 1 左右
若方向向量太小不足 1 時,則會被提高到 1 左右
 
// 假如 pos1 為玩家位置, pos2 為目標點位置
Vector2 pos1 = new Vector2( 10.0f, 15.0f );
Vector2 pos2 = new Vector2( 15.0f, 20.0f );

// 目標位置 - 玩家位置 = 玩家到目標點之間的方向向量
// directionVector 結果為 (5, 5)
Vector2 directionVector = pos2 - pos1;

float distance = directionVector.magnitude;

if ( distance == 0.0f ) 
{
    // 距離為 0, 那表示不用移動了, 已經在目標點上了
    directionVector *= 0.0f;
}
else
{
    directionVector *= (1.0f / distance);
}
 
directionVector 最後結果為 (0.707, 0.707) 左右,而 (0.707, 0.707) 這個位置換算出來的距離長度相當為 1 左右。
 
 
上面作法已經將移動向量調整到 1 左右了,接下來可以乘上想要的移動速度
 
// 假如 pos1 為玩家位置, pos2 為目標點位置
Vector2 pos1 = new Vector2( 10.0f, 15.0f );
Vector2 pos2 = new Vector2( 15.0f, 20.0f );

// 移動速度
float speed = 2.0f;

// 目標位置 - 玩家位置 = 玩家到目標點之間的方向向量
// directionVector 結果為 (5, 5)
Vector2 directionVector = pos2 - pos1;

float distance = directionVector.magnitude;

if ( distance == 0.0f ) 
{
    // 距離為 0, 那表示不用移動了, 已經在目標點上了
    directionVector *= 0.0f;
}
else
{
    directionVector *= (1.0f / distance);
}

directionVector *= speed;
 
directionVector 最後結果為 (1.414, 1.414) 左右,而 (1.414, 1.414) 這個位置換算出來的距離長度,就是我們設定的 2 左右。
 
 
但剛剛我們有提到,我們將速度調整到 1 左右,再去乘上速度,所以這邊我們其實是可以直接針對速度做調整的!
所以我們針對算法再做簡化,最後結果為
 
// 假如 pos1 為玩家位置, pos2 為目標點位置
Vector2 pos1 = new Vector2( 10.0f, 15.0f );
Vector2 pos2 = new Vector2( 15.0f, 20.0f );

// 移動速度
float speed = 2.0f;

// 目標位置 - 玩家位置 = 玩家到目標點之間的方向向量
// directionVector 結果為 (5, 5)
Vector2 directionVector = pos2 - pos1;

// 取得距離長度, 這邊要將方向向量調整到跟移動速度一樣, 
// 最後的 directionVector 為我們需要的方向向量, 可以直接將該值累加到玩家位置上
float distance = directionVector.magnitude;
directionVector *= (distance == 0.0f ? 0.0f : speed / distance);
 
directionVector 最後結果為 (1.414, 1.414) 左右,而 (1.414, 1.414) 這個位置換算出來的距離長度,就是我們設定的 2 左右。
 
 
arrow
arrow
    文章標籤
    Unity C# Vector
    全站熱搜

    岳 發表在 痞客邦 留言(0) 人氣()