Photonについては色々と使い慣れたので、今度はUNETを少し研究してます。

まず思ったのは、PhotonよりもUNETのほうがGUIベースでの開発に向いてるということ。
これは単に、本家が作るのでUnityのインスペクターに精通してるからGUI化しやすいということだと思います。
少しのスクリプト改良で、オンラインで歩くキャラの同期が完了します。

まずメニューシーンとメインシーンを作ります。
メインにはカメラ、ライト、地面があれば大丈夫です。
メニューシーンの前に、下記手順でキャラクターを用意しておきます。

  1. StandardAssetsからCharacterをインポートする。
  2. TPSキャラのプレハブにNetworkIdentityを付け、Local Player Authorityにチェックを入れる。
  3. TPSキャラのプレハブにNetworkTransformとNetworkAnimatorも付ける。
  4. NetworkAnimatorの設定をする。(全てチェックを入れてもok)
  5. TPSキャラの操作スクリプトをネットワーク用に書き換える。
    ・using UnityEngine.Networkingの追加。
    ・MonoBehaviourをNetworkBehaviourに書き換え。
    ・Update系関数(LateUpdateやFixedUpdateなど)にif(!isLocalPlayer)return;の追加。

キャラが終わったら、メニューのほうを下記手順で作成。

  1. 空オブジェクト作成。
  2. 空オブジェクトにNetworkManagerとNetworkManagerHUDを追加。
  3. NetworkManagerにofflineシーンとして登録する。(ゲーム終了などで戻ってくるシーン)
  4. NetworkManagerにキャラのプレハブを登録する。(SpawnInfoの中)

これでビルドして起動してみると、双方の画面で同期するキャラが見れると思う。
向きの同期が少し遅いので、NetworkTransformのInterpolate Rotationを4くらいにしておくと良くなる。

どっちが自分のキャラか分からなくならないように、ローカルキャラに色付けしたい場合は、NetworkBehaviourを継承したオブジェクトが使えるオーバーライド関数を利用するのが便利。

public override void OnStartLocalPlayer()
{
	GetComponentInChildren<SkinnedMeshRenderer>().material.color = Color.red;
}

こうすると、自分のキャラだけが赤くなる。
これでUNETの基本中の基本は終了。

WS000515

次に、ホスト切断時にホストを引き継ぐ方法について。

これは、標準で用意されてるコンポーネントを使用する場合、NetworkManagetと同じオブジェクトに、NetworkMigrationManagerを追加すると出来る。
このコンポーネントは、ゲーム中にホスト不在になった場合、画面上にGUIを表示してボタン選択でホストを引き継げる機能。
標準機能にしては少し粗末な作りだが、拡張は出来るようになっているので、これを基本に自分のゲームにあったものを作ると良い。

拡張する際は、単純にクラスを継承するのが簡単。
例えば、Photonのように自動でホストを引き継ぐ場合は、このスクリプトで行ける。

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
using System.Collections;


public class MyMigrationManager : NetworkMigrationManager
{
	public float reconnectTimeout = 10f;

	Coroutine reconnectCoroutine;

	void Update()
	{
		// ホストの再接続は不具合が出るので禁止.
		//if (hostWasShutdown){}

		// クライアントの再接続.
		if (disconnectedFromHost && reconnectCoroutine==null)
		{
			PeerInfoMessage mess;
			bool beHost;
			if (FindNewHost(out mess, out beHost))
			{
				newHostAddress = mess.address;
				if (beHost)
					waitingToBecomeNewHost = true;
				else
					waitingReconnectToNewHost = true;
			}

			// タイムアウトループ.
			reconnectCoroutine = StartCoroutine(ReconnectCoroutine());
		}
	}

	IEnumerator ReconnectCoroutine()
	{
		// タイムアウトループ.
		for (var t=0f;t<reconnectTimeout;t+=Time.deltaTime)
		{
			if (waitingToBecomeNewHost && NetworkManager.singleton != null)
				BecomeNewHost(NetworkManager.singleton.networkPort);
			else if (waitingReconnectToNewHost)
			{
				Reset(oldServerConnectionId);

				if (NetworkManager.singleton != null)
				{
					NetworkManager.singleton.networkAddress = newHostAddress;
					NetworkManager.singleton.client.ReconnectToNewHost(newHostAddress, NetworkManager.singleton.networkPort);
				}
			}
			yield return null;
		}
		reconnectCoroutine = null;
	}
}

これをNetworkMigrationManagerの代わりに付けておけば、ホスト切断時は自動で新規ホストが選ばれる。
ただし、デフォのNetworkMigrationManagerは、ホストが何度も再接続するとエラーが出るらしいので、自動化処理は見送った。

まだ発展途上の機能のようなので、ドキュメントもほとんど無く、Unity開発者GITから中身を調べて使わなければ、まともに作ることは難しいだろう。

というわけで、ネットワークの機能に関してはまだPhotonのほうが使い勝手が良さそうである。
UNETに関しては、今後の発展とサンプルやドキュメントの充実に期待。