You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Unity+NetCode多人游戏中为所有客户端创建全局变量?

Unity NetCode 全局共享变量实现方案

要实现所有客户端、主机/服务器共用的变量,NetworkVariable是NetCode官方推荐的方案,它会自动处理变量同步,包括新客户端连接时的初始同步。下面是具体实现步骤和代码示例:

一、核心实现:用NetworkVariable同步共享变量

1. 创建全局管理器脚本

新建一个继承自NetworkBehaviour的脚本,挂载到带有NetworkObject组件的GameObject上(这个对象将作为全局状态管理器):

using Unity.Netcode;
using UnityEngine;

public class GlobalGameState : NetworkBehaviour
{
    // 定义共享字符串:所有人可读,仅服务器可写
    public NetworkVariable<string> SharedGameString = new NetworkVariable<string>(
        defaultValue: "初始共享内容",
        readPerm: NetworkVariableReadPermission.Everyone,
        writePerm: NetworkVariableWritePermission.Server);

    // 客户端调用此ServerRpc请求修改共享变量
    [ServerRpc(RequireOwnership = false)]
    public void UpdateSharedStringServerRpc(string newContent)
    {
        // 服务器端修改变量,自动同步到所有客户端
        SharedGameString.Value = newContent;
    }

    // 可选:监听变量变化(所有客户端/服务器都会触发)
    private void Awake()
    {
        SharedGameString.OnValueChanged += OnStringUpdated;
    }

    private void OnStringUpdated(string oldVal, string newVal)
    {
        Debug.Log($"共享字符串更新:{oldVal} → {newVal}");
    }
}

2. 配置全局管理器对象

  • 创建空GameObject,添加NetworkObject组件
  • 将上面的GlobalGameState脚本挂载到该对象上
  • 在NetworkManager的Spawn Prefabs列表中添加这个对象(如果是场景内对象,勾选NetworkObject的「Scene Object」选项,并确保场景被NetworkManager加载)

3. 客户端读取/修改变量的方式

  • 读取:客户端直接访问SharedGameString.Value即可拿到最新值(新客户端连接时会自动同步当前值)
  • 修改:客户端不能直接修改SharedGameString.Value(因为写权限是服务器),必须调用UpdateSharedStringServerRpc("新内容"),由服务器完成修改并同步到所有客户端

二、为什么之前的尝试可能失败?

  • 没有将脚本挂载到NetworkObject上:NetworkVariable必须依附于NetworkBehaviour,而NetworkBehaviour必须在NetworkObject对象上才能生效
  • 权限设置错误:如果给了客户端写权限,会导致多端修改冲突;正确的做法是服务器独占写权限,客户端通过ServerRpc请求修改
  • 直接修改客户端侧的NetworkVariable值:客户端没有写权限时,修改的值不会同步到服务器和其他客户端,仅本地有效

三、备选方案:用ServerRpc/ClientRpc手动同步

如果需要更自定义的同步逻辑,可以手动用Rpc实现,但需要处理新客户端的初始同步:

using Unity.Netcode;
using UnityEngine;

public class GlobalGameState : NetworkBehaviour
{
    private string sharedString = "初始内容";

    // 客户端请求修改
    [ServerRpc(RequireOwnership = false)]
    public void UpdateStringServerRpc(string newVal)
    {
        sharedString = newVal;
        // 通知所有客户端更新
        SyncStringToClientsClientRpc(newVal);
    }

    // 服务器同步给所有客户端
    [ClientRpc]
    private void SyncStringToClientsClientRpc(string newVal)
    {
        sharedString = newVal;
        Debug.Log($"收到同步:{newVal}");
    }

    // 新客户端连接时主动请求初始值
    public override void OnNetworkSpawn()
    {
        if (IsClient && !IsServer)
        {
            RequestInitialStringServerRpc();
        }
    }

    [ServerRpc(RequireOwnership = false)]
    private void RequestInitialStringServerRpc()
    {
        // 仅给请求的客户端发送当前值
        SendInitialStringClientRpc(sharedString, NetworkManager.Singleton.LocalClientId);
    }

    [ClientRpc]
    private void SendInitialStringClientRpc(string currentVal, ulong targetClientId)
    {
        if (NetworkManager.Singleton.LocalClientId == targetClientId)
        {
            sharedString = currentVal;
            Debug.Log($"获取初始值:{currentVal}");
        }
    }
}

这种方式需要手动处理新客户端的初始同步,不如NetworkVariable省心,优先推荐第一种方案。

内容的提问来源于stack exchange,提问作者Happy_cat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:03:14