202 1 オブジェクトの同期方法

miuccie miurror edited this page Jan 6, 2018 · 8 revisions

202-1 - オブジェクトの同期方法


オブジェクトの同期

無事にルームにログインできたら、まずはオブジェクトの生成と位置情報の同期を行ってみましょう。

Photonでは、PhotonViewというコンポーネントをアタッチすることで、他プレイヤーと同期するオブジェクトを指定します。

PhotonViewはクライアント間の通信の橋渡しをする、PUNにおける最重要のコンポーネントです。PhotonではPhotonViewごとに内部的なIDを振り、このIDを使用して別クライアント上のPhotonViewとの同期通信を行っています。

このPhotonViewを用いて、プレイヤーごとのAvatarオブジェクトの生成と位置情報を同期させることにします。


同期オブジェクトの指定

まず、Avatarオブジェクトをインスペクターで開き、AddComponentからPhotonViewコンポーネントを選んでアタッチしてください。

PhotonViewのObvservedプロパティには、同期させたい別のコンポーネントを指定することができますが、ここではオブジェクトのtransformの状態を自動で同期してくれる、PhotonTransformViewを使用してみます。

インスペクターのAddComponentより、PhotonTransformViewコンポーネントを追加してください。

さらに追加したPhotonTransformViewコンポーネントのSyncronized PositionSyncronized Rotationにチェックを入れます。Interpolate Optionには各種補間方法が指定できますが、ここではデフォルトのままとします。

AvatarオブジェクトにPhotonTransformViewをアタッチしたら、PhotonTransformViewのヘッダ部分をドラッグして、PhotonViewのObservedに追加します。


同期オブジェクトのプレファブ化

各プレイヤーを表現するAvatarオブジェクトは、プレイヤーがルームにログインしてくる度にスクリプトから動的に生成する必要があります。

PhotonViewをアタッチしたオブジェクトを動的に生成するには、事前にPrefabとして保存しておく必要があります。

Resourcesという名前のフォルダを作成し、AvatarオブジェクトをそのフォルダへD&Dしてください。この際、大本のAvatarオブジェクトはあとで修正する可能性があるので、ここでは消さずにアクティブのチェックを外しておくだけにします。


同期オブジェクトの動的生成

PhotonViewがアタッチされたオブジェクトを実際に生成するには、PhotonNetwork.Instantiate()を使用します。第一引数にResourcesフォルダ下にあるプレファブへのパスを指定します。

Playerスクリプトを下記のように変更してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace VRStudies { 

public class Player : MonoBehaviour {

        // Joinイベントをリッスン
	//------------------------------------------------------------------------------------------------------------------------------//
	void OnJoinedRoom() {

		// ルームログイン後に呼ぶ
		CreateAvatar ();
	}

	//------------------------------------------------------------------------------------------------------------------------------//
	void CreateAvatar () {

		Debug.Log("Player: 自分のアバターを生成します.");

		// Photon経由で自分のアバターを動的に生成
		// 自分のアバターが他クライアント上にも自動で生成される = 他クライアントが生成したアバターは自クライアント上に自動で生成される
		GameObject avatar = PhotonNetwork.Instantiate("Avatar", new Vector3(0, 1, 0), Quaternion.identity, 0);
		avatar.transform.parent = transform;

		// カメラを自身のアバターの子にする
		GameObject camera = transform.Find("Camera").gameObject;
		camera.transform.parent = avatar.transform;
	}
}
}

Start()を使用せずにOnJoinedRoom()経由でAvatarオブジェクトの生成を行なっていることに注意してください。同期対象のオブジェクトは起動直後ではなく、Photonのルームへのログインが完了するのを待ってから生成するようにする必要があります。

ここで複数クライアントを起動して実行してみて、ルームに新しいプレイヤーがログインする度にAvatarオブジェクトが生成されるのを確認してください。

所有権の判定

先の状態で実行すると、自身を移動させようとした際、他人のAvatarも一緒に動いてしまったのではないでしょうか。キー入力による自キャラの移動などを行いたい場合、自クライアントで生成したオブジェクトだけを操作の対象にする必要があります。

これを行うには、自クライアントが生成し他クライアントへ同期したオブジェクトと、他クライアントで生成され自クライアントへ同期されたオブジェクト を見分ける必要があります。

この判定は、PhotonView.IsMineによって行うことができます。
Avatarスクリプトを下記のように修正して再び実行してみてください。

using UnityEngine;
using System.Collections;

namespace VRStudies { 

public class Avatar : Photon.MonoBehaviour {

	//------------------------------------------------------------------------------------------------------------------------------//
	void Update () {

		// 自クライアントが生成したオブジェクトの場合のみ実行
		if( photonView.isMine == false ){
			return;
		}

		// キーボード入力による移動処理
		var v = Input.GetAxis ("Vertical");
		Vector3 velocity = new Vector3 (0, 0, v);
		velocity = transform.TransformDirection (velocity);
		velocity *= 5f;
		transform.localPosition += velocity * Time.fixedDeltaTime;

		// キーボード入力による回転処理
		var h = Input.GetAxis ("Horizontal");
		transform.Rotate (0, h * 3f, 0);
	}

}
}

なおこの際、Avatarクラスの親クラスをPhoton.MonoBehaivourクラスに変更していることにも注意してください。Photon.MonoBehaviourは、自身のスクリプトが紐づくオブジェクトにアタッチされているPhotonViewコンポーネントへのアクセスを提供するヘルパークラスです。

これで再び実行してみてください。自分のアバターのみが動くようになったでしょうか。


講義で実装したマルチプレーヤー対応は下記シーンにまとめて収められています
https://github.com/yumemi-inc/vr-studies/tree/master/vol2/VR-studies/Assets/VR-studies/1_MultiPlayer/MultiPlayer.unity

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.