//tips
スタジオしまずの嶋津様と打ち合わせ
//PUN同期
PUNの同期について理解を深める。
現在生じている問題は2点
・表示テキスト名への追加・変更処理ができないこと
・球の発射時にパラメーターの干渉でエラーが出ていること
がある。
Photonは、P2P型ネットワーク構造を採用しており、クライアントサーバ方式のサーバのような中心的な管理者は存在せず、ネットワーク内でそれぞれのデバイスが相互に接続され、必要なデータを融通しあっている形となっている。
PhotonNetwork(サーバーへの接続・切断、ルームの作成・参加・退出、プレイヤーリストの取得、ネットワーク上で同期させるオブジェクトの生成・破棄、ネットワーク関連の各種設定などをサポート)を利用する場合、
Photonサーバに接続(ルームの検索など、入り口)→マスタークライアントに接続→「ルーム」に接続
という流れになる。
Photonのサーバに接続し、現在接続されているMasterClientに接続ことになるが、ルームがない場合は自分がMasterClientになってルームを作成する必要がある。
このネットワーク接続段階では、自動的に同期とはならない。
同期の指示を行う必要があり、SampleScene スクリプトに記載したように、
// マッチング後、ランダムな位置に自分自身のネットワークオブジェクトを生成する
var v = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f));
PhotonNetwork.Instantiate("GamePlayer", v, Quaternion.identity);
を呼び出す必要がある。
ネットワーク上で同期させるオブジェクトには、PhotonViewコンポーネントが必須となり、下記の3つの処理を条件として、ネットワークオブジェクトにすることができる
1.PrefabにPhotonViewコンポーネントを追加する
2.PrefabをResourcesフォルダーに入れる
3.PhotonNetwork.Instantiate()でインスタンスを生成する
SampleScene スクリプトは下記。
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()
{
// マッチング後、ランダムな位置に自分自身のネットワークオブジェクトを生成する
var v = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f));
PhotonNetwork.Instantiate("GamePlayer", v, Quaternion.identity);
}
}
これで、同期するオブジェクトを生成することはできたが、各々のオブジェクトを特定して処理したい場合があり、その場合は、マスタークライアントから各クライアントに通知を行い、その通知の中でviewIDを送り、それを元にオブジェクトを特定する。
ネットワークオブジェクトのインスタンスが、自身側で生成したものか、他プレイヤー側で生成したものかの判断はPhotonView.IsMineによって行う。
別のクライアントに対してなにかしらのメッセージを送りたい場合に「RPC(Remote Procedure Call)」を使い、リモートクライアントに対して関数を実行する命令を送る。
GamePlayerスクリプトの、弾を発射する処理と衝突判定部分がある。
// [PunRPC]属性をつけると、RPCでの実行が有効になる
[PunRPC]
private void FireProjectile(Vector3 origin, float angle, PhotonMessageInfo info)
{
int timestamp = info.SentServerTimestamp;
projectileManager.Fire(timestamp, photonView.OwnerActorNr, origin, angle, timestamp);
}
[PunRPC]
private void HitByProjectile(int projectileId, int ownerId)
{
projectileManager.Remove(projectileId, ownerId);
if (photonView.IsMine)
{
PhotonNetwork.LocalPlayer.OnTakeDamage();
}
else if (ownerId == PhotonNetwork.LocalPlayer.ActorNumber)
{
PhotonNetwork.LocalPlayer.OnDealDamage();
}
}
プレイヤー名はPhotonNetworkからの設定変更となるので、エラーの要因はPhotonNetworkの変更がうまくいっていないことが考えられる。
GamePlayerのインスペクターへname labelのアタッチができていなかったことに気がついた。
アタッチを行った後には、きちんとスコア表示ができた。
ただ、下記のエラーは継続中。PhotonViewの番号が2001に変わった。
RPC method 'FireProjectile' found on object with PhotonView 2001 but has wrong parameters. Implement as 'FireProjectile(Single)'. PhotonMessageInfo is optional as final parameter.
UnityEngine.Debug:LogErrorFormat(Object, String, Object[])
Photon.Pun.PhotonNetwork:ExecuteRpc(Hashtable, Player) (at Assets/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs:632)
Photon.Pun.PhotonNetwork:RPC(PhotonView, String, RpcTarget, Player, Boolean, Object[]) (at Assets/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs:1222)
Photon.Pun.PhotonNetwork:RPC(PhotonView, String, RpcTarget, Boolean, Object[]) (at Assets/Photon/PhotonUnityNetworking/Code/PhotonNetwork.cs:2812)
Photon.Pun.PhotonView:RPC(String, RpcTarget, Object[]) (at Assets/Photon/PhotonUnityNetworking/Code/PhotonView.cs:792)
GamePlayer:Update() (at Assets/Script/GamePlayer.cs:59)