.vs
Assets
Library
APIUpdater
Artifacts
Bee
BuildPlayerData
PackageCache
com.unity.collab-proxy@2.5.2
com.unity.editorcoroutines@1.0.0
com.unity.ext.nunit@1.0.6
com.unity.feature.development@1.0.1
com.unity.ide.rider@3.0.31
com.unity.ide.visualstudio@2.0.22
com.unity.ide.vscode@1.2.5
com.unity.modules.ai@1.0.0
com.unity.modules.androidjni@1.0.0
com.unity.modules.animation@1.0.0
com.unity.modules.assetbundle@1.0.0
com.unity.modules.audio@1.0.0
com.unity.modules.cloth@1.0.0
com.unity.modules.director@1.0.0
com.unity.modules.imageconversion@1.0.0
com.unity.modules.imgui@1.0.0
com.unity.modules.jsonserialize@1.0.0
com.unity.modules.particlesystem@1.0.0
com.unity.modules.physics2d@1.0.0
com.unity.modules.physics@1.0.0
com.unity.modules.screencapture@1.0.0
com.unity.modules.subsystems@1.0.0
com.unity.modules.terrain@1.0.0
com.unity.modules.terrainphysics@1.0.0
com.unity.modules.tilemap@1.0.0
com.unity.modules.ui@1.0.0
com.unity.modules.uielements@1.0.0
com.unity.modules.umbra@1.0.0
com.unity.modules.unityanalytics@1.0.0
com.unity.modules.unitywebrequest@1.0.0
com.unity.modules.unitywebrequestassetbundle@1.0.0
com.unity.modules.unitywebrequestaudio@1.0.0
com.unity.modules.unitywebrequesttexture@1.0.0
com.unity.modules.unitywebrequestwww@1.0.0
com.unity.modules.vehicles@1.0.0
com.unity.modules.video@1.0.0
com.unity.modules.vr@1.0.0
com.unity.modules.wind@1.0.0
com.unity.modules.xr@1.0.0
com.unity.performance.profile-analyzer@1.2.2
com.unity.settings-manager@2.0.1
com.unity.test-framework@1.1.33
com.unity.testtools.codecoverage@1.2.6
com.unity.textmeshpro@3.0.6
com.unity.timeline@1.7.6
DocCodeExamples
Documentation~
Editor
Runtime
Activation
Animation
AssetUpgrade
Attributes
Audio
Control
Evaluation
Events
Extensions
Playables
ActivationControlPlayable.cs
ActivationControlPlayable.cs.meta
BasicScriptPlayable.cs
BasicScriptPlayable.cs.meta
DirectorControlPlayable.cs
DirectorControlPlayable.cs.meta
ITimeControl.cs
ITimeControl.cs.meta
NotificationFlags.cs
NotificationFlags.cs.meta
ParticleControlPlayable.cs
ParticleControlPlayable.cs.meta
PrefabControlPlayable.cs
PrefabControlPlayable.cs.meta
TimeControlPlayable.cs
TimeControlPlayable.cs.meta
TimeNotificationBehaviour.cs
TimeNotificationBehaviour.cs.meta
Properties
Scripting
Utilities
Activation.meta
Animation.meta
AssetUpgrade.meta
Attributes.meta
Audio.meta
ClipCaps.cs
ClipCaps.cs.meta
Control.meta
DiscreteTime.cs
DiscreteTime.cs.meta
Evaluation.meta
Events.meta
Extensions.meta
GroupTrack.cs
GroupTrack.cs.meta
ILayerable.cs
ILayerable.cs.meta
Playables.meta
Properties.meta
Scripting.meta
Timeline.deprecated.cs
Timeline.deprecated.cs.meta
TimelineAsset.cs
TimelineAsset.cs.meta
TimelineAsset_CreateRemove.cs
TimelineAsset_CreateRemove.cs.meta
TimelineAttributes.cs
TimelineAttributes.cs.meta
TimelineClip.cs
TimelineClip.cs.meta
TimelinePlayable.cs
TimelinePlayable.cs.meta
TrackAsset.cs
TrackAsset.cs.meta
Unity.Timeline.asmdef
Unity.Timeline.asmdef.meta
Utilities.meta
Samples~
.signature
CHANGELOG.md
CHANGELOG.md.meta
DocCodeExamples.meta
Editor.meta
LICENSE.md
LICENSE.md.meta
README.md
README.md.meta
Runtime.meta
ValidationExceptions.json
ValidationExceptions.json.meta
package.json
package.json.meta
com.unity.ugui@1.0.0
com.unity.visualscripting@1.9.4
PackageManager
PlayModeViewStates
PlayerDataCache
ScriptAssemblies
Search
ShaderCache
SplashScreenCache
StateCache
UIElements
AnnotationManager
ArtifactDB
ArtifactDB-lock
BuildPlayer.prefs
BuildSettings.asset
EditorOnlyScriptingSettings.json
EditorOnlyVirtualTextureState.json
EditorSnapSettings.asset
EditorUserBuildSettings.asset
InspectorExpandedItems.asset
LastBuild.buildreport
LastSceneManagerSetup.txt
LibraryFormatVersion.txt
MonoManager.asset
SceneVisibilityState.asset
ScriptMapper
ShaderCache.db
SourceAssetDB
SourceAssetDB-lock
SpriteAtlasDatabase.asset
Style.catalog
expandedItems
ilpp.pid
Logs
Packages
ProjectSettings
UserSettings
obj
.vsconfig
Assembly-CSharp.Player.csproj
Assembly-CSharp.csproj
TM1.sln
Unity.CollabProxy.Editor.csproj
Unity.EditorCoroutines.Editor.csproj
Unity.Performance.Profile-Analyzer.Editor.csproj
Unity.PlasticSCM.Editor.csproj
Unity.Rider.Editor.csproj
Unity.Settings.Editor.csproj
Unity.TestTools.CodeCoverage.Editor.OpenCover.Model.csproj
Unity.TestTools.CodeCoverage.Editor.OpenCover.Mono.Reflection.csproj
Unity.TestTools.CodeCoverage.Editor.csproj
Unity.TextMeshPro.Editor.csproj
Unity.TextMeshPro.Player.csproj
Unity.TextMeshPro.csproj
Unity.Timeline.Editor.csproj
Unity.Timeline.Player.csproj
Unity.Timeline.csproj
Unity.VSCode.Editor.csproj
Unity.VisualScripting.Core.Editor.csproj
Unity.VisualScripting.Core.Player.csproj
Unity.VisualScripting.Core.csproj
Unity.VisualScripting.Flow.Editor.csproj
Unity.VisualScripting.Flow.Player.csproj
Unity.VisualScripting.Flow.csproj
Unity.VisualScripting.SettingsProvider.Editor.csproj
Unity.VisualScripting.Shared.Editor.csproj
Unity.VisualScripting.State.Editor.csproj
Unity.VisualScripting.State.Player.csproj
Unity.VisualScripting.State.csproj
Unity.VisualStudio.Editor.csproj
UnityEditor.TestRunner.csproj
UnityEditor.UI.csproj
UnityEngine.TestRunner.Player.csproj
UnityEngine.TestRunner.csproj
UnityEngine.UI.Player.csproj
UnityEngine.UI.csproj
259 lines
10 KiB
C#
259 lines
10 KiB
C#
![]() |
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine.Playables;
|
||
|
|
||
|
namespace UnityEngine.Timeline
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Use this PlayableBehaviour to send notifications at a given time.
|
||
|
/// </summary>
|
||
|
/// <seealso cref="UnityEngine.Timeline.NotificationFlags"/>
|
||
|
public class TimeNotificationBehaviour : PlayableBehaviour
|
||
|
{
|
||
|
struct NotificationEntry
|
||
|
{
|
||
|
public double time;
|
||
|
public INotification payload;
|
||
|
public bool notificationFired;
|
||
|
public NotificationFlags flags;
|
||
|
|
||
|
public bool triggerInEditor
|
||
|
{
|
||
|
get { return (flags & NotificationFlags.TriggerInEditMode) != 0; }
|
||
|
}
|
||
|
public bool prewarm
|
||
|
{
|
||
|
get { return (flags & NotificationFlags.Retroactive) != 0; }
|
||
|
}
|
||
|
public bool triggerOnce
|
||
|
{
|
||
|
get { return (flags & NotificationFlags.TriggerOnce) != 0; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
readonly List<NotificationEntry> m_Notifications = new List<NotificationEntry>();
|
||
|
double m_PreviousTime;
|
||
|
bool m_NeedSortNotifications;
|
||
|
|
||
|
Playable m_TimeSource;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets an optional Playable that provides duration and Wrap mode information.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// timeSource is optional. By default, the duration and Wrap mode will come from the current Playable.
|
||
|
/// </remarks>
|
||
|
public Playable timeSource
|
||
|
{
|
||
|
set { m_TimeSource = value; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates and initializes a ScriptPlayable with a TimeNotificationBehaviour.
|
||
|
/// </summary>
|
||
|
/// <param name="graph">The playable graph.</param>
|
||
|
/// <param name="duration">The duration of the playable.</param>
|
||
|
/// <param name="loopMode">The loop mode of the playable.</param>
|
||
|
/// <returns>A new TimeNotificationBehaviour linked to the PlayableGraph.</returns>
|
||
|
public static ScriptPlayable<TimeNotificationBehaviour> Create(PlayableGraph graph, double duration, DirectorWrapMode loopMode)
|
||
|
{
|
||
|
var notificationsPlayable = ScriptPlayable<TimeNotificationBehaviour>.Create(graph);
|
||
|
notificationsPlayable.SetDuration(duration);
|
||
|
notificationsPlayable.SetTimeWrapMode(loopMode);
|
||
|
notificationsPlayable.SetPropagateSetTime(true);
|
||
|
return notificationsPlayable;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Adds a notification to be sent with flags, at a specific time.
|
||
|
/// </summary>
|
||
|
/// <param name="time">The time to send the notification.</param>
|
||
|
/// <param name="payload">The notification.</param>
|
||
|
/// <param name="flags">The notification flags that determine the notification behaviour. This parameter is set to Retroactive by default.</param>
|
||
|
/// <seealso cref="UnityEngine.Timeline.NotificationFlags"/>
|
||
|
public void AddNotification(double time, INotification payload, NotificationFlags flags = NotificationFlags.Retroactive)
|
||
|
{
|
||
|
m_Notifications.Add(new NotificationEntry
|
||
|
{
|
||
|
time = time,
|
||
|
payload = payload,
|
||
|
flags = flags
|
||
|
});
|
||
|
m_NeedSortNotifications = true;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This method is called when the PlayableGraph that owns this PlayableBehaviour starts.
|
||
|
/// </summary>
|
||
|
/// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
|
||
|
public override void OnGraphStart(Playable playable)
|
||
|
{
|
||
|
SortNotifications();
|
||
|
var currentTime = playable.GetTime();
|
||
|
for (var i = 0; i < m_Notifications.Count; i++)
|
||
|
{
|
||
|
// case 1257208 - when a timeline is _resumed_, only reset notifications after the resumed time
|
||
|
if (m_Notifications[i].time > currentTime && !m_Notifications[i].triggerOnce)
|
||
|
{
|
||
|
var notification = m_Notifications[i];
|
||
|
notification.notificationFired = false;
|
||
|
m_Notifications[i] = notification;
|
||
|
}
|
||
|
}
|
||
|
m_PreviousTime = playable.GetTime();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This method is called when the Playable play state is changed to PlayState.Paused
|
||
|
/// </summary>
|
||
|
/// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
|
||
|
/// <param name="info">Playable context information such as weight, evaluationType, and so on.</param>
|
||
|
public override void OnBehaviourPause(Playable playable, FrameData info)
|
||
|
{
|
||
|
if (playable.IsDone())
|
||
|
{
|
||
|
SortNotifications();
|
||
|
for (var i = 0; i < m_Notifications.Count; i++)
|
||
|
{
|
||
|
var e = m_Notifications[i];
|
||
|
if (!e.notificationFired)
|
||
|
{
|
||
|
var duration = playable.GetDuration();
|
||
|
var canTrigger = m_PreviousTime <= e.time && e.time <= duration;
|
||
|
if (canTrigger)
|
||
|
{
|
||
|
Trigger_internal(playable, info.output, ref e);
|
||
|
m_Notifications[i] = e;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This method is called during the PrepareFrame phase of the PlayableGraph.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// Called once before processing starts.
|
||
|
/// </remarks>
|
||
|
/// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
|
||
|
/// <param name="info">Playable context information such as weight, evaluationType, and so on.</param>
|
||
|
public override void PrepareFrame(Playable playable, FrameData info)
|
||
|
{
|
||
|
// Never trigger on scrub
|
||
|
if (info.evaluationType == FrameData.EvaluationType.Evaluate)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SyncDurationWithExternalSource(playable);
|
||
|
SortNotifications();
|
||
|
var currentTime = playable.GetTime();
|
||
|
|
||
|
// Fire notifications from previousTime till the end
|
||
|
if (info.timeLooped)
|
||
|
{
|
||
|
var duration = playable.GetDuration();
|
||
|
TriggerNotificationsInRange(m_PreviousTime, duration, info, playable, true);
|
||
|
var dx = playable.GetDuration() - m_PreviousTime;
|
||
|
var nFullTimelines = (int)((info.deltaTime * info.effectiveSpeed - dx) / playable.GetDuration());
|
||
|
for (var i = 0; i < nFullTimelines; i++)
|
||
|
{
|
||
|
TriggerNotificationsInRange(0, duration, info, playable, false);
|
||
|
}
|
||
|
TriggerNotificationsInRange(0, currentTime, info, playable, false);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var pt = playable.GetTime();
|
||
|
TriggerNotificationsInRange(m_PreviousTime, pt, info,
|
||
|
playable, true);
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < m_Notifications.Count; ++i)
|
||
|
{
|
||
|
var e = m_Notifications[i];
|
||
|
if (e.notificationFired && CanRestoreNotification(e, info, currentTime, m_PreviousTime))
|
||
|
{
|
||
|
Restore_internal(ref e);
|
||
|
m_Notifications[i] = e;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_PreviousTime = playable.GetTime();
|
||
|
}
|
||
|
|
||
|
void SortNotifications()
|
||
|
{
|
||
|
if (m_NeedSortNotifications)
|
||
|
{
|
||
|
m_Notifications.Sort((x, y) => x.time.CompareTo(y.time));
|
||
|
m_NeedSortNotifications = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool CanRestoreNotification(NotificationEntry e, FrameData info, double currentTime, double previousTime)
|
||
|
{
|
||
|
if (e.triggerOnce)
|
||
|
return false;
|
||
|
if (info.timeLooped)
|
||
|
return true;
|
||
|
|
||
|
//case 1111595: restore the notification if the time is manually set before it
|
||
|
return previousTime > currentTime && currentTime <= e.time;
|
||
|
}
|
||
|
|
||
|
void TriggerNotificationsInRange(double start, double end, FrameData info, Playable playable, bool checkState)
|
||
|
{
|
||
|
if (start <= end)
|
||
|
{
|
||
|
var playMode = Application.isPlaying;
|
||
|
for (var i = 0; i < m_Notifications.Count; i++)
|
||
|
{
|
||
|
var e = m_Notifications[i];
|
||
|
if (e.notificationFired && (checkState || e.triggerOnce))
|
||
|
continue;
|
||
|
|
||
|
var notificationTime = e.time;
|
||
|
if (e.prewarm && notificationTime < end && (e.triggerInEditor || playMode))
|
||
|
{
|
||
|
Trigger_internal(playable, info.output, ref e);
|
||
|
m_Notifications[i] = e;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (notificationTime < start || notificationTime > end)
|
||
|
continue;
|
||
|
|
||
|
if (e.triggerInEditor || playMode)
|
||
|
{
|
||
|
Trigger_internal(playable, info.output, ref e);
|
||
|
m_Notifications[i] = e;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SyncDurationWithExternalSource(Playable playable)
|
||
|
{
|
||
|
if (m_TimeSource.IsValid())
|
||
|
{
|
||
|
playable.SetDuration(m_TimeSource.GetDuration());
|
||
|
playable.SetTimeWrapMode(m_TimeSource.GetTimeWrapMode());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Trigger_internal(Playable playable, PlayableOutput output, ref NotificationEntry e)
|
||
|
{
|
||
|
output.PushNotification(playable, e.payload);
|
||
|
e.notificationFired = true;
|
||
|
}
|
||
|
|
||
|
static void Restore_internal(ref NotificationEntry e)
|
||
|
{
|
||
|
e.notificationFired = false;
|
||
|
}
|
||
|
}
|
||
|
}
|