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

Unity中OnTriggerStay2D()因其他物体触发OnTriggerExit2D()失效

故障根本原因

现有逻辑存在两个核心缺陷:

  1. 状态判断逻辑没有绑定具体碰撞体:OnTriggerExit2D回调只要检测到任意带PuzzlePiece标签的物体离开,就直接把isCovered全局置为false,完全不校验离开的是不是原本放在瓦片上的那块拼图,也不检查碰撞区域内是否还有其他已放置的拼图块。
  2. 对Unity 2D物理触发逻辑的认知偏差:当触发器区域内同时存在多个碰撞体时,只要其中一个碰撞体触发退出事件,Unity不会自动为剩余留在区域内的碰撞体持续触发OnTriggerStay2D回调,必须等对应碰撞体重新进入触发器范围才会恢复Stay调用。这就是为什么路过的拼图离开后,就算原本放好的拼图还在碰撞区,OnTriggerStay2D也不会再执行把状态改回true。
修复方案

不要用单个布尔值直接标记覆盖状态,改为维护当前触发区域内所有符合条件的已放置拼图集合,通过集合是否为空判断覆盖状态,具体调整点:

  • 用HashSet存储当前处于传感器范围内、且isPlaced为true的拼图块引用,避免重复记录
  • 三个触发器回调只针对当前触发事件的碰撞体做增删操作,不直接修改全局覆盖标记
  • 将isCovered改为只读属性,实时返回集合元素数量是否大于0
  • 补充OnTriggerEnter2D逻辑,避免拼图刚进入区域时第一帧的状态丢失

修复后的完整代码如下:

using System.Collections.Generic;
using UnityEngine;

public class GridTileSensor : MonoBehaviour
{
    private readonly HashSet<GameObject> _placedPiecesInSensor = new HashSet<GameObject>();
    // 实时判断是否处于覆盖状态
    public bool isCovered => _placedPiecesInSensor.Count > 0;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        CheckAndAddPiece(collision);
    }

    private void OnTriggerStay2D(Collider2D collision)
    {
        if (!collision.gameObject.CompareTag("PuzzlePiece")) return;
        
        Dragger pieceDragger = collision.gameObject.GetComponent<Dragger>();
        if (pieceDragger.isPlaced)
        {
            _placedPiecesInSensor.Add(collision.gameObject);
        }
        else
        {
            // 处理已放置的拼图被玩家重新拿起拖动的情况
            _placedPiecesInSensor.Remove(collision.gameObject);
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("PuzzlePiece"))
        {
            // 仅移除当前离开的拼图块,不影响区域内其他拼图
            _placedPiecesInSensor.Remove(collision.gameObject);
        }
    }

    private void CheckAndAddPiece(Collider2D collision)
    {
        if (!collision.gameObject.CompareTag("PuzzlePiece")) return;
        
        Dragger pieceDragger = collision.gameObject.GetComponent<Dragger>();
        if (pieceDragger.isPlaced)
        {
            _placedPiecesInSensor.Add(collision.gameObject);
        }
    }
}

优化提示:可以给拼图块提前缓存Dragger组件引用,避免每帧调用GetComponent产生不必要的性能开销,不影响核心逻辑修复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:45:32