Unity中OnCollisionEnter2D与OnCollisionExit2D失效问题求助
问题解决:立方体与Block碰撞但isGrounded仍为false无法跳跃

问题分析
你的代码核心问题出在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"); } }
关键修改点
- 新增
groundContactCount计数器,替代原来的isGrounded直接赋值逻辑 - 用只读属性
isGrounded来判断是否接地,避免手动赋值出错 OnCollisionEnter2D中碰到Ground/Block时计数+1,OnCollisionExit2D时计数-1(并限制最小值为0)- 移除跳跃时手动设置
isGrounded = false的代码,因为计数器会自动处理离开地面的情况
这样修改后,无论立方体同时接触多少个Ground/Block,只要有一个接触存在,isGrounded就会保持true,完全解决你的问题。
内容的提问来源于stack exchange,提问作者Brian Serrano
相关产品推荐
相关产品推荐

