客户端/服务器 RPC 如何使用全局变量?

How Client / Server RPC works with global variables?

提问人:Tom3652 提问时间:11/13/2023 最后编辑:derHugoTom3652 更新时间:11/17/2023 访问量:72

问:

我是Unity的新手,对于我所看到的行为,我找不到任何合乎逻辑的答案。

我写了一个基本的脚本,例如:


public class PlayerPosition : NetworkBehaviour
{

    private Dictionary<string, int> testDict = new();

    [ServerRpc(RequireOwnership = false)]
    private void HitServerRpc(string key, int value)
    {
        RefreshClientRpc(key, value);
    }

    [ClientRpc]
    private void RefreshClientRpc(string key, int value)
    {
        testDict[key] = value;
        foreach (var item in testDict)
            {
                Debug.Log($"Item in current dict {item}");
            }
    }

   // Other logical code that calls only HitServerRpc().

}

我在客户端/主机情况下在我的播放器上使用此脚本。
我有一个客户端和一个主机(服务器 + 客户端)用于测试和问题。
Prefab

我的问题是:当通过 2 个不同的 RPC 调用(每个客户端一个)添加至少 2 个不同的键和值时,为什么只有一个键和一个值?testDict

即使在两个不同的客户端上调用了日志,日志也只显示一次:Item in current dictHitServerRpc()

  • HitServerRpc("user1", 3)
  • HitServerRpc("user2", 4)

所有客户端都应等于:testDict{{"user1", 3}, {"user2", 4}}

PS:最奇怪的是,我试图在静态类中移动并在静态类内部更新它,而不是处理RPC调用的类,它现在在主机上具有正确的值,但在客户端上仍然没有。testDict

C# 游戏引擎 unity-networking

评论


答:

2赞 derHugo 11/14/2023 #1

所有客户端的 testDict 都应等于:{{"user1", 3}, {"user2", 4}}

我明白你为什么这么想,但不是!这些调用中的每一个都来自不同的客户端 ->,因此来自/到你的 的不同实例。PlayerPosition

假设在您的描述中,您有两个玩家和 .user1user2

其中每个都调用了各自的地方当局实例。然后,它作为 ClientRPC 中继到其他连接的客户端,但仍然只中继到它们各自的实例。HitServerRpcPlayerPosition

试图将此可视化

user 1 Device              Server       user 2 Device

user 1 (local auth) ---->  user 1 ----> user1
user 2              <----  user 2 <---- user 2 (local auth)

结果是,相应的字典确实是同步的,但是,属于用户 1 的用户将只知道密钥,因此另一个实例只拥有密钥。PlayPositionuser1user2

所以我认为在您的用例中,实际上使用静态是有意义的。不过,没有必要把它放到不同的类中。你可以使用

private static readonly Dictionary<string, int> testDict = new();

因此,所有本地实例都使用相同的字典实例。PlayerPosition

评论

0赞 Tom3652 11/14/2023
感谢您的回复!我现在真的明白了!但是,尽管有静态变量,但这仍然不适用于客户端,仅适用于主机:/你知道为什么吗?
1赞 derHugo 11/14/2023
您能否添加更多日志并查看它们是否真的在您的设备上出现?正如您自己所说,日志应该在两个客户端设备上出现两次(确保在控制台中禁用折叠)...我会将日志添加到方法本身的顶部,例如和相应的.附加允许您在记录的消息上单击一次,它将突出显示层次结构中的相应实例Debug.Log(nameof(HitServerRpc), this);Debug.Log(nameof(RefreshClientRpc), this);this
0赞 Tom3652 11/14/2023
是的!实际上我已经记录了所有内容,在客户端上我始终只得到 1 个项目,而在主机上我得到 2 个项目。我已经构建了 2 个 unity 编辑器(有 2 台计算机)和编辑器 + android 物理设备,结果保持不变(日志也是如此)......我看到了你的编辑,让我试试这些!