一,环境:
Unity 2018.4.2
二,结构
一个Prefab一段Timeline演出,Prefab上会挂PlayableDirector组件,并绑定Timeline Asset。
Timeline Asset的编辑内容
三,现象
对预制执行Select Dependencies发现:
该预制额外地引用了一些无关的资源,例如两个FBX资源,动作(skill2_x),甚至还引用了其它的Timeline Asset(4110092,BossShow)。
四,分析
1,通过查看prefab和meta文件:
发现PlayableDirector的m_SceneBindings有很多guid的引用。但由图1、图2可见Timeline Asset中其实只有8个绑定。
2,选择Inspector的Debug模式
发现竟然有28个绑定。
3,经测试发现,复制Prefab时,PlayableDirector组件的Binding也会跟着复制,即使关联新的TimelineAsset,也不会清空重新赋值,估计Unity后面版本会修复。
五,解决
PlayableDirector组件的Binding字段是写在c++,也没有提供访问或清空的接口。因此采用重挂组件再赋值的办法。
public static void OptimizeBinding(GameObject go)
{
var prefab = GameObject.Instantiate(go);
var director = prefab.GetComponent<PlayableDirector>();
if (director == null)
{
return;
}
var timelineAsset = director.playableAsset as TimelineAsset;
if (timelineAsset == null)
{
return;
}
Dictionary<UnityEngine.Object, UnityEngine.Object> bindings = new Dictionary<UnityEngine.Object, UnityEngine.Object>();
foreach (var pb in director.playableAsset.outputs)
{
var key = pb.sourceObject;
var value = director.GetGenericBinding(key);
if (!bindings.ContainsKey(key))
{
bindings.Add(key, value);
}
}
GameObject.DestroyImmediate(director);
director = prefab.AddComponent<PlayableDirector>();
director.playableAsset = timelineAsset;
director.playOnAwake = false;
foreach (var pair in bindings)
{
director.SetGenericBinding(pair.Key, pair.Value);
}
var path = AssetDatabase.GetAssetPath(go);
PrefabUtility.SaveAsPrefabAsset(prefab, path, out var success);
GameObject.DestroyImmediate(prefab);
}
六,结果
运行脚本后,Prefab不再引用不相关的资源,PlayableDirector的Binding数量也跟TimelineAsset的Track数量一致。