Unityでカメラが壁に遮られキャラクターが見えなくなったらカメラを移動させる

記事内に広告が含まれています。

Unity内のステージで広い草原であれば考えなくてもいい事なんですが、ゲームステージに建物や山のような地形があった場合、カメラとキャラクターの間に何らかの障害物が映り、キャラクターが見えなくなってしまう事があります。

こうなるとキャラクターが今どこを動いているのかわからなくなってしまいます。

カメラ12

そこで今回は障害物がカメラと主人公の間に入った時にカメラを移動させ、常に主人公が写るようにしていきます。

スポンサーリンク

キャラクターが壁のせいで見えなくなる時の対処

障害物が邪魔で主人公が見えなくなった時はカメラが自動で位置を変えキャラクターを表示するか、またはキャラクターが狭い建物に入った時(入口のOnTriggerEnterで判定)にあらかじめ設定してあった別のカメラの表示に切り替えて、キャラクターが見えなくならないようにするという方法があります。

カメラを切り替える方法はメインカメラで表示していたものを固定のカメラに切り替え、メインカメラをOffにするという機能を追加すればいいんですが、

カメラの切り替えに関しては

Unityでカメラをスクリプトから切り替えられるようにする
Unityで二つのカメラをスクリプトから切り替えるようにし、視点変更機能を作成してきます。

を参照してください。

今回は自動でカメラの位置を変える機能を追加してみます。

↑のような感じで主人公とカメラの間に壁や敵が入った場合はその位置にカメラを移動させています。

狭い部屋などを主人公キャラクターが移動する事がある時は便利ですね。(^^)/

今回のサンプルでは壁だけでなく敵も障害物と同じ対象にしてますが、対象はレイヤーの指定をするかしないかだけなのですぐ変更出来ます。

キャラクターとカメラの間に障害物があるかを調べるスクリプトの作成

カメラとキャラクターの間に障害物があるかどうか判定し障害物があった時はカメラの位置を移動します。

障害物があるかどうか調べる為にPhysics.Linecastを使います。

Linecastは始点から終点にレイを飛ばして、他のゲームオブジェクトと衝突するかどうかを調べる事が出来ます。

charaLookAtPositionは主人公の子要素に配置したカメラが見るポイントをインスペクタで設定します。

障害物と判定するゲームオブジェクトのレイヤーはインスペクタで設定出来ます。

UpdateメソッドではPhysics.Linecastを使ってcharaLookAtPositionからカメラまでレイを飛ばして、指定したレイヤーと衝突しているかどうかを調べます。

衝突した位置はhit.pointで得られますが、この位置はワールド空間の位置なのでカメラ位置もtransform.positionの位置に設定します。

いきなりカメラが移動するとパッと切り替わってしまう為、Vector3.Lerpを使って滑らかに移動するようにします。

障害物と接触していた場合に滑らかに移動させると障害物の中身が見えてしまうので、障害物と接触していた時は一気にぶつかったポイントにカメラを移動させています。

レイが衝突していなければカメラのローカル位置を元の位置に滑らかに移動するようにします。

カメラの回転ではQuaternion.Slerpを使って『現在の角度』から『カメラからキャラクターのカメラが見る位置の方向の角度』へと徐々に回転させています。

Debug.DrawLineで視覚的にレイを確認

Debug.DrawLineを使用するとシーンビューで視覚的にレイの様子を確認する事が出来ます。

↑の場合は主人公の子要素にカメラが見るポイントを作成し、その位置からカメラ位置にレイを表示します。

レイの色を赤色、レイを表示する間隔を0(0なので常に表示)、最後の条件はレイの前に他のゲームオブジェクトがあった場合に隠されているレイを表示するかどうかです。

カメラ13

上のような感じで通常表示されるカメラ位置とは違う位置で表示され、壁でキャラクターが見えなくなる事はなくなりました。

これで自動でカメラの位置を変更する事が出来るようになりました。
初期のバイオみたいに、ある部屋はこの視点で、ある通路はこの視点で、みたいのもレトロな感じで面白そうですけどね。

カメラが自動でキャラクターを映す機能を作り終えて

カメラがうまくキャラクターを表示してくれず色々やっていた記憶がありますが、単純に処理を間違えていました・・・(^_^;)
レイを飛ばす方向を

『RayCastゲームオブジェクトからキャラクター』へ飛ばしていましたが、実際に壁が間に入ったかどうかは

『キャラクターからRayCastゲームオブジェクト』へ飛ばす必要があります。

なぜならRayCastからレイを飛ばすとRayCast側の壁を接触場所にしてしまって結局キャラクターを映せないという事になります。
キャラクターからRayCastの方にレイを飛ばせばキャラクター側の壁が接触場所になるので必ずキャラクターを映してくれます。

これでちゃんとキャラクターを映してくれると思います。

以前書いていた不要な処理は混乱を招くので削除しました。

タイトルとURLをコピーしました