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

Unity Mirror网络环境下如何获取其他玩家数值并求和?

问题分析与解决方案

核心问题点

  • 遍历玩家逻辑错误:SumDatas中判断的是当前对象名称而非遍历到的玩家对象,且重复查找固定名称的对象,无法正确获取所有玩家的数值。
  • 缺少数值获取方法:PlayerManager的value是私有字段,没有公共方法供外部读取。
  • 静态类同步问题:PlayerStat是静态类,客户端与服务器的静态变量相互独立,无法跨客户端同步总和数据。
  • 权限逻辑问题:玩家数值的求和应该由服务器端处理(Mirror中服务器为权威节点),避免客户端私自计算导致数据不一致。

修正后的代码实现

1. 完善PlayerManager类

添加公共获取方法,并确保服务器端处理数值变更:

public class PlayerManager : NetworkBehaviour
{
    [SyncVar(hook = nameof(onValueChanged))]
    private int value = 0;

    // 提供公共方法获取当前玩家的数值
    public int GetValue()
    {
        return value;
    }

    private void Update()
    {
        // 客户端按下按键时发送命令给服务器修改数值
        if (isClient && Input.GetKeyDown("x"))
        {
            CmdIncrementValue();
        }
    }

    public override void OnStartServer()
    {
        Debug.Log("玩家成功加入游戏房间");
    }

    // 客户端发送命令给服务器修改数值
    [Command]
    private void CmdIncrementValue()
    {
        value++;
        Debug.Log($"服务器收到客户端请求,当前数值:{value}");
        // 通知游戏管理类更新总和
        GameManager.Instance.UpdatePlayerSum();
    }

    [TargetRpc]
    private void ReplyHola()
    {
        Debug.Log("收到服务器回复");
    }

    [ClientRpc]
    private void Message()
    {
        Debug.Log("Ping...");
    }

    private void onValueChanged(int oldValue, int newValue)
    {
        Debug.Log($"数值变更:旧值{oldValue},新值{newValue}");
    }
}

2. 创建全局游戏管理类(服务器端处理求和)

public class GameManager : NetworkBehaviour
{
    public static GameManager Instance;

    [SyncVar(hook = nameof(OnSumChanged))]
    private int totalPlayerValue = 0;

    private void Awake()
    {
        if (Instance == null)
            Instance = this;
        else
            Destroy(gameObject);
    }

    // 服务器端计算所有玩家数值总和
    [Server]
    public void UpdatePlayerSum()
    {
        totalPlayerValue = 0;
        foreach (PlayerManager player in FindObjectsOfType<PlayerManager>())
        {
            totalPlayerValue += player.GetValue();
        }
        Debug.Log($"服务器计算总和:{totalPlayerValue}");
    }

    // 总和变更时通知客户端更新
    private void OnSumChanged(int oldSum, int newSum)
    {
        Debug.Log($"当前所有玩家数值总和:{newSum}");
        // 这里可以更新UI或者其他业务逻辑
    }
}

3. 修正客户端临时求和方法(可选)

如果需要在客户端临时计算本地可见玩家的数值,修正后的方法:

private void SumDatas()
{
    int tempSum = 0;
    foreach (PlayerManager player in FindObjectsOfType<PlayerManager>())
    {
        tempSum += player.GetValue();
    }
    Debug.Log($"客户端本地计算总和:{tempSum}");
    // 注意:本地计算的总和可能与服务器不一致,仅用于临时显示,权威数据以服务器同步的为准
}

关键注意事项

  • 服务器权威原则:所有玩家数据的修改和计算必须在服务器端执行,客户端仅负责发送操作请求和接收同步后的结果。
  • SyncVar同步:全局总和用SyncVar标记,确保所有客户端能实时获取服务器计算的正确数值。
  • 对象查找优化:避免频繁使用FindObjectsOfType,建议在玩家加入时将PlayerManager实例添加到全局列表中,提升运行性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:40:30