//tips
//photon is mine の使い方
Photonでのマルチプレイ同期の際、自分の画面のみにUI/動作を反映させたい場合の対応を考える。
photon is mineの使用が自画面のみの表示に利用できるか確認していく。
PhotonView.IsMine は、そのオブジェクトをプレイヤーが生成したかどうかを表すもので、インスタンスがクライアントによって制御されている場合、photonView.IsMineはtrueになり、このインスタンスはこのコンピュータのアプリケーション内でプレイしているユーザーを表す。
falseの場合、PhotonViewコンポーネントに依存し、設定したtransformとanimatorコンポーネントを同期する。
一般的に、ルーム内にてオブジェクト生成の同期を取る際は、PhotonNetwork.Instantiate()を使用し、自分が作成したオブジェクトなのか、他の人が作成したオブジェクトなのか判断する場合に、
isMineプロパティを使用することになる。
これをベースに考えるとNumberPropのpnumberを自身で生成したオブジェクトからしか取れないようにすれば良いので、if (photonView.IsMine)をpnumberの条件分岐前につければ良い。ただ、NumberPropはプレイヤーオブジェクトにアタッチされていないのでphotonView.IsMineを使用できない。
一旦簡単なシーンを作成し、photon is mineの運用を確認していく。
まずは簡単にPhotonNetwork.Instantiate("GamePlayer", v, Quaternion.identity);で生成するgameobjectに下記のスクリプトをアタッチするところから始めた。
using Photon.Pun;
using UnityEngine;
// MonoBehaviourPunCallbacksを継承すると、photonViewプロパティが使えるようになる
public class MoveMine : MonoBehaviourPunCallbacks
{
private void Update()
{
// 自身が生成したオブジェクトだけに移動処理を行う
if (photonView.IsMine)
{
var dx = 0.1f * Input.GetAxis("Horizontal");
var dy = 0.1f * Input.GetAxis("Vertical");
transform.Translate(dx, 0, dy);
}
}
}
ちなみにphotonへの接続は下記を利用した。
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
// MonoBehaviourではなくMonoBehaviourPunCallbacksを継承して、Photonのコールバックを受け取れるようにする
public class SampleScene : MonoBehaviourPunCallbacks
{
private void Start()
{
// PhotonServerSettingsに設定した内容を使ってマスターサーバーへ接続する
PhotonNetwork.ConnectUsingSettings();
}
// マスターサーバーへの接続が成功した時に呼ばれるコールバック
public override void OnConnectedToMaster()
{
// "room"という名前のルームに参加する(ルームが無ければ作成してから参加する)
PhotonNetwork.JoinOrCreateRoom("room", new RoomOptions(), TypedLobby.Default);
}
// マッチングが成功した時に呼ばれるコールバック
public override void OnJoinedRoom()
{
PhotonNetwork.IsMessageQueueRunning = true;
// マッチング後、ランダムな位置に自分自身のネットワークオブジェクトを生成する
var v = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f));
PhotonNetwork.Instantiate("GamePlayer", v, Quaternion.identity);
/*
// 現在のサーバー時刻を、ゲームの開始時刻に設定する
if (PhotonNetwork.IsMasterClient && !PhotonNetwork.CurrentRoom.HasStartTime())
{
PhotonNetwork.CurrentRoom.SetStartTime(PhotonNetwork.ServerTimestamp);
}
*/
}
// 他プレイヤーが参加した時に呼ばれるコールバック
public override void OnPlayerEnteredRoom(Player player)
{
Debug.Log(player.NickName + "が参加しました");
}
// 他プレイヤーが退出した時に呼ばれるコールバック
public override void OnPlayerLeftRoom(Player player)
{
Debug.Log(player.NickName + "が退出しました");
}
}
次にUIの表示について確認していく。プレイヤーのスクリプトであるMoveMineにnumberProp.Faceon();を加えて、faceon.SetActive(true);のUI表示を行わせてみた。
using Photon.Pun;
using UnityEngine;
// MonoBehaviourPunCallbacksを継承すると、photonViewプロパティが使えるようになる
public class MoveMine : MonoBehaviourPunCallbacks
{
NumberProp numberProp;
bool flag =true;
private void Update()
{
// 自身が生成したオブジェクトだけに移動処理を行う
if (photonView.IsMine)
{
var dx = 0.1f * Input.GetAxis("Horizontal");
var dy = 0.1f * Input.GetAxis("Vertical");
transform.Translate(dx, 0, dy);
}
}
public void Onflag()
{
numberProp = GameObject.FindWithTag("PlayerNumber").GetComponent<NumberProp>();
numberProp.Faceon();
flag = false;
}
}
これはきちんと稼働した。次は、Getpnumberスクリプトのランダム値抽出も組み込んで考える。NumberPropのスクリプト側からプレイヤーの値を読み取り、UI操作を行う方法を考える。
Getpnumberスクリプトを下記の形にして試したところ、numbers.Count == 1として認識され、きちんとUIの表示はなされた。一方でマルチプレイヤーとして、他の参加者を参加させようとしても、getpnumber.ransu == 0がgetpnumberのransu抽出より早く認識されてしまい、全ての場合でUI表示がされてしまう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class Getpnumber : MonoBehaviour
{
List<int> numbers = new List<int>();
public int ransu;
int index;
private void Start()
{
for (int i = 0; i <= PhotonNetwork.PlayerList.Length - 1; i++)
{
numbers.Add(i);
}
}
public void GetpnumberOn()
{
if (PhotonNetwork.PlayerList.Length == 0) return;
RandomNumber();
}
void RandomNumber()
{
if (numbers.Count > 1)
{
index = Random.Range(0, numbers.Count);
ransu = numbers[index];
Debug.Log(ransu);
numbers.RemoveAt(index);
}
else if(numbers.Count == 1)
{
index = 0;
ransu = numbers[index];
Debug.Log(ransu);
numbers.RemoveAt(index);
}
}
}
numbers.Countをプールする場所を作る必要がありそう、つまり、一旦入室前に集合させる必要があることになる。なので、そちらの可能性も考えていく。
SampleSceneスクリプトのPhotonNetwork.Instantiate("GamePlayer", v, Quaternion.identity);の生成箇所前にif (PhotonNetwork.PlayerList.Length == 2)の制約を加える。
この制約を加えることで片方のシーンにのみUIを表示することができたが、もう片方のシーンにはプレイヤーを存在させることができなくなっている。
制約条件の組み込み方を別の形に変更する。