Unity中玩家通过门传送直接跳至第三场景的问题求助
问题:穿过门时直接跳转到第三关卡
设置了3个关卡,通过Door对象实现玩家碰撞后传送至下一关卡,但玩家持续向前移动穿过门时,会直接传送至第三关卡。推测是OverlapCollider函数持续检测到碰撞导致多次触发传送逻辑,缩小门的Collider尺寸也无法解决。
相关代码如下:
Door 代码
public class Door : Collidable { public string[] sceneNames; private static int sceneNumber = 0; protected override void OnCollide(Collider2D coll) { if(coll.name == "Player") { GameManager.instance.SaveState(); //Teleport the player to next level sceneNumber++; if (sceneNumber >= sceneNames.Length) { return; } string sceneName = sceneNames[sceneNumber]; SceneManager.LoadScene(sceneName); } } }
Collidable 基类代码
public class Collidable : MonoBehaviour { public ContactFilter2D filter; private BoxCollider2D boxCollider; private Collider2D[] hits = new Collider2D[10]; protected virtual void Start() { boxCollider = GetComponent<BoxCollider2D>(); } protected virtual void Update() { //Collision work boxCollider.OverlapCollider(filter,hits); for (int i = 0; i < hits.Length; i++) { if (hits[i] == null) continue; OnCollide(hits[i]); //The array is not cleaned up, so we do it ourself hits[i] = null; } } protected virtual void OnCollide(Collider2D coll) { Debug.Log("OnCollide was not implemented in " + this.name); } }
碰撞体说明:门和玩家均使用BoxCollider2D,玩家移动时会持续与门的碰撞体重叠。
解决方案
方案1:改用触发事件替代持续检测
将门的Collider设置为Is Trigger,然后替换基类的检测逻辑为OnTriggerEnter2D,这样只会在碰撞开始时触发一次:
修改Collidable类:
public class Collidable : MonoBehaviour { protected virtual void Start() { // 确保Collider设置为Is Trigger GetComponent<BoxCollider2D>().isTrigger = true; } protected virtual void OnTriggerEnter2D(Collider2D coll) { OnCollide(coll); } protected virtual void OnCollide(Collider2D coll) { Debug.Log("OnCollide was not implemented in " + this.name); } }
方案2:给门添加单次触发标记
如果不想修改基类检测逻辑,可以在Door类中添加标记,确保每个门只触发一次传送:
修改Door类:
public class Door : Collidable { public string[] sceneNames; private static int sceneNumber = 0; // 添加触发标记 private bool hasTriggered = false; protected override void OnCollide(Collider2D coll) { if(coll.name == "Player" && !hasTriggered) { hasTriggered = true; GameManager.instance.SaveState(); sceneNumber++; if (sceneNumber >= sceneNames.Length) { return; } string sceneName = sceneNames[sceneNumber]; SceneManager.LoadScene(sceneName); } } }
额外优化:static场景计数器的潜在问题
sceneNumber使用static修饰,可能导致场景重新加载后计数器不会重置(比如玩家回到之前的关卡)。如果需要支持关卡回溯,可以将sceneNumber移到GameManager中管理,或者在场景加载时重置该值。
内容的提问来源于stack exchange,提问作者jonathan
相关产品推荐
相关产品推荐

