tanaka's Programming Memo

プログラミングについてのメモ。

UNET 別のプロジェクトからプレハブを生成する(追記)

Unity5.1のUNETの講義で、教員PCが立てたホストに学生さんたちが接続して、オブジェクトをSpawnしようとしたところ、学生さん側で作成したプレハブは、教員PCにデータがないため生成に失敗しました。

NetworkClient.RegisterPrefab()で登録すればよいかと思いましたが駄目でした。この関数は、サーバーとクライアントが同じプレハブを持っていることが前提で、該当するプレハブをネットワークで管理できるように登録するもので、クライアントが持っていて、サーバーが持っていないプレハブを登録するものではありませんでした。そのような利用をする場合は、AssetBundleを利用すればうまくいきそうですが、Pro版の機能なので講義では使えません。

(2015/8/25追記) tsubaki_t1様からご指摘いただき、Unity5からAssetBundleがFree版でも利用できるようになったのでAssetBundleで実現できそうです。 → Unity 4 free と比較して Unity5 Personal Editionで出来るようになった事 - テラシュールブログ

解決策1

UNETでサーバーとクライアントの間で同じプレハブかどうかを判別するのは、プレハブが持つNetworkIdentityのassetIDが同じ値かどうかです。この値が同じプレハブをサーバーとクライアントが持っていれば、異なるプレハブであってもそれがそれぞれのPC上で生成されます。

Unity5.1.2の段階では、NetworkIdentityのassetIDは、ゲームオブジェクトにNetworkIdentityコンポーネントを追加してプレハブ化した時にUnityが自動的に設定するようです。この値は生成後は変更されないので、プレハブをエクスポートして教員と学生が共有すれば、それ以降の作業を個別に進めてもネットワークの制御は維持されます。

講義に利用する予定のゲームオブジェクトについて、予めNetworkIdentityを付加したプレハブを用意しておいて配布する。

解決案2(今のところうまくいかず)

プレイヤー以外のオブジェクトの場合、Spawn時にカスタムのAssetIDを設定する例が公式マニュアルにあります。これがうまく動作すれば、同じAssetIDを付加することで予めプレハブを用意しなくても目的は達成できそうです。

資料が少なく、今のところ動作に成功していません。

プレイヤー用のオブジェクトは、ClientScene.AddPlayer()で生成しますが、この関数にはAssetIDの指定はできず、NetworkManagerのPlayerPrefab欄にサーバーとクライアントで別のオブジェクトを指定すると、サーバー側にはサーバーに登録されているプレハブからクライアント用のオブジェクトが生成されて、クライアント側ではエラーが発生しました。Unity5.1.2の時点では、プレイヤー用のオブジェクトは同一のものである必要があり、この方法は摘要できなさそうです。

解決案3

PRO版があれば、AssetBundleでそれぞれのプレハブを動的に共有することが可能かも知れません。この方法であれば、完全に同じプレハブを全PCで共有できるメリットがあります。今回は用途外なので検証などはしません。

AssetBundleでプレハブを配信することで実現できそうです。これなら各メンバーが作ったプレハブを全員で共有できそうで一番よい解決策なのですが、AssetBundle自体を触ったことがないので後期に扱いたいと思います。(2015/8/25追記)