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

Unity脚本功能正常却出现NullReferenceException的排查与解决

解决Unity中NullReferenceException在GameObject.FindGameObjectWithTag上的问题

报错信息:
NullReferenceException: Object reference not set to an instance of an object DestroyCollision.OnCollisionEnter2D (UnityEngine.Collision2D collision) (at Assets/Scripts/DestroyCollision.cs:66)

报错原因

GameObject.FindGameObjectWithTag("Shield")返回null导致报错,核心原因是:该API仅能查找场景中处于激活状态(activeSelf = true)的对象。

你的代码逻辑中,第一次碰撞到Shield时,对象处于激活状态,Find方法能正常找到并执行SetActive(false);但如果后续有重复碰撞触发(比如多个碰撞体连续触发该逻辑),此时Shield已经被禁用,FindGameObjectWithTag会返回null,调用SetActive自然抛出空引用异常。你觉得功能正常是因为首次逻辑执行成功,不影响核心功能,但后续触发会持续输出错误。

修复方案

最优方案:直接操作碰撞到的对象

既然已经通过collision.gameObject.tag == "Shield"确认碰撞对象就是目标Shield,无需额外查找,直接操作该对象即可彻底避免空引用风险:

if (collision.gameObject.tag == "Shield")
{
    collision.gameObject.SetActive(false);
    Destroy(this.gameObject);
}

备选方案:提前缓存全局引用

如果需要在多个逻辑中访问Shield对象,建议在脚本初始化阶段缓存引用,避免重复查找的性能开销和空引用问题:

private GameObject shield;

void Awake()
{
    // 初始化时一次性查找并缓存
    shield = GameObject.FindGameObjectWithTag("Shield");
}

void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.tag == "Shield" && shield != null)
    {
        shield.SetActive(false);
        Destroy(this.gameObject);
    }
}

注意:若Shield对象可能在运行时被销毁,需额外判断引用有效性。

特殊场景:查找非激活对象

如果确实需要定位非激活状态的Shield对象,可使用FindObjectsOfType并开启includeInactive参数(性能开销较高,不推荐频繁调用):

if (collision.gameObject.tag == "Shield")
{
    GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(true);
    foreach (GameObject obj in allObjects)
    {
        if (obj.CompareTag("Shield"))
        {
            obj.SetActive(false);
            break;
        }
    }
    Destroy(this.gameObject);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:30:59