Unity TimeLine 数据绑定

恢复丢失的timeline绑定数据 

Unity TimeLine 数据绑定_第1张图片

         在使用Timline的过程中 经常会发生 绑定的信息丢失了的情况。一般交付给我们的资源是美术制作好的timeline 动画 我们并不知道 绑定的节点对应物体。所以非常有必要。做一个绑定数据的记录工具。而且我们也需要对资源打包处理 ,在把资源做成AB包时 ,场景中的绑定信息也会丢失。这时就需要我们要动态的加载绑定信息。上代码。

TimeLineWinEditor

主要负责创建 记录文件的。代码比较简单。直接看就行了。 

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

public class TimeLineWinEditor : EditorWindow
{
    public static PlayableDirector playableDirector;
    void OnGUI()
    {
        playableDirector = EditorGUILayout.ObjectField(playableDirector, typeof(PlayableDirector), true) as PlayableDirector;
        if (GUILayout.Button("创建TimeLine记忆文件"))
        {
            Fork();
        }
        if (GUILayout.Button("读取TimeLine记忆文件"))
        {
            Restore();
        }
    }
    //[MenuItem("TimelineTools/存储timeline绑定 %_i")]
    private static void Fork()
    {
        List bindingnames_Game;
        List bindingnames_Editor;

        bindingnames_Editor = new List();
        bindingnames_Game = new List();

        //获取timelineAsset中所有轨道的迭代器

        var bindings = playableDirector.playableAsset.outputs.GetEnumerator();

        //复制轨道中的对象名称

        while (bindings.MoveNext())
        {
            //获取当前轨道的绑定键
            Object sourceObject = bindings.Current.sourceObject;
            string bindingname_Editor;
            string bindingname_Game;
            //根据绑定键获取当前轨道绑定物体的名称
            if (sourceObject != null)
            {
                if (playableDirector.GetGenericBinding(sourceObject))
                {
                    Object obj1 = playableDirector.GetGenericBinding(sourceObject);
                    GameObject go = obj1 as GameObject;
                    if (go == null)
                    {
                        Animator animaotr = obj1 as Animator;
                        if (animaotr == null)
                        {
                            AudioSource audioSource = obj1 as AudioSource;
                            go = audioSource.gameObject;
                        }
                        else
                        {
                            go = animaotr.gameObject;
                        }

                    }
                    List gameObjectNames = new List();
                    while (go && go.name != null && go.name != "Point light")
                    {
                        gameObjectNames.Add(go.name);
                        if (go.transform.parent != null)
                        {
                            go = go.gameObject.transform.parent.gameObject;
                        }
                        else
                        {
                            go = null;
                        }
                    }
                    gameObjectNames.RemoveAt(gameObjectNames.Count - 1);
                    gameObjectNames.Reverse();
                    string path1 = null;
                    foreach (string str in gameObjectNames)
                    {
                        path1 += str;
                        path1 += "/";
                    }
                    if (path1 != null)
                    {
                        if (path1.Length > 0)
                        {
                            path1 = path1.Substring(0, path1.Length - 1);
                        }
                    }
                    Debug.Log(path1);
                    bindingname_Editor = playableDirector.GetGenericBinding(sourceObject).name;
                    bindingname_Game = path1;

                }
                else
                {
                    bindingname_Editor = "";
                    bindingname_Game = "";
                    Debug.Log(sourceObject + "null");
                }
                if (!string.IsNullOrEmpty(bindingname_Game))
                {
                    bindingnames_Game.Add(bindingname_Game);
                }
                if (!string.IsNullOrEmpty(bindingname_Editor))
                {
                    bindingnames_Editor.Add(bindingname_Editor);
                }
            }
        }

        string path0 = string.Format("Assets/Resources/BindingAssets/{0}.asset", playableDirector.playableAsset.name);


        //如果已经存在有binding的绑定,则决定是否替换或者保留
        if (File.Exists(path0))
        {
            if (EditorUtility.DisplayDialog("注意", "替换原来的binding?", "是", "否"))
            {
                File.Delete(path0);
            }
            else
                return;
        }

        //实例化类
        BindingAsset bindingAsset = ScriptableObject.CreateInstance();
        //赋初值
        bindingAsset.playableName_Game = new string[bindingnames_Game.Count];
        bindingAsset.playableName_Editor = new string[bindingnames_Editor.Count];

        for (int i = 0; i < bindingnames_Game.Count; i++)
        {
            bindingAsset.playableName_Game[i] = bindingnames_Game[i];
        }

        for (int i = 0; i < bindingnames_Editor.Count; i++)
        {
            bindingAsset.playableName_Editor[i] = bindingnames_Editor[i];
        }

        //如果实例化为空,返回
        if (!bindingAsset)
        {
            Debug.LogWarning("bindingAsset not found");
            return;
        }

        //自定义资源保存路径
        string path = Application.dataPath + "/Resources/BindingAssets";

        //如果项目不包含该路径,创建一个
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }


        path = string.Format("Assets/Resources/BindingAssets/{0}.asset", playableDirector.playableAsset.name);

        AssetDatabase.CreateAsset(bindingAsset, path);
    }

  
    private static void Restore()
    {

        string path = string.Format("Assets/Resources/BindingAssets/{0}.asset", playableDirector.playableAsset.name);
        if (!File.Exists(path))
            return;

        BindingAsset bindingAsset = AssetDatabase.LoadAssetAtPath(path);


        //获取timelineAsset中所有轨道的迭代器
        var bindings = playableDirector.playableAsset.outputs.GetEnumerator();

        int i = 0;

        //根据对象名称恢复timeline的轨道
        while (bindings.MoveNext())
        {

            //获取当前轨道的绑定键
            Object sourceObject = bindings.Current.sourceObject;

            if (sourceObject != null)
            {
                //通过名称找到需要绑定的物体
                GameObject gameObject = FindObject2(bindingAsset.playableName_Editor[i]);
                //通过绑定键和绑定物体的键值对,绑定Binding信息
                playableDirector.SetGenericBinding(sourceObject, gameObject);
                i++;
            }
        }
    }

    private static GameObject FindObject2(string name)
    {
        foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)))
        {
            if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
            {
                if (go.name == name)
                    return go;
            }
        }
        return null;
    }
}

 BindingAsset

记录信息的配置文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



[CreateAssetMenu(menuName = "BindingAsset", fileName = "bindingAsset", order = 2)]
public class BindingAsset : ScriptableObject
{
    public string[] playableName_Editor;
    public string[] playableName_Game;
}

AutoBindTimeLine

运行时自动绑定Timeline数据

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Playables;

public class AutoBindTimeLine : MonoBehaviour
{
    public static AutoBindTimeLine instance;
    public  delegate void BindTimeLine(PlayableDirector playable);
    public  event BindTimeLine mBindTimeLine;
    public PlayableDirector mPlayableDirector;

    private void Awake()
    {
        instance = this;
    }
    // Start is called before the first frame update
    void Start()
    {
        mBindTimeLine += AutoBindTimeLine_onBindTimeLine;
        
    }

    public void OnBindTimeLine(PlayableDirector mPlayableDirector)
    {
        if (mBindTimeLine != null)
        {
            mBindTimeLine?.Invoke(mPlayableDirector);
        }
    }
    private void AutoBindTimeLine_onBindTimeLine(PlayableDirector playable)
    {
        string path = string.Format("Assets/Resources/BindingAssets/{0}.asset", playable.playableAsset.name);
        if (!File.Exists(path))
            return;

        BindingAsset bindingAsset = Resources.Load("BindingAssets/" + playable.playableAsset.name);

        //获取timelineAsset中所有轨道的迭代器

        var bindings = playable.playableAsset.outputs.GetEnumerator();

        int i = 0;

        //根据对象名称恢复timeline的轨道

        while (bindings.MoveNext())
        {
            Debug.Log(i);
            //获取当前轨道的绑定键
            Object sourceObject = bindings.Current.sourceObject;
            if (sourceObject != null)
            {
                Debug.Log(bindingAsset.playableName_Game[i]);
                GameObject gameObject = transform.Find(bindingAsset.playableName_Game[i]).gameObject;
                //通过绑定键和绑定物体的键值对,绑定Binding信息
                playable.SetGenericBinding(sourceObject, gameObject);
                i++;
            }
        }
    }
}

我们的脚本AutoBindTimeLine 要挂在一个父节点上面才能find到下面的子物体。

Unity TimeLine 数据绑定_第2张图片

 

你可能感兴趣的:(Unity,unity)