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
相关产品推荐
相关产品推荐

