今回は最初の村やワールドマップでユニティちゃんを動かす時に、PS3コントローラーの右スティックやマウス操作でカメラの視点を変更出来るようにしていきます。
前回はユニティちゃんの影を濃くしました。
ユニティちゃんのRPGを作ってみようの他の記事は
から見ることが出来ます。
今までは最初の村やワールドマップのカメラは固定の視点でFollow Targetスクリプトを取り付けてユニティちゃんを追いかけるようにしていました。
せっかく3DのRPGを作っているので、コントローラーの右スティックやマウスを動かした時にユニティちゃんを見るカメラの視点を変更出来るようにしたいと思います。
ユニティちゃんの子要素にカメラが見るポイントを作成する
カメラ機能を取り付ける前にユニティちゃんの子要素にカメラが見るポイントを作成します。
Villageシーンのヒエラルキー上のユニティちゃんとWorldMapシーンのヒエラルキー上のユニティちゃんの子要素に右クリックからCreate Emptyを選択し、名前をLookPosとしてカメラが見る位置に移動させます。
上のようにユニティちゃんのお腹の辺りにLookPosを移動させました。
CinemachineのFree Lock Cameraを追加する
カメラの操作スクリプトを一から作成すると大変です。
ですがUnityにはCinemachineというカメラの機能が備わったので、それを使う事で簡単にカメラ操作が行えるようになります。
まずはVillageシーンを開いて、UnityメニューのCinemachine→Create FreeLook Cameraを選択します。
FreeLook Cameraはターゲットを中心にしてTop(上)、Middle(中間)、Bottom(下)の高さと半径を指定してその範囲でカメラを動かすことが出来ます。
新しくCM FreeLook1というゲームオブジェクトが作成されます。
FollowにはUnityChan、Look AtにはUnityChanの子要素に作ったLookPosを設定します。
LensのField Of Viewを60にします。
Axis ControlのY AxisのMax Speedを2、Input Axis NameにCamera Yと入力します。
Camera YはInput Managerで作成した設定の名前で後で作成します。Camera Yに割り当てられたジョイスティック等が押された時にY方向のカメラの移動が行われます。
X AxisのMax Speedを100にします。
Input Axis NameにはCamera Xを入力します。
OrbitsのBinding ModeをWorld Spaceにします。
TopRig、MiddleRig、BottomRigは上中下でのカメラの高さとターゲットからの半径を指定します。
ここら辺の値は好みの値を設定してみてください。
カメラ操作するボタン設定をInput Managerで行う
先ほどカメラのY軸とX軸の操作をそれぞれInputManagerで設定したCamera YとCamera Xで行うようにしたので、それらの設定を作成します。
PS3コントローラーの場合は右スティックを倒した時で、マウスは動かした時に対応するようにします。
UnityメニューのEdit→Project Settings…を選択し、Input項目を選択します。
新しい設定を4つ増やすのでSizeを4増やします。
新たに出来た設定の名前をCamera Xを2つ、Camera Yを2つ作成します。
まずはマウス操作の設定を作成します。
これは元々あるMouse XとMouse Yの設定とほとんど同じです。
Camera YのSensitivityを0.01にして移動量を少し減らし、Invertにチェックを入れてマウスを↑に動かしたらカメラが下に移動し、マウスを↓に動かしたらカメラが上に移動するようにします。
次はPS3コントローラー等のコントローラーの設定をします。
Camera XのAxisは3rd axis(右スティックの横)で、Camera YのAxisは6th axis(右スティックの縦)を設定しました。
コントローラーの種類によって設定する軸が変わると思います。
これでInput Managerの設定が出来ました。
カメラに障害物を認識させる
ここまででUnityのプレイボタンを押すとカメラ操作が出来ると思います。
ただし地面の高い所等がユニティちゃんとカメラの間に入ってしまうとうまくユニティちゃんが映されなくなってしまいます。
そこで障害物がカメラの間に挟まったらカメラが自動で障害物の前に入りユニティちゃんを映すようにします。
地面などのゲームオブジェクトにレイヤーを設定する
カメラが障害物と判定する為には障害物と認識するゲームオブジェクトのレイヤーを設定する必要があります。
そこでまずはTerrainで作ったフィールド等、障害物とするゲームオブジェクトのレイヤーにFieldレイヤーを新しく設定します。
VillageシーンのVillage→VillageGroundを選択し、インスペクタのLayer部分を押し、Add Layerを選択します。
User Layer 8にFieldと入力したら、ヒエラルキー上のVillageGroundを選択し、LayerをFieldに変更します。
WorldMapシーンの地面などのLayerにも作成したFieldレイヤーを設定しておきます。
仮想カメラに障害物を認識する機能を取り付ける
CM FreeLook1を選択し、インスペクタのCinemachine Free Lookの一番下のExtensionsのAdd Extensionを押し、CinemachineColliderを選択します。
Cinemachine Colliderが追加されるので設定を行います。
Collide AgainstにFieldレイヤーを設定します。これが障害物として認識するレイヤーの設定です。
Avoid Obstaclesにチェックを入れます。これで障害物を避けるようにカメラが動きます。
StrategyにPull Camera Forwardを設定します。これはカメラの動き方の設定になります。
Dampingを8にしてカメラが元の位置に戻る速さを遅くします。
ここまででカメラの設定が出来ましたので、CM FreeLook1を選択しCtrl+Cキーをおしてコピーし、WorldMapシーンのヒエラルキー上でCtrl+Vキーで貼り付けます。
WorldMapシーンのCM FreeLook1のFollow TargetにWorldMapシーンのUnityChanゲームオブジェクトを設定し、Look AtにWorldMapシーンのUnityChan子要素のLookPosを設定します。
WorldMapシーンのMain CameraのAdd ComponentからCinemachine→CinemachineBrainを選択し取り付けます。
WorldMapシーンのWorldMapゲームオブジェクトの子要素にあるWorldMapGroundのインスペクタでLayerをFieldに変更します。
カメラの動きはCM FreeLook1で行うようにしたので、VillageシーンとWorldMapシーンのMain Cameraに取り付けていたFollow Targetスクリプトは名前の横のチェックを外して無効化するか削除しておきます。
キャラクターの移動方法を変更する
さてここまででカメラ機能の取り付けは完了しましたが、ひとつだけ気になることがあります。
それはキャラクターの移動です。
カメラが上下に移動と左右に回転する事が出来るようになった為、今までのキャラクターの動かし方だとカメラが↑の方向を向いていてキーボードの↑を押してもキャラクターが↓方向に動いてしまい違和感のある動きになってしまいます。
上の例では今までのカメラの方向の逆方向にカメラを回転させていて、ここで↑の方向のキーを押すと上の方向に行くのが自然ですが、↑のキーを押すと画像上の↓の方向にキャラクターが移動してしまいます。
これは今までのキャラクターの移動は『キャラクターの位置+入力した方向』にキャラクターを向かせてそちらに移動させていたからです。
入力方向にはそのままInput.GetAxis(“Horizontal”)とInput.GetAxis(“Vertical”)の値を入れていたので、カメラの向いている方向が変わっても常に同じ方向への移動に固定されてしまってます。
これだと動きが不自然で動かしづらいので、キャラクターが動く方向はカメラの向いている向きに合わせて変更するようにします。
Assets/RPG/Scripts/Character/UnityChanScriptスクリプトを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | void Update() { if (state == State.Normal) { if (characterController.isGrounded) { velocity = Vector3.zero; var input = new Vector3(-Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")); if (input.magnitude > 0.1f) { // 押した方向をカメラの向きに合わせて変換 var convertInputToCameraDirection = Quaternion.FromToRotation(input, new Vector3(Camera.main.transform.forward.x, 0f, Camera.main.transform.forward.z)); // ユニティちゃんの角度をカメラの方向に合わせた角度のY値分だけ回転させる transform.rotation = Quaternion.AngleAxis(convertInputToCameraDirection.eulerAngles.y, Vector3.up); animator.SetFloat("Speed", input.magnitude); if (input.magnitude > 0.5f) { velocity += transform.forward * runSpeed; } else { velocity += transform.forward * walkSpeed; } } else { animator.SetFloat("Speed", 0f); } |
キャラクターの向きを
1 2 3 | transform.LookAt(transform.position + input.normalized); |
としていましたが、入力方向をカメラの向いている方向へと変換する為、Quaternion.FromToRotationを使って入力方向からカメラ方向(Y軸は0にした)への角度を求め、Quaternion.AngleAxisを使ってVector3.up(グローバルのY軸)を軸にして計算した角度のY軸の値分回転した角度をユニティちゃんの角度に入れています。
ここら辺の計算は難しいですね・・・・(^_^;)
以下の記事も参照してみてください。
いつまで経っても覚えられないが・・・・(´Д`)
これでカメラの向きに合わせて入力した方向にユニティちゃんが移動するようになりました。
実行して確認してみます。
上のようになりました。
終わりに
カメラの動きはCinemachineを使えば簡単に出来ると思っていたのでよかったのですが、キャラクターの移動方法に関しては完全にノーマークだった為に少し苦労しました・・・(^_^;)
この作品はユニティちゃんライセンス条項の元に提供されています