【Unity4.6】サーバ・クライアントを別Unityプロジェクトに分けたときのRPC呼び出し

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]を追加

パラメータは適宜設定のこと。
![サーバ側](https://qiita-image-store.s3.amazonaws.com/0/78568/c8521864-e4c2-a231-38d6-2207458e5743.png)

* [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]を追加

パラメータは適宜設定のこと。
![img150603Client_.png](https://qiita-image-store.s3.amazonaws.com/0/78568/8207e6c3-1efd-aeaf-a53c-2d3ae1d8748d.png)

* [Project Settings]/[Player]/[Run In Background]にチェックを付けておくこと

# 実行

サーバ側を実行してからクライアント側を実行すると、それぞれのコンソールにいろいろ出力される。
サーバ側のコンソールを見てみると、RPCが呼ばれていることがわかる。
ちなみに、同名のRPCメソッドを持つスクリプトコンポーネントが複数存在する場合は、Inspectorで上の位置に貼られているものから先着で呼ばれるようだ。