镜像中的ClientRPC方法调用未正确保留其他客户端的事件引用



我正在使用Unity的镜像库测试两个客户端之间的聊天系统。在我的Player对象上,我附加了一个脚本,该脚本存储了一个应该通过ClientRPC调用的事件。

public delegate void ReceivedChatMessageHandler(string message);
public event ReceivedChatMessageHandler ChatMessageReceived;
[Client]
public void SendChatMessage(string message)
{
if (!Keyboard.current.enterKey.wasPressedThisFrame) return;
if (string.IsNullOrWhiteSpace(message)) return;
CmdSendMessage(message);
}
[Command]
private void CmdSendMessage(string message)
{
RpcHandleMessage(message);
}
[ClientRpc]
public void RpcHandleMessage(string message)
{
if (ChatMessageReceived != null)
{
ChatMessageReceived($"[Player]: {message}n");
}
}

每个玩家都为自己的本地UI向该事件附加了一个事件处理程序,该UI应该在聊天框中显示消息。这很好,两个玩家都可以向服务器发送消息,消息会在他们自己的聊天中弹出(即事件处理程序正确地连接在两个客户端上(。但是,对于没有发送消息的客户端,即使在本地定义了ChatMessageReceived,它也会返回null。

我在网上四处寻找,但找不到任何正确的解释来解释为什么会发生这种情况。如何将通过ClientRPC生成的事件正确地传递给不属于玩家游戏对象本身的其他本地对象?

编辑:事件侦听器通过附加到玩家游戏对象的脚本进行附加。在该脚本启动时,即当玩家游戏对象在中生成时,它将找到Chatbox游戏对象,并将本地玩家的ChatInterface脚本(如上所示(传递给另一个脚本。

public void Start()
{
if (!isLocalPlayer) return;
GameObject.Find("Chat").GetComponent<Chatbox>().PlayerLoaded(this.gameObject.GetComponent<ChatInterface>());
}

然后,Chatbox脚本将自己的本地方法附加到事件处理程序。

public void PlayerLoaded(ChatInterface chat)
{
this.chat = chat;
chat.ChatMessageReceived += Receive;
}

如前所述,每个客户端都可以很好地接收他们在自己的客户端上发送的事件,但来自其他客户端的事件会导致整个事件表现得好像没有在其上定义处理程序一样

我现在在一个旧的Unity论坛线程中找到了问题的答案。重要的部分是:

因此,如果Player1发送命令";CmdMoveForward";命令被执行仅在与Player1关联的对象上的服务器上。同样,当服务器在上调用ClientRPC方法RpcMovePlayer时与Player3关联的对象,在所有Player3对象上的客户端。

由于我正在为本地播放器对象创建一个事件侦听器,但客户端RPC是在与向服务器发送命令的用户相对应的播放器对象上执行的,因此事件侦听器未附加到此事件。这也解释了为什么发送RPC的客户端没有问题,因为他们的事件侦听器连接到了正确的播放器对象。

我现在已经解决了这个问题,把我的聊天箱脚本变成了一个Singleton,这样它就可以很容易地从任何玩家对象调用。保留基于事件的体系结构的另一个选项是将侦听器附加到场景中的每个玩家对象。

相关内容

  • 没有找到相关文章

最新更新