AnimancerGraph.cs 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using Animancer.TransitionLibraries;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Text;
  7. using UnityEngine;
  8. using UnityEngine.Animations;
  9. using UnityEngine.Playables;
  10. using Object = UnityEngine.Object;
  11. namespace Animancer
  12. {
  13. /// <summary>The root node which manages Animancer's <see cref="UnityEngine.Playables.PlayableGraph"/>.</summary>
  14. ///
  15. /// <remarks>
  16. /// This class can be used as a custom yield instruction to wait until all animations finish playing.
  17. /// <para></para>
  18. /// The most common way to access this class is via <see cref="AnimancerComponent.Graph"/>.
  19. /// <para></para>
  20. /// <strong>Documentation:</strong>
  21. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing">
  22. /// Playing Animations</see>
  23. /// </remarks>
  24. ///
  25. /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerGraph
  26. ///
  27. public partial class AnimancerGraph : AnimancerNodeBase,
  28. IAnimationClipCollection,
  29. ICopyable<AnimancerGraph>,
  30. IEnumerator,
  31. IHasDescription
  32. {
  33. /************************************************************************************************************************/
  34. #region Fields and Properties
  35. /************************************************************************************************************************/
  36. private static float _DefaultFadeDuration = 0.25f;
  37. /************************************************************************************************************************/
  38. #if UNITY_EDITOR
  39. /// <summary>[Editor-Only]
  40. /// The namespace that should be used for a class which sets the <see cref="DefaultFadeDuration"/>.
  41. /// </summary>
  42. public const string DefaultFadeDurationNamespace = nameof(Animancer);
  43. /// <summary>[Editor-Only]
  44. /// The name that should be used for a class which sets the <see cref="DefaultFadeDuration"/>.
  45. /// </summary>
  46. public const string DefaultFadeDurationClass = nameof(DefaultFadeDuration);
  47. /// <summary>[Editor-Only]
  48. /// Initializes the <see cref="DefaultFadeDuration"/> (see its example for more information).
  49. /// </summary>
  50. /// <remarks>
  51. /// This method takes about 2 milliseconds if a <see cref="DefaultFadeDuration"/> class exists, or 0 if it
  52. /// doesn't (less than 0.5 rounded off according to a <see cref="System.Diagnostics.Stopwatch"/>).
  53. /// <para></para>
  54. /// The <see cref="DefaultFadeDuration"/> can't simply be stored in the
  55. /// <see cref="Editor.AnimancerSettings"/> because it needs to be initialized before Unity is able to load
  56. /// <see cref="ScriptableObject"/>s.
  57. /// </remarks>
  58. static AnimancerGraph()
  59. {
  60. var typeName = $"{DefaultFadeDurationNamespace}.{DefaultFadeDurationClass}";
  61. var assemblies = AppDomain.CurrentDomain.GetAssemblies();
  62. // Iterate backwards since it's more likely to be towards the end.
  63. for (int iAssembly = assemblies.Length - 1; iAssembly >= 0; iAssembly--)
  64. {
  65. var type = assemblies[iAssembly].GetType(typeName);
  66. if (type != null)
  67. {
  68. var methods = type.GetMethods(AnimancerReflection.StaticBindings);
  69. for (int iMethod = 0; iMethod < methods.Length; iMethod++)
  70. {
  71. var method = methods[iMethod];
  72. if (method.IsDefined(typeof(RuntimeInitializeOnLoadMethodAttribute), false))
  73. {
  74. method.Invoke(null, null);
  75. return;
  76. }
  77. }
  78. }
  79. }
  80. }
  81. #endif
  82. /************************************************************************************************************************/
  83. /// <summary>The fade duration to use if not specified. Default is 0.25.</summary>
  84. ///
  85. /// <exception cref="UnityEngine.Assertions.AssertionException">The value is negative or infinity.</exception>
  86. ///
  87. /// <remarks>
  88. /// <em>Animancer Lite doesn't allow this value to be changed in runtime builds (except to 0).</em>
  89. /// <para></para>
  90. /// <strong>Example:</strong>
  91. /// <see cref="Sprite"/> based games often have no use for fading so you could set this value to 0 using the
  92. /// following script so that you don't need to manually set the <see cref="ITransition.FadeDuration"/> of all
  93. /// your transitions.
  94. /// <para></para>
  95. /// To set this value automatically on startup, put the following class into any script:
  96. /// <para></para><code>
  97. /// namespace Animancer
  98. /// {
  99. /// internal static class DefaultFadeDuration
  100. /// {
  101. /// [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.BeforeSceneLoad)]
  102. /// private static void Initialize() => AnimancerGraph.DefaultFadeDuration = 0;
  103. /// }
  104. /// }
  105. /// </code>
  106. /// Using that specific namespace (<see cref="DefaultFadeDurationNamespace"/>) and class name
  107. /// (<see cref="DefaultFadeDurationClass"/>) allows Animancer to find and run it immediately in the Unity
  108. /// Editor so that newly created transition fields can start with the correct value (using a
  109. /// <c>[UnityEditor.InitializeOnLoadMethod]</c> attribute would run it too late).
  110. /// </remarks>
  111. public static float DefaultFadeDuration
  112. {
  113. get => _DefaultFadeDuration;
  114. set
  115. {
  116. AnimancerUtilities.Assert(value >= 0 && value < float.PositiveInfinity,
  117. $"{nameof(AnimancerGraph)}.{nameof(DefaultFadeDuration)} must not be negative or infinity.");
  118. _DefaultFadeDuration = value;
  119. }
  120. }
  121. /************************************************************************************************************************/
  122. /// <summary>[Internal]
  123. /// The <see cref="UnityEngine.Playables.PlayableGraph"/> containing this <see cref="AnimancerGraph"/>.
  124. /// </summary>
  125. internal PlayableGraph _PlayableGraph;
  126. /// <summary>[Pro-Only]
  127. /// The <see cref="UnityEngine.Playables.PlayableGraph"/> containing this <see cref="AnimancerGraph"/>.
  128. /// </summary>
  129. public PlayableGraph PlayableGraph
  130. => _PlayableGraph;
  131. /// <summary>Returns the <see cref="PlayableGraph"/>.</summary>
  132. public static implicit operator PlayableGraph(AnimancerGraph animancer)
  133. => animancer.PlayableGraph;
  134. /************************************************************************************************************************/
  135. /// <summary>[Internal]
  136. /// The <see cref="Playable"/> of the pre-update <see cref="UpdatableListPlayable"/>.
  137. /// </summary>
  138. /// <remarks>
  139. /// This is the final <see cref="Playable"/> connected to the output of the <see cref="PlayableGraph"/>.
  140. /// </remarks>
  141. internal Playable _PreUpdatePlayable;// Internal for AnimancerLayerList.
  142. /************************************************************************************************************************/
  143. /// <inheritdoc/>
  144. public override AnimancerLayer Layer
  145. => null;
  146. /// <inheritdoc/>
  147. public override int ChildCount
  148. => _Layers.Count;
  149. /// <inheritdoc/>
  150. protected internal override AnimancerNode GetChildNode(int index)
  151. => _Layers[index];
  152. /************************************************************************************************************************/
  153. private AnimancerLayerList _Layers;
  154. /// <summary>The <see cref="AnimancerLayer"/>s which each manage their own set of animations.</summary>
  155. /// <remarks>
  156. /// <strong>Documentation:</strong>
  157. /// <see href="https://kybernetik.com.au/animancer/docs/manual/blending/layers">
  158. /// Layers</see>
  159. /// </remarks>
  160. public AnimancerLayerList Layers
  161. {
  162. get => _Layers;
  163. set
  164. {
  165. #if UNITY_ASSERTIONS
  166. if (value.Graph != this)
  167. throw new ArgumentException(
  168. $"{nameof(AnimancerGraph)}.{nameof(AnimancerLayerList)}.{nameof(AnimancerLayerList.Graph)}" +
  169. $" mismatch: cannot use a list in an {nameof(AnimancerGraph)} that is not its" +
  170. $" {nameof(AnimancerLayerList.Graph)}");
  171. #endif
  172. _Playable = value.Playable;
  173. if (_Layers != null && _Playable.IsValid())
  174. {
  175. var count = _Layers.Count;
  176. for (int i = 0; i < count; i++)
  177. {
  178. var layer = _Playable.GetInput(i);
  179. if (layer.IsValid())
  180. {
  181. _Playable.DisconnectInput(i);
  182. _PlayableGraph.Connect(_Playable, layer, i, _Layers[i].Weight);
  183. }
  184. }
  185. _PreUpdatePlayable.DisconnectInput(0);
  186. // Don't destroy the old Playable since it could still be reused later.
  187. }
  188. _Layers = value;
  189. _PlayableGraph.Connect(_PreUpdatePlayable, _Playable, 0, 1);
  190. }
  191. }
  192. /************************************************************************************************************************/
  193. /// <summary>The <see cref="AnimancerState"/>s managed by this graph.</summary>
  194. /// <remarks>
  195. /// <strong>Documentation:</strong>
  196. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing/states">
  197. /// States</see>
  198. /// </remarks>
  199. public readonly AnimancerStateDictionary States;
  200. /************************************************************************************************************************/
  201. private ParameterDictionary _Parameters;
  202. /// <summary>Dynamic parameters which anything can get or set.</summary>
  203. public ParameterDictionary Parameters
  204. => _Parameters ??= new();
  205. /// <summary>Has the <see cref="Parameters"/> dictionary been initialized?</summary>
  206. public bool HasParameters
  207. => _Parameters != null;
  208. /************************************************************************************************************************/
  209. /// <summary>[Internal] The backing field of <see cref="Events"/>.</summary>
  210. internal NamedEventDictionary _Events;
  211. /// <summary>A dictionary of callbacks to be triggered by any event with a matching name.</summary>
  212. public NamedEventDictionary Events
  213. => _Events ??= new();
  214. /// <summary>Has the <see cref="Events"/> dictionary been initialized?</summary>
  215. public bool HasEvents
  216. => _Events != null;
  217. /************************************************************************************************************************/
  218. /// <summary>[Pro-Only] The optional <see cref="TransitionLibrary"/> this graph can use.</summary>
  219. public TransitionLibrary Transitions { get; set; }
  220. /************************************************************************************************************************/
  221. private readonly IUpdatable.List _PreUpdatables = new();
  222. private readonly IUpdatable.List _PostUpdatables = new();
  223. /// <summary>Objects to be updated before time advances.</summary>
  224. public IReadOnlyIndexedList<IUpdatable> PreUpdatables
  225. => _PreUpdatables;
  226. /// <summary>Objects to be updated after time advances.</summary>
  227. public IReadOnlyIndexedList<IUpdatable> PostUpdatables
  228. => _PostUpdatables;
  229. /************************************************************************************************************************/
  230. /// <summary>The component that is playing this <see cref="AnimancerGraph"/>.</summary>
  231. public IAnimancerComponent Component { get; private set; }
  232. /************************************************************************************************************************/
  233. /// <summary>Determines what time source is used to update the <see cref="UnityEngine.Playables.PlayableGraph"/>.</summary>
  234. public DirectorUpdateMode UpdateMode
  235. {
  236. get => _PlayableGraph.GetTimeUpdateMode();
  237. set => _PlayableGraph.SetTimeUpdateMode(value);
  238. }
  239. /************************************************************************************************************************/
  240. private bool _KeepChildrenConnected;
  241. /// <summary>
  242. /// Should playables stay connected to the graph at all times?
  243. /// Otherwise they will be disconnected when their <see cref="AnimancerNode.Weight"/> is 0.
  244. /// </summary>
  245. ///
  246. /// <remarks>
  247. /// This value defaults to <c>false</c> and can be set by <see cref="SetKeepChildrenConnected"/>.
  248. /// <para></para>
  249. /// <strong>Example:</strong><code>
  250. /// [SerializeField]
  251. /// private AnimancerComponent _Animancer;
  252. ///
  253. /// public void Initialize()
  254. /// {
  255. /// _Animancer.Graph.SetKeepChildrenConnected(true);
  256. /// }
  257. /// </code></remarks>
  258. public override bool KeepChildrenConnected
  259. => _KeepChildrenConnected;
  260. /// <summary>Sets <see cref="KeepChildrenConnected"/>.</summary>
  261. /// <remarks>This method exists because the <see cref="KeepChildrenConnected"/> override can't add a setter.</remarks>
  262. public void SetKeepChildrenConnected(bool value)
  263. {
  264. if (_KeepChildrenConnected == value)
  265. return;
  266. _KeepChildrenConnected = value;
  267. if (value)
  268. {
  269. for (int i = _Layers.Count - 1; i >= 0; i--)
  270. _Layers.GetLayer(i).ConnectAllStates();
  271. }
  272. else
  273. {
  274. for (int i = _Layers.Count - 1; i >= 0; i--)
  275. _Layers.GetLayer(i).DisconnectInactiveStates();
  276. }
  277. }
  278. /************************************************************************************************************************/
  279. private bool _SkipFirstFade;
  280. /// <summary>
  281. /// Normally the first animation on the Base Layer should not fade in because there is nothing fading out. But
  282. /// sometimes that is undesirable, such as if the <see cref="Animator.runtimeAnimatorController"/> is assigned
  283. /// since Animancer can blend with that.
  284. /// </summary>
  285. /// <remarks>
  286. /// Setting this value to false ensures that the <see cref="AnimationLayerMixerPlayable"/> has at least two
  287. /// inputs because it ignores the <see cref="AnimancerNode.Weight"/> of the layer when there is only one.
  288. /// </remarks>
  289. public bool SkipFirstFade
  290. {
  291. get => _SkipFirstFade;
  292. set
  293. {
  294. _SkipFirstFade = value;
  295. if (!value && _Layers.Count < 2)
  296. {
  297. _Layers.Count = 1;
  298. Playable.SetInputCount(2);
  299. }
  300. }
  301. }
  302. /************************************************************************************************************************/
  303. #endregion
  304. /************************************************************************************************************************/
  305. #region Initialization
  306. /************************************************************************************************************************/
  307. /// <summary>
  308. /// Creates an <see cref="AnimancerGraph"/> in an existing
  309. /// <see cref="UnityEngine.Playables.PlayableGraph"/>.
  310. /// </summary>
  311. public AnimancerGraph(
  312. PlayableGraph graph,
  313. TransitionLibrary transitions = null)
  314. {
  315. _PlayableGraph = graph;
  316. Transitions = transitions;
  317. Graph = this;
  318. _PreUpdatePlayable = UpdatableListPlayable.Create(this, 2, _PreUpdatables);
  319. var postUpdate = UpdatableListPlayable.Create(this, 0, _PostUpdatables);
  320. _PlayableGraph.Connect(postUpdate, 0, _PreUpdatePlayable, 1);
  321. States = new(this);
  322. #if UNITY_EDITOR
  323. Editor.AnimancerGraphCleanup.AddGraph(this);
  324. #endif
  325. }
  326. /// <summary>
  327. /// Creates an <see cref="AnimancerGraph"/> in a new
  328. /// <see cref="UnityEngine.Playables.PlayableGraph"/>.
  329. /// </summary>
  330. public AnimancerGraph(TransitionLibrary transitions = null)
  331. : this(CreateGraph(), transitions)
  332. {
  333. }
  334. /************************************************************************************************************************/
  335. /// <summary>
  336. /// Creates a new empty <see cref="UnityEngine.Playables.PlayableGraph"/>
  337. /// and consumes the name set by <see cref="SetNextGraphName"/> if it was called.
  338. /// </summary>
  339. /// <remarks>
  340. /// The caller is responsible for calling <see cref="Destroy()"/> on the returned object,
  341. /// except in Edit Mode where it will be called automatically.
  342. /// </remarks>
  343. public static PlayableGraph CreateGraph()
  344. {
  345. #if UNITY_EDITOR
  346. var name = _NextGraphName;
  347. _NextGraphName = null;
  348. return name != null
  349. ? PlayableGraph.Create(name)
  350. : PlayableGraph.Create();
  351. #else
  352. return PlayableGraph.Create();
  353. #endif
  354. }
  355. /************************************************************************************************************************/
  356. #if UNITY_EDITOR
  357. private static string _NextGraphName;
  358. #endif
  359. /// <summary>[Editor-Conditional]
  360. /// Sets the display name for the next instance to give its <see cref="UnityEngine.Playables.PlayableGraph"/>.
  361. /// </summary>
  362. [System.Diagnostics.Conditional(Strings.UnityEditor)]
  363. public static void SetNextGraphName(string name)
  364. {
  365. #if UNITY_EDITOR
  366. _NextGraphName = name;
  367. #endif
  368. }
  369. /************************************************************************************************************************/
  370. #if UNITY_EDITOR
  371. /// <summary>[Editor-Only] Returns "Component Name (Animancer)".</summary>
  372. public override string ToString()
  373. => !Component.IsNullOrDestroyed()
  374. ? $"{Component.gameObject.name} ({nameof(Animancer)})"
  375. : _PlayableGraph.IsValid()
  376. ? _PlayableGraph.GetEditorName()
  377. : $"Destroyed ({nameof(Animancer)})";
  378. #endif
  379. /************************************************************************************************************************/
  380. private PlayableOutput _Output;
  381. /// <summary>The <see cref="PlayableOutput"/> connected to this <see cref="AnimancerGraph"/>.</summary>
  382. public PlayableOutput Output
  383. {
  384. get
  385. {
  386. if (!_Output.IsOutputValid())
  387. _Output = _PlayableGraph.FindOutput(_PreUpdatePlayable);
  388. return _Output;
  389. }
  390. }
  391. /************************************************************************************************************************/
  392. /// <summary>
  393. /// Plays this graph on the <see cref="IAnimancerComponent.Animator"/>
  394. /// and sets the <see cref="Component"/>.
  395. /// </summary>
  396. public void CreateOutput(IAnimancerComponent animancer)
  397. => CreateOutput(animancer.Animator, animancer);
  398. /// <summary>Plays this playable on the specified `animator` and sets the <see cref="Component"/>.</summary>
  399. public void CreateOutput(Animator animator, IAnimancerComponent animancer)
  400. {
  401. #if UNITY_ASSERTIONS
  402. if (animator == null)
  403. throw new ArgumentNullException(nameof(animator),
  404. $"An {nameof(Animator)} component is required to play animations.");
  405. #if UNITY_EDITOR
  406. if (UnityEditor.EditorUtility.IsPersistent(animator))
  407. throw new ArgumentException(
  408. $"The specified {nameof(Animator)} component is a prefab which means it cannot play animations.",
  409. nameof(animator));
  410. #endif
  411. if (animancer != null)
  412. {
  413. Debug.Assert(animancer.IsGraphInitialized && animancer.Graph == this,
  414. $"{nameof(CreateOutput)} was called on an {nameof(AnimancerGraph)} which does not match the" +
  415. $" {nameof(IAnimancerComponent)}.{nameof(IAnimancerComponent.Graph)}.");
  416. Debug.Assert(animator == animancer.Animator,
  417. $"{nameof(CreateOutput)} was called with an {nameof(Animator)} which does not match the" +
  418. $" {nameof(IAnimancerComponent)}.{nameof(IAnimancerComponent.Animator)}.");
  419. #if UNITY_EDITOR
  420. CaptureInactiveInitializationStackTrace(animancer);
  421. #endif
  422. }
  423. if (Output.IsOutputValid())
  424. {
  425. Debug.LogWarning(
  426. $"A {nameof(PlayableGraph)} output is already connected to the {nameof(AnimancerGraph)}." +
  427. $" The old output should be destroyed using `animancerComponent.Graph.DestroyOutput();`" +
  428. $" before calling {nameof(CreateOutput)}.", animator);
  429. }
  430. #endif
  431. Layers ??= new AnimancerLayerMixerList(this);
  432. Component = animancer;
  433. // Generic Rigs can blend with an underlying Animator Controller but Humanoids can't.
  434. SkipFirstFade = animator.isHuman || animator.runtimeAnimatorController == null;
  435. AnimancerEvent.Invoker.Initialize(animator.updateMode);
  436. #pragma warning disable CS0618 // Type or member is obsolete.
  437. // Unity 2022 marked this method as [Obsolete] even though it's the only way to use Animate Physics mode.
  438. AnimationPlayableUtilities.Play(animator, _PreUpdatePlayable, _PlayableGraph);
  439. #pragma warning restore CS0618 // Type or member is obsolete.
  440. _IsGraphPlaying = true;
  441. }
  442. /************************************************************************************************************************/
  443. /// <summary>[Pro-Only]
  444. /// Inserts a `playable` after the root of the <see cref="PlayableGraph"/>
  445. /// so that it can modify the final output.
  446. /// </summary>
  447. /// <remarks>It can be removed using <see cref="AnimancerUtilities.RemovePlayable"/>.</remarks>
  448. public void InsertOutputPlayable(Playable playable)
  449. {
  450. var output = Output;
  451. _PlayableGraph.Connect(playable, output.GetSourcePlayable(), 0, 1);
  452. output.SetSourcePlayable(playable);
  453. }
  454. /// <summary>[Pro-Only]
  455. /// Inserts an animation job after the root of the <see cref="PlayableGraph"/>
  456. /// so that it can modify the final output.
  457. /// </summary>
  458. /// <remarks>
  459. /// It can can be removed by passing the returned value into <see cref="AnimancerUtilities.RemovePlayable"/>.
  460. /// </remarks>
  461. public AnimationScriptPlayable InsertOutputJob<T>(T data)
  462. where T : struct, IAnimationJob
  463. {
  464. var playable = AnimationScriptPlayable.Create(_PlayableGraph, data, 1);
  465. InsertOutputPlayable(playable);
  466. return playable;
  467. }
  468. /************************************************************************************************************************/
  469. /// <inheritdoc/>
  470. void ICopyable<AnimancerGraph>.CopyFrom(AnimancerGraph copyFrom, CloneContext context)
  471. => CopyFrom(copyFrom, context);
  472. /// <summary>Copies all layers and states from `copyFrom` into this graph.</summary>
  473. public void CopyFrom(AnimancerGraph copyFrom, bool includeInactiveStates = false)
  474. {
  475. var context = CloneContext.Pool.Instance.Acquire();
  476. CopyFrom(copyFrom, context, includeInactiveStates);
  477. CloneContext.Pool.Instance.Release(context);
  478. }
  479. /// <summary>Copies all layers and states from `copyFrom` into this graph.</summary>
  480. public void CopyFrom(AnimancerGraph copyFrom, CloneContext context, bool includeInactiveStates = false)
  481. {
  482. if (copyFrom == this)
  483. return;
  484. var wouldCloneUpdatables = context.WillCloneUpdatables;
  485. context.WillCloneUpdatables = true;
  486. Speed = copyFrom.Speed;
  487. SetKeepChildrenConnected(copyFrom.KeepChildrenConnected);
  488. SkipFirstFade = copyFrom.SkipFirstFade;
  489. IsGraphPlaying = copyFrom.IsGraphPlaying;
  490. FrameID = copyFrom.FrameID;
  491. context[copyFrom] = this;
  492. // Register states in the context.
  493. foreach (var copyFromState in copyFrom.States)
  494. if (States.TryGet(copyFromState.Key, out var copyToState))
  495. context[copyFromState] = copyToState;
  496. var layerCount = copyFrom._Layers.Count;
  497. // Register layers in the context.
  498. for (int i = 0; i < layerCount; i++)
  499. {
  500. var copyFromLayer = copyFrom._Layers[i];
  501. var copyToLayer = _Layers[i];
  502. context[copyFromLayer] = copyToLayer;
  503. }
  504. // Copy existing layers.
  505. for (int i = 0; i < layerCount; i++)
  506. {
  507. var copyFromLayer = copyFrom._Layers[i];
  508. var copyToLayer = _Layers[i];
  509. copyToLayer.CopyFrom(copyFromLayer, context);
  510. copyToLayer.CopyStatesFrom(copyFromLayer, context, includeInactiveStates);
  511. }
  512. // Stop any extra layers.
  513. for (int i = layerCount; i < _Layers.Count; i++)
  514. _Layers[i].Stop();
  515. _PreUpdatables.CloneFrom(copyFrom._PreUpdatables, context);
  516. _PostUpdatables.CloneFrom(copyFrom._PostUpdatables, context);
  517. context.WillCloneUpdatables = wouldCloneUpdatables;
  518. }
  519. /************************************************************************************************************************/
  520. #endregion
  521. /************************************************************************************************************************/
  522. #region Cleanup
  523. /************************************************************************************************************************/
  524. /// <summary>Is this <see cref="AnimancerGraph"/> currently usable (not destroyed)?</summary>
  525. /// <remarks>Calls <see cref="DisposeAll"/> if the <see cref="PlayableGraph"/> was already destroyed.</remarks>
  526. public bool IsValidOrDispose()
  527. {
  528. if (_PlayableGraph.IsValid())
  529. return true;
  530. DisposeAll();
  531. return false;
  532. }
  533. /************************************************************************************************************************/
  534. /// <summary>Destroys the <see cref="PlayableGraph"/> and everything in it. This operation cannot be undone.</summary>
  535. /// <remarks>If the <see cref="PlayableGraph"/> is owned by another system, use <see cref="DestroyPlayables"/> instead.</remarks>
  536. public void Destroy()
  537. {
  538. OnGraphDestroyed();
  539. if (_PlayableGraph.IsValid())
  540. {
  541. _PlayableGraph.Destroy();
  542. #if UNITY_EDITOR
  543. Editor.AnimancerGraphCleanup.RemoveGraph(this);
  544. #endif
  545. }
  546. }
  547. /// <summary>
  548. /// Destroys this <see cref="AnimancerGraph"/> and everything inside it (layers, states, etc.)
  549. /// without destroying the <see cref="PlayableGraph"/>.
  550. /// </summary>
  551. /// <remarks>
  552. /// This can be useful if Animancer was initialized inside a <see cref="UnityEngine.Playables.PlayableGraph"/> owned by another
  553. /// system such as Unity's Animation Rigging package. Otherwise, use <see cref="Destroy"/>.
  554. /// </remarks>
  555. public void DestroyPlayables()
  556. {
  557. OnGraphDestroyed();
  558. if (_PlayableGraph.IsValid())
  559. _PlayableGraph.DestroySubgraph(_PreUpdatePlayable);
  560. }
  561. /************************************************************************************************************************/
  562. /// <summary>Destroys the <see cref="Output"/> if it exists and returns true if successful.</summary>
  563. public bool DestroyOutput()
  564. {
  565. var output = Output;
  566. if (!output.IsOutputValid())
  567. return false;
  568. _PlayableGraph.DestroyOutput(output);
  569. return true;
  570. }
  571. /************************************************************************************************************************/
  572. /// <summary>Calls <see cref="OnGraphDestroyed"/> in case <see cref="Destroy"/> wasn't called.</summary>
  573. ~AnimancerGraph()
  574. => OnGraphDestroyed();
  575. /// <summary>Calls <see cref="AnimancerLayer.OnGraphDestroyed"/> on all layers.</summary>
  576. private void OnGraphDestroyed()
  577. {
  578. if (_Layers != null)
  579. {
  580. var layerCount = _Layers.Count;
  581. for (int i = 0; i < layerCount; i++)
  582. _Layers[i].OnGraphDestroyed();
  583. }
  584. DisposeAll();
  585. }
  586. /************************************************************************************************************************/
  587. private List<IDisposable> _Disposables;
  588. /// <summary>A list of objects that need to be disposed when this <see cref="AnimancerGraph"/> is destroyed.</summary>
  589. /// <remarks>This list is primarily used to dispose native arrays used by Animation Jobs.</remarks>
  590. public List<IDisposable> Disposables
  591. => _Disposables ??= new();
  592. /************************************************************************************************************************/
  593. /// <summary>Calls <see cref="IDisposable.Dispose"/> on all <see cref="Disposables"/> and discards them.</summary>
  594. private void DisposeAll()
  595. {
  596. if (_Disposables == null ||
  597. _Disposables.Count == 0)
  598. return;
  599. GC.SuppressFinalize(this);
  600. var previous = Current;
  601. Current = this;
  602. var i = _Disposables.Count;
  603. DisposeNext:
  604. try
  605. {
  606. while (--i >= 0)
  607. {
  608. _Disposables[i].Dispose();
  609. }
  610. _Disposables.Clear();
  611. }
  612. catch (Exception exception)
  613. {
  614. Debug.LogException(exception, Component as Object);
  615. goto DisposeNext;
  616. }
  617. Current = previous;
  618. }
  619. /************************************************************************************************************************/
  620. #region Inverse Kinematics
  621. // These fields are stored here but accessed via the LayerList.
  622. /************************************************************************************************************************/
  623. private bool _ApplyAnimatorIK;
  624. /// <inheritdoc/>
  625. public override bool ApplyAnimatorIK
  626. {
  627. get => _ApplyAnimatorIK;
  628. set
  629. {
  630. _ApplyAnimatorIK = value;
  631. for (int i = _Layers.Count - 1; i >= 0; i--)
  632. _Layers.GetLayer(i).ApplyAnimatorIK = value;
  633. }
  634. }
  635. /************************************************************************************************************************/
  636. private bool _ApplyFootIK;
  637. /// <inheritdoc/>
  638. public override bool ApplyFootIK
  639. {
  640. get => _ApplyFootIK;
  641. set
  642. {
  643. _ApplyFootIK = value;
  644. for (int i = _Layers.Count - 1; i >= 0; i--)
  645. _Layers.GetLayer(i).ApplyFootIK = value;
  646. }
  647. }
  648. /************************************************************************************************************************/
  649. #endregion
  650. /************************************************************************************************************************/
  651. #endregion
  652. /************************************************************************************************************************/
  653. #region Playing
  654. /************************************************************************************************************************/
  655. /// <summary>Calls <see cref="IAnimancerComponent.GetKey"/> on the <see cref="Component"/>.</summary>
  656. /// <remarks>If the <see cref="Component"/> is null, this method returns the `clip` itself.</remarks>
  657. public object GetKey(AnimationClip clip)
  658. => Component != null
  659. ? Component.GetKey(clip)
  660. : clip;
  661. /************************************************************************************************************************/
  662. /// <summary>
  663. /// Gets the state registered with the <see cref="IHasKey.Key"/>,
  664. /// stops and rewinds it to the start, then returns it.
  665. /// </summary>
  666. /// <remarks>Note that playing something new will automatically stop the old animation.</remarks>
  667. public AnimancerState Stop(IHasKey hasKey)
  668. => Stop(hasKey.Key);
  669. /// <summary>
  670. /// Calls <see cref="AnimancerNode.Stop"/> on the state registered with the `key`
  671. /// to stop it from playing and rewind it to the start.
  672. /// </summary>
  673. /// <remarks>Note that playing something new will automatically stop the old animation.</remarks>
  674. public AnimancerState Stop(object key)
  675. {
  676. if (States.TryGet(key, out var state))
  677. state.Stop();
  678. return state;
  679. }
  680. /// <summary>
  681. /// Calls <see cref="AnimancerNode.Stop"/> on all animations
  682. /// to stop them from playing and rewind them to the start.
  683. /// </summary>
  684. /// <remarks>Note that playing something new will automatically stop the old animation.</remarks>
  685. public void Stop()
  686. {
  687. for (int i = _Layers.Count - 1; i >= 0; i--)
  688. _Layers.GetLayer(i).Stop();
  689. }
  690. /************************************************************************************************************************/
  691. /// <summary>Is a state registered with the <see cref="IHasKey.Key"/> and currently playing?</summary>
  692. public bool IsPlaying(IHasKey hasKey)
  693. => IsPlaying(hasKey.Key);
  694. /// <summary>Is a state registered with the `key` and currently playing?</summary>
  695. public bool IsPlaying(object key)
  696. => States.TryGet(key, out var state)
  697. && state.IsPlaying;
  698. /// <summary>Is least one animation being played?</summary>
  699. public bool IsPlaying()
  700. {
  701. if (!_IsGraphPlaying)
  702. return false;
  703. for (int i = _Layers.Count - 1; i >= 0; i--)
  704. if (_Layers.GetLayer(i).IsAnyStatePlaying())
  705. return true;
  706. return false;
  707. }
  708. /************************************************************************************************************************/
  709. /// <summary>Is the `clip` currently being played by at least one state in the specified layer?</summary>
  710. /// <remarks>
  711. /// This method is inefficient because it searches through every state,
  712. /// unlike <see cref="IsPlaying(object)"/> which only checks the state registered using the specified key.
  713. /// </remarks>
  714. public bool IsPlayingClip(AnimationClip clip)
  715. {
  716. if (!_IsGraphPlaying)
  717. return false;
  718. for (int i = _Layers.Count - 1; i >= 0; i--)
  719. if (_Layers.GetLayer(i).IsPlayingClip(clip))
  720. return true;
  721. return false;
  722. }
  723. /************************************************************************************************************************/
  724. /// <summary>Calculates the total <see cref="AnimancerNode.Weight"/> of all states in all layers.</summary>
  725. public float GetTotalWeight()
  726. {
  727. float weight = 0;
  728. for (int i = _Layers.Count - 1; i >= 0; i--)
  729. weight += _Layers.GetLayer(i).GetTotalChildWeight();
  730. return weight;
  731. }
  732. /************************************************************************************************************************/
  733. /// <summary>[<see cref="IAnimationClipCollection"/>] Gathers all the animations in all layers.</summary>
  734. public void GatherAnimationClips(ICollection<AnimationClip> clips)
  735. => _Layers.GatherAnimationClips(clips);
  736. /************************************************************************************************************************/
  737. // IEnumerator for yielding in a coroutine to wait until animations have stopped.
  738. /************************************************************************************************************************/
  739. /// <summary>Are any animations playing?</summary>
  740. /// <remarks>This allows this object to be used as a custom yield instruction.</remarks>
  741. bool IEnumerator.MoveNext()
  742. {
  743. for (int i = _Layers.Count - 1; i >= 0; i--)
  744. if (_Layers.GetLayer(i).IsPlayingAndNotEnding())
  745. return true;
  746. return false;
  747. }
  748. /// <summary>Returns null.</summary>
  749. object IEnumerator.Current => null;
  750. /// <summary>Does nothing.</summary>
  751. void IEnumerator.Reset() { }
  752. /************************************************************************************************************************/
  753. #region Key Error Methods
  754. #if UNITY_EDITOR
  755. /************************************************************************************************************************/
  756. // These are overloads of other methods that take a System.Object key to ensure the user doesn't try to use an
  757. // AnimancerState as a key, since the whole point of a key is to identify a state in the first place.
  758. /************************************************************************************************************************/
  759. /// <summary>[Warning]
  760. /// You should not use an <see cref="AnimancerState"/> as a key.
  761. /// Just call <see cref="AnimancerNode.Stop"/>.
  762. /// </summary>
  763. [Obsolete("You should not use an AnimancerState as a key. Just call AnimancerState.Stop().", true)]
  764. public AnimancerState Stop(AnimancerState key)
  765. {
  766. key.Stop();
  767. return key;
  768. }
  769. /// <summary>[Warning]
  770. /// You should not use an <see cref="AnimancerState"/> as a key.
  771. /// Just check <see cref="AnimancerState.IsPlaying"/>.
  772. /// </summary>
  773. [Obsolete("You should not use an AnimancerState as a key. Just check AnimancerState.IsPlaying.", true)]
  774. public bool IsPlaying(AnimancerState key) => key.IsPlaying;
  775. /************************************************************************************************************************/
  776. #endif
  777. #endregion
  778. /************************************************************************************************************************/
  779. #endregion
  780. /************************************************************************************************************************/
  781. #region Evaluation
  782. /************************************************************************************************************************/
  783. private bool _IsGraphPlaying = true;
  784. /// <summary>Indicates whether the <see cref="UnityEngine.Playables.PlayableGraph"/> is currently playing.</summary>
  785. public bool IsGraphPlaying
  786. {
  787. get => _IsGraphPlaying;
  788. set
  789. {
  790. if (value)
  791. UnpauseGraph();
  792. else
  793. PauseGraph();
  794. }
  795. }
  796. /// <summary>
  797. /// Resumes playing the <see cref="UnityEngine.Playables.PlayableGraph"/> if <see cref="PauseGraph"/> was called previously.
  798. /// </summary>
  799. public void UnpauseGraph()
  800. {
  801. if (!_IsGraphPlaying)
  802. {
  803. _PlayableGraph.Play();
  804. _IsGraphPlaying = true;
  805. #if UNITY_EDITOR
  806. // In Edit Mode, unpausing the graph doesn't work properly unless we force it to change.
  807. if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
  808. Evaluate(0.00001f);
  809. #endif
  810. }
  811. }
  812. /// <summary>
  813. /// Freezes the <see cref="UnityEngine.Playables.PlayableGraph"/> at its current state.
  814. /// <para></para>
  815. /// If you call this method, you are responsible for calling <see cref="UnpauseGraph"/> to resume playing.
  816. /// </summary>
  817. public void PauseGraph()
  818. {
  819. if (_IsGraphPlaying)
  820. {
  821. _PlayableGraph.Stop();
  822. _IsGraphPlaying = false;
  823. }
  824. }
  825. /************************************************************************************************************************/
  826. /// <summary>
  827. /// Evaluates all of the currently playing animations to apply their states to the animated objects.
  828. /// </summary>
  829. public void Evaluate()
  830. {
  831. _PlayableGraph.Evaluate();
  832. AnimancerEvent.Invoker.InvokeAllAndClear();
  833. }
  834. /// <summary>
  835. /// Advances all currently playing animations by the specified amount of time (in seconds) and evaluates the
  836. /// graph to apply their states to the animated objects.
  837. /// </summary>
  838. public void Evaluate(float deltaTime)
  839. {
  840. _PlayableGraph.Evaluate(deltaTime);
  841. AnimancerEvent.Invoker.InvokeAllAndClear();
  842. }
  843. /************************************************************************************************************************/
  844. #endregion
  845. /************************************************************************************************************************/
  846. #region Description
  847. /************************************************************************************************************************/
  848. /// <inheritdoc/>
  849. public void AppendDescription(
  850. StringBuilder text,
  851. string separator = "\n")
  852. {
  853. text.AppendField(null, nameof(AnimancerGraph), Component);
  854. separator += Strings.Indent;
  855. var layerDetailsSeparator = separator + Strings.Indent;
  856. text.AppendField(separator, "Layer Count", _Layers.Count);
  857. AnimancerNode.AppendIKDetails(text, separator, this);
  858. var count = _Layers.Count;
  859. for (int i = 0; i < count; i++)
  860. {
  861. text.Append(separator);
  862. _Layers[i].AppendDescription(text, layerDetailsSeparator);
  863. }
  864. States.AppendDescriptionOrOrphans(text, separator);
  865. text.AppendLine();
  866. AppendInternalDetails(text, Strings.Indent, separator + Strings.Indent);
  867. AppendGraphDetails(text, separator, Strings.Indent);
  868. }
  869. /************************************************************************************************************************/
  870. /// <summary>Appends all registered <see cref="IUpdatable"/>s and <see cref="IDisposable"/>s.</summary>
  871. public void AppendInternalDetails(
  872. StringBuilder text,
  873. string sectionPrefix,
  874. string itemPrefix)
  875. {
  876. AppendAll(text, sectionPrefix, itemPrefix, _PreUpdatables, "Pre Updatables");
  877. text.AppendLine();
  878. AppendAll(text, sectionPrefix, itemPrefix, _PostUpdatables, "Post Updatables");
  879. text.AppendLine();
  880. AppendAll(text, sectionPrefix, itemPrefix, _Disposables, "Disposables");
  881. }
  882. /************************************************************************************************************************/
  883. /// <summary>Appends everything in the `collection`.</summary>
  884. private static void AppendAll(
  885. StringBuilder text,
  886. string sectionPrefix,
  887. string itemPrefix,
  888. ICollection collection,
  889. string name)
  890. {
  891. var count = collection != null
  892. ? collection.Count
  893. : 0;
  894. text.AppendField(sectionPrefix, name, count);
  895. if (collection == null)
  896. return;
  897. var separator = $"{itemPrefix}{Strings.Indent}";
  898. foreach (var item in collection)
  899. {
  900. text.Append(itemPrefix);
  901. if (item is AnimancerNode node)
  902. text.Append(node.GetPath());
  903. else
  904. text.AppendDescription(item, separator);
  905. }
  906. }
  907. /************************************************************************************************************************/
  908. private const string NoPlayable = "No Playable";
  909. /// <summary>Appends the structure of the <see cref="PlayableGraph"/>.</summary>
  910. public void AppendGraphDetails(
  911. StringBuilder text,
  912. string itemPrefix = "\n",
  913. string indent = Strings.Indent)
  914. {
  915. var indentedPrefix = itemPrefix + indent;
  916. var outputCount = _PlayableGraph.GetOutputCount();
  917. for (int i = 0; i < outputCount; i++)
  918. {
  919. var output = _PlayableGraph.GetOutput(i);
  920. text.Append(itemPrefix)
  921. .Append(output.GetPlayableOutputType().Name);
  922. #if UNITY_EDITOR
  923. text.Append(" \"")
  924. .Append(UnityEditor.Playables.PlayableOutputEditorExtensions.GetEditorName(output))
  925. .Append('"');
  926. #endif
  927. text.Append(": ");
  928. var playable = output.GetSourcePlayable();
  929. AppendGraphDetails(text, playable, indentedPrefix, indent);
  930. }
  931. }
  932. /// <summary>Appends the structure of the <see cref="PlayableGraph"/>.</summary>
  933. private void AppendGraphDetails(
  934. StringBuilder text,
  935. Playable playable,
  936. string itemPrefix = "\n",
  937. string indent = Strings.Indent)
  938. {
  939. text.Append(itemPrefix);
  940. if (!playable.IsValid())
  941. {
  942. text.Append(NoPlayable);
  943. return;
  944. }
  945. text.Append(playable.GetPlayableType().Name);
  946. var inputCount = playable.GetInputCount();
  947. if (inputCount == 0)
  948. return;
  949. itemPrefix += indent;
  950. for (int i = 0; i < inputCount; i++)
  951. {
  952. var child = playable.GetInput(i);
  953. AppendGraphDetails(text, child, itemPrefix, indent);
  954. }
  955. }
  956. /************************************************************************************************************************/
  957. #endregion
  958. /************************************************************************************************************************/
  959. #region Update
  960. /************************************************************************************************************************/
  961. /// <summary>[Pro-Only]
  962. /// Adds the `updatable` to the list that need to be updated before the playables if it wasn't there already.
  963. /// </summary>
  964. /// <remarks>
  965. /// The <see cref="Animator.updateMode"/> determines the update rate.
  966. /// <para></para>
  967. /// This method is safe to call at any time, even during an update.
  968. /// <para></para>
  969. /// The execution order is non-deterministic. Specifically, the most recently added will be updated first and
  970. /// <see cref="CancelPreUpdate"/> will change the order by swapping the last one into the place of the removed
  971. /// object.
  972. /// </remarks>
  973. public void RequirePreUpdate(IUpdatable updatable)
  974. {
  975. #if UNITY_ASSERTIONS
  976. if (updatable is AnimancerNode node)
  977. {
  978. Validate.AssertPlayable(node);
  979. Validate.AssertGraph(node, this);
  980. }
  981. #endif
  982. _PreUpdatables.Add(updatable);
  983. }
  984. /************************************************************************************************************************/
  985. /// <summary>[Pro-Only]
  986. /// Adds the `updatable` to the list that need to be updated after the playables if it wasn't there already.
  987. /// </summary>
  988. /// <remarks>
  989. /// The <see cref="Animator.updateMode"/> determines the update rate.
  990. /// <para></para>
  991. /// This method is safe to call at any time, even during an update.
  992. /// <para></para>
  993. /// The execution order is non-deterministic.
  994. /// Specifically, the most recently added will be updated first and <see cref="CancelPostUpdate"/>
  995. /// will change the order by swapping the last one into the place of the removed object.
  996. /// </remarks>
  997. public void RequirePostUpdate(IUpdatable updatable)
  998. {
  999. #if UNITY_ASSERTIONS
  1000. if (updatable is AnimancerNode node)
  1001. {
  1002. Validate.AssertPlayable(node);
  1003. Validate.AssertGraph(node, this);
  1004. }
  1005. #endif
  1006. _PostUpdatables.Add(updatable);
  1007. }
  1008. /************************************************************************************************************************/
  1009. /// <summary>Removes the `updatable` from the list of objects that need to be updated before the playables.</summary>
  1010. /// <remarks>
  1011. /// This method is safe to call at any time, even during an update.
  1012. /// <para></para>
  1013. /// The last element is swapped into the place of the one being removed so that the rest of them don't need to
  1014. /// be moved down one place to fill the gap. This is more efficient, but means that the update order can change.
  1015. /// </remarks>
  1016. public void CancelPreUpdate(IUpdatable updatable)
  1017. => _PreUpdatables.Remove(updatable);
  1018. /// <summary>Removes the `updatable` from the list of objects that need to be updated after the playebles.</summary>
  1019. /// <remarks>
  1020. /// This method is safe to call at any time, even during an update.
  1021. /// <para></para>
  1022. /// The last element is swapped into the place of the one being removed so that the rest of them don't need to
  1023. /// be moved down one place to fill the gap. This is more efficient, but means that the update order can change.
  1024. /// </remarks>
  1025. public void CancelPostUpdate(IUpdatable updatable)
  1026. => _PostUpdatables.Remove(updatable);
  1027. /************************************************************************************************************************/
  1028. /// <summary>The graph currently being executed.</summary>
  1029. /// <remarks>
  1030. /// During <see cref="AnimancerEvent"/> invocations,
  1031. /// use <c>AnimancerEvent.Current.State.Graph</c> instead.
  1032. /// </remarks>
  1033. public static AnimancerGraph Current { get; private set; }
  1034. /// <summary>The current <see cref="FrameData.deltaTime"/>.</summary>
  1035. /// <remarks>After each update, this property will be left at its most recent value.</remarks>
  1036. public static float DeltaTime { get; private set; }
  1037. /// <summary>The current <see cref="FrameData.frameId"/>.</summary>
  1038. /// <remarks>
  1039. /// After each update, this property will be left at its most recent value.
  1040. /// <para></para>
  1041. /// <see cref="AnimancerState.Time"/> uses this value to determine whether it has accessed the playable's time
  1042. /// since it was last updated in order to cache its value.
  1043. /// </remarks>
  1044. public ulong FrameID { get; private set; }
  1045. /************************************************************************************************************************/
  1046. /// <summary>[Internal] Calls <see cref="IUpdatable.Update"/> on each of the `updatables`.</summary>
  1047. internal void UpdateAll(IUpdatable.List updatables, float deltaTime, ulong frameID)
  1048. {
  1049. var previous = Current;
  1050. Current = this;
  1051. DeltaTime = deltaTime;
  1052. updatables.UpdateAll();
  1053. if (FrameID != frameID)// Pre-Update.
  1054. {
  1055. // Any time before or during this method will still have all Playables at their time from last frame,
  1056. // so we don't want them to think their time is dirty until we' a're done with the pre-update.
  1057. FrameID = frameID;
  1058. AssertPreUpdate();
  1059. }
  1060. else// Post-Update.
  1061. {
  1062. for (int i = _Layers.Count - 1; i >= 0; i--)
  1063. _Layers[i].UpdateEvents();
  1064. }
  1065. Current = previous;
  1066. }
  1067. /************************************************************************************************************************/
  1068. /// <summary>[Assert-Conditional] Called during the pre-update to perform msome safety checks.</summary>
  1069. [System.Diagnostics.Conditional(Strings.Assertions)]
  1070. private void AssertPreUpdate()
  1071. {
  1072. #if UNITY_ASSERTIONS
  1073. if (OptionalWarning.AnimatorSpeed.IsEnabled() &&
  1074. Component != null)
  1075. {
  1076. var animator = Component.Animator;
  1077. if (animator != null &&
  1078. animator.speed != 1 &&
  1079. animator.runtimeAnimatorController == null)
  1080. {
  1081. animator.speed = 1;
  1082. OptionalWarning.AnimatorSpeed.Log(
  1083. $"{nameof(Animator)}.{nameof(Animator.speed)} doesn't affect {nameof(Animancer)}." +
  1084. $" Use {nameof(AnimancerGraph)}.{nameof(Speed)} instead.", animator);
  1085. }
  1086. }
  1087. #endif
  1088. }
  1089. /************************************************************************************************************************/
  1090. #endregion
  1091. /************************************************************************************************************************/
  1092. }
  1093. }