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

如何在Unity非运行时通过代码自动检查并创建丢失的GameObject

编辑器下自动恢复必要场景对象的实现方案

原实现代码存在的硬伤

  • 类定义错误:[InitializeOnLoad]修饰的是纯编辑器静态工具类,完全不需要继承MonoBehaviour。原写法会引入不必要的运行时类依赖,甚至可能因为类的序列化逻辑在打包后残留冗余代码,违反“自动恢复逻辑绝不参与游戏运行”的要求。
  • 对象查找失效:GameObject.Find只能检索场景中处于激活状态的对象,失活状态的同名必要对象会被误判为丢失,触发重复创建。
  • 无性能防护:EditorApplication.hierarchyChanged事件在Hierarchy面板的每一次操作(拖动物体、改名字、改组件参数)时都会触发,没有节流逻辑会导致全场景遍历频繁执行,拖慢编辑器响应速度。
  • 创建逻辑缺失:仅创建空的同名GameObject,没有挂载ObjectsGenerator、PlayerData等必要业务脚本,等于做了无用功。
  • 无运行时隔离:没有判断当前编辑器是否处于Play模式,很容易在游戏运行过程中误触发创建逻辑。

修正后可直接使用的实现

所有逻辑通过编译宏完全隔离在编辑器环境内,不会被打包进游戏包体:

#if UNITY_EDITOR
using System.Linq;
using UnityEditor;
using UnityEngine;

// 编辑器启动时自动初始化的静态校验类,无任何运行时依赖
[InitializeOnLoad]
public static class RequiredSceneObjectChecker
{
    // 封装必要对象的配置,避免到处硬编码名字和组件
    private class RequiredObjectConfig
    {
        public string TargetObjectName;
        public System.Type[] RequiredComponents;
    }

    static RequiredSceneObjectChecker()
    {
        // 初始化时注册回调
        EditorApplication.hierarchyChanged += OnHierarchyDirty;
        EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        // 项目刚打开、编辑器加载完成时,执行一次全量校验
        CheckAndRestoreRequiredObjects();
    }

    // Play模式切换回调,确保运行时完全关闭校验逻辑
    private static void OnPlayModeStateChanged(PlayModeStateChange state)
    {
        // 进入运行模式时,直接解绑Hierarchy变化的监听,绝不执行任何创建
        if (state == PlayModeStateChange.EnteredPlayMode)
        {
            EditorApplication.hierarchyChanged -= OnHierarchyDirty;
        }
        // 退出运行模式、回到编辑态时,重新开启监听
        if (state == PlayModeStateChange.ExitingPlayMode)
        {
            EditorApplication.hierarchyChanged += OnHierarchyDirty;
        }
    }

    // 节流标记,合并短时间内多次高频触发的Hierarchy变更
    private static bool _isCheckScheduled;
    private static void OnHierarchyDirty()
    {
        // 编辑态才处理,运行中直接跳过
        if (EditorApplication.isPlaying) return;
        
        if (_isCheckScheduled) return;
        _isCheckScheduled = true;
        // 延迟到编辑器的下一帧执行校验,避免连续操作时重复跑逻辑
        EditorApplication.delayCall += () =>
        {
            CheckAndRestoreRequiredObjects();
            _isCheckScheduled = false;
        };
    }

    private static void CheckAndRestoreRequiredObjects()
    {
        // 进入运行模式的过程中,绝不执行任何创建、修改操作
        if (EditorApplication.isPlayingOrWillChangePlaymode) return;

        // 在这里配置所有需要强制存在的场景对象,维护时只需要改这个列表
        var requiredObjectList = new[]
        {
            new RequiredObjectConfig()
            {
                TargetObjectName = "SceneBuilder",
                // 把这个对象上必须挂的所有脚本列在这里
                RequiredComponents = new[] {
                    typeof(ObjectsGenerator),
                    typeof(PlayerData)
                }
            }
        };

        foreach (var config in requiredObjectList)
        {
            // 查找时包含失活对象,避免误判丢失
            var targetObj = Object.FindObjectsOfType<GameObject>(includeInactive: true)
                .FirstOrDefault(go => go.name == config.TargetObjectName);

            if (targetObj == null)
            {
                // 对象完全丢失时,新建对应对象并挂载所有必要组件
                var restoredObj = new GameObject(config.TargetObjectName);
                foreach (var componentType in config.RequiredComponents)
                {
                    restoredObj.AddComponent(componentType);
                }
                Debug.Log($"已自动恢复必要场景对象:{config.TargetObjectName}");
            }
            else
            {
                // 对象存在但组件缺失时,自动补全缺失的组件
                foreach (var componentType in config.RequiredComponents)
                {
                    if (targetObj.GetComponent(componentType) == null)
                    {
                        targetObj.AddComponent(componentType);
                        Debug.Log($"为对象{config.TargetObjectName}补全缺失组件:{componentType.Name}");
                    }
                }
            }
        }
    }
}
#endif

实现效果

  • 完全隔离运行时:所有逻辑被UNITY_EDITOR宏包裹,且运行模式下会主动解绑所有事件监听,绝对不会在游戏运行、打包后执行任何创建逻辑。
  • 适配全空场景:哪怕打开的场景没有任何对象,只要处于编辑态就会自动创建带全量必要组件的目标对象,不依赖任何已存在的引用。
  • 维护成本极低:后续新增需要固定存在的场景对象,只需要在requiredObjectList配置列表中添加对应条目即可,不需要手动做菜单、不需要写自定义Editor扩展。
  • 性能损耗可忽略:通过延迟调用机制合并高频的Hierarchy变更事件,不会因为频繁的场景操作导致编辑器卡顿。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 05:54:02