ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

Unityのサーバクライアント通信

参考サイト

Unityで通信してみよう!
ほかにも参考にしたはずだが、覚えていない。

本題

Unityでマルチプレイ通信をしたかった。一番簡単かつ手軽そうな上記サイトを参考に構築した。

スクリプト「NetworkManager.cs」

using UnityEngine;
using System.Collections;

public class NetworkManager : MonoBehaviour {
	//ファイヤーウォールを無効化してテスト
	//ファイヤーウォールの接続を許可すること.
    public GameObject objectPrefab;
	public GameObject objectPrefab2;
    //string ip = "127.0.0.1";
	public string ip = "localhost";
	public string port = "5037";
    bool connected = false;

	//サーバ立ち上げ時に呼ばれるメソッド
	public void OnServerInitialized()
	{
		connected = true;
		//ネットワーク内のすべてのPCでインスタンス化が行われるメソッド
		Network.Instantiate(objectPrefab, objectPrefab.transform.position, objectPrefab.transform.rotation, 1);
	}

	//サーバに接続したときに呼ばれるメソッド
    public void OnConnectedToServer()
    {
   		connected = true;
		Network.Instantiate(objectPrefab2, objectPrefab2.transform.position, objectPrefab2.transform.rotation, 2);
    }
		
    public void OnGUI()
    {
        if(!connected)
        {
			//
			GUI.Label (new Rect (40, 250, 100, 30), "HOST IP");
			Rect rect1 = new Rect(100, 250, 250, 30);
			ip = GUI.TextField(rect1, ip, 32);

            if( GUI.Button( new Rect( 10, 10, 90, 90), "Client"))
            {    
				//(hostのIPアドレス,hostが接続を受け入れているポート番号)
                Network.Connect(ip, int.Parse(port) ); 
            }
            if( GUI.Button( new Rect(10, 110, 90, 90), "Server"))
            {    
				//(接続可能人数,接続を受け入れるポート番号,NATのパンチスルー機能の設定)
                Network.InitializeServer(10, int.Parse(port), false);
			}
        }
    }

    void Start () {}
    void Update () {}
}

正直書いた記憶がない。絶対どこかのコピペしたと思うんですけど。

サンプル実装

1.空のオブジェクトを作成し、それに上記のスクリプトを張り付ける。名前を「NetworkManager」とする。

f:id:takeg:20141102053440p:plain
こんな感じ。「Object Prefab」の欄はまだ気にしない。

2.適当にオブジェクトを作成する。それに「Network View」コンポーネントをつける。「Add Component>Miscellaneous>Network View」でできる。

f:id:takeg:20141102054617p:plain
赤いカプセル「Player1」と緑色のカプセル「Player2」を作成。
f:id:takeg:20141102054832p:plain
「Player1」はこんな感じ。「Network View」コンポーネントをつける。もちろん「Player2」にもつける。
「Player1」と「Player2」はプレファブにし、Hierarchyビュー上から消しておく。
この際、各Positionの値はカメラに映るように設定しておくこと。

3.「Network Manager」の「Object Prefab」に「Player1」を設定する。

上記の1節のような設定にする。
「Object Prefab」には「Player1」を、「Object Prefab2」には「Player2」を設定する。

4.ビルドして実行する。

名前は「test.exe」とでもして、実行する。
f:id:takeg:20141102055902p:plain
実行すると、このような画面になる(真ん中の白いオブジェクトは便宜上作成した)。

さて、ここから実際に通信できているのか確かめるのだが、1つのPC上で確認するため、IPアドレスlocalhostのままで実行する。
あとたぶんいろいろ警告が出たりすると思われるが、自己責任の上、実行してください。

5.「Server」を押す。

f:id:takeg:20141102060117p:plain
赤いカプセル「Player1」が生成されたのがわかる。スクリプトでいう「OnServerInitialized()」が実行され、「Player1」がインスタンス化されたからである。

6.もう一度実行ファイルを実行する。

今実行している画面は消さずに、もう一度「test.exe」を実行する。

7.今度は「Client」を押す。

たぶん何も変化がないと思われるが、立ち上げている2つの画面を交互にクリックしていくと緑のカプセル「Player2」も生成されるはず。これは一つのPC上で立ち上げていることが原因らしい。
f:id:takeg:20141102061312p:plain
こんな感じになったら成功。
両方の画面で緑の「Player2」が作成されていれば、両画面で通信ができている証拠。

注意点

うまくいかない場合は、ファイアウォールが通信を妨げているか、ポートの設定がうまくいっていない可能性がある。ファイアウォールは一時的に止めておくと良いかも。あと上記スクリプトではポート番号5037となっているが、各人で接続可能なポート番号は異なるので注意。

空きポート番号の調べ方

コマンドスクリプトを立ち上げ、「netstat -an」を実行。状態LISTENINGが待ち受け状態で、そのローカルアドレスを調べればよい。たとえば「127.0.0.1:5037」は「(ローカルアドレス):(ポート番号)」で、5037が待ち受け状態のポート番号。
とか書いたけど、正直よくわからないのでググってください。

IPアドレスの調べ方

コマンドプロンプトで「ipconfig」を実行。IPv4アドレスがそれ。