Labyrinthのつくりかた – カメラ操作編

わんちゃん
基本的な肩越しカメラの実装方法を紹介します!

1. はじめに

この解説は、そらまめゲームスが開発中の3D謎解きゲーム「Labyrinth(仮題)」の実装方法を解説したものです。

Labyrinth

Labyrinthではゲームのシステム部分のUE4プロジェクトを公開しております!私たちの方針はノウハウの全公開ですので、少しずつですが実装方法をご紹介していこうと思います。

あくまでLabyrinthでの実装事例を報告したもので、推奨される実装方法とは限りません。
難しい実装は何一つしていませんのであまり期待をしないでくださいね!

実装を参考にするのは自己責任でお願いします。

もっと良い実装方法があれば是非教えて下さい!質が上がれば皆が幸せになります!(主に私が)

2. 要件定義

Labyrinthでは肩越しカメラでの操作を想定しています。
カメラの注視点(見ている先)を主人公のやや右側に置き、その点を起点にカメラが動きます。

最近のゲームでは手ブレのような演出や、いろいろな補間処理が入っているのでかなり複雑な設計になっていると思いますが、Labyrinthでは至ってシンプルな実装になっています。

以下の操作でカメラを動かすことができます。

  • 一本指でスワイプするとカメラを動かすことができる
  • 二本指でピンチするとズームすることができる
  • 二本指でスワイプするとカメラ自体を回転することができる

1本指でのカメラ操作(クリックで再生)

2本指でのカメラ操作(クリックで再生)

これらの実装方法について解説していきます!

3. 先に結論!

  • 入力はPlayerControllerからのイベントで取得
  • 更新はTickで毎フレーム処理する
  • 可変フレームレート対応は大事
  • デバッグ機能を用意してモバイル実機上で調整できるように!

4. 解説

4.1. 全体像

  • カメラは、PlayerCharacterのブループリントクラスで管理します。
  • タッチ入力は、前回作成したPlayerControllerのイベントを使用します。
  • スワイプなどのイベントをPlayerCharacterが受け取り、カメラを動かす速度を算出します。
  • PlayerCharacterのTickにて、算出した速度を用いてカメラを動かしたり、速度を減衰(ブレーキ)したりします。

わざわざTickで処理しなくても、タッチ入力のイベントを受け取った時点でカメラを動かすことは可能ですが、そうすると、タッチを離すとピタッと止まってしまう動きになり、慣性のような滑らかな動きになりません。

今回のように、タッチ入力を一旦速度にしてからTickで動かしてあげると、滑らかに動かすことができます。

4.2. PlayerCharacterの構造

主人公の水無瀬 遥ちゃんのやや右側に、SpringArmコンポーネントを追加し、その子にカメラを追加します。

こうすることで、SpringArmを動かせば自撮り棒のようにカメラがついてきます。

画像はPlayerCharacterを継承したPlayerHarukaクラスのビューポート

カメラの注視点(見ている先)を主人公の横にずらすには、SpringArmコンポーネントのSocket Offsetで設定すると良いです。こうすることで、カメラを動かしてもキャラクターが常に画面左に居続けるような動き方になります。

Socket Offsetで動かした場合(クリックで再生)

TransformやTarget Offsetで動かした場合(クリックで再生)

4.3. PlayerControllerの入力イベントを取得する

PlayerControllerからスワイプなどのイベントを取得するために、PlayerCharacterのBeginPlayにてイベントをバインドします。

PlayerCharacterのBeginPlayにて取得したいイベントをバインドする

図のように、スワイプ、二本指ズーム、二本指スワイプのイベントにバインドして、それぞれカメラ移動、カメラズーム、カメラ回転の速度を算出する関数を呼び出すようにしました。

4.4. 入力イベントを元に速度を算出する

スワイプによってカメラ移動やカメラズームの速度を算出する関数が呼び出されます。

関数の中では以下の2つの計算をしています。

  1. タッチ入力値を加速度に変換
  2. 加速度を速度に加算

カメラ移動、カメラズーム、カメラ回転は似たような計算をしているので、ここではカメラ移動の解説をします。

4.4.1. 入力値を加速度に変換

タッチ入力値を元に速度を算出

タッチ入力値を加速度として使用するために用意した変数にセットします。
その際に補正値を掛けて、ちょうど良い数値になるようにします。補正値はゲーム中にデバッグ機能として調整できるようにしておくと楽になります。

4.4.2. 加速度を速度に加算

加速度を速度に足すときは最大速度チェックを!

ただ加算しているだけですが、ちゃんと最大速度と最小速度で抑えておかないとどこまででも速くなってしまいます。最大値と最小値もゲーム中にデバッグで調整できるようにしておきます。

4.5. 速度をカメラに反映する

PlayerCharacterのTickでのカメラ更新処理

PlayerCharacterのTickにて実際にカメラを動かします。シンプルですね!

ここでもカメラ移動のみ見てみます。ズームと回転も似たような処理をしているのでぜひ参考にしてみてください。

4.5.1. カメラ移動値を更新する

実際にカメラを操作する値を更新する

値をループさせたり上限値を設けたりといった最終調整を行います。

移動値を更新(算出)する際に気を付けることは、Tickで行っていますので可変フレームレートに対応することです。

フレームレートによる差を吸収するために、alweiさんの記事を参考に可変フレームレート対応をしました。

Input値をフレームレートによって補正してくれる

[Apply Value at FPS]というブループリント関数ライブラリにfloat値を流し込むと、前フレームからの経過時間をもとに値を補正してくれます。

可変フレームレート対応は、どんなときに気をつけるべきか慣れてないとわかりづらく、対応漏れが起きやすいです。私も苦手です!

気を配る箇所としては、ものを動かす時、カウントを数える時、などをフレームごとに行う場合が要注意ポイントです。

わんちゃん
私の場合はフレームレートを変更するデバッグ機能を入れておくことで、フレームレートを変えても正しく動くかどうか確認できるようにしています。

4.5.2. カメラ位置を更新する

移動値をSpringArmに適用する

いよいよ値をカメラに反映します。といっても、実際は自撮り棒であるSpringArmの方を動かします。

4.5.3. カメラ速度を減衰させる

速度を減衰させる

速度は減衰させないと常にその速さで動き続けてしまいます。

タッチ操作の指を離した後も、少し余韻を残しつつ停止するような動きになるように、速度を減衰させて止めるようにします。

さりげなくMath Expressionという機能をつかって、数式を簡潔にしています!ノードがぐちゃぐちゃにならないのでオススメです!

また減衰の際にも可変フレームレート対応が必要となりますのでご注意ください!

4.6. デバッグ機能で調整する

ゲーム操作周りは、プレー感に直結する部分なので調整は入念に行う必要があります。

その際に、PCゲームであればUE4エディタ上で動かしながら調整できますが、モバイルの場合は実機上で動かしながら調整できることが望ましいです。

Labyrinthでは今回のカメラ操作に関するパラメータはすべて実機上で調整できるようにデバッグ機能を用意しました。

クリックで再生

正直ここまで用意するのは手間がかかりますし、自己満足の部分が大きいです…。
たいていの場合は、「これは実機で動かしてみないとわからんな~」という値のみを実機で調整できるようにしてやればいいかと思います!

また、デバッグ機能としてフレームレートを変更できるようにして、可変フレームレートの動作確認をできるようにしています。簡単な実装でいつでも確認できるようになるのでオススメです!

ボタン一発で可変対応切り替え

フレームレート変更

5. 配布UE4プロジェクト

以下のリンク先からUE4プロジェクトを取得すると、今回の実装をすべて確認することができます!自己責任でお好きにご利用くださいませ!