Unity2D宝箱功能bug:范围外按X进入范围后错误掉落道具求助
Unity2D宝箱触发Bug修复方案
问题根因
TouchingChestBoxCollider状态未正确重置:玩家离开宝箱触发范围后,该变量仍然保持为true,导致范围外按X也能触发xIsPressed赋值。同时OnTriggerStay2D中未判断碰撞对象就直接修改该变量,可能被其他碰撞体误触发。xIsPressed状态永久残留:该变量被赋值为true后没有任何重置逻辑,只要历史上有过一次在TouchingChestBoxCollider为true时按下X的操作,后续进入宝箱范围时就会直接触发掉落。即使之前是误触发的xIsPressed=true,状态也会一直保留。
修复方案
推荐方案(逻辑最贴合需求)
利用xIsPressed仅需存活一帧的特性,每次Update结束后重置状态,从根源避免残留:
- 修正
TouchingChestBoxCollider的赋值与重置逻辑,仅玩家碰撞时修改状态 - 在LateUpdate中重置
xIsPressed为false,确保按下状态仅生效一帧 - 优化
OnTriggerStay2D的判断顺序,减少无效逻辑执行
修改后完整代码
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class ChestOpener : MonoBehaviour { [SerializeField] private GameObject ChestItSelf; [SerializeField] private GameObject[] itemsWeapon; [SerializeField] private GameObject[] itemsMedi; [SerializeField] private SpriteRenderer spriteRenderer; [SerializeField] private Sprite openSprite, closeSprite; private int random; private Vector2 destination; private GameObject objectsWeapon; private GameObject objectsWeapon2; private GameObject objectsMedi; private bool HasItDropped = false; private bool MoveItemNow = false; private bool xIsPressed = false; private bool TouchingChestBoxCollider = false; private void Update() { if (Input.GetKeyDown(KeyCode.X) && TouchingChestBoxCollider == true) { xIsPressed = true; } if (MoveItemNow == true ) { objectsWeapon.transform.position = Vector2.Lerp(objectsWeapon.transform.position, new Vector2(transform.position.x, transform.position.y - 4), Time.deltaTime * 1f); objectsWeapon2.transform.position = Vector2.Lerp(objectsWeapon2.transform.position, new Vector2(transform.position.x-2, transform.position.y - 4), Time.deltaTime * 1f); } } // 新增LateUpdate,每帧结束重置X键按下状态,避免残留 private void LateUpdate() { xIsPressed = false; } private void OnTriggerStay2D(Collider2D collision) { // 仅处理玩家的碰撞事件 if (collision.gameObject.tag != "Player") return; TouchingChestBoxCollider = true; if (HasItDropped == false && xIsPressed == true) { DropDownItem(); } } private void DropDownItem() { spriteRenderer.sprite = openSprite; random = UnityEngine.Random.Range(0, itemsWeapon.Length); objectsWeapon = Instantiate(itemsWeapon[random], transform.position, Quaternion.identity); objectsWeapon2 = Instantiate(itemsWeapon[random], transform.position, Quaternion.identity); MoveItemNow = true; HasItDropped = true; } private void OnTriggerExit2D(Collider2D collision) { // 仅玩家离开时重置触摸状态 if (collision.gameObject.tag != "Player") return; TouchingChestBoxCollider = false; spriteRenderer.sprite = closeSprite; Invoke("FareWellChest", 2f); } private void FareWellChest() { if (HasItDropped == true) { Destroy(ChestItSelf); } } }
极简改法(改动量最小)
如果不想新增LateUpdate,也可以仅修改3处逻辑即可解决问题:
OnTriggerStay2D中仅玩家碰撞时才给TouchingChestBoxCollider赋值为trueOnTriggerExit2D玩家离开时,同时重置TouchingChestBoxCollider和xIsPressed为falseDropDownItem执行完成后,重置xIsPressed为false
内容的提问来源于stack exchange,提问作者YuDotNet
相关产品推荐
相关产品推荐

