You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:25:20