unity Timeline封装

最近下载了Unity2017,有一个Timeline的新功能,编辑起来还是比较好上手的,不过如果是要进行动态绑定,就必须使用API,而API用起来步骤有点多,所以自己封装了一下

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

public class TimelineUnit
{
    public string name;
    public PlayableDirector director;
    public PlayableAsset asset;
    public Dictionary bindings;
    public Dictionary> clips;

    public void Init(string name, PlayableDirector director, PlayableAsset asset)
    {
        director.playableAsset = asset;
        this.name = name;
        this.director = director;
        this.asset = asset;

        bindings = new Dictionary();
        clips = new Dictionary>();
        foreach (var o in asset.outputs)
        {
            var trackName = o.streamName;
            bindings.Add(trackName, o);

            var track = o.sourceObject as TrackAsset;
            var clipList = track.GetClips();
            foreach (var c in clipList)
            {
                if (!clips.ContainsKey(trackName))
                {
                    clips[trackName] = new Dictionary();
                }
                var name2Clips = clips[trackName];
                if (!name2Clips.ContainsKey(c.displayName))
                {
                    name2Clips.Add(c.displayName, c.asset as PlayableAsset);
                }
            }
        }
    }

    public void SetBinding(string trackName, Object o)
    {
        director.SetGenericBinding(bindings[trackName].sourceObject, o);
    }

    public T GetTrack(string trackName) where T : TrackAsset
    {
        return bindings[trackName].sourceObject as T;
    }

    public T GetClip(string trackName, string clipName) where T : PlayableAsset
    {
        if (clips.ContainsKey(trackName))
        {
            var track = clips[trackName];
            if (track.ContainsKey(clipName))
            {
                return track[clipName] as T;
            }
            else
            {
                Debug.LogError("GetClip Error, Track does not contain clip, trackName: " + trackName + ", clipName: " + clipName);
            }
        }
        else
        {
            Debug.LogError("GetClip Error, Track does not contain clip, trackName: " + trackName + ", clipName: " + clipName);
        }
        return null;
    }

    public void Play()
    {
        director.Play();
    }
}

我把Timeline和它的属性进行了包装,封成一个TimelineUnit,然后再封装一个挂Timeline的接口

using UnityEngine;
using UnityEngine.Playables;

public class TimelineHelper
{
    public static TimelineUnit AddTimeline(GameObject go, string timelineName)
    {
        var unit = new TimelineUnit();
        var director = go.GetComponent();
        if (null == director)
            director = go.AddComponent();
        var asset = Resources.Load("TimelineRes/" + timelineName);
        unit.Init(timelineName, director, asset);
        return unit;
    }
}

现在做一个Timeline,然后进行测试


unity Timeline封装_第1张图片

一个AnimationTrack,一个PlayableTrack,动画轨道不多讲,难点是PlayableTrack,这个是可以自定义逻辑的轨道

需要写两个类,一个继承PlayableAsset,一个继承PlayableBehaviour

using UnityEngine;
using UnityEngine.Playables;

public class MoveObjPlayableAsset : PlayableAsset
{
    public GameObject go;
    public Vector3 pos;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var bhv = new MoveObjPlayableBehaviour();
        bhv.go = go;
        bhv.pos = pos;
        return ScriptPlayable.Create(graph, bhv);
    }
}

using UnityEngine;
using UnityEngine.Playables;

public class MoveObjPlayableBehaviour : PlayableBehaviour
{
    public GameObject go;
    public Vector3 pos;

    public override void OnGraphStart(Playable playable)
    {
        base.OnGraphStart(playable);

        Debug.Log("OnGraphStart=======================");
    }

    public override void OnGraphStop(Playable playable)
    {
        base.OnGraphStop(playable);
        Debug.Log("OnGraphStop=======================");
    }

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        base.OnBehaviourPlay(playable, info);
        Debug.Log("OnBehaviourPlay=======================");
        if (null != go)
        {
            go.transform.position = pos;
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        base.OnBehaviourPause(playable, info);
        Debug.Log("OnBehaviourPause=======================");
        if (null != go)
        {
            go.transform.position = Vector3.zero;
        }
    }

    public override void OnBehaviourDelay(Playable playable, FrameData info)
    {
        base.OnBehaviourDelay(playable, info);
        Debug.Log("OnBehaviourDelay=======================");
    }
}

这样,就可以将MoveObjPlayableAsset脚本直接拖动到PlayableTrack轨道上,具体的脚本逻辑在MoveObjPlayableBehaviour中写,我这里的逻辑是改变物体的坐标,具体逻辑就看具体需求了,这里只是举个例子


程序入口我放在一个runner的脚本里,挂在场景中的一个物体上

using UnityEngine;

public class Runner : MonoBehaviour
{
    void Start()
    {
        var go = new GameObject("TimelineGo");
        var unit = TimelineHelper.AddTimeline(go, "myTimeline");
    unit.director.extrapolationMode = UnityEngine.Playables.DirectorWrapMode.Loop;
        unit.SetBinding("at", go);
        
        var p = unit.GetClip("myPlayable", "b");
        p.go = gameObject;
        unit.Play();
    }
}


运行就可以看到有一个TimelineGo物体挂了Timeline运行了


你可能感兴趣的:(unity3D,Unity3D)