AnimancerState.cs 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using UnityEngine;
  7. using UnityEngine.Playables;
  8. using Object = UnityEngine.Object;
  9. #if UNITY_EDITOR
  10. using UnityEditor;
  11. #endif
  12. namespace Animancer
  13. {
  14. /// <summary>
  15. /// Base class for all states in an <see cref="AnimancerGraph"/> graph which manages one or more
  16. /// <see cref="Playable"/>s.
  17. /// </summary>
  18. ///
  19. /// <remarks>
  20. /// This class can be used as a custom yield instruction to wait until the animation either stops playing or
  21. /// reaches its end.
  22. /// <para></para>
  23. /// <strong>Documentation:</strong>
  24. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing/states">
  25. /// States</see>
  26. /// </remarks>
  27. /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerState
  28. ///
  29. public abstract partial class AnimancerState : AnimancerNode,
  30. IAnimationClipCollection,
  31. ICloneable<AnimancerState>,
  32. ICopyable<AnimancerState>
  33. {
  34. /************************************************************************************************************************/
  35. #region Graph
  36. /************************************************************************************************************************/
  37. /// <summary>Sets the <see cref="AnimancerNodeBase.Graph"/>.</summary>
  38. /// <exception cref="InvalidOperationException">
  39. /// The <see cref="AnimancerNodeBase.Parent"/> has a different <see cref="AnimancerNodeBase.Graph"/>.
  40. /// Setting the <see cref="AnimancerNodeBase.Parent"/>'s <see cref="AnimancerNodeBase.Graph"/>
  41. /// will apply to its children recursively because they must always match.
  42. /// </exception>
  43. public virtual void SetGraph(AnimancerGraph graph)
  44. {
  45. if (Graph == graph)
  46. return;
  47. RemoveFromOldGraph(graph);
  48. Graph = graph;
  49. AddToNewGraph();
  50. FadeGroup?.ChangeGraph(graph);
  51. }
  52. private void RemoveFromOldGraph(AnimancerGraph newGraph)
  53. {
  54. if (Graph == null)
  55. {
  56. #if UNITY_ASSERTIONS
  57. if (Parent != null && Parent.Graph != newGraph)
  58. throw new InvalidOperationException(
  59. "Unable to set the Graph of a state which has a Parent." +
  60. " Setting the Parent's Graph will apply to its children recursively" +
  61. " because they must always match.");
  62. #endif
  63. return;
  64. }
  65. Graph.States.Unregister(this);
  66. if (Parent != null && Parent.Graph != newGraph)
  67. {
  68. Parent.OnRemoveChild(this);
  69. Parent = null;
  70. Index = -1;
  71. }
  72. _Time = TimeD;
  73. DestroyPlayable();
  74. }
  75. private void AddToNewGraph()
  76. {
  77. if (Graph != null)
  78. {
  79. Graph.States.Register(this);
  80. CreatePlayable();
  81. }
  82. for (int i = ChildCount - 1; i >= 0; i--)
  83. GetChild(i)?.SetGraph(Graph);
  84. if (Parent != null)
  85. CopyIKFlags(Parent);
  86. }
  87. /************************************************************************************************************************/
  88. /// <summary>Connects this state to the `parent` at its next available child index.</summary>
  89. /// <remarks>If the `parent` is <c>null</c>, this state will be disconnected from everything.</remarks>
  90. public void SetParent(AnimancerNode parent)
  91. {
  92. #if UNITY_ASSERTIONS
  93. if (Parent == parent)
  94. Debug.LogWarning(
  95. $"{nameof(Parent)} is already set to {AnimancerUtilities.ToStringOrNull(parent)}.",
  96. Graph?.Component as Object);
  97. #endif
  98. if (Parent != null)
  99. {
  100. Parent.OnRemoveChild(this);
  101. Parent = null;
  102. }
  103. if (parent == null)
  104. {
  105. FadeGroup?.ChangeParent(this);
  106. Index = -1;
  107. return;
  108. }
  109. SetGraph(parent.Graph);
  110. Parent = parent;
  111. parent.OnAddChild(this);
  112. CopyIKFlags(parent);
  113. FadeGroup?.ChangeParent(this);
  114. }
  115. /// <summary>[Internal]
  116. /// Directly sets the <see cref="AnimancerNodeBase.Parent"/> and <see cref="AnimancerNode.Index"/>
  117. /// without triggering any other connection methods.
  118. /// </summary>
  119. internal void SetParentInternal(AnimancerNode parent, int index = -1)
  120. {
  121. Parent = parent;
  122. Index = index;
  123. }
  124. /************************************************************************************************************************/
  125. // Layer.
  126. /************************************************************************************************************************/
  127. /// <summary>
  128. /// The index of the <see cref="AnimancerLayer"/> this state is connected to
  129. /// (determined by the <see cref="AnimancerNodeBase.Parent"/>).
  130. /// </summary>
  131. /// <returns><c>-1</c> if this state isn't connected to a layer.</returns>
  132. public int LayerIndex
  133. {
  134. get
  135. {
  136. if (Parent == null)
  137. return -1;
  138. var layer = Parent.Layer;
  139. if (layer == null)
  140. return -1;
  141. return layer.Index;
  142. }
  143. set => SetParent(value >= 0
  144. ? Graph.Layers[value]
  145. : null);
  146. }
  147. /************************************************************************************************************************/
  148. #endregion
  149. /************************************************************************************************************************/
  150. #region Key and Clip
  151. /************************************************************************************************************************/
  152. internal object _Key;
  153. /// <summary>
  154. /// The object used to identify this state in the graph <see cref="AnimancerGraph.States"/> dictionary.
  155. /// Can be null.
  156. /// </summary>
  157. public object Key
  158. {
  159. get => _Key;
  160. set
  161. {
  162. if (Graph == null)
  163. {
  164. _Key = value;
  165. }
  166. else
  167. {
  168. Graph.States.Unregister(this);
  169. _Key = value;
  170. Graph.States.Register(this);
  171. }
  172. }
  173. }
  174. /************************************************************************************************************************/
  175. /// <summary>The <see cref="AnimationClip"/> which this state plays (if any).</summary>
  176. /// <exception cref="NotSupportedException">This state type doesn't have a clip and you try to set it.</exception>
  177. public virtual AnimationClip Clip
  178. {
  179. get => null;
  180. set
  181. {
  182. MarkAsUsed(this);
  183. throw new NotSupportedException($"{GetType()} doesn't support setting the {nameof(Clip)}.");
  184. }
  185. }
  186. /// <summary>The main object to show in the Inspector for this state (if any).</summary>
  187. /// <exception cref="NotSupportedException">This state type doesn't have a main object and you try to set it.</exception>
  188. /// <exception cref="InvalidCastException">This state can't use the assigned value.</exception>
  189. public virtual Object MainObject
  190. {
  191. get => null;
  192. set
  193. {
  194. MarkAsUsed(this);
  195. throw new NotSupportedException($"{GetType()} doesn't support setting the {nameof(MainObject)}.");
  196. }
  197. }
  198. #if UNITY_EDITOR
  199. /// <summary>[Editor-Only] The base type which can be assigned to the <see cref="MainObject"/>.</summary>
  200. public virtual Type MainObjectType
  201. => null;
  202. #endif
  203. /************************************************************************************************************************/
  204. /// <summary>
  205. /// Sets the `currentObject` and calls <see cref="AnimancerNode.RecreatePlayable"/>.
  206. /// If the `currentObject` was being used as the <see cref="Key"/> then it is changed as well.
  207. /// </summary>
  208. /// <exception cref="ArgumentNullException">The `newObject` is null.</exception>
  209. protected bool ChangeMainObject<T>(ref T currentObject, T newObject)
  210. where T : Object
  211. {
  212. if (newObject == null)
  213. {
  214. MarkAsUsed(this);
  215. throw new ArgumentNullException(nameof(newObject));
  216. }
  217. if (ReferenceEquals(currentObject, newObject))
  218. return false;
  219. if (ReferenceEquals(_Key, currentObject))
  220. Key = newObject;
  221. currentObject = newObject;
  222. if (Graph != null)
  223. RecreatePlayable();
  224. return true;
  225. }
  226. /************************************************************************************************************************/
  227. /// <summary>The average velocity of the Root Motion caused by this state.</summary>
  228. public virtual Vector3 AverageVelocity => default;
  229. /************************************************************************************************************************/
  230. #endregion
  231. /************************************************************************************************************************/
  232. #region Playing
  233. /************************************************************************************************************************/
  234. /// <summary>Is the <see cref="Time"/> automatically advancing?</summary>
  235. private bool _IsPlaying;
  236. /************************************************************************************************************************/
  237. /// <summary>Is the <see cref="Time"/> automatically advancing?</summary>
  238. ///
  239. /// <remarks>
  240. /// <strong>Example:</strong><code>
  241. /// void IsPlayingExample(AnimancerComponent animancer, AnimationClip clip)
  242. /// {
  243. /// var state = animancer.States.GetOrCreate(clip);
  244. ///
  245. /// if (state.IsPlaying)
  246. /// Debug.Log(clip + " is playing");
  247. /// else
  248. /// Debug.Log(clip + " is paused");
  249. ///
  250. /// state.IsPlaying = false;// Pause the animation.
  251. ///
  252. /// state.IsPlaying = true;// Unpause the animation.
  253. /// }
  254. /// </code></remarks>
  255. public bool IsPlaying
  256. {
  257. get => _IsPlaying;
  258. set
  259. {
  260. SetIsPlaying(value);
  261. UpdateIsActive();
  262. }
  263. }
  264. /// <summary>
  265. /// Sets <see cref="IsPlaying"/> and applies it to the <see cref="Playable"/>
  266. /// without calling <see cref="UpdateIsActive"/>.
  267. /// </summary>
  268. protected internal void SetIsPlaying(bool isPlaying)
  269. {
  270. if (_IsPlaying == isPlaying)
  271. return;
  272. _IsPlaying = isPlaying;
  273. if (_Playable.IsValid())
  274. {
  275. if (_IsPlaying)
  276. _Playable.Play();
  277. else
  278. _Playable.Pause();
  279. }
  280. OnSetIsPlaying();
  281. }
  282. /// <summary>Called when the value of <see cref="IsPlaying"/> is changed.</summary>
  283. protected virtual void OnSetIsPlaying() { }
  284. /************************************************************************************************************************/
  285. /// <summary>Creates and assigns the <see cref="Playable"/> managed by this state.</summary>
  286. /// <remarks>This method also applies the <see cref="AnimancerNodeBase.Speed"/> and <see cref="IsPlaying"/>.</remarks>
  287. protected sealed override void CreatePlayable()
  288. {
  289. base.CreatePlayable();
  290. if (Parent != null && (IsActive || Parent.KeepChildrenConnected))
  291. Graph._PlayableGraph.Connect(Parent.Playable, Playable, Index, Weight);
  292. if (!_IsPlaying)
  293. _Playable.Pause();
  294. RawTime = _Time;
  295. }
  296. /************************************************************************************************************************/
  297. /// <summary>Is this state playing and not fading out?</summary>
  298. /// <remarks>
  299. /// If true, this state will usually be the <see cref="AnimancerLayer.CurrentState"/> but that is not always
  300. /// the case.
  301. /// </remarks>
  302. public bool IsCurrent
  303. => _IsPlaying
  304. && TargetWeight > 0;
  305. /// <summary>Is this state not playing and at 0 <see cref="AnimancerNode.Weight"/>?</summary>
  306. public bool IsStopped
  307. => !_IsPlaying
  308. && Weight == 0;
  309. /************************************************************************************************************************/
  310. /// <summary>
  311. /// Plays this state immediately, without any blending and without affecting any other states.
  312. /// </summary>
  313. /// <remarks>
  314. /// Unlike <see cref="AnimancerLayer.Play(AnimancerState)"/>,
  315. /// this method only affects this state and won't stop any others that are playing.
  316. /// <para></para>
  317. /// Sets <see cref="IsPlaying"/> = true and <see cref="AnimancerNode.Weight"/> = 1.
  318. /// <para></para>
  319. /// Doesn't change the <see cref="Time"/> so it will continue from its current value.
  320. /// </remarks>
  321. public void Play()
  322. {
  323. SetIsPlaying(true);
  324. Weight = 1;
  325. }
  326. /************************************************************************************************************************/
  327. /// <inheritdoc/>
  328. protected internal override void StopWithoutWeight()
  329. {
  330. SetIsPlaying(false);
  331. TimeD = 0;
  332. UpdateIsActive();
  333. }
  334. /************************************************************************************************************************/
  335. /// <inheritdoc/>
  336. protected internal override void OnStartFade()
  337. {
  338. UpdateIsActive();
  339. }
  340. /// <inheritdoc/>
  341. protected internal override void InternalClearFade()
  342. {
  343. base.InternalClearFade();
  344. UpdateIsActive();
  345. }
  346. /************************************************************************************************************************/
  347. #endregion
  348. /************************************************************************************************************************/
  349. #region Active
  350. /************************************************************************************************************************/
  351. /// <summary>
  352. /// The index of this state in its parent <see cref="AnimancerLayer.ActiveStates"/> (or -1 if inactive).
  353. /// </summary>
  354. /// <remarks>
  355. /// If this state's direct parent isn't a layer (such as a child of a mixer), this value simply uses 0 to
  356. /// indicate active.
  357. /// </remarks>
  358. internal int _ActiveIndex = ActiveList.NotInList;
  359. /************************************************************************************************************************/
  360. /// <summary>Is this state currently updating or affecting the animation output?</summary>
  361. /// <remarks>
  362. /// This property is true when <see cref="IsPlaying"/> or the <see cref="AnimancerNode.Weight"/> or
  363. /// <see cref="AnimancerNode.TargetWeight"/> are above 0.
  364. /// </remarks>
  365. public bool IsActive
  366. => _ActiveIndex >= 0;
  367. /// <summary>[Internal] Should <see cref="IsActive"/> be true based on the current details of this state?</summary>
  368. internal bool ShouldBeActive
  369. {
  370. get => IsPlaying
  371. || Weight > 0
  372. || FadeGroup != null;
  373. set => _ActiveIndex = value ? 0 : -1;
  374. }
  375. /// <summary>[Internal] If <see cref="IsActive"/> this method sets it to false and returns true.</summary>
  376. internal bool TryDeactivate()
  377. {
  378. if (_ActiveIndex < 0)
  379. return false;
  380. _ActiveIndex = ActiveList.NotInList;
  381. return true;
  382. }
  383. /// <summary>Called when <see cref="IsActive"/> might change.</summary>
  384. internal void UpdateIsActive()
  385. {
  386. var shouldBeActive = ShouldBeActive;
  387. if (IsActive == shouldBeActive)
  388. return;
  389. var parent = Parent;
  390. if (parent != null)
  391. parent.ApplyChildActive(this, shouldBeActive);
  392. else
  393. ShouldBeActive = ShouldBeActive;
  394. }
  395. /************************************************************************************************************************/
  396. /// <inheritdoc/>
  397. public sealed override void SetWeight(float value)
  398. {
  399. base.SetWeight(value);
  400. UpdateIsActive();
  401. }
  402. /************************************************************************************************************************/
  403. /// <summary>[Internal] An <see cref="IIndexer{T}"/> based on <see cref="_ActiveIndex"/>.</summary>
  404. internal readonly struct Indexer : IIndexer<AnimancerState>
  405. {
  406. /************************************************************************************************************************/
  407. /// <summary>The <see cref="AnimancerNodeBase.Graph"/>.</summary>
  408. public readonly AnimancerGraph Graph;
  409. /// <summary>The <see cref="Playable"/> of the <see cref="AnimancerNodeBase.Parent"/>.</summary>
  410. public readonly Playable ParentPlayable;
  411. /************************************************************************************************************************/
  412. /// <summary>Creates a new <see cref="Indexer"/>.</summary>
  413. public Indexer(AnimancerGraph graph, Playable parentPlayable)
  414. {
  415. Graph = graph;
  416. ParentPlayable = parentPlayable;
  417. }
  418. /************************************************************************************************************************/
  419. /// <inheritdoc/>
  420. public readonly int GetIndex(AnimancerState state)
  421. => state._ActiveIndex;
  422. /************************************************************************************************************************/
  423. /// <inheritdoc/>
  424. public readonly void SetIndex(AnimancerState state, int index)
  425. {
  426. if (!Graph.KeepChildrenConnected && state._ActiveIndex < 0)
  427. {
  428. Validate.AssertPlayable(state);
  429. Graph._PlayableGraph.Connect(ParentPlayable, state._Playable, state.Index, state.Weight);
  430. }
  431. state._ActiveIndex = index;
  432. }
  433. /************************************************************************************************************************/
  434. /// <inheritdoc/>
  435. public readonly void ClearIndex(AnimancerState state)
  436. {
  437. if (!Graph.KeepChildrenConnected)
  438. Graph._PlayableGraph.Disconnect(ParentPlayable, state.Index);
  439. state._ActiveIndex = ActiveList.NotInList;
  440. }
  441. /************************************************************************************************************************/
  442. }
  443. /************************************************************************************************************************/
  444. /// <summary>[Internal]
  445. /// An <see cref="IndexedList{TItem, TAccessor}"/> of <see cref="AnimancerState"/>s
  446. /// which tracks <see cref="IsActive"/>.
  447. /// </summary>
  448. internal class ActiveList : IndexedList<AnimancerState, Indexer>
  449. {
  450. /// <summary>The default <see cref="IndexedList{TItem, TIndexer}.Capacity"/> for newly created lists.</summary>
  451. /// <remarks>Default value is 4.</remarks>
  452. public static new int DefaultCapacity { get; set; } = 4;
  453. /// <summary>Creates a new <see cref="ActiveList"/> with the <see cref="DefaultCapacity"/>.</summary>
  454. public ActiveList(Indexer accessor)
  455. : base(DefaultCapacity, accessor)
  456. { }
  457. }
  458. /************************************************************************************************************************/
  459. #endregion
  460. /************************************************************************************************************************/
  461. #region Timing
  462. /************************************************************************************************************************/
  463. // Time.
  464. /************************************************************************************************************************/
  465. /// <summary>
  466. /// The current time of the <see cref="Playable"/>, retrieved by <see cref="Time"/> whenever the
  467. /// <see cref="_TimeFrameID"/> is different from the <see cref="AnimancerGraph.FrameID"/>.
  468. /// </summary>
  469. private double _Time;
  470. /// <summary>
  471. /// The <see cref="AnimancerGraph.FrameID"/> from when the <see cref="Time"/> was last retrieved from the
  472. /// <see cref="Playable"/>.
  473. /// </summary>
  474. private ulong _TimeFrameID;
  475. /************************************************************************************************************************/
  476. /// <summary>The number of seconds that have passed since the start of this animation.</summary>
  477. ///
  478. /// <remarks>
  479. /// This value continues increasing after the animation passes the end of its
  480. /// <see cref="Length"/>, regardless of whether it <see cref="IsLooping"/> or not.
  481. /// <para></para>
  482. /// The underlying <see cref="double"/> can be accessed via <see cref="TimeD"/>.
  483. /// <para></para>
  484. /// Setting this value will skip Events and Root Motion between the old and new time.
  485. /// Use <see cref="MoveTime(float, bool)"/> instead if you don't want that behaviour.
  486. /// <para></para>
  487. /// <em>Animancer Lite doesn't allow this value to be changed in runtime builds (except resetting it to 0).</em>
  488. /// <para></para>
  489. /// <strong>Example:</strong><code>
  490. /// void TimeExample(AnimancerComponent animancer, AnimationClip clip)
  491. /// {
  492. /// var state = animancer.Play(clip);
  493. ///
  494. /// // Skip 0.5 seconds into the animation:
  495. /// state.Time = 0.5f;
  496. ///
  497. /// // Skip 50% of the way through the animation (0.5 in a range of 0 to 1):
  498. /// state.NormalizedTime = 0.5f;
  499. ///
  500. /// // Skip to the end of the animation and play backwards:
  501. /// state.NormalizedTime = 1;
  502. /// state.Speed = -1;
  503. /// }
  504. /// </code></remarks>
  505. public float Time
  506. {
  507. get => (float)TimeD;
  508. set => TimeD = value;
  509. }
  510. /// <summary>The underlying <see cref="double"/> value of <see cref="Time"/>.</summary>
  511. public double TimeD
  512. {
  513. get
  514. {
  515. var graph = Graph;
  516. if (graph == null)
  517. return _Time;
  518. var frameID = graph.FrameID;
  519. if (_TimeFrameID != frameID)
  520. {
  521. _TimeFrameID = frameID;
  522. _Time = RawTime;
  523. }
  524. return _Time;
  525. }
  526. set
  527. {
  528. #if UNITY_ASSERTIONS
  529. if (!value.IsFinite())
  530. {
  531. MarkAsUsed(this);
  532. throw new ArgumentOutOfRangeException(
  533. nameof(value),
  534. value,
  535. $"{nameof(Time)} {Strings.MustBeFinite}");
  536. }
  537. #endif
  538. _Time = value;
  539. var graph = Graph;
  540. if (graph != null)
  541. {
  542. _TimeFrameID = graph.FrameID;
  543. RawTime = value;
  544. }
  545. _EventDispatcher?.OnSetTime();
  546. }
  547. }
  548. /************************************************************************************************************************/
  549. /// <summary>
  550. /// The internal implementation of <see cref="Time"/> which directly gets and sets the underlying value.
  551. /// </summary>
  552. /// <remarks>
  553. /// This property should generally not be accessed directly.
  554. /// <para></para>
  555. /// Setting this value will skip Events and Root Motion between the old and new time.
  556. /// Use <see cref="MoveTime(float, bool)"/> instead if you don't want that behaviour.
  557. /// </remarks>
  558. public virtual double RawTime
  559. {
  560. get
  561. {
  562. Validate.AssertPlayable(this);
  563. return _Playable.GetTime();
  564. }
  565. set
  566. {
  567. Validate.AssertPlayable(this);
  568. var time = value;
  569. _Playable.SetTime(time);
  570. _Playable.SetTime(time);
  571. }
  572. }
  573. /************************************************************************************************************************/
  574. /// <summary>
  575. /// The <see cref="Time"/> of this state as a portion of the animation's <see cref="Length"/>, meaning the
  576. /// value goes from 0 to 1 as it plays from start to end, regardless of how long that actually takes.
  577. /// </summary>
  578. ///
  579. /// <remarks>
  580. /// This value continues increasing after the animation passes the end of its
  581. /// <see cref="Length"/>, regardless of whether it <see cref="IsLooping"/> or not.
  582. /// <para></para>
  583. /// The fractional part of the value (<c>NormalizedTime % 1</c>)
  584. /// is the percentage (0-1) of progress in the current loop
  585. /// while the integer part (<c>(int)NormalizedTime</c>)
  586. /// is the number of times the animation has been looped.
  587. /// <para></para>
  588. /// Setting this value will skip Events and Root Motion between the old and new time.
  589. /// Use <see cref="MoveTime(float, bool)"/> instead if you don't want that behaviour.
  590. /// <para></para>
  591. /// <em>Animancer Lite doesn't allow this value to be changed in runtime builds (except resetting it to 0).</em>
  592. /// <para></para>
  593. /// <strong>Example:</strong><code>
  594. /// void TimeExample(AnimancerComponent animancer, AnimationClip clip)
  595. /// {
  596. /// var state = animancer.Play(clip);
  597. ///
  598. /// // Skip 0.5 seconds into the animation:
  599. /// state.Time = 0.5f;
  600. ///
  601. /// // Skip 50% of the way through the animation (0.5 in a range of 0 to 1):
  602. /// state.NormalizedTime = 0.5f;
  603. ///
  604. /// // Skip to the end of the animation and play backwards:
  605. /// state.NormalizedTime = 1;
  606. /// state.Speed = -1;
  607. /// }
  608. /// </code></remarks>
  609. public float NormalizedTime
  610. {
  611. get => (float)NormalizedTimeD;
  612. set => NormalizedTimeD = value;
  613. }
  614. /// <summary>The underlying <see cref="double"/> value of <see cref="NormalizedTime"/>.</summary>
  615. public double NormalizedTimeD
  616. {
  617. get
  618. {
  619. var length = Length;
  620. if (length != 0)
  621. return TimeD / length;
  622. else
  623. return 0;
  624. }
  625. set => TimeD = value * Length;
  626. }
  627. /************************************************************************************************************************/
  628. /// <summary>
  629. /// Sets the <see cref="Time"/> or <see cref="NormalizedTime"/>, but unlike those properties
  630. /// this method doesn't skip Events or Root Motion between the old and new time.
  631. /// </summary>
  632. /// <remarks>
  633. /// The Events and Root Motion will be applied during the next animation update.
  634. /// If you want to apply them immediately you can call <see cref="AnimancerGraph.Evaluate()"/>.
  635. /// <para></para>
  636. /// Events are triggered where <c>old time &lt;= event time &lt; new time</c>.
  637. /// <para></para>
  638. /// Avoid calling this method more than once per frame because doing so will cause
  639. /// Animation Events and Root Motion to be skipped due to an unfortunate design
  640. /// decision in the Playables API. Animancer Events would still be triggered,
  641. /// but only between the old time and the last new time you set
  642. /// (any other values would be ignored).
  643. /// </remarks>
  644. public void MoveTime(float time, bool normalized)
  645. => MoveTime((double)time, normalized);
  646. /// <summary>
  647. /// Sets the <see cref="Time"/> or <see cref="NormalizedTime"/>, but unlike those properties
  648. /// this method doesn't skip Events or Root Motion between the old and new time.
  649. /// </summary>
  650. /// <remarks>
  651. /// The Events and Root Motion will be applied during the next animation update.
  652. /// If you want to apply them immediately you can call <see cref="AnimancerGraph.Evaluate()"/>.
  653. /// <para></para>
  654. /// Avoid calling this method more than once per frame because doing so will cause
  655. /// Animation Events and Root Motion to be skipped due to an unfortunate design
  656. /// decision in the Playables API. Animancer Events would still be triggered,
  657. /// but only between the old time and the last new time you set
  658. /// (any other values would be ignored).
  659. /// </remarks>
  660. public virtual void MoveTime(double time, bool normalized)
  661. {
  662. #if UNITY_ASSERTIONS
  663. if (!time.IsFinite())
  664. {
  665. MarkAsUsed(this);
  666. throw new ArgumentOutOfRangeException(nameof(time), time,
  667. $"{nameof(Time)} {Strings.MustBeFinite}");
  668. }
  669. #endif
  670. var graph = Graph;
  671. if (graph != null)
  672. _TimeFrameID = graph.FrameID;
  673. if (normalized)
  674. time *= Length;
  675. _Time = time;
  676. _Playable.SetTime(time);
  677. }
  678. /************************************************************************************************************************/
  679. // Duration.
  680. /************************************************************************************************************************/
  681. /// <summary>
  682. /// The <see cref="NormalizedTime"/> after which the
  683. /// <see cref="AnimancerEvent.Sequence.OnEnd"/> callback will be invoked every frame.
  684. /// </summary>
  685. /// <remarks>
  686. /// This is a wrapper around <see cref="AnimancerEvent.Sequence.NormalizedEndTime"/>
  687. /// so that if the value hasn't been set (<see cref="float.NaN"/>)
  688. /// it can be determined based on the <see cref="AnimancerNodeBase.EffectiveSpeed"/>:
  689. /// positive speed ends at 1 and negative speed ends at 0.
  690. /// </remarks>
  691. public float NormalizedEndTime
  692. {
  693. get
  694. {
  695. var events = SharedEvents;
  696. if (events != null)
  697. {
  698. var time = events.NormalizedEndTime;
  699. if (!float.IsNaN(time))
  700. return time;
  701. }
  702. return AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(EffectiveSpeed);
  703. }
  704. }
  705. /************************************************************************************************************************/
  706. /// <summary>
  707. /// The number of seconds the animation will take to play fully at its current
  708. /// <see cref="AnimancerNodeBase.EffectiveSpeed"/>.
  709. /// </summary>
  710. ///
  711. /// <remarks>
  712. /// For the time remaining from now until it reaches the end, use <see cref="RemainingDuration"/> instead.
  713. /// <para></para>
  714. /// Setting this value modifies the <see cref="AnimancerNodeBase.Speed"/>, not the <see cref="Length"/>.
  715. /// <para></para>
  716. /// <em>Animancer Lite doesn't allow this value to be changed in runtime builds.</em>
  717. /// <para></para>
  718. /// <strong>Example:</strong><code>
  719. /// void PlayAnimation(AnimancerComponent animancer, AnimationClip clip)
  720. /// {
  721. /// var state = animancer.Play(clip);
  722. ///
  723. /// state.Duration = 1;// Play fully in 1 second.
  724. /// state.Duration = 2;// Play fully in 2 seconds.
  725. /// state.Duration = 0.5f;// Play fully in half a second.
  726. /// state.Duration = -1;// Play backwards fully in 1 second.
  727. /// state.NormalizedTime = 1; state.Duration = -1;// Play backwards from the end in 1 second.
  728. /// }
  729. /// </code></remarks>
  730. public float Duration
  731. {
  732. get
  733. {
  734. var speed = EffectiveSpeed;
  735. if (speed == 0)
  736. return float.PositiveInfinity;
  737. var events = SharedEvents;
  738. if (events != null)
  739. {
  740. var endTime = events.NormalizedEndTime;
  741. if (!float.IsNaN(endTime))
  742. {
  743. if (speed > 0)
  744. return Length * endTime / speed;
  745. else
  746. return Length * (1 - endTime) / -speed;
  747. }
  748. }
  749. return Length / Math.Abs(speed);
  750. }
  751. set
  752. {
  753. var length = Length;
  754. var events = SharedEvents;
  755. if (events != null)
  756. {
  757. var endTime = events.NormalizedEndTime;
  758. if (!float.IsNaN(endTime))
  759. {
  760. if (EffectiveSpeed > 0)
  761. length *= endTime;
  762. else
  763. length *= 1 - endTime;
  764. }
  765. }
  766. EffectiveSpeed = length / value;
  767. }
  768. }
  769. /************************************************************************************************************************/
  770. /// <summary>
  771. /// The number of seconds this state will take to go from its current <see cref="NormalizedTime"/> to the
  772. /// <see cref="NormalizedEndTime"/> at its current <see cref="AnimancerNodeBase.EffectiveSpeed"/>.
  773. /// </summary>
  774. ///
  775. /// <remarks>
  776. /// For the time it would take to play fully from the start, use the <see cref="Duration"/> instead.
  777. /// <para></para>
  778. /// Setting this value modifies the <see cref="AnimancerNodeBase.EffectiveSpeed"/>, not the <see cref="Length"/>.
  779. /// <para></para>
  780. /// <em>Animancer Lite doesn't allow this value to be changed in runtime builds.</em>
  781. /// <para></para>
  782. /// <strong>Example:</strong><code>
  783. /// void PlayAnimation(AnimancerComponent animancer, AnimationClip clip)
  784. /// {
  785. /// var state = animancer.Play(clip);
  786. ///
  787. /// state.RemainingDuration = 1;// Play from the current time to the end in 1 second.
  788. /// state.RemainingDuration = 2;// Play from the current time to the end in 2 seconds.
  789. /// state.RemainingDuration = 0.5f;// Play from the current time to the end in half a second.
  790. /// state.RemainingDuration = -1;// Play from the current time away from the end.
  791. /// }
  792. /// </code></remarks>
  793. public float RemainingDuration
  794. {
  795. get => (Length * NormalizedEndTime - Time) / EffectiveSpeed;
  796. set => EffectiveSpeed = (Length * NormalizedEndTime - Time) / value;
  797. }
  798. /************************************************************************************************************************/
  799. // Length.
  800. /************************************************************************************************************************/
  801. /// <summary>
  802. /// The total time this state would take to play in seconds when <see cref="AnimancerNodeBase.Speed"/> = 1.
  803. /// </summary>
  804. public abstract float Length { get; }
  805. /// <summary>Will this state loop back to the start when it reaches the end?</summary>
  806. /// <remarks>
  807. /// Note that <see cref="Time"/> always continues increasing regardless of this value.
  808. /// See the comments on <see cref="Time"/> for more information.
  809. /// </remarks>
  810. public virtual bool IsLooping => false;
  811. /************************************************************************************************************************/
  812. /// <summary>
  813. /// Gets the details used to trigger <see cref="AnimancerEvent"/>s on this state:
  814. /// <see cref="Length"/>, <see cref="NormalizedTime"/>, and <see cref="IsLooping"/>.
  815. /// </summary>
  816. public virtual void GetEventDispatchInfo(
  817. out float length,
  818. out float normalizedTime,
  819. out bool isLooping)
  820. {
  821. length = Length;
  822. normalizedTime = length != 0
  823. ? Time / length
  824. : 0;
  825. isLooping = IsLooping;
  826. }
  827. /************************************************************************************************************************/
  828. #endregion
  829. /************************************************************************************************************************/
  830. #region Methods
  831. /************************************************************************************************************************/
  832. /// <summary>Destroys the <see cref="Playable"/> and cleans up this state.</summary>
  833. /// <remarks>
  834. /// This method is NOT called automatically, so when implementing a custom state type you must use
  835. /// <see cref="AnimancerGraph.Disposables"/> if you need to guarantee that things will get cleaned up.
  836. /// </remarks>
  837. public virtual void Destroy()
  838. {
  839. if (Parent != null)
  840. {
  841. Parent.OnRemoveChild(this);
  842. Parent = null;
  843. }
  844. FadeGroup = null;
  845. Index = -1;
  846. _EventDispatcher = null;
  847. var graph = Graph;
  848. if (graph != null)
  849. {
  850. graph.States.Unregister(this);
  851. // This is slightly faster than _Playable.Destroy().
  852. if (_Playable.IsValid() && graph._PlayableGraph.IsValid())
  853. graph._PlayableGraph.DestroyPlayable(_Playable);
  854. }
  855. }
  856. /************************************************************************************************************************/
  857. /// <inheritdoc/>
  858. public abstract AnimancerState Clone(CloneContext context);
  859. /************************************************************************************************************************/
  860. /// <inheritdoc/>
  861. public sealed override void CopyFrom(AnimancerNode copyFrom, CloneContext context)
  862. => this.CopyFromBase(copyFrom, context);
  863. /// <inheritdoc/>
  864. public virtual void CopyFrom(AnimancerState copyFrom, CloneContext context)
  865. {
  866. CopyFirstGraphAndKeyFrom(copyFrom, context);
  867. TimeD = copyFrom.TimeD;
  868. IsPlaying = copyFrom.IsPlaying;
  869. base.CopyFrom(copyFrom, context);
  870. CopyEvents(copyFrom, context);
  871. UpdateIsActive();
  872. }
  873. /************************************************************************************************************************/
  874. /// <summary>Sets the <see cref="AnimancerNodeBase.Graph"/> and <see cref="Key"/>.</summary>
  875. private void CopyFirstGraphAndKeyFrom(AnimancerState copyFrom, CloneContext context)
  876. {
  877. if (Graph != null)
  878. return;
  879. Graph = context.GetCloneOrOriginal(copyFrom.Graph);
  880. // If a clone is registered for the key, use it.
  881. // Otherwise, if the key is a state and we're cloning into a different graph, clone the key state.
  882. // Otherwise, just use the same key.
  883. _Key = copyFrom.Key is AnimancerState stateKey && stateKey.Graph != Graph
  884. ? context.GetOrCreateCloneOrOriginal(stateKey)
  885. : context.GetCloneOrOriginal(copyFrom.Key);
  886. // Each key can only be used once per graph,
  887. // so we can only use it if it's different or we have a different graph.
  888. if (_Key == copyFrom.Key && Graph == copyFrom.Graph)
  889. _Key = null;
  890. AddToNewGraph();
  891. }
  892. /************************************************************************************************************************/
  893. /// <summary>[<see cref="IAnimationClipCollection"/>] Gathers all the animations in this state.</summary>
  894. public virtual void GatherAnimationClips(ICollection<AnimationClip> clips)
  895. {
  896. clips.Gather(Clip);
  897. for (int i = ChildCount - 1; i >= 0; i--)
  898. GetChild(i).GatherAnimationClips(clips);
  899. }
  900. /************************************************************************************************************************/
  901. /// <summary>
  902. /// Returns true if the animation is playing and has not yet passed the
  903. /// <see cref="AnimancerEvent.Sequence.EndEvent"/>.
  904. /// </summary>
  905. /// <remarks>
  906. /// This method is called by <see cref="IEnumerator.MoveNext"/> so this object can be used as a custom yield
  907. /// instruction to wait until it finishes.
  908. /// </remarks>
  909. public override bool IsPlayingAndNotEnding()
  910. {
  911. if (!IsPlaying || !_Playable.IsValid())
  912. return false;
  913. var speed = EffectiveSpeed;
  914. if (speed > 0)
  915. {
  916. float endTime;
  917. var events = SharedEvents;
  918. if (events != null)
  919. {
  920. endTime = events.NormalizedEndTime;
  921. if (float.IsNaN(endTime))
  922. endTime = Length;
  923. else
  924. endTime *= Length;
  925. }
  926. else endTime = Length;
  927. return Time <= endTime;
  928. }
  929. else if (speed < 0)
  930. {
  931. float endTime;
  932. var events = SharedEvents;
  933. if (events != null)
  934. {
  935. endTime = events.NormalizedEndTime;
  936. if (float.IsNaN(endTime))
  937. endTime = 0;
  938. else
  939. endTime *= Length;
  940. }
  941. else endTime = 0;
  942. return Time >= endTime;
  943. }
  944. else return true;
  945. }
  946. /************************************************************************************************************************/
  947. #if UNITY_ASSERTIONS
  948. private string _CachedToString;
  949. #endif
  950. /// <summary>
  951. /// Returns the <see cref="AnimancerNode.DebugName"/> if one is set, otherwise a string describing the type of
  952. /// this state and the name of the <see cref="MainObject"/>.
  953. /// </summary>
  954. public override string ToString()
  955. {
  956. #if UNITY_ASSERTIONS
  957. if (NameCache.TryToString(DebugName, out var cachedName))
  958. return cachedName;
  959. if (_CachedToString != null)
  960. return _CachedToString;
  961. #endif
  962. string name;
  963. var type = GetType().Name;
  964. var mainObject = MainObject;
  965. if (mainObject != null)
  966. {
  967. #if UNITY_ASSERTIONS
  968. name = mainObject.GetCachedName();
  969. #else
  970. name = mainObject.name;
  971. #endif
  972. name = $"{name} ({type})";
  973. }
  974. else
  975. {
  976. name = type;
  977. }
  978. #if UNITY_ASSERTIONS
  979. _CachedToString = name;
  980. #endif
  981. return name;
  982. }
  983. /************************************************************************************************************************/
  984. #region Descriptions
  985. /************************************************************************************************************************/
  986. /// <inheritdoc/>
  987. protected override void AppendDetails(StringBuilder text, string separator)
  988. {
  989. text.AppendField(separator, nameof(Key), _Key);
  990. text.AppendField(separator, "ActiveIndex", _ActiveIndex);
  991. var mainObject = MainObject;
  992. if (mainObject != _Key as Object)
  993. text.AppendField(separator, nameof(MainObject), mainObject);
  994. #if UNITY_EDITOR
  995. if (mainObject != null)
  996. text.AppendField(separator, "AssetPath", AssetDatabase.GetAssetPath(mainObject));
  997. #endif
  998. base.AppendDetails(text, separator);
  999. text.AppendField(separator, nameof(IsPlaying), IsPlaying);
  1000. try
  1001. {
  1002. text.AppendField(separator, nameof(Time), TimeD)
  1003. .Append("s / ")
  1004. .Append(Length)
  1005. .Append("s = ")
  1006. .Append((NormalizedTime * 100).ToString("0.00"))
  1007. .Append('%');
  1008. text.AppendField(separator, nameof(IsLooping), IsLooping);
  1009. }
  1010. catch (Exception exception)
  1011. {
  1012. text.Append(separator).Append(exception);
  1013. }
  1014. text.AppendField(separator, nameof(Events), SharedEvents?.DeepToString(false));
  1015. }
  1016. /************************************************************************************************************************/
  1017. #endregion
  1018. /************************************************************************************************************************/
  1019. #endregion
  1020. /************************************************************************************************************************/
  1021. }
  1022. }