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

Unity自定义WarnOnNull属性实现字段自动非空验证

实现Unity自动非空检测的WarnOnNull属性

1. 定义WarnOnNull自定义属性

先创建一个标记用的属性类,用来标识需要做非空检测的字段:

using System;

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class WarnOnNullAttribute : Attribute
{
    // 仅作为标记,无需额外逻辑
}

2. 实现自动检测的通用编辑器工具

编写一个编辑器脚本,自动对所有带WarnOnNull标记的字段做检测——既在编辑模式下实时提示,也在运行时自动验证,完全不需要手动调用:

using UnityEngine;
using UnityEditor;
using System.Reflection;

// 对所有MonoBehaviour生效的通用编辑器
[CustomEditor(typeof(MonoBehaviour), true)]
public class NullCheckAutoEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        var targetMb = target as MonoBehaviour;
        if (targetMb == null) return;

        // 遍历所有实例字段(包括[SerializeField]的私有字段)
        var fields = targetMb.GetType().GetFields(
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        foreach (var field in fields)
        {
            // 检查字段是否带有WarnOnNull标记
            if (field.GetCustomAttribute<WarnOnNullAttribute>() != null)
            {
                var fieldValue = field.GetValue(targetMb);
                if (fieldValue == null)
                {
                    // 在Inspector中显示警告
                    EditorGUILayout.HelpBox($"字段「{field.Name}」未赋值!", MessageType.Warning);
                }
            }
        }
    }

    // 运行时自动触发检测(场景加载前执行)
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void RuntimeAutoNullCheck()
    {
        var allMonoBehaviours = GameObject.FindObjectsOfType<MonoBehaviour>();
        foreach (var mb in allMonoBehaviours)
        {
            var fields = mb.GetType().GetFields(
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            foreach (var field in fields)
            {
                if (field.GetCustomAttribute<WarnOnNullAttribute>() != null)
                {
                    var fieldValue = field.GetValue(mb);
                    if (fieldValue == null)
                    {
                        // 运行时输出警告,附带组件引用方便定位
                        Debug.LogWarning($"[{mb.GetType().Name}] 字段「{field.Name}」未赋值!", mb);
                    }
                }
            }
        }
    }
}

3. 使用方式

给需要检测的[SerializeField]字段加上[WarnOnNull]标记即可,完全无需在Awake/Start中手动调用验证逻辑:

using UnityEngine;
using UnityEngine.UI;

public class UiManager : MonoBehaviour
{
    [SerializeField, WarnOnNull] private Button _startBtn;
    [SerializeField, WarnOnNull] private Text _scoreText;
    [SerializeField, WarnOnNull] private Image _hpBar;
    // ... 上千个字段直接加标记即可
}

效果说明

  • 编辑模式:在Inspector面板中,未赋值的标记字段会直接显示黄色警告,实时提醒你补全赋值。
  • 运行模式:场景加载前会自动扫描所有带标记的字段,为空的字段会在Console输出警告,并且点击警告可以直接跳转到对应的组件,方便定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:15:35