Unityでインディゲームを作る!

Unityでのゲーム制作を目指し、それに関わる話題についてのブログ

ゲーム・テンポとゲーム・スピードについて少し考える。

 ゲームテンポとゲームスピード、どちらも速さ(早さ)に関係する言葉ではありますが、これはきちんと区別すべき概念だと思っています。今回は、この二つの概念について、メモ書き程度に少し考えていきたいです。

 

ゲームテンポ

 いわゆるテンポが良い、テンポが悪い、という風に語られるゲーム・テンポですが、これはゲームの段取りや進行にまつわるスピード感、あるいは早さだと考えられます。実際のゲームプレイそのもののスピード感とはあまり関係なく、ゲームプレイに至るまでの段階や遷移におけるスムーズさを表す言葉であるべきでしょう。

 

 テンポが悪い、というのはもちろん避けるべきことで、ゲームが始まるまでに時間が無駄に掛かる(ロードが長い)、準備が煩わしい、毎回いちいち設定しないといけない、みたいなことですね。ゲーム進行の段取りが悪い、ということであり、ゲームプレイそのものは面白くても、その外側にストレスがあるという状態になります。

 またワン・ゲームのサイクルの長さもテンポに影響を与えるはずです。無駄に長いよりは、子気味良い長さで何回も遊べた方が楽しいと考えられます。

 

 現代では、とにかくスピーディに、テンポよくゲームが進行することの重要性が高くなっているので、ゲームプレイに直接関係なくても気を付けたい部分です。

 

ゲームスピード

 まさしくゲームそのもののスピードであり、ゲーム体験の核に関わる部分です。早ければいい、というものでもなく、速すぎても難しくなってしまうし、遅すぎても簡単になりすぎたり、爽快感が無くなってしまったり、そのゲームに相応しいゲームスピードが出るようにデザインしよう、ということになります。

 

 ゲームスピードは何によって決まるのか?自キャラや敵キャラの動くスピード?ボタンを押す時間間隔の短さ?意思決定までの制限時間?展開の速さ?イベントの頻度?

 

 不思議なもので、見てる分にはスピーディに見えるけど、実際触ってみると、そんなに操作は忙しくなかったり、また逆の場合もあります。理想としてはある程度、スピーディに見える方が見栄えは良いですが、自分で触った時には程よくマイルドなスピード感であることが望ましいはずです。

 

 ゲームプレイそのもののスピード感であり、ゲームデザインと密接に関係する部分なので、そのゲームに適切なゲームスピードを見つけられるようにしたいです。

 最近の傾向としては、必ずしもゲームスピードが速ければいい、ということはなく、瞬間的に速かったとしても、全体的にはむしろゆったりとしてゲームが好まれているような気がします。忙しいゲームはあまり好まれない、ということなのかもしれません。

 

まとめ

 というわけで、ゲームテンポとゲームスピードについて、少し考えてみました。混同されかねない、この二つの言葉に対してはそれぞれを意味、重要性を考えつつ、ゲームを作っていけたらなと思います。

 

君はUnity パッケージ・ドキュメントを知っているか!?

 Unityではパッケージという単位で各機能がモジュール化されており、必要な機能があればパッケージ・マネージャからインストールする、という形式になっています。

 そして、そのパッケージごとに専用のドキュメントが用意されており、実はこれがかなり詳しくて勉強になるものなのです。

 

 どう考えてもこれは活用すべきなんですが、検索にあまり出てこない傾向もあり、あまり周知されていないように思います。そこで、今回はこのパッケージ・ドキュメントへの移動の仕方を簡単にまとめます。

 

ドキュメントページへのリンク

Verified Packages Link

 まずはUnity公式のマニュアルのトップページに行きます。そのページのパッケージ項目(上画像)に検証済みパッケージというリンクがあります。ここをクリックすると公式マニュアルのパッケージ・セクションへと飛びます。

Unity Packages List

 ここに現在、正式版となっているパッケージ群がまとめられており、パッケージ・ドキュメントへのリンクもそれぞれ併記されています。

Unity Released Packages Page

 このページのリスト、あるいは各ページの上部にあるパッケージ・ドキュメントへのリンクをクリックすると、それぞれのページに移動します。例としてAddressablesのページにいますが、ここは一部日本語化されています。

Addressables_Package Document

 

 こんな感じで気になったパッケージ(機能)のドキュメントを流し見でもいいから目を通しておくと良い事があるかもしれません。

 

FMODでグローバル・パラメータをIDでコントロールする [PARAMETER_ID]

FMOD_Global Parameter

 Unityで使うことのできるオーディオ・エンジンのひとつとしてFMODがあります。FMODでは『パラメータ』を使って、臨機応変サウンドを変化させることが可能ですが、プロジェクト全体に作用させることの出来る『グローバル・パラメータ』がver 2.00から導入されました。

 

 FMODUnity.RuntimeManager.StudioSystem.setParameterByNameを使えば、スクリプト上のどこからでも、グローバル・パラメータを変化させることが出来ます。

 しかし、このメソッドは文字列を使っているため、ID(int)を使うことで処理の負荷を下げたいです。

 

 というわけで今回の記事はグローバル・パラメータのIDを取得する方法について書きます。

 

PARAMETER_DESCRIPTIONの取得

 まずはPARAMETER_ID private変数を用意します。今回は_progressID_sceneIDの二つ。取得したIDをキャッシュしておくために必要です。

FMOD_getParameterDescriptionByName

PARAMETER_DESCRIPTION一時変数を二つのパラメータに使いまわしてます

そして、AwakeかStartメソッドで

FMODUnity.RuntimeManager.StudioSystem.getParameterDescriptionByName

を使ってPARAMETER_DESCRIPTIONを取得、id変数からPARAMETER_IDを獲得します。

FMOD_setParameterByID

Update内でゲームを制御するメソッドの一部分

FMODUnity.RuntimeManager.StudioSystem.setParameterByID

を使って、グローバル・パラメータを効率良く変更することが出来るようになります。

 

 グローバル・パラメータを上手く使えばパラメータ管理がかなり楽になるので、上手く活用していきたいですね!

 

Unity Event Trigger コンポーネントを使って、自動で閉じるコントロールパネルを作る!

 よくあるUIとしてアイコンをクリックするとパネルが開き、マウスカーソルがその範囲から離れると自動で閉じる、というモノがあります。これはゲームに限らず様々な分野のアプリで見かけるパターンだと思いますが、今回はこれをEvent Triggerコンポーネントを使って作る!という内容です。

AutoClosePanel_AudioControlPanel

 自分が作っている、とあるミニゲームでは画面右上にスピーカーアイコンがあり、それをクリックするとパネルが展開され、表示されるスライダーで音楽と効果音の音量が調整出来ます。このパネルを閉じる時、もう一度アイコンをクリックするのは面倒ですよね。だからパネルからカーソルが離れたら自動で閉じるようにしたいです。

 

AutoClosePanel_TogglePanelMethod

 このゲームには音楽を管理するスクリプトがあり、そこでオーディオコントロール・パネルの開閉を行うメソッドを定義しています(上写真)。処理内容としては、パネルのゲームオブジェクトへの参照からSetActiveを使って表示を切り替えるだけです。

 それをオーディオアイコンとしているButton(Text Mesh Pro)のonClickにアサインしているわけですが、このメソッドをパネルのEvent Triggerの方にも追加します。

AutoClosePanel_UIpanel

 パネルはヒエラルキーの追加メニューのUI項目から。そこにEvent Triggerコンポーネントを追加し、後はパネルのインスペクター上でRaycast Target設定にチェックを入れておきます。これが無いとマウスカーソルに反応してくれません。

AutoClosePanel_PointerExit

 Event Triggerでは複数の中から自由にイベントを追加でき、今回はPointerExitを選択します。これは対象のUIからカーソルが離れた時に発生するイベントです。

AutoClosePanel_EventTriggerComponent

 該当するスクリプトを持つゲームオブジェクトを選択し、ドロップボックスからToggleAudioControlPanelメソッドを選択します。これで動作を確認すると、確かにカーソルがパネルから外れると自動で閉じるようになっているはずです。

 

 しかし、このままだとアイコンの上にカーソルをやるとパネルが消えてしまいます。アイコンにカーソルが乗ったことでパネル及びその子UIオブジェクトからExitしたと判定されるからです。

AutoClosePanel_AltAudioIconButton

 なのでヒエラルキー上でアイコンの方を上にして(ヒエラルキー上で下にあるものが手前に表示される)、コピーしたアイコンをパネル内部に配置します。すると、従来のアイコンはパネルの下に表示される形になり、PointerExitイベントが発生しなくなります。(ボタンを押して閉じる場合に押すのはコピーされたアイコン)

 

 というわけで、Event Triggerコンポーネントを使うと、Unity UIで簡単に自動開閉するパネルを作ることが出来ました。

 やはり、こうしたゲームプレイとは直接的に関係のない操作については、出来る限り簡潔でストレスの少ないモノにしていきたいですね!

 

Unity Cinemachineを使って、ダッシュ時に自動で進行方向に向くTPSカメラを作る!

CinemachineAdaptiveCamera_Cover

 今回はUnity公式のカメラ制御システムであるCinemachineを使って、マウスなどでカメラをコントロールしつつも、ダッシュ時には進行方向に自動で向いてくれるカメラを作ってみたいと思います。

 カメラの制御は特に3Dゲームで重要で、カメラ操作が多すぎるとプレイヤーへの大きな負担になってしまいます。ゲーム性にもよると思いますが、出来る限りカメラ操作をする量や場面を減らしたいものです。

 そこで今回は歩き時は俯瞰でプレイヤーの周りを見る視点で、走るとプレイヤーの進行方向が良く見えるようにカメラが自動で向いて寄る、というカメラ制御をCinemachineを使って再現してみたいと思います。Recentering機能を使えば、実はかなり簡単に再現することが出来ました。

 

 そして、今回の記事ではInput Systemを入力システムとして採用しています。また、今回の方式はあくまで実験的な内容なので、そのまま本番環境で使えるとは限らない点をご了承ください。

 

準備

 当然ですが、Cinemachine パッケージがインストールされている必要があります。今回は公式デモ・アセットであるStarter Assetsのロボのモデルを使って、Charactor Controllerを利用したプレイヤーキャラを用意しました。ただ移動(歩きとダッシュ)をするだけの簡素なモノです。Player Inputコンポーネントも同じオブジェクトに装着しています。

 そして、FreeLook Cameraヒエラルキー上に追加!メインカメラに自動的にCinemachine Brainコンポーネントが追加されます。FreeLook Cameraはプレイヤーがマウスなどで操作できるのですが、Input System利用時にはインスペクター上から Input Providerコンポーネントの追加が必要です。Followやカメラの距離などの設定を入力すれば準備完了。

 

カメラ視点の意図

 単純な視点操作できるTPS視点カメラだけならコレで完成になります。画面の中心に自キャラが位置し、プレイヤーがキャラとその周辺を見るのに最適な設定であり、ある程度の俯瞰性があるので頻繁にカメラを動かす必要もないし、プレイヤーの動きにカメラがいちいち追随することも無いです。(あくまでこれが今回のカメラ制御に求める挙動であり、適切なカメラ設定はゲーム性によります)

AdaptiveCamera_Walk mode

 問題は走った時で、走るとプレイヤーキャラ周辺ではなく、中距離あるいは長距離のある程度離れた方向に目を向けることが多いと想定すると、この場合プレイヤーは足元付近から前方へと自分でカメラを操作する必要が出てきます。

AdaptiveCamera_Dash mode

 この走り始めた時のカメラ操作を省きたい、というのが今回の意図です。走るということは目的地は少し離れているのであり、その少し離れた地点にカメラが自動で向けば楽だろう、便利だろうということです。

 

Recenteringを使えば簡単!

SwitchingAndRecentering

 というわけで、すこし前置きが長くなりましたが、C#スクリプト上にCinemachineFreeLookインスタンスを作り、そこから

CinemachineAdaptiveCamera_Inspector

m_RecenterToTargetHeading.m_enabledにアクセスすれば、意外と簡単に出来てしまいます。後述しますが、ここでダッシュ時の別のFreeLook Cameraの優先度を100にすることでカメラを切り替えています。

 

 Recenteringとはカメラを定位置(この場合、真後ろ)に自動で戻す機能で、X軸とY軸それぞれあり、インスペクター上でも実は簡単にON/OFF切り替えが出来たりします。ダッシュ時にはこれをtrueにし、立ち止まったり歩きに戻したらfalseにするようにします。

SwitchRecenteringOnDash

 

 ※ダッシュ切り替えをトグルにするべきか、あるいはボタンを押しっぱなしにするかのデザインについては諸説あると思いますが、今回はトグル方式でボタンを押すと交互に切り替わる、という方式にしています。

 

もう一台のFreeLook Cameraを使う

 自動で走る方を向くだけなら、実はもうこれだけでいいのですが、進行方向を向くと同時にプレイヤー側にカメラが寄って欲しいので、もう一台、ほぼ同じ設定の距離や高さを変えたカメラを用意してそれに切り替わるようにします。

 走るということはキャラ周辺には用が無く、遠くまで見渡せた方が良いと考えるからです。そのためにはプレイヤー側によって、少しでも前方への視野を拡げます。

 

 今回の場合、カメラ操作を残しつつダッシュ時にカメラ切り替えも考慮するとなると、工夫をしないとカメラがスムーズに切り替わりません。Cinemachineはアクティブなカメラの中で優先度が一番高いカメラに自動でトランジションしてくれますが、意図しないブレンドになる可能性がこの場合高いからです。

SyncInputToCamera

 なので、今回考えた作戦は片方のFreeLook Cameraへの視点移動入力をもう片方にも同時に入力しておく、というものです。FreeLook及び、Input Providerによるデータ入力はそのカメラがアクティブな時に限られます。なので、スタンバイ状態にあるFreeLookには手動で入力して、二つのカメラの位置をシンクロさせておく、という作戦です。

 Cinemachineにおけるカメラ切り替えはPriority(優先度)を変えたり、優先度の高いカメラをSetActiveで有効にするなどがありますが、スムーズなブレンディングのためにスタンバイ状態のカメラもプレイヤーに追随しておく必要があるので、今回は優先度のコントロールのみで切り替えます。

CinemachineAdaptiveCamera_UpdateMethod

 Updateメソッドの中でSyncFreeCamsメソッドを実行し、常に二つのカメラに同じ視点操作を入力します。そして、ダッシュ有効時にカメラの優先度を上げて、

m_RecenterToTargetHeading.m_enabledをtrueにしてカメラを切り替えます。

 ふたつのカメラは実際にはプレイヤーとの距離が違うので完全にシンクロすることはありません。しかし、スタンバイ状態でも常にカメラ操作とダッシュ時の自動制御に基づいて同じ方向に移動しているので、切り替え時にスムーズなカメラ・ブレンディングを実現することが出来る、ということになります。

 

まとめ

 というわけで、最初はコレできたらかなり便利だな、出来るかな?と不安でしたが、やってみると意外とすんなり素早く出来て、Cinemachineの素晴らしさを改めて認識しました。Timelineなどとの統合性を考えるとカメラ・システムはCinemachineを中心に考えていきたいので、これからも更にCinemachineへの理解を深めたいと思います。