今回はUnityで銃を構えた時にバイオハザードのようにカメラを移動させキャラクターに寄せる機能を搭載してみます。
カメラをキャラクターに寄せない場合キャラクターの手元がよく見えないのと、元々のカメラの視点によりますが、カメラがキャラクターの後ろ側にあった場合、キャラクターの少し左側の敵を攻撃しようと狙いを移すと、キャラクターと被って狙っている位置がわかりづらくなります。
そういった事がないように銃を構えた時はカメラをキャラクターのすぐ後ろ辺りに移動し、全体を見渡せるようにします。
今回の機能を作成すると、
↑のような感じで銃を構えた時にカメラをキャラに寄せる事が出来ます。
以前作成した壁対策用のカメラの移動機能と併用出来るようにスクリプトに処理を追加していきます。
カメラをキャラに寄せるようにした場合はキャラクターの上半身の移動は左には動かさず下は以前よりも制限を加えた方がいいかもしれませんね。
まったく見えない場所を攻撃出来るようになってしまいます。(^_^;)
今回の機能を搭載する前に作っておかなければいけない機能
今回の機能を搭載するにあたって
を作成しておいてください。
また
を作っておくと狙いを定める事が出来ます。
今回はキャラクターを写すカメラの間に壁が入った時のカメラの動き
の記事で作成したAutoRotateCameraスクリプトに処理を追加する形になりますが、AutoRotateCameraを使わない場合は別途スクリプトを作成し修正する事でも同じように出来ます。
ここまでの機能が出来ていればカメラをキャラクターに寄せる機能はさほど難しくないと思います。
カメラを動かすスクリプト
キャラクターとともに動くカメラMainCameraはキャラクターの子要素に置き、AutoRotateCameraに処理を追加します。
カメラを動かす概要と設定項目
壁がカメラとキャラクターとの間に合った場合、カメラを壁の位置に動かしている機能を使っている場合は、銃を構えた時にカメラを動かすとどちらも機能する為、動作がおかしくなります。
そこで銃を構えている時にフラグを立て、壁対策のカメラの動きをしないようにします。
銃を構えるのをやめた時はフラグを下ろし、壁対策のカメラが機能するようにします。
1 2 3 4 5 6 | // 銃を構えた時のカメラの位置 private Vector3 cameraTargetPosition = new Vector3(0.48f, 1.29f, -0.721f); // 銃を構えているかどうか private bool isWaitShot; |
銃を構えた時にカメラの移動する位置(カメラのローカル座標)をあらかじめフィールドとして用意しておきます。
isWaitShotは銃を構えているかどうかで、銃を構えている時は壁対策用のカメラの動きはしないようにします。
カメラを手動で移動させて銃を構えた時のカメラ位置を探ってください。
Updateメソッドでカメラを動かす処理
Updateメソッド内に実際にカメラを動かす処理を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void Update() { if (isWaitShot) { if (transform.localPosition != cameraTargetPosition) { transform.localPosition = Vector3.Lerp(transform.localPosition, cameraTargetPosition, cameraMoveSpeed * Time.deltaTime); } } else { // 通常のカメラ位置を計算 var cameraPos = charaLookAtPosition.position + (-charaLookAtPosition.forward * basePos.z) + (Vector3.up * basePos.y); // カメラの位置をキャラクターの後ろ側に移動させる transform.position = Vector3.Lerp(transform.position, cameraPos, cameraMoveSpeed * Time.deltaTime); RaycastHit hit; // キャラクターとカメラの間に障害物があったら障害物の位置にカメラを移動させる if (Physics.Linecast(charaLookAtPosition.position, transform.position, out hit, obstacleLayer)) { transform.position = hit.point; } // レイを視覚的に確認 Debug.DrawLine(charaLookAtPosition.position, transform.position, Color.red, 0f, false); } } |
isWaitShotがtrueの時は銃を構えている状態なので現在のカメラ位置がターゲット位置と違う時は徐々にターゲット位置に移動させます。
isWaitShotがfalseの時は壁対策のカメラの処理と同じでカメラの位置を徐々にターゲットの位置に動かしているだけです。
MainCameraをキャラクターの子要素にしたので、以前記述していたカメラの回転の処理は削除します。
回転の処理をなくしたのでAutoRotateCameraというスクリプトの名前がおかしくなりましたね・・・・(^_^;)
AutoMoveCameraとかの名前がいいかもしれません。
isWaitShotMoveがfalseになればifの最初の処理が実行されるので、カメラを元に戻す処理を新たに記述する必要はありません。
SetIsWaitShotメソッド
isWaitShotフラグのセットをするメソッドを追加します。
1 2 3 4 5 6 | // 銃を構えているかどうかのセット public void SetIsWaitShot(bool flag) { isWaitShotMove = flag; } |
bool値を受け取って設定するだけです。
カメラの移動機能を呼び出す個所を追加
これでカメラの移動スクリプトが完成したので、次はこのスクリプトの機能を呼び出す処理を追加します。
キャラクター操作スクリプトでAutoRotateCameraスクリプトを設定出来るようにフィールドを作成します。
1 2 3 4 5 | // カメラスクリプト [SerializeField] private AutoRotateCamera autoRotateCamera; |
主人公キャラクター操作スクリプト等で銃を構える、銃を構えるのをやめるという処理がUpdateメソッドにあると思いますが、そこでAutoRotateCameraスクリプトのSetIsWaitShotメソッドを呼び出してフラグを切り替えるだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | } else if (state == MyState.WaitShot) { // マウスの右ボタンを離したらノーマル状態へ遷移 if (!Input.GetButton("Fire2")) { spineXAxis = 0; spineZAxis = 0; isHoldGun = false; animator.SetBool("WaitShot", false); shot.DisableLight(); shot.DisableRaserPointer(); SetState(MyState.Normal); autoRotateCamera.SetIsWaitShot(false); // 構えた状態 } else { shot.AbleRaserPointer(); // 銃を撃つ if (Input.GetButtonDown("Fire1")) { shot.JudgeShot(); } autoRotateCamera.SetIsWaitShot(true); } } |
↑のように銃を構えている状態の処理で銃を構えるのをやめたらautoRotateCamera.SetWaitShotCamera(false)で銃を構えるのをやめた事を知らせ、
銃を構えた状態の時はautoRotateCamera.SetWaitShotCamera(true)で銃を構えている状態であることを知らせます。
キャラクター操作スクリプトではこの切り替えをするだけです。
上が実行結果です。
容量の関係でカメラが寄る場面のみになります。
今までの機能と合わせて、これでほぼバイオハザードの出来上がりです!
(;一_一)
まぁ・・・それはないとしてもモドキぐらいのゲームは作れるんではないでしょうか?(^_^;)