Unity TimeLine学习笔记

Posted such_so

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity TimeLine学习笔记相关的知识,希望对你有一定的参考价值。

目录

一、快捷键

二、常用轨道介绍

Activetion Track(激活轨道)

Animation Track(动画轨道)

1、添加其已有的动画

2、制作帧动画

Audio Track(音频轨道)

Signal Track(信号轨道)

1、点开Markers,右键创建Signal Emitter

2、选中创建的Signal Emitter,创建一个 Signal assets

3、在Signal Receiver 上给他添加要执行的方法就行了

4、在模式中选择第二个,在编辑器模式下就能看到相关信息,推荐选这个

三、自定义轨道

1、自定义Track

2、自定义Clip

3、自定义Behaviour

4、自定义Mixer

先在Track脚本里创建出Mixer

创建MixerBehaviour

四、自定义clip显示窗口,为自定义的clip写一个Editor

 五、自定义signal

六、常见的对话剧情效果制作总结

1、暂停效果

2、快速通过这个clip(在当前clip中点击时跳转到当前clip的最后一帧)

3、跳转到目标帧

①JumpToMarker的实现

② JumpToClip的实现

③JumpToTime的实现(不推荐使用这种方式)

 ④合并方法


一、快捷键

ctrl + 鼠标中键——滑动中键,缩放轨道宽度

F——选中轨道中的其中一个片段,按住f,会将这个片段缩放到最适合编辑的宽高

A——将窗口调整到能看到所有的编辑片段的大小

L(Locked)——选中某一个轨道,按住L,会锁住选中的轨道,让其不再被编辑

M(Muted)——选中一个轨道,按住M,禁用这一条轨道

space——开始播放TimeLine,再按一下就是暂停播放

二、常用轨道介绍

Activetion Track(激活轨道)

控制一个对象的激活与隐藏,在片段内的时间段时激活这个物体,其与时候关闭这个物体

Animation Track(动画轨道)

控制一个对象动画的播放,以及为其制作帧动画,注意:这个对象要有Animator组件

1、添加其已有的动画

 右键选着Add From Animation Clip 选项进行添加已有的动画

2、制作帧动画

点击录制按钮进行录制

移动场景中对应的物体,打下关键帧

 

再次点击录制按钮,停止录制,右键选择Convert To Clip Track将这一段帧动画转换成一个动画片段 

 双击这个帧动画片段可以进入Animation窗口对其进行更加细致的编辑,选中这个动画片段,在右边有窗口显示其相关属性,可以对其进行调节

Audio Track(音频轨道)

拖入音频即可

选中轨道会弹出相关设置界面

Volume——声音大小

Stereo Pan——控制声道的,往右偏移就偏向右声道,反之偏向左声道

Spatial Blend——是否受到3D影响

Signal Track(信号轨道)

通俗来讲,就是能让你在某一帧的时候调用,某一个方法

操作步骤

1、点开Markers,右键创建Signal Emitter

Markers就相当于是一个全局的Signal Track轨道

2、选中创建的Signal Emitter,创建一个 Signal assets

3、在Signal Receiver 上给他添加要执行的方法就行了

4、在模式中选择第二个,在编辑器模式下就能看到相关信息,推荐选这个

三、自定义轨道

Track——代表的就是轨道体,一行

Clip——这个轨道里面的片段

Behavior(Data)——片段里的行为,会执行什么样的操作

Mixer——混合器,片段与片段之间的混合

自定义一个轨道就是对这4个部分进行自定义

1、自定义Track

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline;//要申明TimeLine的命名空间



[TrackColor(100 / 255f, 120 / 255f, 0)]   //定义轨道的颜色
//[TrackClipType(typeof(Light))]   //定义片段类型。但不要声明Unity自带的类型,因为这样的话就只能操作这一个对象,就和自带的轨道一样。我们这里实现可以在一个轨道上操作多个对象
[TrackClipType(typeof(LightClip))] //这里声明我们自定义的Clip类型,实现可以在一个轨道上操作多个对象。在clip里声明对象类型,就可以一个Clip操作一个对象
public class LightTrack : TrackAsset //自定义Track时,要继承自TrackAsset

2、自定义Clip

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables; //需要引入的命名空间
using UnityEngine.Timeline; //需要引入的命名空间


//自定义Clip
public class LightClip : PlayableAsset, ITimelineClipAsset //需要继承自PlayableAsset, 申明一下ITimelineClipAsset接口

    //public Light light;  //这样写是错误的,因为在这里不支持声明此类型,我们要对其进行封装
    public ExposedReference<Light> light;  //对Light类型进行封装,封装成这里可以识别的类型
    public Color Color;
    public float index;


    //在Clip的属性窗口,显示可调节的属性更多(需要有ITimelineClipAsset接口)
    public ClipCaps clipCaps
    
        get  return ClipCaps.All; 
    


    //实现创建Clip的抽象方法
    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    
        var playable = ScriptPlayable<LightBehavior>.Create(graph); //给自定义的Clip,添加自定义的Behavior(这里LightBehavior为自定义的Behavior)

        var behavior = playable.GetBehaviour(); //获取到我们自定义的behavior

        behavior.Light = light.Resolve(graph.GetResolver()); //赋值的时候在对其进行解封
        behavior.LightColor = Color;
        behavior.LightIndex = index;

        return playable;
    

3、自定义Behaviour

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;//需要引入的命名空间

//自定义Behavior
[System.Serializable] 
public class LightBehavior : PlayableBehaviour //需要继承自PlayableBehaviour

    public Light Light; //光源对象

    public Color LightColor; //光源颜色
    public float LightIndex;//光照强度


    //在(Clip)片段上的每一帧调用
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    
        Light.color = LightColor;
        Light.intensity = LightIndex;
    

这里只用到了ProcessFrame这一种方法,在PlayableBehaviour里还封装了许多方法

介绍下常用的两个

OnBehaviourPlay 在进入当前Clip时调用一次

OnBehaviourPause 在离开当前Clip时调用一次

4、自定义Mixer

自己对Mixer的理解,Mixer混合器是一种对轨道中所有Clip进行操作的方法

先在Track脚本里创建出Mixer

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

[TrackColor(0.8f,0,0)]
[TrackClipType(typeof(DialogClip))]
public class DialogTrack : TrackAsset

	/// <summary>
	/// 创建Mixer
	/// </summary>
	/// <param name="graph"></param>
	/// <param name="go"></param>
	/// <param name="inputCount"></param>
	/// <returns></returns>
	public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
	
		var scriptPlayable = ScriptPlayable<DialogMixerBehaviour>.Create(graph, inputCount);

		DialogMixerBehaviour b = scriptPlayable.GetBehaviour();        //得到Mixer的Behavior
		b.markerClips = new Dictionary<string, double>();
		b.endMarkerClips = new Dictionary<string, double>();
		b.clipNameLis = new List<string>();
		b.markerLis = new List<DestinationMarker>();
  

		DialogTrack dialogTrack = this;
                //DestinationMarker是我自定义的一个signalMarker,这里是因为我后面要做信号跳转所用的
		var markerList = dialogTrack.GetMarkers().OfType<DestinationMarker>().ToList(); //得到当前轨道上的所有DestinationMarker信号标记  
               //存储轨道上的DestinationMarker信号标记
		b.markerLis.AddRange(markerList);
  

		//循环遍历轨道上的所有Clip
		foreach (var c in GetClips())
		
			DialogClip clip = (DialogClip)c.asset;
                        if (!b.markerClips.ContainsKey(c.displayName))
                           
                                // 存储Clip的开始帧,Key为Clip的名字                               
                                b.markerClips.Add(c.displayName, (double)c.start);
                                //存储Clip的结束帧,key为Clip的名字
				b.endMarkerClips.Add(c.displayName, (double)c.end);
                           
			if (!b.clipNameLis.Contains(c.displayName))
			
                               //存储Clip的名字    
				b.clipNameLis.Add(c.displayName);
			
		
		return scriptPlayable;
	

创建MixerBehaviour

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

public class DialogMixerBehaviour : PlayableBehaviour

    public Dictionary<string, double> markerClips; //用来存储Clip的开始帧,Key为Clip的名字
    public Dictionary<string, double> endMarkerClips;  //存储Clip的结束帧,key为Clip的名字
	public List<string> clipNameLis;             //存储Clip的名字
	public List<DestinationMarker> markerLis;    //轨道上的DestinationMarker信号标记

	//在整个TimeLine开始播放时会执行一次
	public override void OnBehaviourPlay(Playable playable, FrameData info)
    
		
		int inputCount = playable.GetInputCount();  //得到轨道上所有Clip的Behaviour对象的数量,即Clip的数量

		for (int i = 0; i < inputCount; i++)
		
			ScriptPlayable<DialogBehaviour> inputPlayable = (ScriptPlayable<DialogBehaviour>)playable.GetInput(i);
			DialogBehaviour input = inputPlayable.GetBehaviour();
			
			input.markerClips = markerClips;
			input.endMarkerClips = endMarkerClips;
			input.clipName = clipNameLis[i];
		

		UI.TimeLineDialogUIController.Self.destinations = markerLis;
	


	/// <summary>
	/// ProcessFrame方法 在Mixerbehavior中时,只要整个Timeline还在运行时就会调用,相当于update
	/// </summary>
	/// <param name="playable"></param>
	/// <param name="info"></param>
	/// <param name="playerData"></param>
	public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        

		
	
   

四、自定义clip显示窗口,为自定义的clip写一个Editor

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


[CustomEditor(typeof(DialogClip))] //这里要继承自对应的clip
public class DialogClipInspector : Editor

	//通用窗口显示的属性
	private SerializedProperty rushThrough;
	private SerializedProperty IsJumpProp;
	private SerializedProperty npcId;
	private SerializedProperty segmentId;
	private SerializedProperty hasToPause;
	private SerializedProperty isChoice;

	private void OnEnable()
	
		//通用窗口显示的属性
		npcId = serializedObject.FindProperty("npcId");
		segmentId = serializedObject.FindProperty("segmentId");
		rushThrough = serializedObject.FindProperty("rushThrough");
		hasToPause = serializedObject.FindProperty("hasToPause");
		IsJumpProp = serializedObject.FindProperty("isJump");
		isChoice = serializedObject.FindProperty("isChoice");
	

	public override void OnInspectorGUI()
	
		//通用窗口显示的属性
		EditorGUILayout.PropertyField(npcId);
		EditorGUILayout.PropertyField(segmentId);
		EditorGUILayout.PropertyField(rushThrough);
		EditorGUILayout.PropertyField(hasToPause);
		//isJump
		EditorGUILayout.PropertyField(IsJumpProp);
		//得到IsJumpProp 的bool值
		bool index = IsJumpProp.boolValue;
		
		if (index)
		
			//如果为真,窗口显示下面两个属性 (特定显示属性)
			EditorGUILayout.PropertyField(serializedObject.FindProperty("isAutomaticJump"));
			EditorGUILayout.PropertyField(serializedObject.FindProperty("markerLabel"));
		
		//isChoise
		EditorGUILayout.PropertyField(isChoice);
		bool indexChoice = isChoice.boolValue;
		if (indexChoice)
		
			//如果勾选isChoice,窗口显示下面的属性(特定显示属性)
			EditorGUILayout.PropertyField(serializedObject.FindProperty("choiceJumpTarget"));
		

		serializedObject.ApplyModifiedProperties();
	

勾选相应的选项,弹出与之相关的变量

 没勾选就不显示

 五、自定义signal

这里我们以一个自定义的跳转signal为例子,先看一下效果

 

详请介绍:https://blog.csdn.net/culiao6493/article/details/108641237

里面的实列项目:signal自定义项目

上面这个链接里的文章有很好的讲解,并且有项目源码可以看,这里不做太多的赘述。

六、常见的对话剧情效果制作总结

1、暂停效果

这个用的地方很多,比如某段话完了后要暂停,等待玩家的点击在继续播放下一段对话

官方的项目的做法,用PlayableDirector组件进行控制,简单说一下TimeLine这个组件:

Playable是TimeLine的资源,就是你做的那一堆剧情

PlayableDirector就是TimeLine的播放控制器,里面能够控制播放,暂停,结束等操作

实现方法直接上代码

//这里都写在自定义的Behaviour里面
  
private PlayableDirector director;

public override void OnPlayableCreate(Playable playable)

     //得到当前Playable资源挂载的PlayableDirector组件
     director = (playable.GetGraph().GetResolver() as PlayableDirector);    


//在(Clip)片段上的每一帧调用
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    

        double duration = playable.GetDuration(); //当前clip 总的时间
        double time = playable.GetTime();   //当前的时间   
        //如果当前clip结束时要暂停                         

        if (pauseScheduled)
        
            //当播放到离这段clip还差0.1秒结束时,调用暂停播放
            if (time >= (duration - 0.1f))
            
                UI.TimeLineDialogUIController.Self.PauseTimeline(director);
                pauseScheduled = false;


            
         
    

这里可能会有一点奇怪,明明已经有了OnBehaviourPause(clip结束帧调用)方法不用,反而要用这种方式,后面给出解释

         /// <summary>
        /// 暂停TimeLine的播放
        /// </summary>
        /// <param name="whichOne"></param>
        public void PauseTimeline(PlayableDirector whichOne)
        
            activeDirector = whichOne;

            activeDirector.playableGraph.GetRootPlayable(0).SetSpeed(0d);//将TimeLine的播放速度设为0
            //将当前的时间赋值为当前clip的结束帧
            activeDirector.time = clipEndTime;
        

这里的 clipEndTime 指的是当前clip片段的结束帧,这里讲一下我为啥要这样做,以及为啥不用OnBehaviourPause方法

因为我发现当我在结束帧调用这个方法的时候,其实并不会在当前结束帧就立马暂停,而是向后播放了几帧后才暂停,如果在当前clip后面紧跟着下一个clip,就会播放到下一个clip上面才暂停

至于怎么获取当前clip的结束帧,在自定义Mixer章节里有写。

2、快速通过这个clip(在当前clip中点击时跳转到当前clip的最后一帧)

其实这个功能比较简单,因为我们前面已经储存了所有Clip的结束帧,所以我们只需要判断当前clip在什么时候点击需要跳转到最后一帧就好了

直接上代码

public class DialogBehaviour : PlayableBehaviour

    //外部控制这个变量


    public double rushThrough;                      //快速通过这个Clip

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    
 
        double duration = playable.GetDuration(); //当前clip 总的时间
        double time = playable.GetTime();   //当前的时间
        
        if (rushThrough == 0)
        
           //如果为0,整段clip都可以快速通过
            UI.TimeLineDialogUIController.Self.rushThrough = true;
        
        else if (rushThrough < 0 || rushThrough >= duration)
        
           //如果小于0或者填的时间大于总的时间,整段clip都不可以快速通过
           UI.TimeLineDialogUIController.Self.rushThrough = false;
        
        else
        
            if (time <= rushThrough)
            
               //在rushThrough时间节点之前点击不能快速通过
               UI.TimeLineDialogUIController.Self.rushThrough = false;
            
             else
             
                 //在rushThrough时间节点之后点击可以快速通过
                UI.TimeLineDialogUIController.Self.rushThrough = true;
             
        

                       
    


      

        /// <summary>
        /// 跳转到目标帧
        /// </summary>
        /// <param name="whichOne"></param>
        /// <param name="starTime">目标帧</param>
        public void JumpToTragetFrame(PlayableDirector whichOne, double starTime)
        
            whichOne.time = starTime;
            
        

3、跳转到目标帧

这个一般用在有选项的情况下比较多,选着不同的选项会跳转到不同的地方

目前来说,我用了三种方式,我定义了一个枚举来进行区分

public enum JumpToType
     
      JumpToMarker,  //跳转到信号标记点DestinationMarker
      JumpToTime,   //跳转到摸一个时间节点,格式为 xx:xx , 如 6:30 表示第6秒过30帧
      JumpToClip    //跳转到某一个对话dialogClip
    

 定义了一个数据结构来进行选择

    /// <summary>
    /// 跳转的数据结构
    /// </summary>
    [Serializable]
    public struct TimelineDiaLogDataBase
    
        public JumpToType Type;
        public string jumpToValue;
    

 如果类型选JumpToMarker,value就填marker的名字,JumpToTime,value填时间节点,JumpToClip,value填clip的名字

①JumpToMarker的实现

先自定义一个marker

[DisplayName("Jump/DestinationMarker")]
[CustomStyle("DestinationMarker")]  //自定义marker的图片
public class DestinationMarker : Marker

    [SerializeField] public bool active;  //是否启用
    
    void Reset() 
    
        active = true;
    

关于自定义marker的图片可以看第五节里的链接,里面有详细的讲解和项目

我们就可以在轨道上添加一个marke

然后我们需要在自定义的Track里去获取这个轨道上的所有marke,至于我为啥要在Track里取获取,是因为我只在Track继承的父类里找到了相关的获取方法,应该还有其他的我可能没找到

在自定义Mixer那一章的代码段里有写

② JumpToClip的实现

实现也很简单,把轨道上每个clip的开始帧存下来,点击的时候,将时间设置为对应clip的开始帧就ok了

至于怎么存clip的开始帧,在自定义Mixer一章里有写

③JumpToTime的实现(不推荐使用这种方式)

首先,讲一下我为啥要用xx:xx , 如 6:30 表示第6秒过30帧这种格式,这与timeLine上的显示相对应,方便查看填写

先将填写字符转换成对应的时间,然后再点击的时候,跳转到这个时间点就ok了

        /// <summary>
        /// 将“6:30”(冒号前为时间,后为帧数)格式的字符串进行转换成时间
        /// </summary>
        /// <param name="timeOrFrame"></param>
        public float ConversionCharacter(string timeOrFrame)
        
            float allTime;
            string[] arr = timeOrFrame.Split(':');
            float result;
            bool isNum = isNumberic(arr[1], out result);
            if (isNum)
            
                float timeMs = result / 60;
                bool isNumber = isNumberic(arr[0], out result);
                allTime = result + timeMs;
            
            else
            
                allTime = 0;
            
            return allTime;
        
        /// <summary>
        /// 判断是否为数字
        /// </summary>
        /// <param name="message"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected bool isNumberic(string message, out float result)
        
            System.Text.RegularExpressions.Regex rex =
            new System.Text.RegularExpressions.Regex(@"^(-?\\d+)(\\.\\d+)?$");
            result = -1;
            if (rex.IsMatch(message))
            
                result = float.Parse(message);
                return true;
            
            else
                return false;
        

 ④合并方法

上面三种其实到最后都是转换成相应的时间节点,来进行跳转,所以我们合并一下,统一调用

        /// <summary>
        /// 得到跳转项的目标时间
        /// </summary>
        /// <param name="dataBase"></param>
        /// <returns></returns>
        public double GetChoiceTargetFrame(TimelineDiaLogDataBase dataBase)
        
            double valueTime = 0;
            if (dataBase.Type == JumpToType.JumpToClip)
            
                foreach (var makers in markerClips)
                
                    if (makers.Key == dataBase.jumpToValue)
                    
                        valueTime = makers.Value;
                        break;
                    
                
            
            else if (dataBase.Type == JumpToType.JumpToTime)
            
                var value = dataBase.jumpToValue;
                valueTime = ConversionCharacter(value);

            
            else if (dataBase.Type == JumpToType.JumpToMarker)
            
                foreach (var marker in destinations)
                
                    if (marker.active) //marker是否启用
                                           
                        if (marker.name == dataBase.jumpToValue) //通过marker的名字来进行寻找
                        
                            valueTime = marker.time;
                            break;
                        
                     
                
            
            return valueTime;
        

注意:clip和marker的名字不能重复

unity过场动画组件Timeline

Timeline是Unity2017版本中新加入的功能,可以非常方便的进行场景动画的创建和修改,包括物体、声音、粒子、动画、特效、自定义Playable以及子Timeline等多种资源进行整合,从而能够较方便的生成效果很棒的场景动画,同时可以通过Unity的Recorder资源包录制较为完整的视频并导出。 

 
技术分享图片
 

1.Timeline界面简单介绍

Unity2017中,点击Window->Timeline即可调出Timeline面板。如下图所示: 

 

 
技术分享图片
 

在该面板中,可以创建多种类型的片段,如果你导入AssetStore中的Default Playables资源包(其中预置了多个官方提供的简单Playable实例),其面板如下所示: 

 

 
技术分享图片
 

其中常用的主要有

Activation Track(控制物体的显示和隐藏)

Animation Track(为物体加入动画,可以在场景中方便地录制动画,也可以是已经制作好的Animation Clip)

Audio Track(为动画添加音效,并可对音效进行简单的裁剪和操作)

Control Track(在该轨道上可以添加粒子效果,同时也可以添加子Timeline进行嵌套)

Playable Track(在该轨道中用户可以添加自定义的播放功能)

Track Group(将不同的轨道进行分类,相当于文件夹功能)

当我们创建了TimeLine后,会在指定位置生成TimeLine的文件*.playable,当选中该文件后,会在Inspector面板中看到其相应的属性,如下图所示: 

 

 
技术分享图片
 

其中Frame Rate可以设置该Timeline每秒钟播放多少帧动画。Duration Mode分为Based On Clips和Fixed Length两种模式,Based On Clips模式为按照帧数来播放,当播放到最后一帧时结束播放,Fixed Length模式可以设置总共播放多长时间,当播放到指定时间是停止。Duration设置当前播放的秒数和帧数。

2.Timeline轨道简单介绍

2.1 Activation Track

 

 
技术分享图片
 

该轨道首先需要为其赋值一个GameObject,表示该轨道控制该物体的显示与隐藏,当在Timeline播放过程中,如果处于片段内部,则该物体显示,否则该物体隐藏。

当我们点击该轨道时,会在Inspector面板中看到可以设置的属性,如下所示: 

 
技术分享图片
 

Active(当Timeline播放结束时,将该物体激活,设置为显示状态)

Inactive(当Timeline播放结束时,该物体取消激活,设置为隐藏状态)

Revert(当Timeline播放结束时,该物体还原Timeline在第1帧时的激活状态)

Leave As Is(当Timeline播放结束时,该物体保持在Timeline最后一帧的激活状态)

2.2 Animation Track

Animation Track主要控制动画的播放,包括动画片段、帧动画等。当我们点击Animation Track时,可以设置其属性,如下图所示: 

 
技术分享图片
 

2.2.1 Animation Track 属性

Apply Avatar Mask(启用“阿凡达遮罩”,当启用后将根据选择的遮罩应用在整个轨道中) 

 
技术分享图片
 

Avatar Mask(选择需要的遮罩,并将其应用在当前Animation轨道中) 

最终效果如下: 

 
技术分享图片
 

Apply Track Offsets(启用轨道偏移效果,将所有动画的起始位置都设置为指定的偏移角度和位置上,与动画片段中的Clip Root Motion Offsets功能类似) 

 
技术分享图片
 

Clip Offset Match Fields(该选项可以设置不同动画之间偏移可匹配的变换)

2.2.2 动画轨道使用简介

1.添加Animation Clip 

右击Animation Clip的空白处,选择Add From Animation Clip即可从已有的动画片段中选择。 

 
技术分享图片
 

可以拖拽动画片段调整播放的时间,同时也可以将多个动画片段进行叠加来完成动画过渡效果。 

 

 
技术分享图片
 

2.录制动画 

可以在Animation Clip中点击红色按钮进行录制,通过设置不同的属性来为物体设置关键帧,从而完成不同类型的动画制作。 

 

 
技术分享图片
 

3.设置曲线 

录制的动画可以在动画窗口中打开,在动画窗口中可以通过关键帧点的方式进行控制,也可以通过曲线的方式进行控制。 

 
技术分享图片
 

2.3 Audio Track

Audio Track主要控制动画中的音效,可以设置声音的起始时间、结束时间、淡入时间、淡出时间、播放速度、不同音效间的混合效果、是否循环播放等。其属性如下所示: 

 
技术分享图片
 

2.4 Control Track

Control Track主要控制与时间有关的元素,如粒子效果、Timeline等。 

该轨道可以在指定的父物体下实例化一个Prefab,并对该Prefab中与时间有关的元素进行播放操作。 

 
技术分享图片
 

2.5 Playable Track

Playable Track允许用户自定义相关动画效果,在Default Playables资源包中包含了一部分自定义的功能轨道,包括文字、时间、灯光、位置、寻路、淡入淡出等效果,用户也可以根据自己的需要进行定制化开发,以实现更加复杂的效果。 

 

 
技术分享图片
 
 
技术分享图片
 
 
技术分享图片
 
 
技术分享图片
 
 
技术分享图片
 
 
技术分享图片
 

以下为运行后的调用顺序 

 

 
技术分享图片
 

以下为该Timeline设置的状态,主要部分为PlayableTrack。 

 

 
技术分享图片
 

最终运行效果如下: 

 
技术分享图片
 

该方法也可通过继承BasicPlayableBehaviour类完成,但是在未来的版本中该类可能会被PlayableBehaviour和PlayableAsset类取代。

遇到的问题

在使用TimeLine功能的过程中,如果对物体使用了录制功能进行位置的调整,很多情况下物体的默认位置会发生偏移,最好在使用TimeLine的Animation Track录制功能前先备份场景,以免在设置动画过程中对场景造成破坏。

本人对TimeLine很多功能还不够熟悉,这些只是在使用过程中用到的功能,将Timeline和CineMachine以及Post Processing等功能进行结合可以做出相当炫酷的效果,可参考Unity官方的Adam&Neon动画短片



作者:壹米玖坤
链接:https://www.jianshu.com/p/99202037e902
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。





以上是关于Unity TimeLine学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

Timeline 学习

基于Unity3D之TimeLine的讲解(一)

小松教你手游开发unity实用技能unity ios快捷打包

unity过场动画组件Timeline

Unity手游之路手游代码更新策略探讨

Unity单机手游逆向破解思路(仅供学习参考,禁止用于非法行为)