こんにちは、ちゃらいプログラマです。
Unity Lobby/Relayの最後はRPC送受信周りになります。
※前回の記事はこちら
Unity Lobby/Relay入門 (#1) - アヒルのある日
Unity Lobby/Relay入門 (#2) - アヒルのある日
実装としては、#1で用意していた
public class NetworkObjectBehaviour : NetworkBehaviour
{
}
を使用します。
ただ、このままだとNetworkObjectBehaviourを使用する手段がないので、#2で用意した「MultiGameManagerクラス」に「NetworkObjectBehaviour」のアクセサを定義します。
private NetworkObjectBehaviour m_networkObject = null;
public NetworkObjectBehaviour GetNetworkObject()
{
// Relayネットワークから切断するとnullになります。
// エラー処理は別途必要です。
return m_networkObject ;
}
public void SetNetworkObject(NetworkObjectBehaviour networkObject)
{
m_networkObject = networkObject;
}
では、RPC周りを実装していきます。
public class NetworkObjectBehaviour : NetworkBehaviour
{
// Startで処理しているのはNetworkManager(Unity用意)の生成処理を待つ必要があるためです
public void Start()
{
// NetworkObjectBehaviourはRelayネットワークに接続された人数分生成されます
// IsOwner()で自分自身かどうかを判定できるので、自身の場合に設定しておきます
if(IsOwner())
{
MultiGameManager.Instance.SetNetworkObject(this);
}
}
// RelayネットワークでのRPCルールについて
// ホスト管理方式を採用しているため、ホスト以外のプレイヤーはホスト経由で送受信する必要があります
// 受信側の関数に以下の属性を付与します
// [Unity.Netcode.ClientRpc]
// クライアントで実行されるようになります
// 関数の末尾に【Rpc】を付与しないとエラーになります
// [Unity.Netcode.ServerRpc( RequireOwnership = false )]
// ホストで実行されるようになります
// RequireOwnershipはfalseにしていないと自身の所有権のみしか操作できないのでfalseにしておきましょう
// 関数の末尾に【Rpc】を付与しないとエラーになります
// ケース1:ホストから全員(ホスト含む)に送信する
// [Unity.Netcode.ClientRpc]属性の関数を用意します
// ホストもクライアント判定のため同関数が実行されます
public void SendStart()
{
// ホストのみ実行するように判定します
// IsHostは用意されていますので使用させてもらいます
if(IsHost)
{
ReceiveStartClientRpc();
}
}
[Unity.Netcode.ClientRpc]
private void ReceiveStartClientRpc()
{
// ホスト、クライアント共に実行されます
}
// ケース2:クライアントからホストに送信する
// [Unity.Netcode.ServerRpc]属性の関数を用意します
public void SendClientToHost()
{
// クライアントのみで実行できるようにします
if(!IsHost)
{
ReceiveClientToHostServerRpc();
}
}
[Unity.Netcode.ServerRpc( RequireOwnership = false )]
private void ReceiveClientToHostServerRpc()
{
// ホストのみで処理するようにします
if(IsHost)
{
// 処理を記述
}
}
// ケース3:自分自身以外に送信する
// [Unity.Netcode.ClientRpc][Unity.Netcode.ServerRpc]属性の関数を用意します
public void SendOther()
{
// ホストの場合はクライアントへ反映する
if(IsHost)
{
ReceiveOtherClientRpc();
}
// クライアントの場合はホスト経由で他クライアントへ反映する
else
{
ReceiveOtherServerRpc();
}
}
[Unity.Netcode.ClientRpc]
private void ReceiveOtherClientRpc()
{
// 自身の情報を反映しないように判定を追加します
// IsLocalPlayerは用意されているので使用させてもらいます
if(!IsLocalPlayer)
{
// 他クライアントの情報を反映する処理
}
}
[Unity.Netcode.ServerRpc( RequireOwnership = false )]
private void ReceiveOtherServerRpc()
{
// ホストはクライアント関数をそのまま呼び出せばOKです
ReceiveOtherClientRpc();
}
}
実際にMultiGameManager経由で実行する場合は
MultiGameManager.Instance.GetNetworkObject().SendStart()
のようになります。
いかがでしたでしょうか。
実際に使用するとなると、【ホスト移譲】を実装する必要がありますがかなりややこしいので機会があれば…
個人的にはPhotonEngineで提供されている
Fusion2 のトポロジー:ホストモード
と同じだと感じました。
ではまた次回!