執筆バージョン: Unreal Engine 5.5
|
今回は、プレイヤーの開始位置を決めるアクター「PlayerStart」について、とりわけPlayerStartTagについて話したいと思います。
〇おさらい
以前、弊社ブログでもPlayerStartについて解説したかと思います。
[UE5]OpenLevelのスタート地点を指定する
この時、以下の事がポイントでした。
- 1つのレベルにPlayerStartが複数存在すると、どの位置から開始されるかはランダムで決まる
- PlayerStartにはPlayerStartTagという変数が存在し、タグ名をつけておくとGameModeBaseのFindPlayerStartで検索できる
- OpenLevel関数の引数Optionsに「#PlayerStartTag名」を指定すると任意のPlayerStartから開始できる

※レベルの開始位置は、配置されたPlayerStartを全検索して最初に見つかったPlayerStartを使用します。
この検索結果が毎回同じになるとは限らないため、ランダムで決まってしまうように見えるわけです。
ちなみにPlayerStartをパーシスタントレベル以外に配置してしまうと、この検索時点でそのレベルが読み込まれていなかった場合、検索に含まれず使用されなくなるので注意が必要です。
今回はこれらの内容を元に、PlayerStartTagを用いて様々なケースで任意のプレイヤー開始位置を使用するやり方をご紹介していきたいと思います。
〇同じパーシスタントレベル遷移時にPlayerStartを指定する
まずは、同じダンジョン内のエリア移動や、ゲームオーバー時のリトライ処理を行いたい場合です。
PlayerStartTagを使ってFindPlayerStartで検索したものを「RestartPlayerAtPlayerStart」を呼ぶ時に引数に渡せば簡単に実現できます。
例えばブループリントで実装する場合は以下のようになります。

〇別のパーシスタントレベル遷移時にPlayerStartを指定する
次に、パーシスタントレベルが違うマップへ移動したい場合です。セーブデータをロードする場合でも使う事になるかと思います。
この場合はOpenLevel関数を使用する事になりますが、この時に引数のOptionsに「#」を頭につけてPlayerStartTagを指定すると、指定されたタグのPlayerStartから開始できるようになります。
例えばブループリントで実装する場合は以下のようになります。

〇最初の起動時にPlayerStartを指定する
最後は、ゲームの起動時やエディタでのプレイ実行時などに開始位置を指定したい場合です。
ゲーム起動時はタイトル画面から開始する事になるので、実際に活用するケースは、開発中のエディタでのプレイ実行時になると思います。
この時にPlayerStartを指定したい場合は、DefaultEngine.iniに以下の内容を追記すれば必ず指定されたPlayerStartTagから開始できるようになります。
|
[URL] Portal=任意のPlayerStartTag |
【注意点】

ただし、この対応を行うとエディタ上での「Play From Here」機能が使えなくなってしまいます。
Portalのデフォルト値がiniファイルで指定したPlayerStartTagになるため、外部から直接PlayerStartTagを指定して上書きしない限り、必ずiniファイルで指定したPlayerStartTagが使われてしまうからです。
【対策】
そこで以下の対応を行う事で、PlayFromHereも問題なく使用することができます。
1.GameInstanceクラスなどに、プレイ実行を行ったフラグを用意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
UCLASS() class PLAYERSTART_API UPlayerStartGameInstance : public UGameInstance { GENERATED_BODY() private: #if WITH_EDITOR bool bIsInitialPIE = true; #endif public: #if WITH_EDITOR FORCEINLINE bool GetIsInitialPIE() const { return bIsInitialPIE; } FORCEINLINE void SetIsInitialPIE(bool bNewValue) { bIsInitialPIE = bNewValue; } #endif }; |
2.GameModeクラスのInitNewPlayer関数をオーバーライドして、プレイ実行時にPlayFromHereから起動した場合はPlayerStartTagを指定しないようにする
|
UCLASS(minimalapi) class APlayerStartGameMode : public AGameModeBase { GENERATED_BODY() public: APlayerStartGameMode(); virtual FString InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal = TEXT("")) override; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
FString APlayerStartGameMode::InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal) { #if WITH_EDITOR UPlayerStartGameInstance* GameInstance = GetGameInstance(); // PlayInEditorから呼ばれたかチェック if( GameInstance->GetIsInitialPIE() ) { GameInstance->SetIsInitialPIE(false); UEditorEngine* const EditorEngine = CastChecked(GEngine); if (EditorEngine->GetPlayInEditorSessionInfo()->OriginalRequestParams.HasPlayWorldPlacement()) { // Play From Here が指定されているため、PlayerStartTagを使用しない return Super::InitNewPlayer(NewPlayerController,UniqueId, Options, FString() ); } } #endif return Super::InitNewPlayer(NewPlayerController,UniqueId, Options, Portal); } |
〇最後に
OpenLevel関数でのOptionsの機能や、iniファイルからデフォルト値を変更できるなどの内容は公式ドキュメントでは言及されていません。
そういった場合は「PlayerStartTag」など気になる変数名をエンジン側のソースコード内で検索し、処理を遡っていけばわかる事があります。
また、ソースコードだけでは処理の流れを追うのはかなり難易度が高いですが、調べたい箇所にブレークポイントを設置して、プレイ実行などで処理を走らせる事で、コールスタックを見れば処理の流れは比較的簡単に追う事ができます。

ただし、エンジン側のコールスタックを見たい場合は、「デバッグに必要なエディタシンボル」を別途ダウンロードする必要があるので注意が必要です。
それなりの容量をダウンロードする必要がありますが、エンジン側の挙動を確認したい、デバッグしたい時にはとても便利なので、興味がある方は是非ダウンロードしてみてください。
