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

Unity Mirror多人游戏:解决GameObject仅对单个玩家可见的主机异常

问题分析

你的问题根源在于主机既是服务器又是客户端,共享同一个对象实例:
当非主机客户端拾取时,服务器将对象设为不可见,再通过TargetRpc给拾取者的客户端单独设为可见——此时客户端和服务器的对象是分离的,状态互不干扰,所以其他客户端看不到,拾取者能看到,逻辑正常。
但主机拾取时,TargetRpc在主机客户端执行的SetObjectVisibility(true)会直接修改服务器端的对象状态(因为两者是同一个实例),导致服务器端的对象变回可见,同步给所有客户端,所以所有人都能看到该对象。

修复方案

改用Mirror官方推荐的观察者可见性系统来控制对象的可见范围,这比手动修改Renderer/Image状态更可靠,也能避免主机的实例冲突问题。

步骤1:配置NetworkIdentity

在目标GameObject的NetworkIdentity组件中,将Visibility设置为Visible To Observers(默认是Visible To All)。这样只有被加入观察者列表的客户端能看到该对象。

步骤2:修改代码逻辑

替换原有的可见性控制代码,改为通过管理观察者列表来限制可见范围:

[Command]
public void CmdHideObject()
{
    // 建议替换为更可靠的目标对象查找方式(比如标签、引用),避免FindObjectOfType的不确定性
    var targetHideScript = FindObjectOfType<HideScript>();
    if (targetHideScript != null)
    {
        targetHideScript.HideObject(connectionToClient);
    }
}

[Server]
public void HideObject(NetworkConnectionToClient pickingClient)
{
    NetworkIdentity netIdentity = GetComponent<NetworkIdentity>();
    
    // 清空所有现有观察者,确保只有拾取者能看到
    netIdentity.Observers.Clear();
    
    // 将拾取者的连接加入观察者列表
    if (pickingClient != null)
    {
        netIdentity.AddObserver(pickingClient);
    }
    
    // 确保服务器端对象处于可见状态,同步给拾取者
    SetObjectVisibility(true);
}

private void SetObjectVisibility(bool visible)
{
    GetComponent<Renderer>().enabled = visible;
    foreach (var image in GetComponentsInChildren<Image>())
    {
        image.enabled = visible;
    }
}

补充说明

  1. 为什么这个方案有效?

    • 当Visibility设为Visible To Observers时,不在观察者列表的客户端会自动隐藏该对象(Mirror不会向这些客户端同步该对象的任何数据)。
    • 服务器端保持对象可见,仅将拾取者的连接加入观察者列表,所以只有拾取者能收到同步数据,看到对象;其他客户端看不到。
    • 主机的情况被自动处理:主机作为服务器端的连接会被加入观察者列表,同时因为主机客户端复用服务器实例,直接就能看到可见的对象,不会出现状态冲突。
  2. 优化建议

    • 不要用FindObjectOfType<HideScript>(),可以给目标对象设置唯一标签,用GameObject.FindWithTag()查找,或者在玩家脚本中直接引用目标对象,避免场景中有多个实例时出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:32:10