PUN2:通过RPC调用指定一个实例化的玩家gameObject



我知道你不能通过RPC调用传递gameObject引用,因为每个客户端在每个实例化中使用它自己独特的引用。是否有一种方法可以通过RPC调用在所有客户端上引用特定的游戏对象?

这是我想要完成的一个例子

if(Input.GetKeyDown("r")){
PhotonView.RPC("ChangeReady", RPCTarget.AllBuffered, gameObject)
}
[PunRPC]
void ChangeReady(GameObject PLAYER) {
PlayerScript PSCRIPT = PLAYER.GetComponent<PlayerScript>();
if (PSCRIPT.READY)
{
PSCRIPT.GetComponent<PlayerScript>().READY = false;
}
else {
PSCRIPT.READY = true;
}

}

我正试图为玩家做一个准备好的检查系统,这样他们就可以切换准备好打开和关闭,并将信息传输到其他客户端。不确定如何参考特定的gameObject,因为如前所述,这是不可能在RPC中做到的。

我该怎么做呢?

如果您只想设置就绪状态,有几种方法可以做到这一点:

a)使用CustomProperties,它允许你在键值对中存储玩家特定的数据。然后,你可以在本地检查玩家GameObjects的这些值,并用RPC改变他们的行为。下面是一个例子:

bool ready = (bool)PhotonNetwork.player.customProperties["Ready"];
Hashtable hash = new Hashtable();
hash.Add("Ready", true);
PhotonNetwork.player.SetCustomProperties(hash);

点击此链接获取有关CustomProperties的信息

b)通过在Monobehaviour上实现IPunMagicInstantiateCallback来使用OnPhotonInstantiate

void OnPhotonInstantiate(PhotonMessageInfo info)
{
// e.g. store this gameobject as this player's charater in Player.TagObject
info.sender.TagObject = this.GameObject;
}

TagObject帮助你将GameObject与特定的玩家联系起来。所以一旦他们被实例化,这是自动调用,你的GameObject可以绑定到玩家和检索使用Player.TagObject和执行你的就绪状态逻辑(通过RPC或任何其他方式)

点击此链接了解OnPhotonInstantiate

参见Photon RPC and RaiseEvent =>您可以添加多个参数,前提是PUN可以序列化它们";→参见Photon支持的序列化类型

=比;不,这不是直接可能的。


解决方案你总是需要一种方法来告诉其他设备你所引用的对象,因为它们与你没有相同的引用。

如果你指的是你的光子播放器的对象,虽然你可以通过

发送
PhotonNetwork.LocalPlayer.ActorNumber

,另一边通过ActorNumber得到GameObject

有多种方法可以这样做。

我曾经通过一个像

这样的中心类来做到这一点
public class PhotonUserManager : IInRoomCallbacks, IMatchmakingCallbacks
{
private static PhotonUserManager _instance;
private readonly Dictionary<int, GameObject> _playerObjects = new Dictionary<int, GameObject>();
public static bool TryGetPlayerObject(int actorNumber, out GameObject gameObject)
{
return _instance._playerObjects.TryGetValue(actorNumber, out gameObject);
}
[RuntimeInitializeOnLoadMethod]
private static void Init()
{
_instance = new PhotonUserManager();
PhotonNetwork.AddCallbackTarget(_instance);
}
public void OnCreateRoomFailed(short returnCode, string message){ }
public void OnJoinRoomFailed(short returnCode, string message){ }
public void OnCreatedRoom() { }
public void OnJoinedRoom()
{
Refresh();
}
public void OnLeftRoom()
{
_playerObjects.Clear();
}
public void OnJoinRandomFailed(short returnCode, string message){ }
public void OnFriendListUpdate(List<FriendInfo> friendList) { }
public void OnPlayerEnteredRoom(Player newPlayer) 
{ 
Refresh();
}
public void OnPlayerLeftRoom(Player otherPlayer)
{
if(_playerObjects.ContainsKey(otherPlayer.ActorNumber))
{
_playerObjects.Remove(otherPlayer.ActorNumber);
}
}
public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged){ }
public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps){ }
public void OnMasterClientSwitched(Player newMasterClient){ }
private void Refresh()
{
var photonViews = UnityEngine.Object.FindObjectsOfType<PhotonView>();
foreach (var view in photonViews)
{
var player = view.owner;
//Objects in the scene don't have an owner, its means view.owner will be null => skip
if(player == null) continue;
// we already know this player's object -> nothing to do
if(_playerObjects.ContainsKey(player.ActorNumber)) continue;
var playerObject = view.gameObject;
_playerObjects[player.ActorNumber] = playerObject;
}
}
}

自动收集加入玩家的GameObject。当然这里存在一个限制:如果玩家自己生成并拥有任何东西……它可能会失败,因为每个玩家有多个PhotonView=>在这种情况下,使用具有最低networkidentity的那个。在Photon的viewid是由第一个数字=ActorNumber+ 3位数字id;)

和之后的

if(!PhotonUserManager.TryGetPlayerObject(out var obj))
{
Debug.LogError($"Couldn't get object for actor number {receivedActorNumber}");
}

另一个选项可以使用OnPhotonInstantiate

public class SomeComponentOnYourPlayerPrefab : PunBehaviour
{
public override void OnPhotonInstantiate(PhotonMessageInfo info)
{
// only set if not already set in order to not
// overwrite the tag for a player that spawns something later
if(info.sender.TagObject == null)
{
info.sender.TagObject = gameObject;
}
}
}

,然后再做

var obj = PhotonNetwork.LocalPlayer.Get(receivedActorNumber).TagObject;

最新更新