Unityでネットワークマルチプレイゲームを作るときは、通常ひとつのプロジェクトで作る思想らしい。
しかし場合によって、サーバとクライアントでプロジェクトを明確に分けたいときもある。
今回、サーバとクライアントを分けて開発する必要があり、どうにかRPC呼び出しまで成功したので、メモを置いておく。
サーバ側
- サーバ側のUnityプロジェクトを作成
- サーバ側のスクリプトを用意
ServerSideNetworkManager.cs
using UnityEngine;
using System.Collections;
/// <summary>
/// サーバ側ネットワーク管理
/// </summary>
public class ServerSideNetworkManager : MonoBehaviour {
#region Parameters
NetworkView _thisNetwork = null;
NetworkView thisNetwork{
get{ return _thisNetwork ?? (_thisNetwork = this.networkView); }
}
[Header("<同時接続許容数>")]
[SerializeField] int concurrentConnections = 10;
[Header("<ポート番号>")]
[SerializeField] int port = 8888;
#endregion
void Start(){
if(ErrorCheckOfParameters()) return;
// サーバの初期化
Network.InitializeServer(concurrentConnections, port, !Network.HavePublicAddress());
}
bool ErrorCheckOfParameters(){
var error = false;
if(thisNetwork == null){
Debug.LogError("NetworkViewが存在しません", this);
error = true;
}
return error;
}
#region NetworkEvents
/// <summary>
/// サーバ初期化時
/// </summary>
void OnServerInitialized(){
Debug.Log("Server Initialized.", this);
}
/// <summary>
/// クライアント接続時
/// </summary>
void OnPlayerConnected(NetworkPlayer player){
Debug.Log("Player Connected.\nIP[" + player.ipAddress + "], GUID[" + player.guid + "]", this);
}
/// <summary>
/// クライアント切断時
/// </summary>
void OnPlayerDisconnected(NetworkPlayer player){
Debug.Log("Player Disconnected.\nIP[" + player.ipAddress + "], GUID[" + player.guid + "]", this);
}
/// <summary>
/// RPC呼び出しテスト
/// </summary>
[RPC]
void CallTestRPC(){
Debug.Log("Recieve RPC.");
}
#endregion
}
- ネットワークマネージャ用のオブジェクトを[Create Empty]して適当に命名
- 作ったオブジェクトに[Network View]を追加
- 作ったオブジェクトに、上記スクリプト[ServerSideNetworkManager.cs]を追加
- [Project Settings]/[Player]/[Run In Background]にチェックを付けておくこと
クライアント側
- サーバ側のUnityEditorを残したまま、もうひとつUnityEditorを起動
- クライアント側のUnityプロジェクトを作成
- クライアント側のスクリプトを用意
ClientSideNetworkManager.cs
using UnityEngine;
using System.Collections;
/// <summary>
/// クライアント側ネットワーク管理
/// </summary>
public class ClientSideNetworkManager : MonoBehaviour {
#region Parameters
NetworkView _thisNetwork = null;
NetworkView thisNetwork{
get{ return _thisNetwork ?? (_thisNetwork = this.networkView); }
}
[Header("<接続先IPアドレス>")]
[SerializeField] string ipAddress = "192.168.1.1";
[Header("<ポート番号>")]
[SerializeField] int port = 8888;
#endregion
void Start(){
if(ErrorCheckOfParameters()) return;
// サーバへ接続
Network.Connect(ipAddress, port);
}
bool ErrorCheckOfParameters(){
var error = false;
if(thisNetwork == null){
Debug.LogError("NetworkViewが存在しません", this);
error = true;
}
return error;
}
#region NetworkEvents
/// <summary>
/// サーバ接続時
/// </summary>
void OnConnectedToServer(){
Debug.Log("Connected to Server.", this);
thisNetwork.RPC("CallTestRPC", RPCMode.OthersBuffered);
}
/// <summary>
/// サーバ切断時
/// </summary>
void OnDisconnectedFromServer(NetworkDisconnection disconnection){
Debug.Log("Disconnected from Server.", this);
}
/// <summary>
/// 接続失敗時
/// </summary>
void OnFailedToConnect(NetworkConnectionError error){
Debug.Log("Connection Error.\nError: [" + error + "]");
}
[RPC]
void CallTestRPC(){
// 同名・同引数のRPCメソッドを空でも書いておかないとRPC呼び出しでエラーになる
}
#endregion
}
- ネットワークマネージャ用のオブジェクトを[Create Empty]して適当に命名
- 作ったオブジェクトに[Network View]を追加
- 作ったオブジェクトに、上記スクリプト[ClientSideNetworkManager.cs]を追加
- [Project Settings]/[Player]/[Run In Background]にチェックを付けておくこと
実行
サーバ側を実行してからクライアント側を実行すると、それぞれのコンソールにいろいろ出力される。
サーバ側のコンソールを見てみると、RPCが呼ばれていることがわかる。
ちなみに、同名のRPCメソッドを持つスクリプトコンポーネントが複数存在する場合は、Inspectorで上の位置に貼られているものから先着で呼ばれるようだ。