先日三人称視点の3Dアクションゲーム用のカメラを自作していたら、カメラが壁を貫通してしまう問題が発生して解決するのに少し苦労しました。
この「カメラ貫通問題」は割とありがちだと思うので、おそらく他の皆さんも多少は悩むのではないでしょうか?そこでこの記事では「カメラが壁を貫通しないようにする方法」を簡単にメモしておきます。
Rayを使って壁の有無をチェックする
カメラが壁を突き抜けないようにするやり方は何通りかあると思いますが、ここでは手軽な「Ray(レイ)」を使った方法をご紹介しますね。
Rayを使った壁チェックの考え方
まずはこの方法の考え方についてです。下の画像をご覧ください。
考え方はシンプルで、
- 壁がないと仮定した場合のカメラの座標を算出する。
- ターゲットの座標から1の座標に向かってRayを飛ばす(※このとき、Rayが壁だけに当たるようにレイヤーマスクを設定しておく)。
- もしRayが壁に当たった場合、RaycastHit.pointで当たった座標を取得する。
- 3の座標にカメラを移動させる。
といった流れになります。
ただしこの方法だと、壁とターゲットの距離が近い場合にカメラがターゲットに近づきすぎることがあるのでその点はご注意ください。
壁チェック用メソッドの例
では実際の壁チェック用メソッドの例を掲載しておきます。必要な変数を
- targetPosition:ターゲットの座標
- desiredPosition:壁がなかった場合のカメラの移動先
- wallHit:壁に当たった時のレイキャストの情報
- wallLayers:壁のレイヤーマスク
- wallHitPosition:レイが当たった座標
とすると、壁チェック用のメソッド「WallCheck」は次のようになります。
protected bool WallCheck() { if (Physics.Raycast(targetPosition, desiredPosition - targetPosition, out wallHit, Vector3.Distance(targetPosition, desiredPosition), wallLayers, QueryTriggerInteraction.Ignore)) { wallHitPosition = wallHit.point; return true; } else { return false; } }
WallCheckの戻り値がtrueの時、カメラの座標をwallHitPositionにすればカメラが壁にめり込まないようになります。