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

Unity中玩家离开Collider时禁用Canvas并销毁对象的实现问题

Unity 2D碰撞触发UI禁用与对象销毁实现方案

核心问题定位

原有代码存在3个逻辑错误:

  • 动画对象销毁逻辑错放在Update()生命周期中,箱子开启后下一帧就会直接销毁animateObject,LeanTween缩放动画没有足够时间播放
  • OnTriggerExit2D回调仅处理了交互标记和基础UI显隐,缺失Canvas禁用、目标对象销毁的逻辑
  • 没有做空引用校验,对象销毁后重复调用API会触发空引用报错

修复实现

首先给类补充Canvas引用字段,修正动画播放、触发离开的逻辑,完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;

public class Crate : MonoBehaviour
{
    public float duration;
    public GameObject animateObject;

    public GameObject crateBox;
    // 关联箱子UI所属的Canvas组件,直接在Inspector拖拽赋值
    public Canvas crateCanvas;
    public Text crateText;
    public GameObject crateImage;

    public GameObject crate;

    public bool playerInRange;
    private bool crateOpened = false;
    // 存储LeanTween动画ID,用于对象销毁前取消动画避免报错
    private int tweenId;

    void Update()
    {
        // 箱子未开启时才检测交互输入
        if (!crateOpened && Keyboard.current.eKey.wasPressedThisFrame && playerInRange)
        {
            crateBox.SetActive(true);
            crateOpened = true;
            PlayOpenAnimation();
        }
    }

    private void OnTriggerEnter2D(Collider2D other) {
        if(other.CompareTag("Player")) {
            playerInRange = true;
            crateImage.SetActive(true);
            // 进入范围时启用Canvas
            crateCanvas.enabled = true;
        }
    }

    private void OnTriggerExit2D(Collider2D other) {
        if(other.CompareTag("Player")) {
            playerInRange = false;
            // 离开时禁用Canvas
            crateCanvas.enabled = false;
            crateBox.SetActive(false);
            crateImage.SetActive(false);
            
            // 取消正在播放的补间动画
            LeanTween.cancel(tweenId);
            // 销毁动画对象,先判空避免重复销毁报错
            if (animateObject != null)
            {
                Destroy(animateObject);
            }
        }
    }

    private void PlayOpenAnimation()
    {
        // 初始化动画对象缩放为0,保证从0到1的缩放效果正常
        animateObject.transform.localScale = Vector3.zero;
        tweenId = LeanTween.scale(animateObject, new Vector3(1f, 1f, 1f), duration).id;
    }
}

配置注意事项

  • 所有公开字段在Unity Inspector面板完成拖拽赋值,尤其是crateCanvas字段要关联箱子UI对应的Canvas组件
  • 确认玩家对象的Tag设置为Player,Collider2D的Is Trigger选项已勾选,2D碰撞体矩阵配置正确保证触发事件能正常回调
  • 如果需要动画播放完成后自动销毁对象,只需要给LeanTween加完成回调即可,示例:
    tweenId = LeanTween.scale(animateObject, new Vector3(1f, 1f, 1f), duration)
        .setOnComplete(() => {
            if (animateObject != null) Destroy(animateObject);
        }).id;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:15:35