TimeLine丨(四)利用TimeLine来做一个对话框

大家好,我是SKODE。

小提示:选中左侧目录,可快速找到所需内容

本系列博客地址:传送门

一、目标展示

利用TimeLine,实现对话框效果。

当按下空格键/(你希望的触发操作)时,继续往下进行

二、实现步骤

代码逻辑:

时间轴上代码clip决定显示的UI,决定是否运行完本clip暂停TimeLine,

那暂停后如何继续播放该TimeLine?场景中代码得到允许继续播放的输入命令时,让该TimeLine继续播放即可。

1、给某物体建立TimeLine

选中某物体,Windows-Sequencing-TimeLine,给该物体创建TimeLine属性。

2、创建 Skode_DialogueClip 脚本

该脚本需要被拖到TimeLine上,用以执行下方的 Skode_DialogueBehaviour 。

using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

[Serializable]
public class Skode_DialogueClip : PlayableAsset, ITimelineClipAsset
{
    public Skode_DialogueBehaviour template = new Skode_DialogueBehaviour();

    public ClipCaps clipCaps
    {
        get { return ClipCaps.None; }
    }

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable =ScriptPlayable<Skode_DialogueBehaviour>.Create(graph, template);

        return playable;
    }
}

3、创建 Skode_DialogueBehaviour 脚本

该脚本被 Skode_DialogueClip  实例化执行,有自己的生命周期,执行你想要的程序。

该脚本放在Assets中即可,不用往其他地方挂。

using System;
using UnityEngine;
using UnityEngine.Playables;

[Serializable]
public class Skode_DialogueBehaviour : PlayableBehaviour
{
    //播放到该clip时,UI要显示的文字
    public string dialogueLine;

    [Tooltip("播放完该clip后,是否需要暂停TimeLine")]
    public bool hasToPause = false;

    /// <summary>
    /// 未播放该clip?  false为未播放
    /// </summary>
    bool clipPlayed = false;

    /// <summary>
    /// 播放完该clip后是否需要暂停。false为不需要。
    /// 缓存的bool变量,会在时间轴运行到该clip时,根据 hasToPause 值赋值。
    /// </summary>
    bool pauseScheduled = false;

    /// <summary>
    /// 得到当前 PlayableDirector
    /// </summary>
    PlayableDirector director;

    public override void OnPlayableCreate(Playable playable)
    {
        Debug.Log("OnPlayableCreate");
        director = playable.GetGraph().GetResolver() as PlayableDirector;
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        Debug.Log("ProcessFrame");

        //若还未播放该clip,当前clip的权重>0
        //效果是:时间轴刚进入该clip时执行一次
        if (!clipPlayed && info.weight > 0f)
        {
            Debug.Log("ProcessFrame true");
            Skode_GameManager.ins.SetDialogue(dialogueLine);

            //检测播放完该clip后是否需要暂停,并赋值
            if (Application.isPlaying && hasToPause)
            {
                pauseScheduled = true;
            }

            clipPlayed = true;
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        //因为该回调会在刚运行TimeLine、执行完clip时都会执行一次。
        //因此不能直接判断 hasToPause ,否则刚运行TimeLine就给暂停了。

        if (pauseScheduled)
        {
            pauseScheduled = false;
            Skode_GameManager.ins.PauseTimeline(director);
        }
    }
}

4、创建 Skode_GameManager 脚本

该脚本内有暂停、恢复Timeline、设置UI文字的方法,并能检测输入,恢复TimeLine的执行。

该脚本挂在场景中。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.UI;

public class Skode_GameManager : MonoBehaviour
{
    public static Skode_GameManager ins;

    public Text dialogueLineText;

    PlayableDirector activeDirector;

    private void Awake()
    {
        ins = this;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ResumeTimeline();
        }
    }

    //设置UI文字
    public void SetDialogue(string lineOfDialogue)
    {
        dialogueLineText.text = lineOfDialogue;

        dialogueLineText.gameObject.SetActive(true);
    }

    //暂停TimeLine
    public void PauseTimeline(PlayableDirector whichOne)
    {
        activeDirector = whichOne;

        activeDirector.Pause();
    }

    //恢复播放TimeLine
    public void ResumeTimeline()
    {
        activeDirector.Resume();
    }
}

现在,我们再来说一遍这三个脚本怎么用:

  • Skode_DialogueClip:放在TimeLine上。
  • Skode_DialogueBehaviour:放在Assets中即可。
  • Skode_GameManager:挂在场景中。

一起成长,

我是SKODE。

原创文章 347 获赞 98 访问量 23万+

猜你喜欢

转载自blog.csdn.net/weixin_38239050/article/details/106058439