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

Unity中OnCollisionEnter2D与OnCollisionExit2D失效问题求助

问题解决:立方体与Block碰撞但isGrounded仍为false无法跳跃

立方体与Block碰撞场景

问题分析

你的代码核心问题出在OnCollisionExit2D的逻辑上:只要立方体离开任意一个带有Block标签的物体,就直接把isGrounded设为false。但如果立方体同时接触多个Block(比如从一个Block跳到另一个的瞬间,或者停在多个Block堆叠的表面),离开其中一个Block时,实际上立方体还和其他Block保持接触,这时候错误地将isGrounded设为false,就会导致无法触发跳跃逻辑。

另外,Update里每帧都打印isGrounded,很容易因为Exit事件先触发而显示false,但此时立方体其实还在接触其他地面/Block。

修复方案

改用接触计数的方式来判断是否接地:维护一个计数器,记录当前接触的Ground/Block数量,只要计数大于0,就判定为接地。这种方式能处理多物体接触的场景,避免单次离开事件误判。

修改后的完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Cube1 : MonoBehaviour
{
    public float jumpForce = 7.0f;
    private int groundContactCount = 0;
    // 用属性简化判断,替代原来的isGrounded变量
    private bool isGrounded => groundContactCount > 0;

    private Rigidbody2D rb;
    private AudioSource audio;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        audio = GetComponent<AudioSource>();
    }

    void Update()
    {
        if (isGrounded && (Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0)))
        {
            audio.Play();
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            Debug.Log("Works");
            // 这里不需要手动设isGrounded为false,计数会自动处理
        }

        Debug.Log(isGrounded);
    }

    void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("Ground") || other.gameObject.CompareTag("Block"))
        {
            groundContactCount++;
        }

        string colliderName = other.gameObject.name;
        if (colliderName == "leftCollider" || colliderName == "rightCollider" || colliderName == "bottomCollider" 
            || other.gameObject.CompareTag("Spike") || other.gameObject.CompareTag("Thorn"))
        {
            GameOver();
        }
    }

    void OnCollisionExit2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("Ground") || other.gameObject.CompareTag("Block"))
        {
            // 防止计数变成负数
            groundContactCount = Mathf.Max(0, groundContactCount - 1);
        }
    }

    public void GameOver()
    {
        if (MyVariables.highScore < (int)MyVariables.score)
        {
            MyVariables.highScore = (int)MyVariables.score;
        }
        MyVariables.score = 0;
        MyVariables.obstacleCount = 0;
        Time.timeScale = 1f;
        SceneManager.LoadScene("Menu");
    }
}

关键修改点

  1. 新增groundContactCount计数器,替代原来的isGrounded直接赋值逻辑
  2. 用只读属性isGrounded来判断是否接地,避免手动赋值出错
  3. OnCollisionEnter2D中碰到Ground/Block时计数+1,OnCollisionExit2D时计数-1(并限制最小值为0)
  4. 移除跳跃时手动设置isGrounded = false的代码,因为计数器会自动处理离开地面的情况

这样修改后,无论立方体同时接触多少个Ground/Block,只要有一个接触存在,isGrounded就会保持true,完全解决你的问题。

内容的提问来源于stack exchange,提问作者Brian Serrano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:38:07