动态添加事件帧并持久化保存

撰写于 2019-07-03 修改于 2019-07-03 分类 Unity 标签 Animator

动态添加事件帧并持久化保存

代码中如何在AnimationClip中添加事件帧,并回写,实现事件帧持久化保存。

动态添加事件帧

动态添加事件帧,很简单!有两种方法:

  1. AnimationClip.AddEvent(AnimationEvent evt)

    AnimationClip中提供的有添加事件帧的方法AnimationClip.AddEvent(AnimationEvent evt),但这个并不能实现持久化保存,只是修改了内存数据。
  2. AnimationUtility.SetAnimationEvents(AnimationClip clip, AnimationEvent[] events)

    那怎么办呢?其实文档中已经写了 If you want to add an event to a clip persistently, use AnimationUtility.SetAnimationEvents from the Unity editor.就是如果你想实现持久化保存,就需要使用 AnimationUtility.SetAnimationEvents,这个方法也很简单,使用 AnimationUtility.GetAnimationEvents等到该clip的所有事件,然后可以修改该数组,使用AnimationUtility.SetAnimationEvents重新设置一下。实际使用中,这种方法的确可以实现暂时的持久化:修改后,每次运行场景,都可以读取到添加(或修改)的事件帧。但是,在Animation的Inspector面板中,Events数据面板中并没有看到添加的事件帧,而且,重新打开UnityEditor,所有的修改的事件都被还原了!也就是说,并没有真正的实现持久化!

持久化

动态添加事件帧很简单,但是持久化貌似不简单!
这时就考虑到Evens究竟是如何在本地存储的?牵涉到,Unity对数据的序列化保存,Unity会对Inspector面板上设置的数据进行序列化,并保存在.meta文件中,打开AnimationClip对应的文件,你会发现,除了一个.fbx文件,还会对应一个.meta,打开.meta文件,会看到很多序列化数据,以yaml格式存储,这些数据会被Unity加载并同步更新,我们会很容易的找到animations:clipAnimations:events

该clip对应的事件都会存贮在这里。找到了数据存储的地方,怎么修改呢?总不能暴力写入吧(我没有试过),Unity开放了这么多接口,肯定有办法修改的。是的!Unity提供一个类 AssetImporter,可以让你在导入配置文件时进行修改,在这里我们使用它的子类 ModelImporter,关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
string clipAssertPath = AssetDatabase.GetAssetPath(currentClip);
ModelImporter modelImporter = AssetImporter.GetAtPath(clipAssertPath) as ModelImporter;
if (modelImporter == null)
return;

SerializedObject modelImporterObj = new SerializedObject(modelImporter);
SerializedProperty rootNodeProperty = modelImporterObj.FindProperty("m_ClipAnimations");
SerializedProperty firstProperty = modelImporterObj.GetIterator();

if (!rootNodeProperty.isNull() && rootNodeProperty.isArray)
{
for (int i = 0; i < rootNodeProperty.arraySize; i++)
{
SerializedProperty item = rootNodeProperty.GetArrayElementAtIndex(i);

string clipName = item.FindPropertyRelative("name").stringValue;
if (clipName.Equals(currentClip.name))
{
//找出对应clip的events
var eventItems = item.FindPropertyRelative("events");
break;
}
}
}

通过以上代码,我们可以获取到对应clip的所有events,然后可以通过 SerializedProperty提供的 方法和属性对events进行修改。修改后,并没有保存到.meta文件,需要使用连个关键的方法:

1
2
modelImporterObj.ApplyModifiedProperties();
modelImporter.SaveAndReimport();

然后,大功告成!在.meta可以看到该动的event,在Inspector面板中,也可以看到该动的event

Site by ZHJ using Hexo & Random

Hide