Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AssetDatabase.Refresh准备就绪时发出通知_C#_Unity3d - Fatal编程技术网

C# AssetDatabase.Refresh准备就绪时发出通知

C# AssetDatabase.Refresh准备就绪时发出通知,c#,unity3d,C#,Unity3d,我有一个Unity3D编辑器类,可以动态创建新资源。然后我使用默认选项(强烈推荐)调用。由于刷新是一种异步方式,因此我需要一种在刷新准备就绪时获得通知的方法 背景: 我编写了一个代码生成器来创建C#脚本。这意味着为场景中的活动游戏对象创建一个助手组件。到目前为止,一切正常,该文件是通过System.file.IO中的方法创建的。现在我想将新创建的MonoBehavior自动添加到活动的游戏对象中 当前状态/限制因素: 正如预期的那样,在刷新过程中会销毁所有活动对象。这使得不可能使用任何标准的轮

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

背景

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

当前状态/限制因素:

  • 正如预期的那样,在刷新过程中会销毁所有活动对象。这使得不可能使用任何标准的轮询方法,如调用或协同路由,因为它们在游戏对象被销毁时终止
  • 投票通常不是一个好的解决方案,但在这种情况下也可以。另一方面,我不想使用线程,因为这在Unity中是不推荐的
  • 如果静态构造函数的类具有集合或组件在活动场景中引用,则在刷新准备就绪后立即调用静态构造函数
可能的(麻烦的)工作方式:

  • 定义一个类
    ActionAfterRefresh
    ,该类包含元信息和刷新后要执行的代码,例如要加载的类名和要在构造函数中为其执行
    AddComponent
  • 将此类序列化为特殊缓存目录中的JSON文件
  • 定义一个具有静态构造函数的类
    加载器
    • 查看缓存目录中是否有匹配的JSON文件。如果是这样,创建一个实例并执行代码
    • 删除JSON文件
我想这可能行得通,我想你知道我为什么写这么麻烦。有没有更聪明、更好、更快的方法来实现这一点?我是否忽略了实时保存OnRefreshDatabaseReady事件

感谢您的帮助

通知 方式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;
    }
}

这有点难看,但仍然是一种选择。

谢谢:)EditorWindow的实例确实是所有程序集完全重新加载后唯一幸存下来的东西。我让它以这种方式运行,但在自动关闭它和偶尔出现Unity错误时遇到了一些麻烦。因此,我决定回滚到一个基于文件的解决方案来存储用户以前选择的文件名。不管怎样,好消息。嗨。我尝试了您的解决方案#3,但在我的情况下,从未调用更新函数。使用Unity 2019.2.14f1。@MichaelBoccara对不起,伙计,我不再在游戏开发空间工作了,所以不知道Unity最近在做什么。听上去,你的问题与OP的问题和提议的解决方案无关。您需要弄清楚EditorWindow.Update发生了什么。我不确定在Unity的最新版本中它是否仍然应该被调用。@MichaelBoccara可能会为你的问题创建一个新的SO问题?@SergeyKrusch好的,我有时间会的。谢谢