カメラの壁めり込み対策【ゲーム開発日記】

UnityでTPS型のキャラ移動を作る記事の続きです。
前回の記事まででカメラは回転できるようになりましたが、カメラが壁にめり込むと世界の裏側が見えてしまいます。
できるだけ壁の裏は見えないようにしたいので、今回の記事ではカメラが壁にめり込まないように対策をしていこうと思います。

前回の記事はこちらです!↓

壁めり込み対策の方法

プレイヤーがカメラの操作をできるゲームでカメラを勝手に動かしてしまうのって割と難しいことなんじゃないかなと思います。
一般のゲームを考えても、壁めり込みの対策方法は1つではなくそれぞれ色々工夫している気がします。
めり込むオブジェクトがある場合には上下方向だけ動いて避けるとか、プレイヤーキャラに近づくように避けるとか、特定のめり込まれたくない位置にキャラが入ったらプレイヤーの操作を切ってスクリプトから動かすとかの方法が多いのかなと思います。

今回は上下回転の機能をつけてあるので「めり込むオブジェクトがある場合はプレイヤーキャラに近づくように避ける」にしてみようと思います。

めり込みを判定する

めり込み対策で確保したい視界の範囲判定はPhysics.SphereCastを使うようにしました。
Raycastだと細すぎる気がしたのでSphereにしてみましたが、扱いやすいのはRaycastかなと思います。ゲームの仕様上どのくらい視界の確保が重要なのかで決めるとよさそうです。

SphereCastをプレイヤーキャラの頭部あたりからカメラの方向に飛ばすようにします。
黄色い丸がレイのヒットした場所です。良い感じに壁の位置が取れているみたいですね。

レイがヒットするレイヤーは好きなように指定できるので、敵Mobや小さい構造物をレイヤー分けして除外することもできます。レイヤーを無駄に増やしすぎず上手に区分する必要はありそうですが…。

動きの処理

オブジェクトの動きとしてはRigidbodyを使わずTransformでローカル座標で移動することにします。
必要なのは前後の動きだけで回転の動きとは独立しているのと、Rigidbodyで動かすとおそらく遠心力がかかって思い通りの前後の動きはできないだろうというのが理由です。

SphereCastでの距離

カメラが前方に移動する距離の計算について上から見た図を作ってみました。
水色の円がプレイヤーキャラ、黄色がSphereCastの範囲です。壁接触があった際にカメラが前に移動したら壁を抜ける距離は青矢印です。

もし正確に青矢印を算出するのなら、Mathf.Sqrt(Vector3.SqrMagnitude(カメラ位置 , 接触位置) – SphereCastの半径2 )になるかと思います。
また、カメラ後部の範囲に接触した際は前に進む必要がないので除外する必要があります。
Vector3.Angle(カメラの前向きのベクトル,カメラから接触位置方向のベクトル)が90度以上だったら後ろです。

ただ色々試してみたのですが、SphereCastの半径があまり太くないならそこまでやらなくてもいい気がします。
プレイヤーキャラもカメラも毎フレーム動いているので、ざっくりでも不自然な感じはなさそうです。
なので、僕はシンプルにVector3.Distance(カメラ位置 , 接触位置)を前方向に進む距離としてしまいました。

なおVector3.Distance / Vector3.Magnitude / Mathf.Sqrt / Mathf.Powなどの関数は「平方根の計算は重めの処理なので多用しない方がいい」とよく言われているかと思いますが、今回はゲームの中でも超重要なカメラの動き&処理回数も毎フレームで1回だけなので気にせず使います。

ここまでの結果

自分がイメージしていた基本的な動きとしては大体OKです。
まだ算出した座標に直接移動するようにしている状態なので、接触していない時はカメラの最大距離・接触している時は壁にぴったりの位置にワープ移動してカクついてしまいます。

加減速をつける

カメラの移動距離が長い場合はスピードを速く、短い場合はゆっくりめに動かして滑らかな感じにしたいです。
そこで移動を毎フレーム「目的地点までの距離の一定割合だけ進む」という風にしてみます。

これは進む距離に割合0.2fを乗算するようにしてみたものです。
割と滑らかに動いているんじゃないかなと思いますが、ゆっくりになればなるほど壁の裏が見えるので実際に作るステージと合わせて微調整が必要そうですね。

更にイージングを使って離れた距離での移動速度を上げたい場合は、先ほど固定値で0.2fにした割合をイージングして可変にすると良いかと思います。
イージングについては別の記事にまとめているのでそちらも見てみてください。

カメラの描画範囲

Unityのカメラの初期設定で、オブジェクトがある程度カメラに近い場合に描画がされなくなるようになっています。
壁の向こう側が見えてしまう原因の一つです。

カメラのClipping Planesの値で変更できるので、気になる場合は適宜調整します。
あんまり近くにするとプレイヤーキャラや敵Mobなど構造物以外の邪魔なオブジェクトに視界が遮られることにもなるので、ゲームに合わせて調整が必要です。

シェーダーの方でカメラが近い場合にオブジェクトを半透明にしたりもできるので、Clipping PlanesのNearは0にした上で特定のオブジェクトのシェーダーだけ半透明にさせる方法もあるのかなと思います。

ここまでの仕上がり

前進する時と後退する時でスピードが変わるようにしてみました。
完全に壁裏を見せないというのはどんなゲームでも難しいと思うので、まあこのくらいかなという感じです。
突き抜けて見えそうな箇所にはテクスチャを貼らない・黒い色で塗りつぶした裏地を置いてスカイボックスを見えなくする、等の工夫も必要になるのかなと思いました。

あとは見た目がカプセル状なので分かりづらいですが実はキャラが回転していないので、次の記事ではキャラの回転の処理を作っていこうと思います。

次回の記事はこちら↓

シェアする

「Unity」の記事

もっと読む>>

最新記事

もっと読む>>