通常游戲中制作一段Timeline需要插入對話框问词,以便展示整個劇情的完整性猖腕,本篇文章就講述一下如何在Timeline中添加自定義對話框節(jié)點。
Unity中的Timeline允許Playable Track中添加自定義功能什湘。
實現(xiàn)自定義功能需要分別實現(xiàn)PlayableAsset和PlayableBehaviour耿导。
其中在PlayableBehaviour中用于實現(xiàn)自定義功能的行為;PlayableAsset用于編輯和保存節(jié)點回懦。
兩個腳本分別命名為DIalogPlayableBehaviour和DialogPlayableAsset气笙。
1、首先是DialogPlayableBehaviour腳本怯晕,該腳本需要繼承自PlayableBehaviour潜圃。
(1)在該腳本中覆寫OnPlayableCreate()接口,當Timeline創(chuàng)建時會調(diào)用該接口并傳入對應(yīng)的Playable資源舟茶,我們可以通過Playable對象獲取Playable Director并保存谭期,以便操控Playable的暫停和重新播放。
(2)覆寫OnBehaviourPlay()接口
當對話剪輯播放時吧凉,會調(diào)用該接口隧出,在該接口中調(diào)用我們自己的對話管理邏輯,對話管理邏輯中包含暫停和重啟Timeline客燕,以及調(diào)用對話框功能鸳劳,這里我們編寫了一個DialogManager腳本實現(xiàn)對應(yīng)邏輯,后邊展開講述也搓。
在這里赏廓,我們用了一個變量clipPlayed記錄該剪輯是否播放過,應(yīng)為OnBehaviourPlay()接口在我們調(diào)用PayableDirector的Resume()接口會再次被調(diào)用傍妒,為了防止對話邏輯重復(fù)調(diào)用幔摸,加了這個變量保證只調(diào)用一次對應(yīng)邏輯。同時我們判斷FrameData.weight是否大于零颤练,保證當前播放的是該剪輯既忆。
(2)添加腳本DialogPlayableAsset,繼承自Unity.Playables的PlayableAsset。
在該腳本中定義兩個變量dialogGroupId和DialogManager患雇,分別為對話的ID和對話管理腳本跃脊,對外暴露,可以在編輯器中添加DialogPlayableAsset剪輯時自定義參數(shù)苛吱。
另外覆寫CreatePlayable接口酪术。調(diào)用ScriptPlayable<DialogPlayableBehaviour>.Create(graph),將播放資源項注入到給定圖中。同時初始化DialogPlayableBehaviour的參數(shù)翠储。
實現(xiàn)代碼如下:
using UnityEngine;
using UnityEngine.Playables;
[System.Serializable]
public class DialogPlayableAsset : PlayableAsset
{
? ? public int dialogGroupId;
? ? public ExposedReference<DialogManager> dialogManager;
? ? public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
? ? {
? ? ? ? var playable = ScriptPlayable<DialogPlayableBehaviour>.Create(graph);
? ? ? ? var dialogPlayableBehaviour = playable.GetBehaviour();
? ? ? ? dialogPlayableBehaviour.dialogManager = dialogManager.Resolve(graph.GetResolver());
? ? ? ? dialogPlayableBehaviour.dialogGroupId = dialogGroupId;
? ? ? ? return playable;
? ? }
}
(3)自定義對話管理類DialogManager绘雁,繼承自MonoBhehaviour≡可以將該腳本掛在Timeline預(yù)制體上庐舟。
其中的PauseTimeline()和ResumeTimeline()接口分別用來暫停和重新播放Timeline。
SetDialog()接口中會調(diào)用具體的對話框邏輯住拭,當然我這兒的對話框邏輯是Lua端實現(xiàn)的挪略,所以這樣寫,大家可以根據(jù)需要調(diào)用自己的實現(xiàn)接口废酷。同時添加對話播放結(jié)束事件的監(jiān)聽瘟檩,當對話結(jié)束時調(diào)用ResumeTimeline()接口使Timeline繼續(xù)播放。
腳本實現(xiàn)如下:
using UnityEngine;
using UnityEngine.Playables;
using WCC.Lua;
using System;
public class DialogManager : MonoBehaviour
{
? ? int playDialogGroupId = 0;
? ? PlayableDirector activeDirector;
? ? public void SetDialog(int dialogGroupId)
? ? {
? ? ? ? if (Application.isPlaying)
? ? ? ? {
? ? ? ? ? ? playDialogGroupId = dialogGroupId;
? ? ? ? ? ? GlobalEventManager.AddListener(GlobalEventType.OnDialogGroupEnd, OnDialogGroupEnd);
? ? ? ? ? ? LuaEntrance.Instance.GetLuaEnv().DoString("local TimelineDialogMgr = require\"Logic.Timeline.TimelineDialogManager\"" +
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $"TimelineDialogMgr:DoDialog({dialogGroupId})");
? ? ? ? }
? ? }
? ? public void PauseTimeline(PlayableDirector pd)
? ? {
? ? ? ? activeDirector = pd;
? ? ? ? activeDirector.Pause();
? ? }
? ? public void ResumeTimeline()
? ? {
? ? ? ? if(activeDirector)
? ? ? ? {
? ? ? ? ? ? activeDirector.Resume();
? ? ? ? }
? ? }
? ? private void OnDialogGroupEnd(object o1, object o2, object o3, object o4)
? ? {
? ? ? ? if (playDialogGroupId == Convert.ToInt32(o1))
? ? ? ? {
? ? ? ? ? ? GlobalEventManager.RemoveAllListener(GlobalEventType.OnDialogGroupEnd);
? ? ? ? ? ? ResumeTimeline();
? ? ? ? }
? ? }
}