通知时,AssetDatabase.刷新准备好了

本文关键字:刷新 准备好了 AssetDatabase 通知 | 更新日期: 2023-09-27 18:04:35

我有一个Unity3D编辑器类,它可以动态创建一个新资产。然后调用AssetDatabase。使用默认选项刷新(强烈推荐)。由于刷新是一种异步方式,所以我需要一种方法在刷新准备好时得到通知。

:

我写了一个代码生成器来创建一个c#脚本。这意味着为场景中的活动游戏对象创建一个辅助组件。到目前为止一切正常,文件是由System.File.IO中的方法创建的。现在我想将新创建的MonoBehaviour自动添加到活动的游戏对象中。

当前状态/限制因素:

    如预期的那样,所有活动对象在刷新过程中被销毁。这使得任何标准的轮询方法(如调用或协程)都无法工作,因为它们在游戏对象被销毁时终止。
  • 轮询通常不是好的解决方案,但在这种情况下是可以的。另一方面,我不想使用线程,因为这在Unity中是不推荐的。如果静态构造函数的类设置了InitializeOnLoadAttribute,或者该组件在活动场景中被引用,则在刷新准备好后立即调用静态构造函数。

可能可行的(繁琐的)方法:

  • 定义一个类ActionAfterRefresh,包含元信息和在刷新后执行的代码,例如,在构造函数中加载类名和执行AddComponent的代码。
  • 在一个特殊的缓存目录
  • 中将这个类序列化为JSON文件
  • 定义一个类Loader,它有一个静态构造函数:
    • 查看缓存目录中是否有匹配的JSON文件。如果是,创建一个实例并执行代码
    • 删除JSON文件

我认为这可以工作,我猜你知道为什么我写麻烦。有没有更聪明、更好、更快的方法来实现这一点?我是否忽略了OnRefreshDatabaseReady事件?

谢谢你的帮助

通知时,AssetDatabase.刷新准备好了

通知

1

方式

很有趣,但是你已经列出了这个选项:

  • 静态构造函数在刷新准备好后立即调用,如果它们的类设置了InitializeOnLoadAttribute

所以,如果一些类的静态构造函数与[InitializeOnLoadAttribute]被调用:这是一个好迹象,Unity刚刚重建的解决方案。

2。黑魔法:)

这是没有文档记录的,但是如果你在任何编辑器类的静态方法中添加[DidReloadScripts]属性,这个方法将在Unity重新编译脚本后被调用。看到的例子:

public class SomeEditorClass
{
    [DidReloadScripts]
    public static void OnCompileScripts()
    {
        Debug.Log("Bla-bla-bla");
    }
}

在使用编辑器窗口的重建之间存活

但是为了使用所有这些来解决您的问题,您仍然需要一种在解决方案重建之间存储一些数据的方法。如果你是从编辑器窗口进行"操作",这里有一个你可以使用的技巧:Unity存储EditorWindow对象状态。所以,你可以这样做:

[InitializeOnLoadAttribute]
public class YourWindow : EditorWindow
{
    const string path = @"Assets/Bla-bla-bla.cs";
    private static bool justRecompiled;
    static YourWindow()
    {
        justRecompiled = true;
    }
    [MenuItem("Test/YourWindow")]
    public static void Generate()
    {
        GetWindow(typeof(YourWindow));
    }
    private bool waitingForRecompiling;
    private GameObject gameObject;
    public void OnRecompile()
    {
        MonoScript monoScript = AssetDatabase.LoadAssetAtPath(path, typeof(MonoScript)) as MonoScript;
        Type monoScriptClass = monoScript.GetClass();
        if (gameObject.GetComponent(monoScriptClass) == null)
            gameObject.AddComponent(monoScriptClass);
    }
    public void OnGUI()
    {
        if (GUILayout.Button("Execute"))
            if (Selection.activeGameObject != null)
            {
                // Do your script file generation here
                waitingForRecompiling = true;
                gameObject = Selection.activeGameObject;
                AssetDatabase.ImportAsset(path);
            }
    }
    public void Update()
    {
        if (justRecompiled && waitingForRecompiling)
        {
            waitingForRecompiling = false;
            OnRecompile();
        }
        justRecompiled = false;
    }
}