This script allows Timeline speech to be skipped, causing the Timeline to jump to the end of the current Speech track clip.
To use it:
- Create a new C# file named SkipTimelineSpeech and paste in the code below
- Attach the new Skip Timeline Speech component a Playable Director that contains an AC Speech track.
- Assign the Playable Director in the component's Inspector
- Optionally check "Pause When Begin Speech" to have the Timeline pause when speech tracks begin
SkipTimelineSpeech.cs:
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using AC;
public class SkipTimelineSpeech : MonoBehaviour
{
[SerializeField] private PlayableDirector playableDirector = null;
[SerializeField] private bool pauseWhenBeginSpeech;
private double forceTime;
private void Update ()
{
if (pauseWhenBeginSpeech && IsInSpeech ())
{
playableDirector.time = forceTime;
}
if (SkipSpeechInput ())
{
DoSkip ();
if (pauseWhenBeginSpeech)
{
playableDirector.Resume ();
}
}
}
protected bool SkipSpeechInput ()
{
if (KickStarter.speechManager.canSkipWithMouseClicks && (KickStarter.playerInput.GetMouseState () == MouseState.SingleClick ||
KickStarter.playerInput.GetMouseState () == MouseState.RightClick))
{
return true;
}
if (KickStarter.playerInput.InputGetButtonDown ("SkipSpeech"))
{
return true;
}
return false;
}
private void DoSkip ()
{
if (playableDirector.state != PlayState.Playing) return;
TimelineAsset timeline = (TimelineAsset) playableDirector.playableAsset;
for (int i = 0; i < timeline.outputTrackCount; i++)
{
TrackAsset track = timeline.GetOutputTrack (i);
SpeechTrack speechTrack = track as SpeechTrack;
if (speechTrack)
{
foreach (TimelineClip clip in speechTrack.GetClips ())
{
if (clip != null && clip.asset is SpeechPlayableClip)
{
SpeechPlayableClip speechPlayableClip = clip.asset as SpeechPlayableClip;
if (speechPlayableClip.LastSetBehaviour != null && speechPlayableClip.LastSetBehaviour.Speech != null && speechPlayableClip.LastSetBehaviour.Speech.isAlive)
{
double skipToTime = clip.start + clip.duration;
KickStarter.dialog.KillDialog (speechPlayableClip.LastSetBehaviour.Speech);
if (playableDirector.time < skipToTime)
{
playableDirector.time = skipToTime;
}
return;
}
}
}
}
}
}
private bool IsInSpeech ()
{
if (playableDirector.state != PlayState.Playing) return false;
TimelineAsset timeline = (TimelineAsset) playableDirector.playableAsset;
for (int i = 0; i < timeline.outputTrackCount; i++)
{
TrackAsset track = timeline.GetOutputTrack (i);
SpeechTrack speechTrack = track as SpeechTrack;
if (speechTrack)
{
foreach (TimelineClip clip in speechTrack.GetClips ())
{
if (clip != null && clip.asset is SpeechPlayableClip)
{
SpeechPlayableClip speechPlayableClip = clip.asset as SpeechPlayableClip;
if (speechPlayableClip.LastSetBehaviour != null && speechPlayableClip.LastSetBehaviour.Speech != null && speechPlayableClip.LastSetBehaviour.Speech.isAlive)
{
forceTime = playableDirector.time;
return true;
}
}
}
}
}
return false;
}
}