PUNを使ってネットワーク同期を行う -Vol.2-

photon_realtime_turquoise

Photon運営事務局です。
ここでは前回の記事の引き続きの内容になりますので、
あらかじめ読み進めておいてください。

PUNを使ってネットワーク同期を行う -Vol.1-
http://blog.photoncloud.jp/getting-started-pun-01/

そもそもPhoton Viewとは

クライアント間で通信を行いたい際にオブジェクトにPhotonViewコンポーネントを追加し、
Obaserved(監視対象)を指定してやると、そのオブジェクトがネットワーク上で
同期されるようになります。
なお、子オブジェクトをPhoton上で同期したい場合は、親オブジェクトだけでなく、
子オブジェクトにもPhoton Viewコンポーネントを追加すると同期されます。

詳細については前回の記事のPhotonViewの設定を行うの項目をご覧ください。
PUNを使ってネットワーク同期を行う -Vol.1-
http://blog.photoncloud.jp/getting-started-pun-01/

実際にスクリプトを同期する

それでは前回のプロジェクトのCubeを利用し、様々な変数を同期してみましょう。
前回ではPhoton ViewでTransformの値を同期しました。今回はスクリプトを使って、
変数の同期を行っていこうと思います。

ここではPhotonでCubeに色を同期させます。
前回作成したGameController.csのスクリプトのUpdateメソッドへの追加と、
ChangeColorメソッドを追加してください。

    void Update()
    {
        if (photonView.isMine)
        {
            float x = Input.GetAxis("Horizontal");
            float z = Input.GetAxis("Vertical");
            transform.Translate(x * 0.2f, 0, z * 0.2f);
            if(Input.GetKeyDown(KeyCode.Space))
            {
                renderer.material.color = ChangeColor();
            }
        }
    }

    Color ChangeColor()
    {
        switch(Random.Range(0, 5))
        {
        case 0: return Color.red;
        case 1: return Color.blue;
        case 2: return Color.green;
        case 3: return Color.yellow;
        case 4: return Color.white;
        case 5: return Color.black;
        }
        return Color.clear;
    }

これにより、スペースキーを押下すると、ランダムでColorが変化(6色)するようになります。
21行目のif(Input.GetKeyDown(KeyCode.Space))によってスペースキーが押された際、
ランダムで取得した数値によって、オブジェクトに対して色を指定しています。
詳細についてはUnityのスクリプトリファレンスをご覧下さい。

次に、下記のようなスクリプトを作成します。ここではCubeSerializerクラスとします。
簡単に内容を説明すると、Transformのpositionとrotationの値、
そしてCubeのColorをRBGAの変数に分けて同期を行っています。
詳細については後述します。

using UnityEngine;
using System.Collections;

public class CubeSerializer : Photon.MonoBehaviour
{
    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting) {
            //データの送信
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(renderer.material.color.r);
            stream.SendNext(renderer.material.color.g);
            stream.SendNext(renderer.material.color.b);
            stream.SendNext(renderer.material.color.a);
        } else {
            //データの受信
            transform.position = (Vector3)stream.ReceiveNext();
            transform.rotation = (Quaternion)stream.ReceiveNext();
            float r = (float)stream.ReceiveNext();
            float g = (float)stream.ReceiveNext();
            float b = (float)stream.ReceiveNext();
            float a = (float)stream.ReceiveNext();
            renderer.material.color = new Vector4(r, g, b, a);
        }
    }
}

スクリプトの解説をします。
4行目はPhoton.MonoBehaviourを継承しています。PhotonのMonoBehaviourを継承することによって、オーバーライドされたメソッドを呼び出すことが可能となります。
今回はOnPhotonSerializeViewメソッドを利用するので必ず継承しておく必要があります。

6行目のOnPhotonSerializeViewメソッドで実際に他のキャラクターとの同期を行っています。
このメソッドが呼ばれるタイミングは呼ばれるタイミングは PhotonView.sendRateOnSerializeを変更することで、1秒間に何回呼ばれるか調節可能です。
PhotonではUpdateメソッドとは非同期処理を行っています。

8行目でPhotonStreamが書き込まれているか判断しています。
tream.isWritingの時、自分自身が送信したいデータを書き込み、それ以外の場合は受信を行っています。
ここで送信している内容は前述の通り、オブジェクトのPosition、Rotation、そしてMaterialのColorを
RGBAに分けて送信しています。

アニメーションやMecanimなど自分の好みの変数を同期させたい場合は、
同様に変数として設定すれば、同期させることも可能です。

なお、PhotonのPhotonStreamを使って送信する際はデータがシリアライズ(直列化)されます。
つまりSendNextした順にデータが送信されるので、受信時も同様の順番で取得する必要があります。
19行目以降、データの受信後それぞれにセットしています。

ここで作ったスクリプトをPhotonViewの同期対象とします。
そのためにはまずCubeSerializerのスクリプトをCubeプレハブに追加します。
Inspectorにスクリプトが追加され、Cube Serializerと表示されていることを確認してください。

001

次に、先ほど追加したCube SerializerをPhoton ViewのObaserveにドラッグ&ドロップします。
Observerの対象が、画像のようにCubeになったことを確認してください。

002

これによって、位置と傾き、そしてオブジェクトの色を、スクリプトによって同期ができます。

photonView.isMineとは

photonView.isMineでは、実行しているPhotonViewが自分かどうかを判断しています。
これを用いてやらないと、ネットワーク上のすべてのキャラクターを操作してしまいます。
特にプレイヤーを操作するゲームではご注意ください。

ここまでの作ったサンプルプロジェクトは下記にあります。
サンプルプロジェクトですが、Asset StoreからPUNをインポートし、AppIdの設定後、当サンプルプロジェクトをインポートしてください。
Photon Team Japan/ScenesのフォルダのMainシーンが今回の記事と同等の内容になっていますので、是非一度ご覧になってお試しください。

サンプルプロジェクト