Unity中OnCollisionEnter2D与OnCollisionExit2D地面检测异常问题
解决Unity中玩家切换平台后无法跳跃的问题
你的问题出在碰撞检测的逻辑上:当玩家从Platform01移动到Platform02时,会先触发与Platform01的OnCollisionExit2D,此时代码直接把isOnGrounded设为false,但玩家已经和Platform02处于碰撞状态,可isOnGrounded不会自动恢复为true——因为只有首次碰撞Platform02时才会触发OnCollisionEnter2D,若玩家是“滑”到Platform02上,碰撞进入的时机早于退出Platform01的时机,就会导致isOnGrounded被错误覆盖为false。
正确的做法是统计当前接触的地面碰撞体数量,替代简单的布尔值开关:
- 新增整数变量
groundContactCount,记录当前接触的地面碰撞体数量 - 进入地面碰撞时计数器加1,同时标记为在地面
- 离开地面碰撞时计数器减1,仅当计数器为0时才标记为不在地面
修改后的完整代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class PlayerController : MonoBehaviour { //REFERENCES private Rigidbody2D rb2D; //VARIABLES [SerializeField] float moveSpeed = 0; private float moveX; [SerializeField] bool isOnGrounded = true; [SerializeField] float jumpY; // 新增:地面碰撞计数器 private int groundContactCount = 0; // Start is called before the first frame update void Start() { rb2D = GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update() { moveX = Input.GetAxis("Horizontal"); PlayerJump(); } private void FixedUpdate() { PlayerMove(); } void PlayerMove() { rb2D.velocity = new Vector2(moveX * moveSpeed * Time.fixedDeltaTime, rb2D.velocity.y); } void PlayerJump() { if (Input.GetKeyDown(KeyCode.Space) && isOnGrounded == true) { rb2D.AddForce(new Vector2(rb2D.velocity.x, jumpY)); } } private void OnCollisionEnter2D(Collision2D other) { if (other.gameObject.CompareTag("Ground")) { groundContactCount++; isOnGrounded = true; } } private void OnCollisionExit2D(Collision2D other) { if (other.gameObject.CompareTag("Ground")) { groundContactCount--; // 只有无任何地面接触时,才标记为不在地面 if (groundContactCount <= 0) { isOnGrounded = false; // 防止计数器出现负数 groundContactCount = 0; } } } }
额外优化建议:
- 当前
moveSpeed * Time.fixedDeltaTime的写法会让移动速度偏慢,你可以直接在Inspector中把moveSpeed设为“每秒移动速度”,然后去掉Time.fixedDeltaTime - 2D平台跳跃中,用
rb2D.velocity = new Vector2(rb2D.velocity.x, jumpY)替代AddForce,能避免速度叠加导致的跳跃高度不稳定
内容的提问来源于stack exchange,提问作者Tiến Hưng
相关产品推荐
相关产品推荐

