概要
2022/06/27に Netcode for GameObjects 1.0.0 がリリースになりました🎉
Netcode for GameObjects は、Unity ゲームエンジン用に構築されたネットワーキングライブラリ
以前はMLAPIという名前だったらしい
「DOTS Netcode」とは別にGameObjectに対応しているため「for GameObjects」
これをUnity Third Personサンプルに適用してマルチ同期3Dアクションを作るのが今回の目標です
テスト環境
Unity : 2021.3.6f1 Personal
Netcode for GameObjects : 1.0.1
成果物
コード : https://github.com/tsune2ne/NetcodeTP
自分がHost、他2体がClient接続してます
ServerもビルドしてClient接続できました
コントローラー対応もされてるのでThirdPersonモックとしてもいい感じに使えます
前提知識
オンラインゲームではListenサーバー形式とDedicatedサーバー形式があります
Listenサーバー
クライアントとサーバーが一つのプログラムで一緒に動作する
サーバーはHostと呼ばれ、他クライアントはHostにアクセスして同期する
気軽に作れる半面、Hostの処理が過剰になりボトルになるので重い処理には向かない
Dedicatedサーバー
専用サーバーを用意し、すべてのクライアントが専用サーバーにアクセスして同期する
専用サーバーでは専用の処理が実行されるため、Listenサーバーよりも重い処理に向いている
Unity NetcodeではListenサーバーで簡単に作れつつ、
UnityのDedicated ServerビルドでDedicatedサーバーも作れます
やったこと
- ゲーム開始時にGUIによる初期化処理
- NetworkManagerを作ってPlayerPrefabにPlayerArmatureを設定
- StarterAssetInputsを実行時に操作キャラに設定
- PlayerFollowCameraを実行時に操作キャラに設定
- 理由は後述
- ThirdPersonControllerのUpdateで位置と回転を他端末に同期
- ThirdPersonControllerのアニメーションイベントを他端末に同期
- Animator操作頻度が増えるので別クラスに分離
ハマったこと
HelloWorldチュートリアルが動かない
https://docs-multiplayer.unity3d.com/netcode/current/about/index.html
「Your First Networked Game」→「Module One」→「Module Two」
の順番でやるとOK
ただいくつかバグがあるので注意
- ClientNetworkVariableは使わないので削除
- 「Click + to create a slot.」は嘘。Unity2021では「Player Prefabs」に設定するだけで「Network Prefabs」は不要
NetworkManagerのPlayerPrefsの扱い
起動時にClient別でPlayerPrefabが生成される
入力やカメラ追従は自分管理のPlayerPrefabにだけ設定されるようにしないといけない
TPサンプルではデフォでPlayerArmatureに設定されるので
調整する必要があった
ClientかServerか判別したい
- NetworkManager.Singleton.IsClient
- NetworkManager.Singleton.IsServer
を使う
端末 | 概要 | IsHost | IsClient | IsServer |
---|---|---|---|---|
None | 未設定 | false | false | false |
Host | P2Pの主 | true | true | true |
Client | 1メンバ | false | true | false |
Server | Server起動する場合の主 | false | false | true |
IsHostの扱いを間違えやすい
→ Listenサーバー形式の知識が足りてなかった
IsLocalもあるが今回は除外
自分操作キャラと同期キャラで処理を分けたい
NetworkManager.Singleton.IsOwner を使う
自端末がそのPlayer Prefabを操作しているかが分かる
入力を伝播させるか、親同期を無視するかに使う
NetworkVariableはなに?
HostからClientに変数を同期してくれる
ServerRPCで送る必要がないので簡単
Triggerを送る場合はServerRPCで送ったほうがよい
Serverを起動したい
UNITY_SERVER時にStartServerする
void Start()
{
#if UNITY_SERVER
NetworkManager.Singleton.StartServer();
#endif
}
あとはPlatformを DedicatedServer にしてビルドするとServerバイナリができる
(ServerBuildがなくなってDedicatedServerになったっぽい)
Serverバイナリを起動するとServerとして起動できる
Clientバイナリから接続できる
まとめ
同期通信を実装したのは初めてだったが簡単に対応できた
ThirdPersonサンプルに入れれると簡単にモックが作れるので便利
今後やりたいこと
- 通信チューニングの設定やドキュメントのありかを調べる
- ネットワーク設定してないので外部公開する場合の作業しりたい
- NetworkManagerのConnectionDataでできそう
- Serverでも描画負荷がかかってるので軽減したい
- DOTS Netcodeもやりたい
参考