最近在写一个基于Timeline的编辑器,需要在关闭Timeline编辑器的时候对TBCAsset(继承于TimelineAsset)资源进行保存,并写入一些额外的数据,因为保存有些耗时需要1~2秒,所以需要判定如果只是打开,但并未修改TBCAsset资源点关闭后直接退出
我用EditorUtility.IsDirty来对资源进行判断是否有修改,但发现并不准确,翻看Timeline源码后,发现TimelineAsset的TrackAsset与PlayableAsset资源是通过AssetDatabase.AddObjectToAsset的方式存储的,所以才会导致EditorUtility.IsDirty判断失败,为此我写了两个函数来进行处理,供遇到相同问题的同学参考
public static class TBCEditorUtil
{
public static bool IsDirty(TBCAsset asset)
{
if (EditorUtility.IsDirty(asset))
return true;
var outTracks = asset.GetOutputTracks();
foreach (var track in outTracks)
{
if (EditorUtility.IsDirty(track))
return true;
var clips = track.GetClips();
foreach (var clip in clips)
{
if (EditorUtility.IsDirty(clip.asset))
return true;
}
}
return false;
}
public static void SetDirty(TBCAsset asset)
{
EditorUtility.SetDirty(asset);
var outTracks = asset.GetOutputTracks();
foreach (var track in outTracks)
{
EditorUtility.ClearDirty(track);
var clips = track.GetClips();
foreach (var clip in clips)
{
EditorUtility.ClearDirty(clip.asset);
}
}
}
}
使用代码如下
static IEnumerator SaveAsset()
{
if (TBCEditorUtil.IsDirty(curAsset))
{
EditorUtility.DisplayProgressBar("提示", "正在保存,请稍后...", 0);
TBCEditorUtil.SetDirty(curAsset);
AssetDatabase.SaveAssets();
EditorUtility.DisplayProgressBar("提示", "正在保存,请稍后...", 1f);
yield return new WaitForEndOfFrame();
EditorUtility.ClearProgressBar();
}
}
请注意,由于TimelineAsset内部是AssetDatabase.AddObjectToAsset创建的,所以它们的dirty状态也是单独的,也就是如果不清楚内部Dirty状态,即使使用AssetDatabase.SaveAssets() 保存后,内部依旧是Dirty状态,所以我在SetDirty 函数中清除了其它部件的Dirty状态
文章评论