CharacterMovement周りを読む
214301428行あるけど絶対に読む
続きを読むプレイヤー名の表示、参加者一覧の取得
・ゲーム参加直後はログイン処理がある
・ゲーム開始時クライアント側では、あるはずの変数やインスタンスがちゃんと存在している保証はない
参加者一覧は、各クライアントで、レベルにあるPlayerStateをイテレーターで名前やらPingを取って表示したら良いのだけれど、例えばこれをゲーム開始直後に生成してしまうと、サーバーから人数分すべてのPlayerStateを受信出来ているかどうかが確実ではないなど、ちょっと表示を行う処理のタイミング考えないと行けない
単にDelay置いても良さそうだけれど、100%ではないので、もう少し堅牢な設計がやりたい
プレイヤー上部の名前表示には、そのプレイヤーのPlayerStateと、そのプレイヤーのログイン初期化処理が終了していることが必要で、自分のフローでは、PlayerPawnのスポーン完了をログインフェーズの最後としている
なので、"PlayerStateのAPawn* ControlledPawn変数が値を受け取った瞬間 = 当該ユーザーのログイン、初期化処理が完全に終了したことを、クライアントで認識した瞬間" であるので、"OnRepControlledPawn関数が発火する = 当該ユーザーの情報に安全にアクセスできる"という感じでやっている
なんかもう少し処理を単純にできそうだけれど、とりあえずこれで安定している
マルチプレイ時のプレイヤーポーンのスポーンのタイミング
GameModeのログイン処理、パーシスタントレベルのロードが終わると始まるっぽいけど、ストリーミングでマップをロードするタイプの設計だと、最悪床のロード前にプレイヤーがスポーンして奈落即ち死になる可能性がある
死
かといって、ロード終わった瞬間にプレイヤー周りの処理してしまうと、今度はログイン処理が終了していない可能性があって、最悪な感じになってきている
ここでクッソよく分かる生成タイミングの図を用意する
作りがちなPlayerControllerのBeginとかはよくなく、Levelでロードが完全に終わっており かつ PostLoginが実行されている(PlayerControllerがちゃんと生成されている) 状態でいろいろやっていくと嬉しい
なので
Levelでロードが完全に終わった瞬間、PostLoginが実行されていればPlayerPawnスポーン
あるいは
PostLoginを実行した時、Levelがロード済みならスポーン のどちらかでDoOnceしたら良さそう
Levelがロード済みかどうかは、GameStateの中に変数として保存しておく、もちろんレプリケーションはしない
以下ノード
LevelBP
ListenサーバーではGetPlayerControllerの0が常にOwningなやつっぽいので、Authorityは見てない
ロード終わったタイミングでPlayerControllerがあるかどうかは確実ではないので、あればイベント送る感じにしておく
GameMode
OnPostLoginをオーバーライドすると、ログイン完了毎に呼び出される、サーバー合わせて3人が遊ぶなら3回呼ばれる、Nullの確認は一応したほうが良い気がする
PlayerController
GameStateにあるレベルロード済みかどうかのboolはlocalな変数なので、CliantPostLoginはlocalに実行しないといけない
なのでこのイベントのレプリケーションはRunOnOwingCliantかつ絶対に届いてほしいのでReliableにチェック
詳細はここらへん
Unreal Engine | ブループリントのマルチプレイヤー機能
Pawnをスポーンさせる関数は多分サーバーで実行するならどこでも良いと思うので、あとは適当
ソースもめちゃくちゃ流し読みなので、この記事も適当
マルチプレイのメモ
公式のラーニングやりましょう
Blueprint Multiplayer | Unreal Engine
Unreal Engine | マルチプレイヤー シュートアウト
以下箇条
全体編
・クライアント独自の物(所有権が与えられた物)として、PlayerControllerを渡される
・PlayerControllerには自分のPlayerStateの参照が入っている
・パーシスタンとレベルのロード完了、GameModeでクライアントの参加申請(Login)が通ってプレイヤーコントローラーが作成される、ここでPlayerControllerのBeginは走ってしまうけど、このまだログインシークエンスの途中なので、サーバーとやり取りするような処理はちょっとよくない
→代わりにGameModeでOnPostLogin関数をオーバーライドすることで、PlayerControllerが確実に生成されている段階が取れる、ここからPlayerController内のイベントを発火できるので、それをBeginやInit的に使用すると良い
レプリケート編
・文字をレプリケーションするとき、FNameは圧縮されてないので控える
・replicatedUsing=関数名 指定子で、その変数に変数があった際に指定関数をサーバークライアントそれぞれで実行
ReplicatedUsing | Unreal Engine
BPでこれやるときはRepNotifyを指定して、"OnRep_変数名"関数を作る
Unreal Engine | ブループリントのマルチプレイヤー機能
HUDを何処で作成するか
プレイヤーコントローラーがユニークなので、そこで作成すればよさそう
このときリッスンサーバーではプレイヤーコントローラーが複数個あるため、そのままではHUDが多重に描写されてしまう
SwitchHasAuthorityマクロに続いて、IsLocalPlayerControllerのboolを見れば、操作しているPlayerControllerかどうかわかるので、その先で処理を行うようにする
UE4の解像度設定の実装
前回の内容の派生記事、解像度設定部分だけまとめ
とりあえずフルスクリーンと解像度数値設定のみ
ネットで出てくるコンソールコマンド(r.SetRes)をつかった解像度設定は、Configファイルに反映されないので、自分でゲーム開始時にどうこうする必要がある
Configファイル、GameUserSettings.iniという物があって、ここに解像度設定を書いておけば自動で起動ウインドウのサイズや設定をやってくれる
このConfigファイルを更新してくれたり、ウインドウサイズを変更する関数を持っているのその名もズバリGameUserSettingsクラスがあり、
GameUserSettingsはC++で関数を作成しなくても、デフォルトのBPノード(GetGameUserSettings)で参照を貰えて、関数も大抵BPに公開されているので、ノーコーディングでConfigファイルの読み込み、書き出しまで行ける
使いそうな関数は
GetScreenResolution - Configにある解像度をみる
GetFullscreenMode - ConfigにあるFullscreenMode(ウインドウモード、0はフルスクリーン、1はウインドウドフルスクリーン、2はウインドウのenum)をみる
更新するとき
ConfirmVideoMode - LastUserConfirmedResolutionSizeX みたいに、解像度とウインドウ設定は前回の値を保存しておく変数があって、そこに現在の値を代入する関数、これを使うと例えば、解像度変更でよくある、10秒以内にOKを押すと確定みたいな処理が作りやすいみたいな話だと思う、必要なければいらない
SetScreenResolution - 解像度更新
SetFullscreenMode - ウインドウモード更新
SaveSettings - Configファイル更新
このままだとファイルだけ更新されて見た目変わらないので、おなじみのr.SetResかRequestResolutionChangeで任意のタイミングで変える
ひとつ問題があって、デフォルトのウインドウドフルスクリーンからウインドウモードに変更した時、ツールバーがデスクトップの上に隠れてしまうので、再起動を要請するか、ちょっとずらすコードが要る