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 就可以了。
以下為詳細解說:
方向向量計算公式如下
剛開始我們的做法是這樣的
// 假如 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 左右。
文章標籤
全站熱搜
留言列表