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

Unity Netcode for GameObjects:单玩家触发触发器时无法传送双玩家

问题描述

开发一款双人多人游戏,需求是:任意玩家触发场景物体的触发器时,两名玩家分别传送到关卡预设的不同出生点。目前测试发现,触发触发器的玩家能正确移动到对应出生点,但另一名玩家完全不动。怀疑是同一台机器运行两个实例、切换窗口导致未触发传送,但不确定原因。

挂载在触发物体上的脚本如下:

private void OnTriggerEnter(Collider other)
{
    GameObject[] players = GameObject.FindGameObjectsWithTag("Player");
    Debug.Log(players[0].transform.position);
    Debug.Log(players[1].transform.position);
    if (finalLevel)
    {
        //show end screen
        //disable player input
        endScreen.SetActive(true);
        players[0].SetActive(false);
        players[1].SetActive(false);    
    }
    else
    {
        //send p1 to p1 start point
        //send p2 to p2 start point
        players[0].transform.position = PC1StartPoint.transform.position;
        players[1].transform.position = PC2StartPoint.transform.position;

    }
}
问题分析与解决方法

核心原因

如果是同机运行两个独立游戏实例(比如Unity中开两个Play窗口测试网络多人),你的脚本存在两个关键问题:

  1. 每个实例的GameObject.FindGameObjectsWithTag("Player")只能找到当前实例内的玩家对象,另一个实例的玩家不在当前场景中,自然无法被修改位置。
  2. OnTriggerEnter只在触发事件发生的那个实例上执行,另一个实例完全不知道有触发事件发生,不会主动执行传送逻辑。

如果是同场景本地多人(分屏/同窗口双玩家),则可能是:

  • GameObject.FindGameObjectsWithTag("Player")实际只找到了1个玩家对象(可打印players.Length确认),导致索引players[1]未生效。
  • 非触发玩家的Collider/Rigidbody设置有问题,或者脚本执行时未正确获取到对应出生点对象。

针对性解决

情况1:网络多人(同机双实例)

必须用网络同步框架(比如Unity Netcode for GameObjects、Photon PUN)处理跨实例事件:

  1. 将触发器的触发逻辑改为服务器/主机端专属处理:玩家触发时先向服务器发送请求,由服务器统一执行传送逻辑。
  2. 服务器遍历所有网络玩家,分别设置出生点位置,通过网络同步变量或RPC调用通知所有客户端更新玩家位置。

示例(以Netcode为例):

// 触发器脚本修改为网络行为
public class TriggerTeleport : NetworkBehaviour
{
    public Transform PC1StartPoint;
    public Transform PC2StartPoint;
    public GameObject endScreen;
    public bool finalLevel;

    private void OnTriggerEnter(Collider other)
    {
        // 仅服务器能处理触发逻辑
        if (!IsServer) return;
        
        // 获取所有网络玩家对象
        var networkPlayers = NetworkManager.Singleton.ConnectedClientsList;
        if (networkPlayers.Count < 2) return;

        if (finalLevel)
        {
            endScreen.SetActive(true);
            foreach (var client in networkPlayers)
            {
                client.PlayerObject.SetActive(false);
            }
        }
        else
        {
            // 给第一个玩家设置P1出生点,第二个设置P2出生点
            networkPlayers[0].PlayerObject.transform.position = PC1StartPoint.position;
            networkPlayers[1].PlayerObject.transform.position = PC2StartPoint.position;
        }
    }
}

确保玩家对象带有NetworkObject组件,位置属性通过NetworkTransform组件开启网络同步。

情况2:本地多人(同场景双玩家)

  1. 先添加日志确认玩家数量:
Debug.Log($"找到玩家数量:{players.Length}");

如果数量为1,检查另一个玩家的Tag是否设为Player、是否处于激活状态。
2. 确保触发器的Collider勾选了Is Trigger,两个玩家的Collider未勾选Is Trigger且带有Rigidbody(否则无法触发OnTriggerEnter)。
3. 可将传送逻辑移至全局GameManager脚本中,确保触发时能稳定遍历所有玩家。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:55:13