第08回 3D探索1
2 / 4 カメラ基準の方向をNavMeshの歩行へ渡す
このステップの目的
入力から水平な方向を求め、速度と時間を掛けて移動量へ変換する
編集する関数
ExplorerMotor.Direction(Vector2 input, Transform camera)は入力とカメラを受け取り、水平な方向を返します。Walkはその方向に速度と経過秒数を掛け、NavMeshAgentへ渡します。入力取得とモデルの回転は接続済みの補助処理を使います。
水平な前と右を作る
csharp
Vector3 forward = Vector3.ProjectOnPlane(camera.forward, Vector3.up).normalized;
Vector3 right = Vector3.Cross(Vector3.up, forward);
return Vector3.ClampMagnitude(forward * input.y + right * input.x, 1f);ProjectOnPlaneは、カメラの前方向を水平面へ投影します。投影後の長さを1へそろえる正規化によって、カメラを下へ傾けても歩行速度が変わらなくなります。今回は上下角を制限し、真上・真下を向く状態を作りません。
Crossは二方向に直交する方向を求める外積です。この順序では上方向と水平な前方向から右方向を作ります。前が(0, 0, 1)なら右は(1, 0, 0)です。詳細な外積の計算は補助処理として扱い、まずこの入力と結果を確かめます。
右と前を入力の割合で合成すると、斜め入力(1, 1)の長さは約1.41になります。ClampMagnitudeは長さが1を超える場合だけ1に制限します。常に正規化する場合と異なり、スティックの小さい入力の強さは残ります。
| 入力 | カメラがZの正方向を向く場合の結果 |
|---|---|
| (0, 0) | (0, 0, 0):停止 |
| (0, 0.5) | (0, 0, 0.5):半分の強さ |
| (1, 0) | (1, 0, 0):右 |
| (1, 1) | 約(0.707, 0, 0.707):長さ1の斜め |
1フレーム分の移動量にする
csharp
if (!agent.isOnNavMesh) return;
Vector3 direction = Direction(axes, view);
float speed = sprint ? runSpeed : walkSpeed;
agent.Move(direction * speed * dt);speedの単位は1秒あたりの距離、dtはこのフレームの秒数です。速度2、dtが0.02、入力の長さが1なら移動要求は0.04になります。Moveへ渡すのは目的地ではなく移動量です。歩ける領域によって実際の位置変化が制限されるため、第09回の表示には実際の位置変化から求めたSpeedを使います。
チェックリスト
- ゼロ入力、半分の入力、斜め入力を表と比較した
- カメラを90度回して移動方向を確認した
- 速度と経過時間から移動量を計算できる