GameInstanceとは
レベルを跨いで値を保持することができるクラスです。
以下の場所からGameInstanceクラスを設定します。
ここに設定しないと個別で作成したクラスは動作しません。
なぜGameInstanceが存在するか
「レベルを跨いで値を保持することができる」の意味が分かる方はすっ飛ばして下さい。
UE4の場合、Level上に存在するActorを制御することでゲームを構築していますが、Levelが切り替わって別のLevelに遷移した場合、遷移前のLevel、Actorの情報は全てクリアされてしまうため、ゲーム共通の情報を持つ場合はどこかで値を保持しておく受け皿が必要になってきます。
(上記のLevelはPersistentLevelを指します)
例えば、オプション画面(オプション画面用Level)でゲーム内音量設定をした場合、その設定情報はゲーム内の音量に連動させなくてはならないため、ゲーム中画面(ゲーム用Level)に移行するまで保持しておかなくてはなりません。GameInstanceを使用して設定情報をオプション画面でSet、ゲーム画面でGetすることで、ゲーム内の共通の情報を扱うことができます(グローバル変数のような扱い)。
値保持だけが役割?
ここからが本題。
GameInstanceといえば「値を保持できる」ことは結構知られていますが、他には何かないものでしょうか。GameInstanceに関するドキュメントはAPIくらいしか見当たらなかったのでソースも含めて調べてみました。Verは4.8.3です。
UGameInstance(公式ドキュメント)
先に結論
GameInstanceの機能に関して簡潔にまとめると以下の3点です。
・レベルを跨いだ値の保持
・ゲーム中のプレイヤー管理
・ネットワークリプレイの管理
ゲーム中のプレイヤー管理に関しては、マルチプレイ時などのクライアント側プレイヤーのことを示します。ネットワークリプレイに関しては、
先の記事でも触れていますが、Ver4.8で追加された録画機能のことを示します。オフラインでも録画できますが。
以上、GameInstanceの機能についてです。これ以降は、上記の補足です。
1.Blueprint
Blueprint(以下、BP)に公開されているイベントは以下の4種です。いずれも"BlueprintImplementable"なので、C++側で検出したイベントをBPで受信して駆動します。
これ以外のイベントに関してはBPへ公開されていないため使用できません。
① Event Init
名前の通りGameInstance初期化時に呼ばれます。
② Event Shutdown
名前の通りゲーム終了時に呼ばれます。
③ Event TravelFailure
マルチプレイなどクライアント-サーバ間のエラー発生時、レベル遷移時などに呼ばれます。
オプションとして障害要因(以下参照)がついてきます。
障害要因:ETravelFailure::Type(公式ドキュメント)
④ Event NetworkError
オンラインゲームなどネットワークエラーの発生時に呼ばれます。
オプションとして障害要因がついてきます。
こっちはドキュメント無かったので割愛。
以上、できることは少ないですが、セーブデータの展開や強制終了時の割り込み処理などはここで実装できなくもなさそうです。
余談
ちょっと余談なのですが、GameInstanceはPIE実行時とStandalone実行時で振る舞いが異なります。ここで言う振る舞いとは、「GameInstanceの生成/解放」のことなのですが、以下の違いがあります。
・PIE実行
実行の度にGameInstanceを作成
終了の度にGameInstanceを解放
・Standalone実行
実行時にGameInstanceを作成
終了時にGameInstanceを解放
殆ど違いはありませんが、PIEだと実行する度に作成しており、ソース上でもGameInstanceの生成処理はPIE用とStandalone用で明確に分かれています。何故このような違いがあるかというと、「PIEだとEditor上でGameInstanceクラスを変更できるのに対し、Standaloneだと決まったGameInstanceを使うということが分かっているから」と勝手に解釈していますが、本当の理由までは分かりません。ニュアンス的には合ってそうだと思いますが...
また、これ利用すればゲーム起動時の不具合の切り分けにも使えそうです。
「Editorだと正常に動くんだけど、Packageだとクラッシュする」なんて時にログから追おうとします。GameInstanceの生成が完了した時に以下のように「Game Engine Initialized.」とログが出力されます。これより以前であればデバイス、Pluginの設定、Engineの問題?などが考えられます。StandaloneだとEngineの初期化処理の最後にGameInstanceを生成するため、このログが出力された後にCrashしたりしていればゲーム側に問題がありそうです。
(実際にはクラッシュレポートやエラーログが出るので、あくまで切り分け程度に)
※ゲームログは[Saved]->[Logs]の中に.logファイルがあります
2.C++
C++からの操作だとプレイヤー管理、ネットワークリプレイに関する色んなことができます。と、詳しくは一番上のAPIドキュメント参照なのですが、サンプルプロジェクトのShooterGameが非常に参考になります(寧ろShooterGame以外のプロジェクトだとGameInstanceを使用していないケースしか見当たらない...)。
サンプルとは言えソースは出せなさそうなので、内容に関しては、サンプルプロジェクトから参照下さい。Slateを使ったネットワークリプレイ機能の実装、ネットワークを利用したマルチプレイ機能の実装が参考になりそうです。
その他
・Exc
コンソールコマンドの入力はFExcクラスで受信した後、入力の内容に応じて各クラスに処理を委譲します。GameInstanceクラスでは"Open [Level名]"のコマンドのみ、処理を行います。
"Open [Level名]"は指定したLevelに遷移するコンソールコマンドで、[Level名]が存在していれば正常に遷移します。注意したいのが[Level名]が存在しない時(失敗時)の振る舞いがVer4.7と4.8で異なることです。Ver4.7では失敗時、特に何も起きず現在の状態を継続します。Ver4.8では失敗時、PIE起動だとPIEを強制終了、Standalone起動だと現在のLevelを再起動する動作となります。これが仕様変更によるものなのか、不具合によるものなのか分かりませんが動作が変わっている点では注意が必要です。以下の図は、Ver4.8 PIE実行時にコマンド失敗した時のログです。強制終了していることが出力されています。
まとめ
マルチプレイなし、オンライン対応なしのゲームであれば、
値の保持にしか使わなそうですね!!