Unity自动门问题:碰撞体移动但实体门失效,玩家可穿模
Unity自动门:碰撞穿模与移动逻辑问题
问题描述
我正在开发一款Unity自动门,需求是玩家靠近时门自动打开,离开触发区域后自动关闭。试过两种方案:一是用独立对象做碰撞传感器驱动门移动,二是将门自身的Box Collider设为触发,都没成功。现在的问题是:碰撞体虽然会移动,但玩家能直接穿模过门。
相关代码
public float maximumOpening = 3; public float maximumClosing = 0; public float movementSpeed = 1; bool playerIsHere; bool opening; void Start() { playerIsHere = false; opening = false; } void Update() { if(playerIsHere) { if (movingDoor.transform.position.x < maximumOpening) { movingDoor.transform.position += Vector3.forward * Time.deltaTime; } else { if (movingDoor.transform.position.x > maximumClosing) { movingDoor.transform.position += -Vector3.forward * Time.deltaTime; } } } } private void OnTriggerEnter(Collider col) { if(col.gameObject.tag == "Player") { playerIsHere = true; } } private void OnTriggerExit(Collider col) { if (col.gameObject.tag == "Player") { playerIsHere = false; } }
问题分析与解决办法
- 碰撞穿模原因:如果将门自身的Collider设为
Trigger,它会失去物理碰撞的阻挡效果,玩家自然能直接穿过去。正确的做法是给门设置两个Collider:一个非Trigger的Collider(用于物理阻挡),一个单独的Trigger Collider(可以是门的子对象或独立传感器,用于检测玩家进出)。 - 移动逻辑错误:当前代码的逻辑完全不符合需求——当玩家在触发区时,门开到最大位置后会立刻反向关闭,而且移动方向(
Vector3.forward对应Z轴)和判断的X轴位置不匹配,导致移动混乱。 - 修正后的代码:
public float maximumOpening = 3; public float maximumClosing = 0; public float movementSpeed = 1; public Transform movingDoor; // 确保在Inspector中赋值 bool playerIsHere; void Start() { playerIsHere = false; } void Update() { if (playerIsHere) { // 向打开位置移动,此处假设门沿X轴移动,可根据实际方向调整为Z轴 Vector3 targetPos = new Vector3(maximumOpening, movingDoor.position.y, movingDoor.position.z); movingDoor.position = Vector3.MoveTowards(movingDoor.position, targetPos, movementSpeed * Time.deltaTime); } else { // 向关闭位置移动 Vector3 targetPos = new Vector3(maximumClosing, movingDoor.position.y, movingDoor.position.z); movingDoor.position = Vector3.MoveTowards(movingDoor.position, targetPos, movementSpeed * Time.deltaTime); } } private void OnTriggerEnter(Collider col) { if (col.CompareTag("Player")) // 推荐用CompareTag替代字符串直接比较 { playerIsHere = true; } } private void OnTriggerExit(Collider col) { if (col.CompareTag("Player")) { playerIsHere = false; } }
- 额外配置要求:
- 给门的GameObject添加
Rigidbody组件,并勾选Kinematic(避免物理引擎干扰,同时保留碰撞阻挡); - 确保玩家对象带有非Trigger的Collider和Rigidbody组件(第一人称/第三人称控制器通常默认自带);
- 检查触发用Collider的范围,确保玩家进入时能正确触发事件。
- 给门的GameObject添加
内容的提问来源于stack exchange,提问作者D48345T
相关产品推荐
相关产品推荐

