Unity3D(C#)玩家触碰LevelEnd1无法传送问题求助
问题排查与解决
日志能正常输出说明碰撞检测已经触发,但玩家没被传送,核心问题出在CharacterController组件的特性——直接修改transform.position会被CharacterController的内置移动逻辑覆盖,尤其是当玩家对象带有CharacterController时,它会在FixedUpdate阶段修正位置,导致你设置的坐标被重置。
下面是几种可行的解决方法:
方法1:临时禁用CharacterController再修改位置
先禁用CharacterController,修改坐标后再重新启用,避免内置逻辑干扰:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerTouched : MonoBehaviour { public GameObject Player; private CharacterController _playerController; void Start() { // 提前获取玩家的CharacterController组件 _playerController = Player.GetComponent<CharacterController>(); } public void OnControllerColliderHit(ControllerColliderHit collision) { if (collision.gameObject.tag == "LevelEnd1") { // 禁用控制器 _playerController.enabled = false; // 设置位置 Player.transform.position = new Vector3(-193.5f, 5.860001f, 803.13f); // 延迟一帧再启用(确保位置生效) StartCoroutine(EnableControllerAfterFrame()); Debug.Log("it worked!!"); } } IEnumerator EnableControllerAfterFrame() { yield return null; _playerController.enabled = true; } }
方法2:使用CharacterController的Teleport方法(Unity 2020+支持)
Unity 2020及以上版本给CharacterController加了Teleport方法,专门用来传送玩家,不会和内置逻辑冲突:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerTouched : MonoBehaviour { public GameObject Player; private CharacterController _playerController; void Start() { _playerController = Player.GetComponent<CharacterController>(); } public void OnControllerColliderHit(ControllerColliderHit collision) { if (collision.gameObject.tag == "LevelEnd1") { // 使用Teleport直接传送 _playerController.Teleport(new Vector3(-193.5f, 5.860001f, 803.13f)); Debug.Log("it worked!!"); } } }
额外检查点
- 确认
LevelEnd1对象的碰撞体不是触发器,如果是触发器,需要把OnControllerColliderHit换成OnTriggerEnter(Collider other),并确保玩家的CharacterController勾选了Trigger选项(或者碰撞体的IsTrigger设置和对应函数匹配) - 检查玩家是否有其他脚本在修改位置,比如移动脚本在FixedUpdate里持续更新坐标,导致传送位置被覆盖
内容的提问来源于stack exchange,提问作者berxiv
相关产品推荐
相关产品推荐

