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

Unity Mirror多人跳棋:客户端与主机对象销毁异常求助

Unity Mirror多人跳棋对象销毁同步问题排查与解决

问题核心

  • 基于Unity 2022.3.8 + Mirror开发多人跳棋,服务器强制销毁指定对象无法同步至客户端
  • 使用[Command]和[ClientRpc]时,调用CallServerToDestroy()前mainObj.ObjectToDestroy非空,但RpcDebug()中该变量变为null
  • 静态引用(如transform.GetChild(0).gameObject)可正常销毁,动态对象引用失效

根本原因

  1. Mirror中网络对象的跨端引用不能直接传递GameObject实例,客户端与服务器的对象实例ID不匹配,传递后会丢失有效引用
  2. 动态对象未正确挂载NetworkIdentity组件,或未通过NetworkServer.Spawn()生成,导致服务器无法追踪同步状态
  3. 若[Command]未设置requiresAuthority = false,非授权客户端发起的调用会被服务器拒绝(如果是服务器主动销毁,需关闭权限校验)

解决方案

1. 确保目标对象符合网络同步要求

  • 给需要销毁的对象挂载NetworkIdentity组件,不要勾选Server Only(除非该对象仅服务器可见)
  • 所有网络对象必须通过NetworkServer.Spawn()生成,禁止直接用Instantiate()创建后手动赋值

2. 修改Command/Rpc逻辑,传递netId而非GameObject引用

直接传递GameObject会导致跨端引用失效,改用NetworkIdentity的netId(唯一网络标识)来定位对象:

修改后的核心代码示例

// 调用销毁的入口方法(客户端/服务器均可触发)
public void CallServerToDestroy()
{
    if (mainObj.ObjectToDestroy != null && mainObj.ObjectToDestroy.TryGetComponent(out NetworkIdentity targetNetId))
    {
        CmdDestroyTarget(targetNetId.netId);
    }
}

// 服务器端Command方法,接收netId并执行销毁
[Command(requiresAuthority = false)] // 允许无权限调用(服务器强制销毁场景)
public void CmdDestroyTarget(uint targetNetId)
{
    // 通过netId从服务器已生成对象列表中查找目标
    if (NetworkServer.spawned.TryGetValue(targetNetId, out NetworkIdentity targetIdentity))
    {
        // 使用Mirror内置方法销毁,自动同步至所有客户端
        NetworkServer.Destroy(targetIdentity.gameObject);
        // 如需客户端额外逻辑,传递netId而非GameObject
        RpcNotifyDestroy(targetNetId);
    }
}

// 客户端Rpc方法,处理销毁后的额外逻辑(可选)
[ClientRpc]
public void RpcNotifyDestroy(uint targetNetId)
{
    if (NetworkClient.spawned.TryGetValue(targetNetId, out NetworkIdentity targetIdentity))
    {
        Debug.Log($"客户端已同步销毁对象:{targetIdentity.gameObject.name}");
    }
}

3. 替代方案:直接使用NetworkServer.Destroy自动同步

如果不需要额外客户端逻辑,服务器直接调用NetworkServer.Destroy()即可,无需手动编写ClientRpc,Mirror会自动向所有客户端发送销毁指令。

关键注意事项

  • 禁止在客户端直接销毁网络对象,必须由服务器发起销毁操作
  • 检查NetworkIdentity的Local Player Authority设置,若对象属于玩家权限,需确保服务器有权限销毁(或关闭权限校验)
  • 若目标对象是临时生成的特效/道具,确保生成时调用NetworkServer.Spawn()并在销毁时调用NetworkServer.Destroy()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:57:00