unity 2017中Timeline使用笔记

1.unity2017版本中最新出炉Timeline

     第一次看到timeline觉得这个东西和以前自己的做视频时使用的剪辑软件video studio/premiere/After Effect等非常的相似,同样的视频轨道,随意滑动,非常便于操作 如下图所示。

unity 2017中Timeline使用笔记_第1张图片

  现在开始简要介绍一下timeline的基本操作:

         1.直接在面板上新建一个空物体,create empty,随便取个名字叫做timeline manger;

         2.直接点击windows ,点击timeline  editor;就会弹出如上图所所示的timeline 操作界面,然后删掉出现的第一个轨道。            因为没什么用。unity 2017中Timeline使用笔记_第2张图片

3.点击timeline下面的add,就可以添加几个轨道: 其中

activeation track可以让物体在什么时间在什么地点出现或者消失;

animation track可以添加动画片段,或者自己点击红色圆圈自己录制动画;

audio track 可以添加音效片段;

playable track 可以写上控制代码,这里我在后面将重点讲解;

control track 自己还没有用过。。。。。;

2.timeline具体使用方法事例

  目前网上已经有人将timeline的相关函数都进行了封装,我们可以很方便的进行使用。具体的封装方法见链接。点击打开链接

我自己稍微改了一下,具体代码见下。

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

public class TimelineUnit {

    public string name;
    public PlayableDirector director;
    public PlayableAsset asset;
    public Dictionary bindings;
    public Dictionary> clips;
    public Dictionary playables;

    public void Init(string path, PlayableDirector director)
    {
        this.name = path;               // director标签
        this.director = director;       // 获取当前组件
        playables = new Dictionary();
        InitPlayables(path);            // 获得所有的动画
    }

    public void Switch(string assetName)
    {

        if (!playables.TryGetValue(assetName, out this.asset))
        {
            Debug.LogError("No Asset exist!");
            return;
        }
        director.playableAsset = asset; // 导演Manager
        
        bindings = new Dictionary(); // PlayableAsset下的所有binding
        clips = new Dictionary>(); // binding里的所有clip
        foreach (var o in asset.outputs) // 每一个binding,其实就是trackasset和需要动画的模型之间的链接关系
        {
            var trackname = o.streamName;
            bindings.Add(trackname, o);  // 每一个binding的名字和binding绑定

            var track = o.sourceObject as TrackAsset; // 每个binding下的对象为track
            var clipList = track.GetClips(); // 获得每一个track下的所有动画片段
            foreach (var c in clipList) // 存入clips
            {
                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 Remove()
    {
        bindings.Clear();
        clips.Clear();
    }

    // 动画和模型进行绑定
    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;
    }

    // 读入所有动画资源
    private void InitPlayables(string path)
    {
        PlayableAsset[] o = Resources.LoadAll(path + "/");
        foreach (var asset in o)
        {
            playables.Add(asset.ToString().Replace(" (UnityEngine.Timeline.TimelineAsset)", ""), asset);
            Debug.Log(asset.ToString());
        }
    }

    // 控制动画的播放,停止等
    public void Play()
    {
        director.Play();
    }

    public void pause()
    {

        director.Pause();
     
    }

    public void Stop()
    {

        director.Stop();

    }
    public void Resume()
    {

        director.Resume();

    }


   
}

 

下面是自己的代码:

 

(注意:TextPlayableBehaviour 不用挂在物体上,里面包含了不同情况下自动执行的逻辑)

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

// A behaviour that is attached to a playable
public class TextPlayableBehaviour : PlayableBehaviour
{
    public Text _text;
    public string s;
    private PlayableDirector director;
	// Called when the owning graph starts playing
    public override void OnGraphStart(Playable playable)
    {
     director = GameObject.Find("TimelineManager").GetComponent();//找到timelinemanger,取得控制权
     
    }
     Called each frame while the state is set to Play
    public override void PrepareFrame(Playable playable, FrameData info)
    {
        _text.text = s;
    }

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
       
        _text.enabled = true;//为了让text可视化
        //  Debug.Log("为true了");
    }

     Called when the state of the playable is set to Paused
    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
      _text.enabled = false;
        if (director.time > 0.4f)//因为未知原因导致,一开始就检测到了onbehavior pause,所以设定一定的时间范围,延缓0.4s再检测,此时onbehavior pause是在正常的地方停下
        {
            director.Pause();
        }
    }

     Called when the owning graph stops playing
    //public override void OnGraphStop(Playable playable) {
    //    //director.Pause();
    //   Debug.Log("OnGraphStop起作用了");
    //}

     Called when the state of the playable is set to Play
    //public override void OnBehaviourPlay(Playable playable, FrameData info) {

    //    _text.enabled = true;
    //}

     Called when the state of the playable is set to Paused
    //public override void OnBehaviourPause(Playable playable, FrameData info) {

    //   // director.Pause();
    //    Debug.Log("OnBehaviourPause起作用了");

    //}

  
}

(注意:TextPlayableAsset写好后,直接在playableTrack中的直接add 就行了,这里主要是生成了一个具体的TextPlayableAsset,其中new了一个TextPlayableBehaviour 的对象)

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.UI;
using TMPro;

[System.Serializable]
public class TextPlayableAsset : PlayableAsset
{
    public ExposedReference text;
    public string s;


    // Factory method that generates a playable based on this asset
    public override Playable CreatePlayable(PlayableGraph graph, GameObject go) {

        TextPlayableBehaviour t = new TextPlayableBehaviour();
        t._text = text.Resolve(graph.GetResolver());
        t.s = s;
       
        // Debug.Log("textplayableasset"+s);
      //  t._text.enabled = false;
        
        return ScriptPlayable.Create(graph, t);
	}
}

接下来就创建一个空物体,名字叫做timelinemanger,自己写一个timelinemanger的函数,里面new一个timelineunit的对象,就可以使用timeline中的各种方法了。(由于项目中的方法太复杂,也就不便于贴出来了)但是出于对读者的尊重,我还是写一个(awake的函数)吧。剩下的就是如何触发play 或者是stop了,这就交由读者了。

private void Awake () {
        director = GetComponent();
        text = GameObject.Find("text_result");
        //如果没有PlayableDirector,则添加
        if (null == director)
         {
            director = gameObject.AddComponent();  
         }
        //初始化工作
        helper = new TimelineUnit();
        helper.Init("operaiton_Animation", director);
      text.GetComponent().text = null;   
    helper.Switch(timeline_name);
        helper.SetBinding("Animation Track", GameObject.Find("garbage car"));
      
	}

其中在使用过成中的一些注意如下:

(1)setbinding函数必须得有一个动画轨道,也就是你必须得在使用switch()函数之后才能够调用setbinding函数将自己的动画与对象进行绑定。

(2)你可以参照下面的代码,直接复制粘贴一个PlayableAsset和PlayableBehaviour,这样你就可以动态的显示文字了,但是好像不能当时就改变(这里大家如果做到了,麻烦跟我说一下)。而且如果是多个PlayableAsset对应这同一个textUI,那么在playabletrack中的PlayableAsset最好起不一样的名字,因为会产生错误(比如找不到对应的PlayableAsset)。

(3)我不知道PlayableAsset中的ExposedReference是什么意思,为什么没有它就不能传值了,此处我并没有做过具体实验,(大牛如果知道,告诉小弟我一声)。

 

 

 

 

你可能感兴趣的:(互联网技术)