通知时,AssetDatabase.刷新准备好了
本文关键字:刷新 准备好了 AssetDatabase 通知 | 更新日期: 2023-09-27 18:04:35
我有一个Unity3D编辑器类,它可以动态创建一个新资产。然后调用AssetDatabase。使用默认选项刷新(强烈推荐)。由于刷新是一种异步方式,所以我需要一种方法在刷新准备好时得到通知。
:
我写了一个代码生成器来创建一个c#脚本。这意味着为场景中的活动游戏对象创建一个辅助组件。到目前为止一切正常,文件是由System.File.IO中的方法创建的。现在我想将新创建的MonoBehaviour自动添加到活动的游戏对象中。
当前状态/限制因素:
- 如预期的那样,所有活动对象在刷新过程中被销毁。这使得任何标准的轮询方法(如调用或协程)都无法工作,因为它们在游戏对象被销毁时终止。
- 轮询通常不是好的解决方案,但在这种情况下是可以的。另一方面,我不想使用线程,因为这在Unity中是不推荐的。如果静态构造函数的类设置了InitializeOnLoadAttribute,或者该组件在活动场景中被引用,则在刷新准备好后立即调用静态构造函数。
可能可行的(繁琐的)方法:
- 定义一个类
ActionAfterRefresh
,包含元信息和在刷新后执行的代码,例如,在构造函数中加载类名和执行AddComponent
的代码。 - 在一个特殊的缓存目录 中将这个类序列化为JSON文件
- 定义一个类
Loader
,它有一个静态构造函数:- 查看缓存目录中是否有匹配的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;
}
}