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窗口测试网络多人),你的脚本存在两个关键问题:
- 每个实例的
GameObject.FindGameObjectsWithTag("Player")只能找到当前实例内的玩家对象,另一个实例的玩家不在当前场景中,自然无法被修改位置。 OnTriggerEnter只在触发事件发生的那个实例上执行,另一个实例完全不知道有触发事件发生,不会主动执行传送逻辑。
如果是同场景本地多人(分屏/同窗口双玩家),则可能是:
GameObject.FindGameObjectsWithTag("Player")实际只找到了1个玩家对象(可打印players.Length确认),导致索引players[1]未生效。- 非触发玩家的Collider/Rigidbody设置有问题,或者脚本执行时未正确获取到对应出生点对象。
针对性解决
情况1:网络多人(同机双实例)
必须用网络同步框架(比如Unity Netcode for GameObjects、Photon PUN)处理跨实例事件:
- 将触发器的触发逻辑改为服务器/主机端专属处理:玩家触发时先向服务器发送请求,由服务器统一执行传送逻辑。
- 服务器遍历所有网络玩家,分别设置出生点位置,通过网络同步变量或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:本地多人(同场景双玩家)
- 先添加日志确认玩家数量:
Debug.Log($"找到玩家数量:{players.Length}");
如果数量为1,检查另一个玩家的Tag是否设为Player、是否处于激活状态。
2. 确保触发器的Collider勾选了Is Trigger,两个玩家的Collider未勾选Is Trigger且带有Rigidbody(否则无法触发OnTriggerEnter)。
3. 可将传送逻辑移至全局GameManager脚本中,确保触发时能稳定遍历所有玩家。
内容的提问来源于stack exchange,提问作者user28706358
相关产品推荐
相关产品推荐

