最近在写一个基于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状态
文章评论