1. 程式人生 > >Unity2017中Timeline的簡單使用方法

Unity2017中Timeline的簡單使用方法

Timeline是Unity2017版本中新加入的功能,可以非常方便的進行場景動畫的建立和修改,包括物體、聲音、粒子、動畫、特效、自定義Playable以及子Timeline等多種資源進行整合,從而能夠較方便的生成效果很棒的場景動畫,同時可以通過Unity的Recorder資源包錄製較為完整的視訊並匯出。
Unity官方提供的Recorder外掛

1.Timeline介面簡單介紹

Unity2017中,點選Window->Timeline即可調出Timeline面板。如下圖所示:
Timeline功能面板
在該面板中,可以建立多種型別的片段,如果你匯入AssetStore中的Default Playables資源包(其中預置了多個官方提供的簡單Playable例項),其面板如下所示:
加入Default Playables資源包後可以建立的功能片段


其中常用的主要有

  • Activation Track(控制物體的顯示和隱藏)
  • Animation Track(為物體加入動畫,可以在場景中方便地錄製動畫,也可以是已經制作好的Animation Clip)
  • Audio Track(為動畫新增音效,並可對音效進行簡單的裁剪和操作)
  • Control Track(在該軌道上可以新增粒子效果,同時也可以新增子Timeline進行巢狀)
  • Playable Track(在該軌道中使用者可以新增自定義的播放功能)
  • Track Group(將不同的軌道進行分類,相當於資料夾功能)

當我們建立了TimeLine後,會在指定位置生成TimeLine的檔案*.playable,當選中該檔案後,會在Inspector面板中看到其相應的屬性,如下圖所示:
Timeline檔案屬性設定


其中Frame Rate可以設定該Timeline每秒鐘播放多少幀動畫。Duration Mode分為Based On Clips和Fixed Length兩種模式,Based On Clips模式為按照幀數來播放,當播放到最後一幀時結束播放,Fixed Length模式可以設定總共播放多長時間,當播放到指定時間是停止。Duration設定當前播放的秒數和幀數。

2.Timeline軌道簡單介紹

2.1 Activation Track

Activation Track軌道
該軌道首先需要為其賦值一個GameObject,表示該軌道控制該物體的顯示與隱藏,當在Timeline播放過程中,如果處於片段內部,則該物體顯示,否則該物體隱藏。

當我們點選該軌道時,會在Inspector面板中看到可以設定的屬性,如下所示:
Activation Track屬性

  • Active(當Timeline播放結束時,將該物體啟用,設定為顯示狀態)
  • Inactive(當Timeline播放結束時,該物體取消啟用,設定為隱藏狀態)
  • Revert(當Timeline播放結束時,該物體還原Timeline在第1幀時的啟用狀態)
  • Leave As Is(當Timeline播放結束時,該物體保持在Timeline最後一幀的啟用狀態)

2.2 Animation Track

Animation Track主要控制動畫的播放,包括動畫片段、幀動畫等。當我們點選Animation Track時,可以設定其屬性,如下圖所示:
Animation Track屬性面板

2.2.1 Animation Track 屬性

  • Apply Avatar Mask(啟用“阿凡達遮罩”,當啟用後將根據選擇的遮罩應用在整個軌道中)
    Avatar Mask面板
  • Avatar Mask(選擇需要的遮罩,並將其應用在當前Animation軌道中)
    最終效果如下:
    加入Avatar Mask後
  • Apply Track Offsets(啟用軌道偏移效果,將所有動畫的起始位置都設定為指定的偏移角度和位置上,與動畫片段中的Clip Root Motion Offsets功能類似)
    動畫片段中的Clip Root Motion Offsets
  • Clip Offset Match Fields(該選項可以設定不同動畫之間偏移可匹配的變換)

2.2.2 動畫軌道使用簡介

1.新增Animation Clip
右擊Animation Clip的空白處,選擇Add From Animation Clip即可從已有的動畫片段中選擇。
新增Animation Clip
可以拖拽動畫片段調整播放的時間,同時也可以將多個動畫片段進行疊加來完成動畫過渡效果。
動畫片段
2.錄製動畫
可以在Animation Clip中點選紅色按鈕進行錄製,通過設定不同的屬性來為物體設定關鍵幀,從而完成不同型別的動畫製作。
錄製動畫
3.設定曲線
錄製的動畫可以在動畫視窗中開啟,在動畫視窗中可以通過關鍵幀點的方式進行控制,也可以通過曲線的方式進行控制。
曲線控制動畫

2.3 Audio Track

Audio Track主要控制動畫中的音效,可以設定聲音的起始時間、結束時間、淡入時間、淡出時間、播放速度、不同音效間的混合效果、是否迴圈播放等。其屬性如下所示:
音樂效果

2.4 Control Track

Control Track主要控制與時間有關的元素,如粒子效果、Timeline等。
該軌道可以在指定的父物體下例項化一個Prefab,並對該Prefab中與時間有關的元素進行播放操作。
Control Track面板

2.5 Playable Track

Playable Track允許使用者自定義相關動畫效果,在Default Playables資源包中包含了一部分自定義的功能軌道,包括文字、時間、燈光、位置、尋路、淡入淡出等效果,使用者也可以根據自己的需要進行定製化開發,以實現更加複雜的效果。
使用者可以在程式碼中繼承PlayableBehaviour和PlayableAsset兩個類,在其中完成自定義的動畫功能。

/// <summary>
///該類主要實現在TimeLine的PlayableTrack中顯示我們定義的功能,並完成賦值
/// </summary>
public class PlayableBehaviourSample : PlayableAsset
{
    //使用ExposedReference進行賦值操作
    public ExposedReference<GameObject> ShowNumberText;

    private Text text;

    public int startNum;


    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var scriptPlayable = ScriptPlayable<PlayableTest>.Create(graph);
        //從ExposedReference中獲取我們需要的控制元件
        text = ShowNumberText.Resolve(graph.GetResolver()).GetComponent<Text>();
        //對指定的PlayableBehaviour中的屬性進行賦值
        scriptPlayable.GetBehaviour().ShowNumberText = text;
        scriptPlayable.GetBehaviour().StartNum = startNum;
        return scriptPlayable;
    }
}



/// <summary>
/// 讀秒功能
/// </summary>
public class PlayableTest : PlayableBehaviour
{
    //顯示文字的控制元件
    public Text ShowNumberText;
    public int StartNum;
    float time;
    int currentNum;
    /// <summary>
    /// 當該PlayableBehaviour的PlayableGraph啟動時呼叫
    /// </summary>
    /// <param name="playable"></param>
    public override void OnGraphStart(Playable playable)
    {
        base.OnGraphStart(playable);
        Debug.Log("OnGraphStart Called");
        currentNum = StartNum;
        ShowNumberText.text = "Start Number Is " + StartNum;
        Debug.Log(ShowNumberText.text);
    }

    /// <summary>
    /// 當該PlayableBehaviour的PlayState轉換為PlayState.Play時呼叫
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        base.OnBehaviourPlay(playable, info);
        Debug.Log("OnBehaviourPlay Called");
    }

    /// <summary>
    /// 該函式與ProcessFrame函式功能相同,都是在該PlayableBehaviour播放的每一幀中呼叫,相當於Update函式的功能
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    public override void PrepareFrame(Playable playable, FrameData info)
    {
        base.PrepareFrame(playable, info);
        Debug.Log("PrepareFrame Called");
        time += Time.deltaTime;
        if (time > 1.0f)
        {
            currentNum++;
            ShowNumberText.text = "Current Number Is " + currentNum;
            Debug.Log(ShowNumberText.text);
            time -= 1.0f;
        }
    }

    /// <summary>
    /// 該函式與PrepareFrame函式功能相同,都是在該PlayableBehaviour播放的每一幀中呼叫,相當於Update函式的功能
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    /// <param name="playerData"></param>
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        base.ProcessFrame(playable, info, playerData);
        Debug.Log("ProcessFrame Called");
    }

    /// <summary>
    /// 該函式在PlayableBehaviour片段的PlayState轉換為Delay時呼叫
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    public override void OnBehaviourDelay(Playable playable, FrameData info)
    {
        base.OnBehaviourDelay(playable, info);
        Debug.Log("OnBehaviourDelay Called");
    }

    /// <summary>
    /// 該函式在PlayableBehaviour片段的PlayState轉換為Pause時呼叫
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        base.OnBehaviourPause(playable, info);
        Debug.Log("OnBehaviourPause Called");

        ShowNumberText.text = "End Number Is " + currentNum;
        Debug.Log(ShowNumberText.text);
    }

    /// <summary>
    /// 該函式在PlayableBehaviour片段停止播放時呼叫
    /// </summary>
    /// <param name="playable"></param>
    public override void OnGraphStop(Playable playable)
    {
        base.OnGraphStop(playable);
        Debug.Log("OnGraphStop Called");

    }

    /// <summary>
    /// 該函式在PlayableBehaviour片段建立時呼叫
    /// </summary>
    /// <param name="playable"></param>
    public override void OnPlayableCreate(Playable playable)
    {
        base.OnPlayableCreate(playable);
        Debug.Log("OnPlayableCreate Called");
    }

    /// <summary>
    /// 該函式在PlayableBehaviour片段銷燬時呼叫
    /// </summary>
    /// <param name="playable"></param>
    public override void OnPlayableDestroy(Playable playable)
    {
        base.OnPlayableDestroy(playable);
        Debug.Log("OnPlayableDestroy Called");
    }

    /// <summary>
    /// 該函式在PlayableGraph的PrepareData階段被呼叫
    /// </summary>
    /// <param name="playable"></param>
    /// <param name="info"></param>
    public override void PrepareData(Playable playable, FrameData info)
    {
        base.PrepareData(playable, info);
        Debug.Log("PrepareData Called");
    }
}

以下為執行後的呼叫順序
呼叫順序
以下為該Timeline設定的狀態,主要部分為PlayableTrack。
Timeline狀態
最終執行效果如下:
執行效果

該方法也可通過繼承BasicPlayableBehaviour類完成,但是在未來的版本中該類可能會被PlayableBehaviour和PlayableAsset類取代。

遇到的問題

在使用TimeLine功能的過程中,如果對物體使用了錄製功能進行位置的調整,很多情況下物體的預設位置會發生偏移,最好在使用TimeLine的Animation Track錄製功能前先備份場景,以免在設定動畫過程中對場景造成破壞。

本人對TimeLine很多功能還不夠熟悉,這些只是在使用過程中用到的功能,將Timeline和CineMachine以及Post Processing等功能進行結合可以做出相當炫酷的效果,可參考Unity官方的Adam&Neon動畫短片

如有問題歡迎大家提出,今後有時間會再簡單介紹CineMachine和Post Processing相關內容。