#memo

indiedev太郎

Boids

ABZU最高!→Boidsやろう!→糞重い!!

https://i.gyazo.com/bba715ac2ded3aedb0740496895411e5.gif

計算減らせそうな部分
・2,3段階くらいのレベルつくって、そこで計算をさせて、魚自身はそこの値見て動くだけにする
・プレイヤーとの距離で処理の精度を調節する
・Separationの簡略化でそれっぽくが難しい
・単純にメッシュ増えると重くなる(2000くらいから辛い)

https://i.gyazo.com/e003da415e6a98aa8f6f0054ab510b60.gif

あのイワシ玉どうやってんだろう…

プレイヤー名の表示、参加者一覧の取得

https://i.gyazo.com/1bc48631950e8f0b26b3b92e735410bb.png

・ゲーム参加直後はログイン処理がある
・ゲーム開始時クライアント側では、あるはずの変数やインスタンスがちゃんと存在している保証はない

参加者一覧は、各クライアントで、レベルにあるPlayerStateをイテレーターで名前やらPingを取って表示したら良いのだけれど、例えばこれをゲーム開始直後に生成してしまうと、サーバーから人数分すべてのPlayerStateを受信出来ているかどうかが確実ではないなど、ちょっと表示を行う処理のタイミング考えないと行けない
単にDelay置いても良さそうだけれど、100%ではないので、もう少し堅牢な設計がやりたい

よくわかるフロー図
https://i.gyazo.com/9a91f68a0078cf8467241711ce42a372.png

プレイヤー上部の名前表示には、そのプレイヤーのPlayerStateと、そのプレイヤーのログイン初期化処理が終了していることが必要で、自分のフローでは、PlayerPawnのスポーン完了をログインフェーズの最後としている
なので、"PlayerStateのAPawn* ControlledPawn変数が値を受け取った瞬間 = 当該ユーザーのログイン、初期化処理が完全に終了したことを、クライアントで認識した瞬間" であるので、"OnRepControlledPawn関数が発火する = 当該ユーザーの情報に安全にアクセスできる"という感じでやっている

なんかもう少し処理を単純にできそうだけれど、とりあえずこれで安定している

マルチプレイ時のプレイヤーポーンのスポーンのタイミング

GameModeのログイン処理、パーシスタントレベルのロードが終わると始まるっぽいけど、ストリーミングでマップをロードするタイプの設計だと、最悪床のロード前にプレイヤーがスポーンして奈落即ち死になる可能性がある
https://i.gyazo.com/9f60984498e04cfb81aa69b221654c7f.png

かといって、ロード終わった瞬間にプレイヤー周りの処理してしまうと、今度はログイン処理が終了していない可能性があって、最悪な感じになってきている
ここでクッソよく分かる生成タイミングの図を用意する
https://i.gyazo.com/c3b30cc1b176a8cb611ba9d1fd66c096.png

作りがちなPlayerControllerのBeginとかはよくなく、Levelでロードが完全に終わっており かつ PostLoginが実行されている(PlayerControllerがちゃんと生成されている) 状態でいろいろやっていくと嬉しい

なので
Levelでロードが完全に終わった瞬間、PostLoginが実行されていればPlayerPawnスポーン
あるいは
PostLoginを実行した時、Levelがロード済みならスポーン のどちらかでDoOnceしたら良さそう

Levelがロード済みかどうかは、GameStateの中に変数として保存しておく、もちろんレプリケーションはしない

以下ノード

LevelBP
https://i.gyazo.com/cfbc05468a917f125191315f9af60894.png
ListenサーバーではGetPlayerControllerの0が常にOwningなやつっぽいので、Authorityは見てない
ロード終わったタイミングでPlayerControllerがあるかどうかは確実ではないので、あればイベント送る感じにしておく

GameMode
https://i.gyazo.com/0ca54847b5d3649b9b90d0ac7e7bb8d9.png
OnPostLoginをオーバーライドすると、ログイン完了毎に呼び出される、サーバー合わせて3人が遊ぶなら3回呼ばれる、Nullの確認は一応したほうが良い気がする

PlayerController
https://i.gyazo.com/6d52a22b3e616df804237cca838e7e86.png
GameStateにあるレベルロード済みかどうかのboolはlocalな変数なので、CliantPostLoginはlocalに実行しないといけない
なのでこのイベントのレプリケーションはRunOnOwingCliantかつ絶対に届いてほしいのでReliableにチェック
詳細はここらへん
Unreal Engine | ブループリントのマルチプレイヤー機能

Pawnをスポーンさせる関数は多分サーバーで実行するならどこでも良いと思うので、あとは適当
ソースもめちゃくちゃ流し読みなので、この記事も適当

フレームワークについて

マルチプレイの実装みてて、今あらためてフレームワークの役割をちゃんと見ておく必要ある、これはかなり初期にやっておくべきだった感ある
まず適当にゲーム起動して、WorldOutlinerで何があるかみる、ViewOptionsからサーバーに何がありクライアントになにがあるかも見る

続きを読む

UE4の解像度設定の実装

https://i.gyazo.com/e117692314aebab0ae7c662c61203dad.gif


前回の内容の派生記事、解像度設定部分だけまとめ
とりあえずフルスクリーンと解像度数値設定のみ

ネットで出てくるコンソールコマンド(r.SetRes)をつかった解像度設定は、Configファイルに反映されないので、自分でゲーム開始時にどうこうする必要がある
Configファイル、GameUserSettings.iniという物があって、ここに解像度設定を書いておけば自動で起動ウインドウのサイズや設定をやってくれる

このConfigファイルを更新してくれたり、ウインドウサイズを変更する関数を持っているのその名もズバリGameUserSettingsクラスがあり、
GameUserSettingsはC++で関数を作成しなくても、デフォルトのBPノード(GetGameUserSettings)で参照を貰えて、関数も大抵BPに公開されているので、ノーコーディングでConfigファイルの読み込み、書き出しまで行ける

https://i.gyazo.com/a1c6c93c9a2c8571241b34afd559dcfc.png

使いそうな関数は
GetScreenResolution - Configにある解像度をみる
GetFullscreenMode - ConfigにあるFullscreenMode(ウインドウモード、0はフルスクリーン、1はウインドウドフルスクリーン、2はウインドウのenum)をみる

更新するとき
ConfirmVideoMode - LastUserConfirmedResolutionSizeX みたいに、解像度とウインドウ設定は前回の値を保存しておく変数があって、そこに現在の値を代入する関数、これを使うと例えば、解像度変更でよくある、10秒以内にOKを押すと確定みたいな処理が作りやすいみたいな話だと思う、必要なければいらない
SetScreenResolution - 解像度更新
SetFullscreenMode - ウインドウモード更新
SaveSettings - Configファイル更新

このままだとファイルだけ更新されて見た目変わらないので、おなじみのr.SetResかRequestResolutionChangeで任意のタイミングで変える

ひとつ問題があって、デフォルトのウインドウドフルスクリーンからウインドウモードに変更した時、ツールバーがデスクトップの上に隠れてしまうので、再起動を要請するか、ちょっとずらすコードが要る