本講座では、UnityとC#を用いて3DFPSゲームを作成していきます。
前回はカメラオブジェクトとしてプレイヤーを作成し、前後左右への移動処理を実装しました。
前回の記事 :
今回はまずプレイヤーの目にあたるカメラを任意に動かせるようにします。
次に、ジャンプできるようにしてFPSゲームの移動処理を完成させていきましょう。
Unity C#でカメラの回転操作を行う
カメラ操作は画面をドラックして任意に回転させる方法で実現させることにします。
スクリプトの記載
早速回転処理を追加した「AppPlayerController」を先に記載し後ほど解説していきます。
追加した部分に黄色くマーカーをつけ、追加のない部分は「・・・」という文字で省略します。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
・・・ public class AppPlayerController : MonoBehaviour { ・・・ // X軸周りのカメラ回転速度. [SerializeField] float xRotationSpeed = 5f; // Y軸周りのカメラ回転速度. [SerializeField] float yRotationSpeed = 5f; ・・・ // マウスクリックを開始した位置. Vector3 startMousePosition = Vector3.zero; // クリック開始時点でのカメラの角度. Vector3 startCameraRotation = Vector3.zero; ・・・ void Update() { // クリックの開始. if( Input.GetMouseButtonDown( 0 ) == true ) { // マウスの位置とカメラの角度を保管. startMousePosition = Input.mousePosition; startCameraRotation = Camera.main.gameObject.transform.localRotation.eulerAngles; } // クリック中(ドラッグ). if( Input.GetMouseButton( 0 ) == true ) { // 現時点のマウス位置を取得. var currentMousePosition = Input.mousePosition; // クリック開始位置からの差分を算出. var def = ( currentMousePosition - startMousePosition ); // 現在のカメラ角度. var currentCameraRotation = Camera.main.transform.localRotation.eulerAngles; // 回転角度を算出. currentCameraRotation.x = startCameraRotation.x + ( def.y * xRotationSpeed * 0.01f ); currentCameraRotation.y = startCameraRotation.y + ( -def.x * yRotationSpeed * 0.01f ); // カメラに適用. Camera.main.transform.localRotation = Quaternion.Euler( currentCameraRotation ); } // クリック終了. if( Input.GetMouseButtonUp( 0 ) == true ) { // 保管した値をリセット. startMousePosition = Vector3.zero; startCameraRotation = Vector3.zero; } } ・・・ } |
追加したのは変数と「Update」関数内の処理です。
他の部分は省略しています。
1 2 3 4 5 6 7 8 9 |
// X軸周りのカメラ回転速度. [SerializeField] float xRotationSpeed = 5f; // Y軸周りのカメラ回転速度. [SerializeField] float yRotationSpeed = 5f; // マウスクリックを開始した位置. Vector3 startMousePosition = Vector3.zero; // クリック開始時点でのカメラの角度. Vector3 startCameraRotation = Vector3.zero; |
まずは変数。「xRotationSpeed」「yRotationSpeed」はカメラ回転の速度です。UnityのInspectorから変更できるように「SerializeField」属性をつけておきましょう。型は「float」です。
「startMousePosition」「startCameraRotation 」は「Vector3」型でそれぞれマウス位置、カメラ角度を保管するため変数です。後ほど使用します。
次に追加した「Update」関数の処理です。ここの「if文」の条件になっている「Input.MouseButton〇〇」について。
まずは関数名の部分
Input.GetMouseButtonDown() | マウスのボタンをクリックした瞬間にtrue |
Input.GetMouseButton() | マウスのボタンをクリックしている間(ドラッグ中)にtrue |
Input.GetMouseButtonUp() | マウスのボタンのクリックを離す瞬間にtrue |
になります。そして関数の引数の部分、上のコードでは「0」になっている部分は
0 | 左クリック |
1 | 右クリック |
2 | 真ん中クリック |
を取得できます。つまり「Input.GetMouseButtonDown( 0 ) == true」というのは「マウス左クリックをした瞬間」というのが条件となります。
では改めて、最初の処理
1 2 3 4 5 6 |
if( Input.GetMouseButtonDown( 0 ) == true ) { // マウスの位置とカメラの角度を保管. startMousePosition = Input.mousePosition; startCameraRotation = Camera.main.gameObject.transform.localRotation.eulerAngles; } |
条件は先に言ったように「マウス左クリックをした瞬間」です。
「startMousePosition」には「Input.mousePosition」を保管します。
「startCameraRotation」には前回にも出てきたメインカメラの角度「Camera.main.gameObject.transform.localRotation.eulerAngles」を保管しておきます。
次にクリック中の処理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if( Input.GetMouseButton( 0 ) == true ) { // 現時点のマウス位置を取得. var currentMousePosition = Input.mousePosition; // クリック開始位置からの差分を算出. var def = ( currentMousePosition - startMousePosition ); // 現在のカメラ角度. var currentCameraRotation = Camera.main.transform.localRotation.eulerAngles; // 回転角度を算出. currentCameraRotation.x = startCameraRotation.x + ( def.y * xRotationSpeed * 0.01f ); currentCameraRotation.y = startCameraRotation.y + ( -def.x * yRotationSpeed * 0.01f ); // カメラに適用. Camera.main.transform.localRotation = Quaternion.Euler( currentCameraRotation ); } |
まずは「currentMousePosition」という変数に「Input.mousePosition」つまりその時点でのマウスの位置を保管します。「var」は前回もでてきた「型推論」でこの場合「Vector3」になります。
変数「def」には「currentMousePosition」から「startMousePosition」を引いた値、つまりスタートのマウスの位置からの移動量(Vector3)を算出しています。
次に「currentCameraRotation」には現在のカメラ角度「Camera.main.transform.localRotation.eulerAngles」を保管します。
次が重要です。
1 2 |
currentCameraRotation.x = startCameraRotation.x + ( def.y * xRotationSpeed * 0.01f ); currentCameraRotation.y = startCameraRotation.y + ( -def.x * yRotationSpeed * 0.01f ); |
まず取得したカメラ角度のxの値、つまりX軸周りの角度「currentCameraRotation.x」にクリック開始時の角度のx「startCameraRotation.x」プラス「def.y * xRotationSpeed * 0.01f」という値を代入します。
この「def.y」は先に算出したマウスの移動量のYの値、つまり画面の縦方向の移動量になります。そこに係数「xRotationSpeed」をかけて回転量を算出します(0.01fは桁を合わせるための係数)。
回転のX軸まわりというのは、前回解説した首を頷く方向(前後)の回転なのでマウスの上下の動きを連動させます。
同じようにY軸周りの角度「currentCameraRotation.y」にはクリック開始時の角度のyの値「startCameraRotation.y」プラス、マウスの移動量のxの値、つまり横方向の移動量「def.x」に係数をかけた値になります。
こちらが「ー」になっているのはドラッグ時の回転の方向を合わせるためですので、もし回転方向がやりにくいと思ったら、ここの「+ー」を入れ替えてください。
そして最後に
1 |
Camera.main.transform.localRotation = Quaternion.Euler( currentCameraRotation ); |
「Camera.main.transform.localRotation」カメラの角度に、算出した値「currentCameraRotation」を「Vector3」型から「Quaternion」型に変換して代入して完了です。
FPSカメラ回転の確認
まずInspectorの「AppPlayerController」はこのように「SerializeField」を付けた変数が増えています。
では再生して、画面内をマウスでドラックしてカメラの回転を試してみます。この時同時に移動してみるとカメラの向いている方向を前として移動できていることも確認しておきましょう。
(画面の大きさはまだ設定していないので各自違って問題ありません)
現在ドラックして右に移動するとカメラが左に回転します。また上に移動するとカメラは下に回転します。この方向を変更したい場合は、「xRotationSpeed」「yRotationSpeed」の「+ー」を変更してみましょう。
これで移動処理が完成しました。
FPSゲームのジャンプを実装する
次にジャンプできるようにしていきましょう。
今回はジャンプが必須になるようなフィールドは作成していませんが、FPSにありがちなので作ってみましょう。
ジャンプ機能C#スクリプトの記載
ではまずは「AppPlayerController」に追記していきましょう。
まずはジャンプの基本処理だけ記載していきます。追加部分以外は省略しています。
PhysicMaterialで摩擦量の修正を行う
最後に少し細かい設定をしていきます。
現在、床以外にもフェンスや岩などコライダーの設定されているゲームオブジェクトがあります。
それらに正面からぶつかるとそこで止まり、例えばジャンプ中にぶつかると少し空中で止まったりもします。
これは、コライダー同士の衝突のときに生じる摩擦が移動のための力を上回っているためです。この辺りは細かく計算し出すと質量など色々関わってきて大変ですので、Unityではその摩擦量を設定できるようになっています。
まずは「Assets/AppMain」に(好きなフォルダを作成してもOK)右クリック「Create→PhysicMaterial」で新しく「PhysicMaterial」を作成し「WallPhysicMaterial」という名前にします。
これを選択しInspectorを見てください。
Dynamic Friction | 動いているものに対する摩擦 |
Static Friction | 静止しているものに対する摩擦 |
Bounciness | 跳ねかた |
FrictionCombine | 摩擦の計算方法 |
Bounce Combine | 跳ねの計算方法 |
となります。
変更するのは「Dynamic Friction」「Static Friction」の摩擦の二つです。これは「0〜1」の値をとり、0が摩擦なしです。この二つを「0〜0.1」の値にしておきましょう。ここでは「0.1」にします。
「Bounciness」は変更せず「0」のままです。こちらは0で跳ねないようになります。
そして「FrictionCombine」ですが、摩擦というのは二つ(以上)の物体の接触によって発生します。そのため両方の値をどのように計算するかというのが、ここの設定になります。
これを「Minimum」に設定します。
「Minimum」は接触している物体の小さい方の値を参照します。
「Bounce Combine」は同じようにはねる時の計算方法で、変更しませんが「Average」で両方の平均値を参照します。
ではこれを設定していきます。
設定するのは「Collider」の「Material」の部分です。
今回はフェンスの部分に設定したいので、まずはHierarchyの「Forest/GROUP_Fences」の子にある「Fence(番号)」を全て一括選択します。
そして、Inspectorの「Box Collider」の「Material」に「WallPhysicMaterial」をドラック&ドロップして設定します。
これで、フェンスへの設定は完了です。橋や岩や木などより細かく設定したい場合はそれぞれに「PhysicMaterial」を作成し設定してみましょう。
Unityエディタでテストプレイ
では、最後に再生して「Space」ボタンを押してみましょう。
ちゃんとジャンプできるでしょうか?。少し待機時間が長いなと思う方は先ほど設定した「0.5f」を短くしても構いません。
またフェンスに向かってジャンプしてスーっと滑り落ちる感じを確かめてみましょう。PhysicMaterialの値を変更すると、この動き方も変化していきますので試してみるのもいいでしょう。
今回はここまでになります。次回は武器を使って攻撃する処理を作成していきましょう。
次回の記事 :
コメント