この記事はFPSゲームの作り方講座の第16回目で、VRでのFPSゲームの作り方を解説しています。
前回でVR版への移植の流れを解説し、実際にMeta Questを用いてのジャンプ、移動、UIの実装を行いました。
前回の記事:
今回は矢を放つ攻撃の処理VR版に移植していきます。
VRの場合コントローラーがあるので、そこに弓を持って打てるようにしていきます。
VR空間で体を使って実際に狙いを定めて弓を射る!そんな体験を作っていきましょう。
FPSゲーム講座のVR対応、ほぼほぼできたかな。
— ばこ@Unity入門の森 (@bako_XRgame) November 28, 2022
あとはいくつか調整&オプション要素の解説記事を作成して仕上げです。
今日は弓矢を射る処理をVR化しました。
実際に身体を使って狙いを定めて敵を倒すのって楽しいです。
PC、スマホ、VR全対応の新作講座をお楽しみに!#Unity入門の森 #VR pic.twitter.com/QkAPKN4LDt
今回の講座ではこんな感じで動き回って弓矢を放てるようになります。
武器オブジェクトの再配置 VRハンドと弓矢を結合させる
まずはヒエラルキー上で武器オブジェクトを手に持つ位置に移動させます。
現在「MainCamera」の子に「Weapon」が配置されていますので、これを「Player/OVRCameraRig/TrackingSpace/LeftHandAnchor」の子に移動しましょう。
そして、「Weapon」とその子にある「Elven Long Bow」の「Transform」のPositionを変更しておきましょう。「Weapon」のPositionの値は左手に持っている時の位置を想定して微妙な調整をしています。後々ずれてると思ったら調整してください。
Rotation、ScaleはそのままでOKです。
そして「Weapon」の子にある「ArrowPoint」、矢を生成する位置も調整します。
一旦プレハブの「Arrow」を「ArrowPoint」の子に置いて、位置を確かめながら調整しましょう。大体矢を引く前の矢の位置になるように、「ArrowPoint」の位置を調整します。この時「Arrow」の位置は「0」のままにしておいてください。「0」になっていなかったらしておきましょう。
下記のように調整しました。そうするとエディターのSceneウインドウでは画像のような位置になります。
Editor上では下記のように左右の手が向かい合っているような状態になっていますので、その左手を見て調整してください。
では一旦ビルドしてみて、左手のコントローラーに弓矢がくっついているのを確認しておきましょう。確かめたら「Arrow」は消しておいてください。(矢のみ削除して、「ArrowPoint」は残しておいてください)
VRで弓矢を使った攻撃処理を作成
次に先ほど仮で配置した矢を生成する処理を作成していきます。
矢を生成方法は、ゲームによって様々です。ここではシンプルに左手(弓を持っている手)のグリップボタンを押すと弓に矢が生成されるようにします。
ちなみに弓は左手に付きっぱなしにしています。
矢の生成処理を実装しよう
今までPCでは「UpdatePcCameraAndAttackAndJump()」とスマホでは「UpdateMobileCameraAndAttack()」で攻撃処理を行なっていましたが、これらはすでに削除(コメントアウトもしくは不使用に)しているので、「Update()」で実行している「UpdateVRInput()」に処理を追加していきましょう。
「UpdateVRInput()」関数のみ記載します。
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 54 55 56 57 58 59 60 61 62 63 |
public class AppPlayerController : MonoBehaviour { ・・・ // --------------------------------------------------------------------------------- /// <summary> /// VR用処理. /// </summary> // --------------------------------------------------------------------------------- void UpdateVRInput() { // 終了時リトライ処理. ・・・ // 矢を生成. // 左コントローラーグリップボタンダウン. if( OVRInput.GetDown( OVRInput.Button.PrimaryHandTrigger ) == true ) { if( gameController != null && gameController.CurrentGameParam.State == AppGameController.GameState.Play ) { if( isAttackWait == false ) { var currentArrowGo = Instantiate( arrowPrefab , arrowPoint.position , arrowPoint.rotation , arrowPoint ); currentArrow = currentArrowGo.GetComponent<Arrow>(); currentArrow.OnCreated(); isAttackWait = true; attackChargeTime = 0; } } } // 左コントローラーグリップボタン押してる間. if( OVRInput.Get( OVRInput.Button.PrimaryHandTrigger ) == true ) { } // 左コントローラーグリップボタンアップ. if (OVRInput.GetUp(OVRInput.Button.PrimaryHandTrigger) == true) { if (currentArrow != null) { // 破棄しておく. Destroy(currentArrow.gameObject); currentArrow = null; isAttackWait = false; } else { isAttackWait = false; } } // ジャンプ処理. if( OVRInput.GetDown( OVRInput.Button.One ) == true && isJumping == false ) { isJumping = true; rigid.AddForce( rigid.gameObject.transform.up * jumpPower , ForceMode.Impulse ); } } ・・・ } |
処理の多くはPC、スマホの攻撃処理に近いので一旦コピーしてから修正してもいいかと思います。
まずは「if( OVRInput.GetDown( OVRInput.Button.PrimaryHandTrigger ) == true )」で左コントローラーグリップボタンを押した瞬間です。この「OVRInput.Button.PrimaryHandTrigger」が左コントローラーのグリップボタンを指します。
次の
1 2 3 4 5 6 7 8 9 10 11 12 |
if( gameController != null && gameController.CurrentGameParam.State == AppGameController.GameState.Play ) { if( isAttackWait == false ) { var currentArrowGo = Instantiate( arrowPrefab , arrowPoint.position , arrowPoint.rotation , arrowPoint ); currentArrow = currentArrowGo.GetComponent<Arrow>(); currentArrow.OnCreated(); isAttackWait = true; attackChargeTime = 0; } } |
の部分はPCスマホと同じです。
「Nullチェック」と「ゲームステイトがPlay」の時を条件に、さらにそのカッコ内では「isAttackWait」が「false」の時に、矢を生成して「OnCreated()」を実行、「isAttackWait」を「true」、「attackChargeTime」を「0」にします。
次の条件
「if( OVRInput.Get( OVRInput.Button.PrimaryHandTrigger ) == true )」は左コントローラーのグリップボタンを押している間の処理ですが、今回は中に処理はひつようありません。一応わかりやすいように記載しておきます。
最後は「if( OVRInput.GetUp( OVRInput.Button.PrimaryHandTrigger ) == true )」で左コントローラーのグリップボタンを上げた時です。
処理は「currentArrow」が「null」じゃない時に、「Destroy()」して矢を破棄しておきます。そして他はPCスマホと同じで「currentArrow」を「null」、「isAttackWait」を「false」にします。
また「currentArrow」が「null」のときは「isAttackWait」を「false」にする処理のみ行います。
終了時処理(省略)、ジャンプ処理はすでに追加されているところです。
では、一旦この段階でビルドしてみましょう。
左手のグリップボタンを押すと弓に矢が生成され弓にセットされているような状態になり、ボタンを離すと消えます。
次にこの矢を放てるようにしていきましょう。
弓を引いて矢を放つ体験を作成しよう
弓矢の放ち方を決めます。
左手のグリップボタンを押して矢をセットしている間に、矢を右手で持って引きます。
そして右手のボタンを離すと発射します。ここはちょうど弓で矢を放つ動きを再現できるようにしてみましょう。
動作が複数の動きの連結で実現するため、少々ややこしいです。少しずつ分割して作成していきます。
矢に掴むポイントを作成
最初に矢に掴むためのポイントを作成します。「Arrow」プレハブを開いて、「Arrow」の子に新しく空オブジェクトを作成し「GrabPoint」という名前にします。
下記画像ではわかりやすいように緑の球を置いていますが、これはなくても構いません。もちろんあっても構いませんが、その場合はコライダーを消す、そして必要な時に見た目「Mesh Renderer」を消すのを忘れないようにしましょう。
位置は下記のようにしています。大体羽のあたりになるように調整しましょう。
さいごに
今回の講座で「左手グリップで矢を生成」→「右手グリップで矢を掴む」→「右手グリップをしたまま手を引く」→「右手グリップを離すと矢を発射」という操作を実現できました。
移動しながらでもジャンプしながらでも弓矢を放つことができます。物陰から弓矢を放つ、敵の方を向きながら後ろに移動しながら弓矢を放つ、高いところから狙い撃つなど弓矢独自のアクションをVRゲームに取り込むことができますね。
PCであったチャージ(引いている時間)は今回は解説しませんが、矢を引き始めた時に時間計測を開始して、放つ時に取得すればOKなので処理自体はさほど変わりません。チャージ機能も欲しい方はぜひ作成してみましょう。
また、武器の付け替えや落として拾うなどの処理を追加しても面白いかもしれませんね。
ここまでで、ある程度動くようになってきましたが、まだいくつか調整できるところがあるので次回最後にVR用の調整をしておきましょう。
次回の記事 :
コメント