LoginSignup
23
23

More than 5 years have passed since last update.

[Unity] NetworkViewを使ってネットワークでオブジェクトを同期させる

Last updated at Posted at 2015-02-11

Unityにはリアルタイムに、ネットワークを介してオブジェクトの位置などを同期する仕組みが用意されています。
Hello Worldはとても簡単で、NetworkViewコンポーネントを該当のオブジェクトにアタッチするだけです。

実際にはいくつかの分岐処理などを書かないとなりませんが、ネットワークを通してデータのやり取りをする部分などはほぼUnityが対応してくれます。これはとても便利な機能です。さすがUnity。
(ちなみにこちらの記事を参考にさせていただきました)

セットアップ手順

  1. ネットワークを介して操作したいオブジェクトをPrefab化する
  2. 該当オブジェクトにNetworkViewコンポーネントをアタッチする
  3. NetworkManager的なオブジェクトを作り、操作するためのスクリプトをアタッチする
  4. Networkクラスのメソッドを用いてセットアップする
    1. 具体的にはNetwork.InstanciateNetwork.DestroyNetwork.ConnectNetwork.InitializeServerメソッドなどを用いる

具体的に見て行きましょう。

Prefab化する

このあたりはネットワーク関係なく通常の手順ですね。
Prefab化することでスクリプトから動的に生成することが可能となります。
ただひとつ注意点として、通常はInstantiateを使ってインスタンス化しますが、NetworkViewを介して操作するオブジェクトはNetwork.Instantiateメソッドを使ってインスタンス化します。
(基本的な引数はInstantiateと同様、第4引数にグループをint型で指定します)

Network.Instantiate
Network.Instantiate(objectPrefab, objectPrefab.transform.position, objectPrefab.transform.rotation, 1);

NetworkViewコンポーネントをアタッチする

通常通り、Add ComponentNetworkViewと検索すると出てくるコンポーネントをアタッチします。
基本的にはこれだけです。

NetworkViewのアタッチ

NetworkManagerを作る

通常のPrefab同様、Prefab化してコンポーネントをアタッチしても画面にはなにも表示されません。
それを管理するオブジェクトがないからです。
なので、空のオブジェクトでもカメラでもなんでもいいですが、NetworkManagerの役割を担うオブジェクトに、NetworkViewをコントロールするスクリプトをアタッチします。

具体的には、Prefabをインスタンス化する処理と、サーバの起動、クライアントからの接続といった処理を実装します。

NetworkManager
using UnityEngine;
using System.Collections;

public class NetworkManager : MonoBehaviour {
    public GameObject objectPrefab;
    string ip      = "127.0.0.1";
    string port    = "1192";
    bool connected = false;

    private void CreatePlayer() {
        connected = true;
        Network.Instantiate(objectPrefab, objectPrefab.transform.position, objectPrefab.transform.rotation, 1);
    }

    public void OnConnectedToServer() {
        connected = true;
    }

    public void OnServerInitialized() {
        CreatePlayer();
    }

    public void OnGUI() {
        if (!connected) {
            if (GUI.Button(new Rect(10, 10, 90, 90), "Client")) {
                Network.Connect(ip, int.Parse(port));
            }
            if (GUI.Button(new Rect(10, 110, 90, 90), "Master")) {
                Network.InitializeServer(10, int.Parse(port), false);
            }
        }
    }
}

Network.Connectメソッド

こちらはクライアントサイドで実行するものです。Connectからも分かるように、サーバを起動したのちに実行することでサーバに接続します。
引数はIPアドレスとポート番号です。

Network.Connect
Network.Connect(ip, int.Parse(port));

Network.InitializedServerメソッド

こちらも見た通り、サーバサイドとして起動するためのメソッドです。
引数はコネクション数ととポート番号を指定します。第三引数にはNatを使うかのbool値を指定します。

Network.InitializeServer
Network.InitializeServer(10, int.Parse(port), false);

RPC(Remote Procedure Call)

さて、以上で位置や回転などは自動的に同期されるようになります。
しかし、例えばキャラクターが移動してなにかしらのアクションを実行するためのメソッドを呼びだそうとするとします。
しかし普通に実装するとこれはうまく行きません。
ネットワーク越しでは直接関数が実行できないからです。
そこで利用されるのがRPC(Remote Procedure Call)と呼ばれる、リモートの関数呼び出しを可能にする技術です。

これはUnityは関係なく、一般的に用いられる方法です。
これをUnityでも利用してリモートでのメソッド呼び出しを可能にします。

具体的には以下のように定義、実行することで実現できます。

定義

RPC-define
[RPC]
void AnyMetho(string name, int num) {
    // RPC経由で実行したいメソッド
}

[RPC]というAttributeを付けることでRPCで利用することを宣言できます。

実行

RPC-perform
networkView.RPC("AnyMethod", RPCMode.All, "name", 10);

networkViewRPCメソッドを、上記のようにメソッド名やモード、RPCで呼び出したいメソッドの引数を指定して実行することでRPCに対応したメソッドを実行することができます。

※ ここでのnetworkViewはGameObjectにアタッチされているNetworkViewコンポーネントです。NetworkViewコンポーネントがアタッチされているとGetComponentを実行しなくても参照可能です。

23
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
23