AnimancerPlayable.cs 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using UnityEngine;
  7. using UnityEngine.Animations;
  8. using UnityEngine.Playables;
  9. using Object = UnityEngine.Object;
  10. namespace Animancer
  11. {
  12. /// <summary>
  13. /// A <see cref="PlayableBehaviour"/> which can be used as a substitute for the
  14. /// <see cref="RuntimeAnimatorController"/> normally used to control an <see cref="Animator"/>.
  15. /// </summary>
  16. ///
  17. /// <remarks>
  18. /// This class can be used as a custom yield instruction to wait until all animations finish playing.
  19. /// <para></para>
  20. /// The most common way to access this class is via <see cref="AnimancerComponent.Playable"/>.
  21. /// <para></para>
  22. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/playing">Playing Animations</see>
  23. /// </remarks>
  24. ///
  25. /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerPlayable
  26. ///
  27. public sealed partial class AnimancerPlayable : PlayableBehaviour,
  28. IEnumerator, IPlayableWrapper, IAnimationClipCollection
  29. {
  30. /************************************************************************************************************************/
  31. #region Fields and Properties
  32. /************************************************************************************************************************/
  33. private static float _DefaultFadeDuration = 0.25f;
  34. /************************************************************************************************************************/
  35. #if UNITY_EDITOR
  36. /// <summary>[Editor-Only]
  37. /// The namespace that should be used for a class which sets the <see cref="DefaultFadeDuration"/>.
  38. /// </summary>
  39. public const string DefaultFadeDurationNamespace = nameof(Animancer);
  40. /// <summary>[Editor-Only]
  41. /// The name that should be used for a class which sets the <see cref="DefaultFadeDuration"/>.
  42. /// </summary>
  43. public const string DefaultFadeDurationClass = nameof(DefaultFadeDuration);
  44. /// <summary>[Editor-Only]
  45. /// Initializes the <see cref="DefaultFadeDuration"/> (see its example for more information).
  46. /// </summary>
  47. /// <remarks>
  48. /// This method takes about 2 milliseconds if a <see cref="DefaultFadeDuration"/> class exists, or 0 if it
  49. /// doesn't (less than 0.5 rounded off according to a <see cref="System.Diagnostics.Stopwatch"/>).
  50. /// <para></para>
  51. /// The <see cref="DefaultFadeDuration"/> can't simply be stored in the
  52. /// <see cref="Editor.AnimancerSettings"/> because it needs to be initialized before Unity is able to load
  53. /// <see cref="ScriptableObject"/>s.
  54. /// </remarks>
  55. static AnimancerPlayable()
  56. {
  57. var assemblies = AppDomain.CurrentDomain.GetAssemblies();
  58. // Iterate backwards since it's more likely to be towards the end.
  59. for (int iAssembly = assemblies.Length - 1; iAssembly >= 0; iAssembly--)
  60. {
  61. var type = assemblies[iAssembly].GetType(DefaultFadeDurationNamespace + "." + DefaultFadeDurationClass);
  62. if (type != null)
  63. {
  64. var methods = type.GetMethods(Editor.AnimancerEditorUtilities.StaticBindings);
  65. for (int iMethod = 0; iMethod < methods.Length; iMethod++)
  66. {
  67. var method = methods[iMethod];
  68. if (method.IsDefined(typeof(RuntimeInitializeOnLoadMethodAttribute), false))
  69. {
  70. method.Invoke(null, null);
  71. return;
  72. }
  73. }
  74. }
  75. }
  76. }
  77. #endif
  78. /************************************************************************************************************************/
  79. /// <summary>The fade duration to use if not specified. Default is 0.25.</summary>
  80. /// <exception cref="UnityEngine.Assertions.AssertionException">The value is negative or infinity.</exception>
  81. /// <remarks><em>Animancer Lite doesn't allow this value to be changed in runtime builds (except to 0).</em></remarks>
  82. /// <example>
  83. /// <see cref="Sprite"/> based games often have no use for fading so you could set this value to 0 using the
  84. /// following script so that you don't need to manually set the <see cref="ITransition.FadeDuration"/> of all
  85. /// your transitions.
  86. /// <para></para>
  87. /// To set this value automatically on startup, put the following class into any script:
  88. /// <para></para><code>
  89. /// namespace Animancer
  90. /// {
  91. /// internal static class DefaultFadeDuration
  92. /// {
  93. /// [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.BeforeSceneLoad)]
  94. /// private static void Initialize() => AnimancerPlayable.DefaultFadeDuration = 0;
  95. /// }
  96. /// }
  97. /// </code>
  98. /// Using that specific namespace (<see cref="DefaultFadeDurationNamespace"/>) and class name
  99. /// (<see cref="DefaultFadeDurationClass"/>) allows Animancer to find and run it immediately in the Unity
  100. /// Editor so that newly created transition fields can start with the correct value (using a
  101. /// <c>[UnityEditor.InitializeOnLoadMethod]</c> attribute would run it too late).
  102. /// </example>
  103. public static float DefaultFadeDuration
  104. {
  105. get => _DefaultFadeDuration;
  106. set
  107. {
  108. AnimancerUtilities.Assert(value >= 0 && value < float.PositiveInfinity,
  109. $"{nameof(AnimancerPlayable)}.{nameof(DefaultFadeDuration)} must not be negative or infinity.");
  110. _DefaultFadeDuration = value;
  111. }
  112. }
  113. /************************************************************************************************************************/
  114. /// <summary>[Internal] The <see cref="PlayableGraph"/> containing this <see cref="AnimancerPlayable"/>.</summary>
  115. internal PlayableGraph _Graph;
  116. /// <summary>[Pro-Only] The <see cref="PlayableGraph"/> containing this <see cref="AnimancerPlayable"/>.</summary>
  117. public PlayableGraph Graph => _Graph;
  118. /// <summary>[Internal] The <see cref="Playable"/> containing this <see cref="AnimancerPlayable"/>.</summary>
  119. internal Playable _RootPlayable;
  120. /// <summary>[Internal] The <see cref="Playable"/> which layers connect to.</summary>
  121. internal Playable _LayerMixer;
  122. /************************************************************************************************************************/
  123. /// <summary>[Internal] The <see cref="Playable"/> which layers connect to.</summary>
  124. Playable IPlayableWrapper.Playable => _LayerMixer;
  125. /// <summary>[Internal] An <see cref="AnimancerPlayable"/> is the root of the graph so it has no parent.</summary>
  126. IPlayableWrapper IPlayableWrapper.Parent => null;
  127. /// <summary>[Internal] The current blend weight of this node which determines how much it affects the final output.</summary>
  128. float IPlayableWrapper.Weight => 1;
  129. /// <summary>[Internal] The <see cref="LayerList.Count"/>.</summary>
  130. int IPlayableWrapper.ChildCount => Layers.Count;
  131. /// <summary>[Internal] Returns the layer at the specified `index`.</summary>
  132. AnimancerNode IPlayableWrapper.GetChild(int index) => Layers[index];
  133. /************************************************************************************************************************/
  134. // These collections can't be readonly because when Unity clones the Template it copies the memory without running the
  135. // field initializers on the new clone so everything would be referencing the same collections.
  136. /************************************************************************************************************************/
  137. /// <summary>The <see cref="AnimancerLayer"/>s which each manage their own set of animations.</summary>
  138. /// <remarks>
  139. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/blending/layers">Layers</see>
  140. /// </remarks>
  141. public LayerList Layers { get; private set; }
  142. /// <summary>The <see cref="AnimancerState"/>s managed by this playable.</summary>
  143. /// <remarks>
  144. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/playing/states">States</see>
  145. /// </remarks>
  146. public StateDictionary States { get; private set; }
  147. /// <summary>All of the nodes that need to be updated.</summary>
  148. private Key.KeyedList<IUpdatable> _PreUpdatables;
  149. /// <summary>All of the objects that need to be updated early.</summary>
  150. private Key.KeyedList<IUpdatable> _PostUpdatables;
  151. /// <summary>A <see cref="PlayableBehaviour"/> that updates the <see cref="_PostUpdatables"/>.</summary>
  152. private PostUpdate _PostUpdate;
  153. /************************************************************************************************************************/
  154. /// <summary>The component that is playing this <see cref="AnimancerPlayable"/>.</summary>
  155. public IAnimancerComponent Component { get; private set; }
  156. /************************************************************************************************************************/
  157. /// <summary>
  158. /// The number of times the <see cref="AnimancerLayer.CurrentState"/> has changed on layer 0. By storing this
  159. /// value and later comparing the stored value to the current value, you can determine whether the state has
  160. /// been changed since then, even it has changed back to the same state.
  161. /// </summary>
  162. public int CommandCount => Layers[0].CommandCount;
  163. /************************************************************************************************************************/
  164. /// <summary>Determines what time source is used to update the <see cref="PlayableGraph"/>.</summary>
  165. public DirectorUpdateMode UpdateMode
  166. {
  167. get => _Graph.GetTimeUpdateMode();
  168. set => _Graph.SetTimeUpdateMode(value);
  169. }
  170. /************************************************************************************************************************/
  171. private float _Speed = 1;
  172. /// <summary>How fast the <see cref="AnimancerState.Time"/> of all animations is advancing every frame.</summary>
  173. ///
  174. /// <remarks>
  175. /// 1 is the normal speed.
  176. /// <para></para>
  177. /// A negative value will play the animations backwards.
  178. /// <para></para>
  179. /// Setting this value to 0 would pause all animations, but calling <see cref="PauseGraph"/> is more efficient.
  180. /// <para></para>
  181. /// <em>Animancer Lite does not allow this value to be changed in runtime builds.</em>
  182. /// </remarks>
  183. ///
  184. /// <example><code>
  185. /// void SetSpeed(AnimancerComponent animancer)
  186. /// {
  187. /// animancer.Playable.Speed = 1;// Normal speed.
  188. /// animancer.Playable.Speed = 2;// Double speed.
  189. /// animancer.Playable.Speed = 0.5f;// Half speed.
  190. /// animancer.Playable.Speed = -1;// Normal speed playing backwards.
  191. /// }
  192. /// </code></example>
  193. public float Speed
  194. {
  195. get => _Speed;
  196. set => _LayerMixer.SetSpeed(_Speed = value);
  197. }
  198. /************************************************************************************************************************/
  199. private bool _KeepChildrenConnected;
  200. /// <summary>
  201. /// Should playables stay connected to the graph at all times?
  202. /// Otherwise they will be disconnected when their <see cref="AnimancerNode.Weight"/> is 0.
  203. /// </summary>
  204. ///
  205. /// <remarks>
  206. /// Humanoid Rigs default this value to <c>false</c> so that playables will be disconnected from the graph
  207. /// while they are at 0 weight which stops it from evaluating them every frame.
  208. /// <para></para>
  209. /// Generic Rigs default this value to <c>true</c> because they do not always animate the same standard set of
  210. /// values so every connection change has a higher performance cost than with Humanoid Rigs which is generally
  211. /// more significant than the gains for having fewer playables connected at a time.
  212. /// <para></para>
  213. /// The default is set by <see cref="CreateOutput(Animator, IAnimancerComponent)"/>.
  214. /// </remarks>
  215. ///
  216. /// <example><code>
  217. /// [SerializeField]
  218. /// private AnimancerComponent _Animancer;
  219. ///
  220. /// public void Initialize()
  221. /// {
  222. /// _Animancer.Playable.KeepChildrenConnected = true;
  223. /// }
  224. /// </code></example>
  225. public bool KeepChildrenConnected
  226. {
  227. get => _KeepChildrenConnected;
  228. set
  229. {
  230. if (_KeepChildrenConnected == value)
  231. return;
  232. _KeepChildrenConnected = value;
  233. if (value)
  234. {
  235. _PostUpdate.IsConnected = true;
  236. for (int i = Layers.Count - 1; i >= 0; i--)
  237. Layers.GetLayer(i).ConnectAllChildrenToGraph();
  238. }
  239. else
  240. {
  241. for (int i = Layers.Count - 1; i >= 0; i--)
  242. Layers.GetLayer(i).DisconnectWeightlessChildrenFromGraph();
  243. }
  244. }
  245. }
  246. /************************************************************************************************************************/
  247. private bool _SkipFirstFade;
  248. /// <summary>
  249. /// Normally the first animation on the Base Layer should not fade in because there is nothing fading out. But
  250. /// sometimes that is undesirable, such as if the <see cref="Animator.runtimeAnimatorController"/> is assigned
  251. /// since Animancer can blend with that.
  252. /// </summary>
  253. /// <remarks>
  254. /// Setting this value to false ensures that the <see cref="AnimationLayerMixerPlayable"/> has at least two
  255. /// inputs because it ignores the <see cref="AnimancerNode.Weight"/> of the layer when there is only one.
  256. /// </remarks>
  257. public bool SkipFirstFade
  258. {
  259. get => _SkipFirstFade;
  260. set
  261. {
  262. _SkipFirstFade = value;
  263. if (!value && Layers.Count < 2)
  264. {
  265. Layers.Count = 1;
  266. _LayerMixer.SetInputCount(2);
  267. }
  268. }
  269. }
  270. /************************************************************************************************************************/
  271. #endregion
  272. /************************************************************************************************************************/
  273. #region Initialization
  274. /************************************************************************************************************************/
  275. /// <summary>
  276. /// Since <see cref="ScriptPlayable{T}.Create(PlayableGraph, int)"/> needs to clone an existing instance, we
  277. /// keep a static template to avoid allocating an extra garbage one every time. This is why the fields are
  278. /// assigned in <see cref="OnPlayableCreate"/> rather than being readonly with field initializers.
  279. /// </summary>
  280. private static readonly AnimancerPlayable Template = new AnimancerPlayable();
  281. /************************************************************************************************************************/
  282. /// <summary>
  283. /// Creates a new <see cref="PlayableGraph"/> containing an <see cref="AnimancerPlayable"/>.
  284. /// <para></para>
  285. /// The caller is responsible for calling <see cref="DestroyGraph()"/> on the returned object, except in Edit Mode
  286. /// where it will be called automatically.
  287. /// <para></para>
  288. /// Consider calling <see cref="SetNextGraphName"/> before this method to give it a name.
  289. /// </summary>
  290. public static AnimancerPlayable Create()
  291. {
  292. #if UNITY_EDITOR
  293. var name = _NextGraphName;
  294. _NextGraphName = null;
  295. var graph = name != null ?
  296. PlayableGraph.Create(name) :
  297. PlayableGraph.Create();
  298. #else
  299. var graph = PlayableGraph.Create();
  300. #endif
  301. return ScriptPlayable<AnimancerPlayable>.Create(graph, Template, 2)
  302. .GetBehaviour();
  303. }
  304. /************************************************************************************************************************/
  305. /// <summary>Creates an <see cref="AnimancerPlayable"/> in an existing <see cref="PlayableGraph"/>.</summary>
  306. public static AnimancerPlayable Create(PlayableGraph graph)
  307. {
  308. return ScriptPlayable<AnimancerPlayable>.Create(graph, Template, 2)
  309. .GetBehaviour();
  310. }
  311. /************************************************************************************************************************/
  312. /// <summary>[Internal] Called by Unity when it creates this <see cref="AnimancerPlayable"/>.</summary>
  313. public override void OnPlayableCreate(Playable playable)
  314. {
  315. _RootPlayable = playable;
  316. _Graph = playable.GetGraph();
  317. _PostUpdatables = new Key.KeyedList<IUpdatable>();
  318. _PreUpdatables = new Key.KeyedList<IUpdatable>();
  319. _PostUpdate = PostUpdate.Create(this);
  320. Layers = new LayerList(this, out _LayerMixer);
  321. States = new StateDictionary(this);
  322. playable.SetInputWeight(0, 1);
  323. #if UNITY_EDITOR
  324. RegisterInstance();
  325. #endif
  326. }
  327. /************************************************************************************************************************/
  328. #if UNITY_EDITOR
  329. private static string _NextGraphName;
  330. #endif
  331. /// <summary>[Editor-Conditional]
  332. /// Sets the display name for the next <see cref="Create()"/> call to give its <see cref="PlayableGraph"/>.
  333. /// </summary>
  334. /// <remarks>
  335. /// Having this method separate from <see cref="Create()"/> allows the
  336. /// <see cref="System.Diagnostics.ConditionalAttribute"/> to compile it out of runtime builds which would
  337. /// otherwise require #ifs on the caller side.
  338. /// </remarks>
  339. [System.Diagnostics.Conditional(Strings.UnityEditor)]
  340. public static void SetNextGraphName(string name)
  341. {
  342. #if UNITY_EDITOR
  343. _NextGraphName = name;
  344. #endif
  345. }
  346. /************************************************************************************************************************/
  347. #if UNITY_EDITOR
  348. /// <summary>[Editor-Only] Returns "AnimancerPlayable (Graph Name)".</summary>
  349. public override string ToString()
  350. => $"{nameof(AnimancerPlayable)} ({(_Graph.IsValid() ? _Graph.GetEditorName() : "Graph Not Initialized")})";
  351. #endif
  352. /************************************************************************************************************************/
  353. /// <summary>
  354. /// Outputs the <see cref="PlayableOutput"/> connected to the <see cref="AnimancerPlayable"/> and returns true
  355. /// if it was found. Otherwise returns false.
  356. /// </summary>
  357. public bool TryGetOutput(out PlayableOutput output)
  358. {
  359. var outputCount = _Graph.GetOutputCount();
  360. for (int i = 0; i < outputCount; i++)
  361. {
  362. output = _Graph.GetOutput(i);
  363. if (output.GetSourcePlayable().Equals(_RootPlayable))
  364. return true;
  365. }
  366. output = default;
  367. return false;
  368. }
  369. /************************************************************************************************************************/
  370. /// <summary>
  371. /// Plays this playable on the <see cref="IAnimancerComponent.Animator"/> and sets the
  372. /// <see cref="Component"/>.
  373. /// </summary>
  374. public void CreateOutput(IAnimancerComponent animancer)
  375. => CreateOutput(animancer.Animator, animancer);
  376. /// <summary>Plays this playable on the specified `animator` and sets the <see cref="Component"/>.</summary>
  377. public void CreateOutput(Animator animator, IAnimancerComponent animancer)
  378. {
  379. #if UNITY_ASSERTIONS
  380. if (animator == null)
  381. throw new ArgumentNullException(nameof(animator),
  382. $"An {nameof(Animator)} component is required to play animations.");
  383. #if UNITY_EDITOR
  384. if (UnityEditor.EditorUtility.IsPersistent(animator))
  385. throw new ArgumentException(
  386. $"The specified {nameof(Animator)} component is a prefab which means it cannot play animations.",
  387. nameof(animator));
  388. #endif
  389. if (animancer != null)
  390. {
  391. Debug.Assert(animancer.IsPlayableInitialized && animancer.Playable == this,
  392. $"{nameof(CreateOutput)} was called on an {nameof(AnimancerPlayable)} which does not match the" +
  393. $" {nameof(IAnimancerComponent)}.{nameof(IAnimancerComponent.Playable)}.");
  394. Debug.Assert(animator == animancer.Animator,
  395. $"{nameof(CreateOutput)} was called with an {nameof(Animator)} which does not match the" +
  396. $" {nameof(IAnimancerComponent)}.{nameof(IAnimancerComponent.Animator)}.");
  397. }
  398. if (TryGetOutput(out var output))
  399. {
  400. Debug.LogWarning(
  401. $"A {nameof(PlayableGraph)} output is already connected to the {nameof(AnimancerPlayable)}." +
  402. $" The old output should be destroyed using `animancerComponent.Playable.DestroyOutput();`" +
  403. $" before calling {nameof(CreateOutput)}.", animator);
  404. }
  405. #endif
  406. Component = animancer;
  407. var isHumanoid = animator.isHuman;
  408. // Generic Rigs get better performance by keeping children connected but Humanoids don't.
  409. KeepChildrenConnected = !isHumanoid;
  410. // Generic Rigs can blend with an underlying Animator Controller but Humanoids can't.
  411. SkipFirstFade = isHumanoid || animator.runtimeAnimatorController == null;
  412. #pragma warning disable CS0618 // Type or member is obsolete.
  413. AnimationPlayableUtilities.Play(animator, _RootPlayable, _Graph);
  414. #pragma warning restore CS0618 // Type or member is obsolete.
  415. _IsGraphPlaying = true;
  416. }
  417. /************************************************************************************************************************/
  418. /// <summary>[Pro-Only]
  419. /// Inserts a `playable` after the root of the <see cref="Graph"/> so that it can modify the final output.
  420. /// </summary>
  421. /// <remarks>It can be removed using <see cref="AnimancerUtilities.RemovePlayable"/>.</remarks>
  422. public void InsertOutputPlayable(Playable playable)
  423. {
  424. var output = _Graph.GetOutput(0);
  425. _Graph.Connect(output.GetSourcePlayable(), 0, playable, 0);
  426. playable.SetInputWeight(0, 1);
  427. output.SetSourcePlayable(playable);
  428. }
  429. /// <summary>[Pro-Only]
  430. /// Inserts an animation job after the root of the <see cref="Graph"/> so that it can modify the final output.
  431. /// </summary>
  432. /// <remarks>
  433. /// It can can be removed by passing the returned value into <see cref="AnimancerUtilities.RemovePlayable"/>.
  434. /// </remarks>
  435. public AnimationScriptPlayable InsertOutputJob<T>(T data) where T : struct, IAnimationJob
  436. {
  437. var playable = AnimationScriptPlayable.Create(_Graph, data, 1);
  438. var output = _Graph.GetOutput(0);
  439. _Graph.Connect(output.GetSourcePlayable(), 0, playable, 0);
  440. playable.SetInputWeight(0, 1);
  441. output.SetSourcePlayable(playable);
  442. return playable;
  443. }
  444. /************************************************************************************************************************/
  445. #endregion
  446. /************************************************************************************************************************/
  447. #region Cleanup
  448. /************************************************************************************************************************/
  449. /// <summary>Is this <see cref="AnimancerPlayable"/> currently usable (not destroyed)?</summary>
  450. public bool IsValid => _Graph.IsValid();
  451. /************************************************************************************************************************/
  452. /// <summary>Destroys the <see cref="Graph"/>. This operation cannot be undone.</summary>
  453. public void DestroyGraph()
  454. {
  455. if (_Graph.IsValid())
  456. _Graph.Destroy();
  457. }
  458. /************************************************************************************************************************/
  459. /// <summary>
  460. /// Destroys the <see cref="PlayableOutput"/> connected to this <see cref="AnimancerPlayable"/> and returns
  461. /// true if it was found. Otherwise returns false.
  462. /// </summary>
  463. public bool DestroyOutput()
  464. {
  465. if (TryGetOutput(out var output))
  466. {
  467. _Graph.DestroyOutput(output);
  468. return true;
  469. }
  470. else return false;
  471. }
  472. /************************************************************************************************************************/
  473. /// <summary>Cleans up the resources managed by this <see cref="AnimancerPlayable"/>.</summary>
  474. public override void OnPlayableDestroy(Playable playable)
  475. {
  476. var previous = Current;
  477. Current = this;
  478. DisposeAll();
  479. GC.SuppressFinalize(this);
  480. // No need to destroy every layer and state individually because destroying the graph will do so anyway.
  481. Layers = null;
  482. States = null;
  483. Current = previous;
  484. }
  485. /************************************************************************************************************************/
  486. private List<IDisposable> _Disposables;
  487. /// <summary>A list of objects that need to be disposed when this <see cref="AnimancerPlayable"/> is destroyed.</summary>
  488. /// <remarks>This list is primarily used to dispose native arrays used in Animation Jobs.</remarks>
  489. public List<IDisposable> Disposables => _Disposables ?? (_Disposables = new List<IDisposable>());
  490. /************************************************************************************************************************/
  491. /// <summary>Calls <see cref="IDisposable.Dispose"/> on all the <see cref="Disposables"/>.</summary>
  492. ~AnimancerPlayable() => DisposeAll();
  493. /// <summary>Calls <see cref="IDisposable.Dispose"/> on all the <see cref="Disposables"/>.</summary>
  494. private void DisposeAll()
  495. {
  496. if (_Disposables == null)
  497. return;
  498. var i = _Disposables.Count;
  499. DisposeNext:
  500. try
  501. {
  502. while (--i >= 0)
  503. {
  504. _Disposables[i].Dispose();
  505. }
  506. _Disposables.Clear();
  507. _Disposables = null;
  508. }
  509. catch (Exception exception)
  510. {
  511. Debug.LogException(exception, Component as Object);
  512. goto DisposeNext;
  513. }
  514. }
  515. /************************************************************************************************************************/
  516. #region Inverse Kinematics
  517. // These fields are stored here but accessed via the LayerList.
  518. /************************************************************************************************************************/
  519. private bool _ApplyAnimatorIK;
  520. /// <inheritdoc/>
  521. public bool ApplyAnimatorIK
  522. {
  523. get => _ApplyAnimatorIK;
  524. set
  525. {
  526. _ApplyAnimatorIK = value;
  527. for (int i = Layers.Count - 1; i >= 0; i--)
  528. Layers.GetLayer(i).ApplyAnimatorIK = value;
  529. }
  530. }
  531. /************************************************************************************************************************/
  532. private bool _ApplyFootIK;
  533. /// <inheritdoc/>
  534. public bool ApplyFootIK
  535. {
  536. get => _ApplyFootIK;
  537. set
  538. {
  539. _ApplyFootIK = value;
  540. for (int i = Layers.Count - 1; i >= 0; i--)
  541. Layers.GetLayer(i).ApplyFootIK = value;
  542. }
  543. }
  544. /************************************************************************************************************************/
  545. #endregion
  546. /************************************************************************************************************************/
  547. #endregion
  548. /************************************************************************************************************************/
  549. #region Playing
  550. /************************************************************************************************************************/
  551. /// <summary>Calls <see cref="IAnimancerComponent.GetKey"/> on the <see cref="Component"/>.</summary>
  552. /// <remarks>If the <see cref="Component"/> is null, this method returns the `clip` itself.</remarks>
  553. public object GetKey(AnimationClip clip) => Component != null ? Component.GetKey(clip) : clip;
  554. /************************************************************************************************************************/
  555. // Play Immediately.
  556. /************************************************************************************************************************/
  557. /// <summary>Stops all other animations on the same layer, plays the `clip`, and returns its state.</summary>
  558. /// <remarks>
  559. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  560. /// To restart it from the beginning you can use <c>...Play(clip).Time = 0;</c>.
  561. /// <para></para>
  562. /// This method is safe to call repeatedly without checking whether the `clip` was already playing.
  563. /// </remarks>
  564. public AnimancerState Play(AnimationClip clip)
  565. => Play(States.GetOrCreate(clip));
  566. /// <summary>Stops all other animations on the same layer, plays the `state`, and returns it.</summary>
  567. /// <remarks>
  568. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  569. /// To restart it from the beginning you can use <c>...Play(state).Time = 0;</c>.
  570. /// <para></para>
  571. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  572. /// </remarks>
  573. public AnimancerState Play(AnimancerState state)
  574. {
  575. return GetLocalLayer(state).Play(state);
  576. }
  577. /************************************************************************************************************************/
  578. // Cross Fade.
  579. /************************************************************************************************************************/
  580. /// <summary>
  581. /// Starts fading in the `clip` while fading out all other states in the same layer over the course of the
  582. /// `fadeDuration`. Returns its state.
  583. /// </summary>
  584. /// <remarks>
  585. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`, this
  586. /// method will allow it to complete the existing fade rather than starting a slower one.
  587. /// <para></para>
  588. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will fade in the layer itself
  589. /// and simply <see cref="AnimancerState.Play"/> the `state`.
  590. /// <para></para>
  591. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  592. /// <para></para>
  593. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  594. /// </remarks>
  595. public AnimancerState Play(AnimationClip clip, float fadeDuration, FadeMode mode = default)
  596. => Play(States.GetOrCreate(clip), fadeDuration, mode);
  597. /// <summary>
  598. /// Starts fading in the `state` while fading out all others in the same layer over the course of the
  599. /// `fadeDuration`. Returns the `state`.
  600. /// </summary>
  601. /// <remarks>
  602. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`, this
  603. /// method will allow it to complete the existing fade rather than starting a slower one.
  604. /// <para></para>
  605. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will fade in the layer itself
  606. /// and simply <see cref="AnimancerState.Play"/> the `state`.
  607. /// <para></para>
  608. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  609. /// <para></para>
  610. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  611. /// </remarks>
  612. public AnimancerState Play(AnimancerState state, float fadeDuration, FadeMode mode = default)
  613. {
  614. return GetLocalLayer(state).Play(state, fadeDuration, mode);
  615. }
  616. /************************************************************************************************************************/
  617. // Transition.
  618. /************************************************************************************************************************/
  619. /// <summary>
  620. /// Creates a state for the `transition` if it didn't already exist, then calls
  621. /// <see cref="Play(AnimancerState)"/> or <see cref="Play(AnimancerState, float, FadeMode)"/>
  622. /// depending on the <see cref="ITransition.FadeDuration"/>.
  623. /// </summary>
  624. /// <remarks>
  625. /// This method is safe to call repeatedly without checking whether the `transition` was already playing.
  626. /// </remarks>
  627. public AnimancerState Play(ITransition transition)
  628. => Play(transition, transition.FadeDuration, transition.FadeMode);
  629. /// <summary>
  630. /// Creates a state for the `transition` if it didn't already exist, then calls
  631. /// <see cref="Play(AnimancerState)"/> or <see cref="Play(AnimancerState, float, FadeMode)"/>
  632. /// depending on the <see cref="ITransition.FadeDuration"/>.
  633. /// </summary>
  634. /// <remarks>
  635. /// This method is safe to call repeatedly without checking whether the `transition` was already playing.
  636. /// </remarks>
  637. public AnimancerState Play(ITransition transition, float fadeDuration, FadeMode mode = default)
  638. {
  639. var state = States.GetOrCreate(transition);
  640. state = Play(state, fadeDuration, mode);
  641. transition.Apply(state);
  642. return state;
  643. }
  644. /************************************************************************************************************************/
  645. // Try Play.
  646. /************************************************************************************************************************/
  647. /// <summary>
  648. /// Stops all other animations on the same layer, plays the animation registered with the `key`, and returns
  649. /// that state. Or if no state is registered with that `key`, this method does nothing and returns null.
  650. /// </summary>
  651. /// <remarks>
  652. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  653. /// If you wish to force it back to the start, you can simply set the returned state's time to 0.
  654. /// <para></para>
  655. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  656. /// </remarks>
  657. /// <exception cref="ArgumentNullException">The `key` is null.</exception>
  658. public AnimancerState TryPlay(object key)
  659. => States.TryGet(key, out var state) ? Play(state) : null;
  660. /// <summary>
  661. /// Starts fading in the animation registered with the `key` while fading out all others in the same layer
  662. /// over the course of the `fadeDuration`. Or if no state is registered with that `key`, this method does
  663. /// nothing and returns null.
  664. /// </summary>
  665. /// <remarks>
  666. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`, this
  667. /// method will allow it to complete the existing fade rather than starting a slower one.
  668. /// <para></para>
  669. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will fade in the layer itself
  670. /// and simply <see cref="AnimancerState.Play"/> the `state`.
  671. /// <para></para>
  672. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  673. /// <para></para>
  674. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  675. /// </remarks>
  676. /// <exception cref="ArgumentNullException">The `key` is null.</exception>
  677. public AnimancerState TryPlay(object key, float fadeDuration, FadeMode mode = default)
  678. => States.TryGet(key, out var state) ? Play(state, fadeDuration, mode) : null;
  679. /************************************************************************************************************************/
  680. /// <summary>
  681. /// Returns the <see cref="AnimancerNode.Layer"/> if the <see cref="AnimancerNode.Root"/> is this.
  682. /// Otherwise returns the first layer in this graph.
  683. /// </summary>
  684. private AnimancerLayer GetLocalLayer(AnimancerState state)
  685. {
  686. if (state.Root == this)
  687. {
  688. var layer = state.Layer;
  689. if (layer != null)
  690. return layer;
  691. }
  692. return Layers[0];
  693. }
  694. /************************************************************************************************************************/
  695. /// <summary>
  696. /// Gets the state registered with the <see cref="IHasKey.Key"/>, stops and rewinds it to the start, then
  697. /// returns it.
  698. /// </summary>
  699. public AnimancerState Stop(IHasKey hasKey) => Stop(hasKey.Key);
  700. /// <summary>
  701. /// Calls <see cref="AnimancerState.Stop"/> on the state registered with the `key` to stop it from playing and
  702. /// rewind it to the start.
  703. /// </summary>
  704. public AnimancerState Stop(object key)
  705. {
  706. if (States.TryGet(key, out var state))
  707. state.Stop();
  708. return state;
  709. }
  710. /// <summary>
  711. /// Calls <see cref="AnimancerState.Stop"/> on all animations to stop them from playing and rewind them to the
  712. /// start.
  713. /// </summary>
  714. public void Stop()
  715. {
  716. for (int i = Layers.Count - 1; i >= 0; i--)
  717. Layers.GetLayer(i).Stop();
  718. }
  719. /************************************************************************************************************************/
  720. /// <summary>Is a state registered with the <see cref="IHasKey.Key"/> and currently playing?</summary>
  721. public bool IsPlaying(IHasKey hasKey) => IsPlaying(hasKey.Key);
  722. /// <summary>Is a state registered with the `key` and currently playing?</summary>
  723. public bool IsPlaying(object key) => States.TryGet(key, out var state) && state.IsPlaying;
  724. /// <summary>Is least one animation being played?</summary>
  725. public bool IsPlaying()
  726. {
  727. if (!_IsGraphPlaying)
  728. return false;
  729. for (int i = Layers.Count - 1; i >= 0; i--)
  730. {
  731. if (Layers.GetLayer(i).IsAnyStatePlaying())
  732. return true;
  733. }
  734. return false;
  735. }
  736. /************************************************************************************************************************/
  737. /// <summary>
  738. /// Returns true if the `clip` is currently being played by at least one state in the specified layer.
  739. /// <para></para>
  740. /// This method is inefficient because it searches through every state to find any that are playing the `clip`,
  741. /// unlike <see cref="IsPlaying(object)"/> which only checks the state registered using the specified key.
  742. /// </summary>
  743. public bool IsPlayingClip(AnimationClip clip)
  744. {
  745. if (!_IsGraphPlaying)
  746. return false;
  747. for (int i = Layers.Count - 1; i >= 0; i--)
  748. if (Layers.GetLayer(i).IsPlayingClip(clip))
  749. return true;
  750. return false;
  751. }
  752. /************************************************************************************************************************/
  753. /// <summary>Calculates the total <see cref="AnimancerNode.Weight"/> of all states in all layers.</summary>
  754. public float GetTotalWeight()
  755. {
  756. float weight = 0;
  757. for (int i = Layers.Count - 1; i >= 0; i--)
  758. weight += Layers.GetLayer(i).GetTotalWeight();
  759. return weight;
  760. }
  761. /************************************************************************************************************************/
  762. /// <summary>[<see cref="IAnimationClipCollection"/>] Gathers all the animations in all layers.</summary>
  763. public void GatherAnimationClips(ICollection<AnimationClip> clips) => Layers.GatherAnimationClips(clips);
  764. /************************************************************************************************************************/
  765. // IEnumerator for yielding in a coroutine to wait until animations have stopped.
  766. /************************************************************************************************************************/
  767. /// <summary>Are any animations playing?</summary>
  768. /// <remarks>This allows this object to be used as a custom yield instruction.</remarks>
  769. bool IEnumerator.MoveNext()
  770. {
  771. for (int i = Layers.Count - 1; i >= 0; i--)
  772. if (Layers.GetLayer(i).IsPlayingAndNotEnding())
  773. return true;
  774. return false;
  775. }
  776. /// <summary>Returns null.</summary>
  777. object IEnumerator.Current => null;
  778. /// <summary>Does nothing.</summary>
  779. void IEnumerator.Reset() { }
  780. /************************************************************************************************************************/
  781. #region Key Error Methods
  782. #if UNITY_EDITOR
  783. /************************************************************************************************************************/
  784. // These are overloads of other methods that take a System.Object key to ensure the user doesn't try to use an
  785. // AnimancerState as a key, since the whole point of a key is to identify a state in the first place.
  786. /************************************************************************************************************************/
  787. /// <summary>[Warning]
  788. /// You should not use an <see cref="AnimancerState"/> as a key.
  789. /// Just call <see cref="AnimancerState.Stop"/>.
  790. /// </summary>
  791. [Obsolete("You should not use an AnimancerState as a key. Just call AnimancerState.Stop().", true)]
  792. public AnimancerState Stop(AnimancerState key)
  793. {
  794. key.Stop();
  795. return key;
  796. }
  797. /// <summary>[Warning]
  798. /// You should not use an <see cref="AnimancerState"/> as a key.
  799. /// Just check <see cref="AnimancerState.IsPlaying"/>.
  800. /// </summary>
  801. [Obsolete("You should not use an AnimancerState as a key. Just check AnimancerState.IsPlaying.", true)]
  802. public bool IsPlaying(AnimancerState key) => key.IsPlaying;
  803. /************************************************************************************************************************/
  804. #endif
  805. #endregion
  806. /************************************************************************************************************************/
  807. #endregion
  808. /************************************************************************************************************************/
  809. #region Evaluation
  810. /************************************************************************************************************************/
  811. private bool _IsGraphPlaying = true;
  812. /// <summary>Indicates whether the <see cref="PlayableGraph"/> is currently playing.</summary>
  813. public bool IsGraphPlaying
  814. {
  815. get => _IsGraphPlaying;
  816. set
  817. {
  818. if (value)
  819. UnpauseGraph();
  820. else
  821. PauseGraph();
  822. }
  823. }
  824. /// <summary>
  825. /// Resumes playing the <see cref="PlayableGraph"/> if <see cref="PauseGraph"/> was called previously.
  826. /// </summary>
  827. public void UnpauseGraph()
  828. {
  829. if (!_IsGraphPlaying)
  830. {
  831. _Graph.Play();
  832. _IsGraphPlaying = true;
  833. #if UNITY_EDITOR
  834. // In Edit Mode, unpausing the graph does not work properly unless we force it to change.
  835. if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
  836. Evaluate(Time.maximumDeltaTime);
  837. #endif
  838. }
  839. }
  840. /// <summary>
  841. /// Freezes the <see cref="PlayableGraph"/> at its current state.
  842. /// <para></para>
  843. /// If you call this method, you are responsible for calling <see cref="UnpauseGraph"/> to resume playing.
  844. /// </summary>
  845. public void PauseGraph()
  846. {
  847. if (_IsGraphPlaying)
  848. {
  849. _Graph.Stop();
  850. _IsGraphPlaying = false;
  851. }
  852. }
  853. /************************************************************************************************************************/
  854. /// <summary>
  855. /// Evaluates all of the currently playing animations to apply their states to the animated objects.
  856. /// </summary>
  857. public void Evaluate() => _Graph.Evaluate();
  858. /// <summary>
  859. /// Advances all currently playing animations by the specified amount of time (in seconds) and evaluates the
  860. /// graph to apply their states to the animated objects.
  861. /// </summary>
  862. public void Evaluate(float deltaTime) => _Graph.Evaluate(deltaTime);
  863. /************************************************************************************************************************/
  864. /// <summary>Returns a detailed descrption of all currently playing states and other registered states.</summary>
  865. public string GetDescription()
  866. {
  867. var text = ObjectPool.AcquireStringBuilder();
  868. AppendDescription(text);
  869. return text.ReleaseToString();
  870. }
  871. /// <summary>Appends a detailed descrption of all currently playing states and other registered states.</summary>
  872. public void AppendDescription(StringBuilder text)
  873. {
  874. text.Append($"{nameof(AnimancerPlayable)} (")
  875. .Append(Component)
  876. .Append(") Layer Count: ")
  877. .Append(Layers.Count);
  878. const string separator = "\n ";
  879. AnimancerNode.AppendIKDetails(text, separator, this);
  880. var count = Layers.Count;
  881. for (int i = 0; i < count; i++)
  882. {
  883. text.Append(separator);
  884. Layers[i].AppendDescription(text, separator);
  885. }
  886. text.AppendLine();
  887. AppendInternalDetails(text, Strings.Indent, Strings.Indent + Strings.Indent);
  888. }
  889. /// <summary>Appends all registered <see cref="IUpdatable"/>s and <see cref="IDisposable"/>s.</summary>
  890. public void AppendInternalDetails(StringBuilder text, string sectionPrefix, string itemPrefix)
  891. {
  892. AppendAll(text, sectionPrefix, itemPrefix, _PreUpdatables, "Pre Updatables");
  893. text.AppendLine();
  894. AppendAll(text, sectionPrefix, itemPrefix, _PostUpdatables, "Post Updatables");
  895. text.AppendLine();
  896. AppendAll(text, sectionPrefix, itemPrefix, _Disposables, "Disposables");
  897. }
  898. private static void AppendAll(StringBuilder text, string sectionPrefix, string itemPrefix, ICollection collection, string name)
  899. {
  900. var count = collection != null ? collection.Count : 0;
  901. text.Append(sectionPrefix).Append(name).Append(": ").Append(count);
  902. if (collection != null)
  903. {
  904. foreach (var item in collection)
  905. {
  906. text.AppendLine().Append(itemPrefix).Append(item);
  907. }
  908. }
  909. }
  910. /************************************************************************************************************************/
  911. #endregion
  912. /************************************************************************************************************************/
  913. #region Update
  914. /************************************************************************************************************************/
  915. /// <summary>[Pro-Only]
  916. /// Adds the `updatable` to the list that need to be updated before the playables if it was not there already.
  917. /// </summary>
  918. /// <remarks>
  919. /// This method is safe to call at any time, even during an update.
  920. /// <para></para>
  921. /// The execution order is non-deterministic. Specifically, the most recently added will be updated first and
  922. /// <see cref="CancelPreUpdate"/> will change the order by swapping the last one into the place of the removed
  923. /// object.
  924. /// </remarks>
  925. public void RequirePreUpdate(IUpdatable updatable)
  926. {
  927. #if UNITY_ASSERTIONS
  928. if (updatable is AnimancerNode node)
  929. {
  930. Validate.AssertPlayable(node);
  931. Validate.AssertRoot(node, this);
  932. }
  933. #endif
  934. _PreUpdatables.AddNew(updatable);
  935. }
  936. /************************************************************************************************************************/
  937. /// <summary>[Pro-Only]
  938. /// Adds the `updatable` to the list that need to be updated after the playables if it was not there already.
  939. /// </summary>
  940. /// <remarks>
  941. /// This method is safe to call at any time, even during an update.
  942. /// <para></para>
  943. /// The execution order is non-deterministic. Specifically, the most recently added will be updated first and
  944. /// <see cref="CancelPostUpdate"/> will change the order by swapping the last one into the place of the removed
  945. /// object.
  946. /// </remarks>
  947. public void RequirePostUpdate(IUpdatable updatable)
  948. {
  949. #if UNITY_ASSERTIONS
  950. if (updatable is AnimancerNode node)
  951. {
  952. Validate.AssertPlayable(node);
  953. Validate.AssertRoot(node, this);
  954. }
  955. #endif
  956. _PostUpdatables.AddNew(updatable);
  957. }
  958. /************************************************************************************************************************/
  959. /// <summary>Removes the `updatable` from the `updatables`.</summary>
  960. /// <remarks>
  961. /// This method is safe to call at any time, even during an update.
  962. /// <para></para>
  963. /// The last element is swapped into the place of the one being removed so that the rest of them do not need to
  964. /// be moved down one place to fill the gap. This is more efficient, but means that the update order can change.
  965. /// </remarks>
  966. private void CancelUpdate(Key.KeyedList<IUpdatable> updatables, IUpdatable updatable)
  967. {
  968. var index = updatables.IndexOf(updatable);
  969. if (index < 0)
  970. return;
  971. updatables.RemoveAtSwap(index);
  972. if (_CurrentUpdatable < index && updatables == _CurrentUpdatables)
  973. _CurrentUpdatable--;
  974. }
  975. /// <summary>Removes the `updatable` from the list of objects that need to be updated before the playables.</summary>
  976. /// <remarks>
  977. /// This method is safe to call at any time, even during an update.
  978. /// <para></para>
  979. /// The last element is swapped into the place of the one being removed so that the rest of them do not need to
  980. /// be moved down one place to fill the gap. This is more efficient, but means that the update order can change.
  981. /// </remarks>
  982. public void CancelPreUpdate(IUpdatable updatable) => CancelUpdate(_PreUpdatables, updatable);
  983. /// <summary>Removes the `updatable` from the list of objects that need to be updated after the playebles.</summary>
  984. /// <remarks>
  985. /// This method is safe to call at any time, even during an update.
  986. /// <para></para>
  987. /// The last element is swapped into the place of the one being removed so that the rest of them do not need to
  988. /// be moved down one place to fill the gap. This is more efficient, but means that the update order can change.
  989. /// </remarks>
  990. public void CancelPostUpdate(IUpdatable updatable) => CancelUpdate(_PostUpdatables, updatable);
  991. /************************************************************************************************************************/
  992. /// <summary>The number of objects that have been registered by <see cref="RequirePreUpdate"/>.</summary>
  993. public int PreUpdatableCount => _PreUpdatables.Count;
  994. /// <summary>The number of objects that have been registered by <see cref="RequirePostUpdate"/>.</summary>
  995. public int PostUpdatableCount => _PostUpdatables.Count;
  996. /************************************************************************************************************************/
  997. /// <summary>Returns the object registered by <see cref="RequirePreUpdate"/> at the specified `index`.</summary>
  998. public IUpdatable GetPreUpdatable(int index) => _PreUpdatables[index];
  999. /// <summary>Returns the object registered by <see cref="RequirePostUpdate"/> at the specified `index`.</summary>
  1000. public IUpdatable GetPostUpdatable(int index) => _PostUpdatables[index];
  1001. /************************************************************************************************************************/
  1002. /// <summary>The object currently executing <see cref="PrepareFrame"/>.</summary>
  1003. public static AnimancerPlayable Current { get; private set; }
  1004. /// <summary>The current <see cref="FrameData.deltaTime"/>.</summary>
  1005. /// <remarks>After <see cref="PrepareFrame"/>, this property will be left at its most recent value.</remarks>
  1006. public static float DeltaTime { get; private set; }
  1007. /// <summary>The current <see cref="FrameData.frameId"/>.</summary>
  1008. /// <remarks>
  1009. /// After <see cref="PrepareFrame"/>, this property will be left at its most recent value.
  1010. /// <para></para>
  1011. /// <see cref="AnimancerState.Time"/> uses this value to determine whether it has accessed the playable's time
  1012. /// since it was last updated in order to cache its value.
  1013. /// </remarks>
  1014. public ulong FrameID { get; private set; }
  1015. /// <summary>The list <see cref="IUpdatable"/>s currently being updated.</summary>
  1016. private static Key.KeyedList<IUpdatable> _CurrentUpdatables;
  1017. /// <summary>The index of the <see cref="IUpdatable"/> currently being updated.</summary>
  1018. private static int _CurrentUpdatable = -1;
  1019. /************************************************************************************************************************/
  1020. /// <summary>[Internal]
  1021. /// Calls <see cref="IUpdatable.Update"/> on everything registered using <see cref="RequirePreUpdate"/>.
  1022. /// </summary>
  1023. /// <remarks>
  1024. /// Called by the <see cref="PlayableGraph"/> before the rest of the <see cref="Playable"/>s are evaluated.
  1025. /// </remarks>
  1026. public override void PrepareFrame(Playable playable, FrameData info)
  1027. {
  1028. #if UNITY_ASSERTIONS
  1029. if (OptionalWarning.AnimatorSpeed.IsEnabled() && Component != null)
  1030. {
  1031. var animator = Component.Animator;
  1032. if (animator != null &&
  1033. animator.speed != 1 &&
  1034. animator.runtimeAnimatorController == null)
  1035. {
  1036. animator.speed = 1;
  1037. OptionalWarning.AnimatorSpeed.Log(
  1038. $"{nameof(Animator)}.{nameof(Animator.speed)} does not affect {nameof(Animancer)}." +
  1039. $" Use {nameof(AnimancerPlayable)}.{nameof(Speed)} instead.", animator);
  1040. }
  1041. }
  1042. #endif
  1043. UpdateAll(_PreUpdatables, info.deltaTime * info.effectiveParentSpeed);
  1044. if (!_KeepChildrenConnected)
  1045. _PostUpdate.IsConnected = _PostUpdatables.Count != 0;
  1046. // Any time before or during this method will still have all Playables at their time from last frame, so we
  1047. // don't want them to think their time is dirty until we are done.
  1048. FrameID = info.frameId;
  1049. }
  1050. /************************************************************************************************************************/
  1051. /// <summary>Calls <see cref="IUpdatable.Update"/> on each of the updatables`.</summary>
  1052. private void UpdateAll(Key.KeyedList<IUpdatable> updatables, float deltaTime)
  1053. {
  1054. var previous = Current;
  1055. Current = this;
  1056. var previousUpdatables = _CurrentUpdatables;
  1057. _CurrentUpdatables = updatables;
  1058. DeltaTime = deltaTime;
  1059. var previousUpdatable = _CurrentUpdatable;
  1060. _CurrentUpdatable = updatables.Count;
  1061. ContinueNodeLoop:
  1062. try
  1063. {
  1064. while (--_CurrentUpdatable >= 0)
  1065. {
  1066. updatables[_CurrentUpdatable].Update();
  1067. }
  1068. }
  1069. catch (Exception exception)
  1070. {
  1071. Debug.LogException(exception, Component as Object);
  1072. goto ContinueNodeLoop;
  1073. }
  1074. _CurrentUpdatable = previousUpdatable;
  1075. _CurrentUpdatables = previousUpdatables;
  1076. Current = previous;
  1077. }
  1078. /************************************************************************************************************************/
  1079. #region Post Update
  1080. /************************************************************************************************************************/
  1081. /// <summary>Indicates whether the internal <see cref="PostUpdate"/> is currently executing.</summary>
  1082. public static bool IsRunningPostUpdate(AnimancerPlayable animancer) => _CurrentUpdatables == animancer._PostUpdatables;
  1083. /************************************************************************************************************************/
  1084. /// <summary>
  1085. /// A <see cref="PlayableBehaviour"/> which connects to a later port than the main layer mixer so that its
  1086. /// <see cref="PrepareFrame"/> method gets called after all other playables are updated in order to call
  1087. /// <see cref="IUpdatable.Update"/> on the <see cref="_PostUpdatables"/>.
  1088. /// </summary>
  1089. private class PostUpdate : PlayableBehaviour
  1090. {
  1091. /************************************************************************************************************************/
  1092. /// <summary>See <see cref="AnimancerPlayable.Template"/>.</summary>
  1093. private static readonly PostUpdate Template = new PostUpdate();
  1094. /// <summary>The <see cref="AnimancerPlayable"/> this behaviour is connected to.</summary>
  1095. private AnimancerPlayable _Root;
  1096. /// <summary>The underlying <see cref="Playable"/> of this behaviour.</summary>
  1097. private Playable _Playable;
  1098. /************************************************************************************************************************/
  1099. /// <summary>Creates a new <see cref="PostUpdate"/> for the `root`.</summary>
  1100. public static PostUpdate Create(AnimancerPlayable root)
  1101. {
  1102. var instance = ScriptPlayable<PostUpdate>.Create(root._Graph, Template, 0)
  1103. .GetBehaviour();
  1104. instance._Root = root;
  1105. return instance;
  1106. }
  1107. /************************************************************************************************************************/
  1108. /// <summary>[Internal] Called by Unity when it creates this <see cref="AnimancerPlayable"/>.</summary>
  1109. public override void OnPlayableCreate(Playable playable) => _Playable = playable;
  1110. /************************************************************************************************************************/
  1111. private bool _IsConnected;
  1112. /// <summary>
  1113. /// Indicates whether this behaviour is connected to the <see cref="PlayableGraph"/> and thus, whether it
  1114. /// will receive <see cref="PrepareFrame"/> calls.
  1115. /// </summary>
  1116. public bool IsConnected
  1117. {
  1118. get => _IsConnected;
  1119. set
  1120. {
  1121. if (value)
  1122. {
  1123. if (!_IsConnected)
  1124. {
  1125. _IsConnected = true;
  1126. _Root._Graph.Connect(_Playable, 0, _Root._RootPlayable, 1);
  1127. }
  1128. }
  1129. else
  1130. {
  1131. if (_IsConnected)
  1132. {
  1133. _IsConnected = false;
  1134. _Root._Graph.Disconnect(_Root._RootPlayable, 1);
  1135. }
  1136. }
  1137. }
  1138. }
  1139. /************************************************************************************************************************/
  1140. /// <summary>[Internal]
  1141. /// Calls <see cref="IUpdatable.Update"/> on everything registered using <see cref="RequirePostUpdate"/>.
  1142. /// </summary>
  1143. /// <remarks>
  1144. /// Called by the <see cref="PlayableGraph"/> after the rest of the <see cref="Playable"/>s are evaluated.
  1145. /// </remarks>
  1146. public override void PrepareFrame(Playable playable, FrameData info)
  1147. {
  1148. _Root.UpdateAll(_Root._PostUpdatables, info.deltaTime * info.effectiveParentSpeed);
  1149. // Ideally we would be able to update the dirty nodes here instead of in the early update so that they
  1150. // can respond immediately to the effects of the post update.
  1151. // However, doing that with KeepChildrenConnected == false causes problems where states that aren't
  1152. // connected early (before they update) don't affect the output even though weight changes do apply. So
  1153. // in the first frame when cross fading to a new animation it will lower the weight of the previous
  1154. // state a bit without the corresponding increase to the new animation's weight having any effect,
  1155. // giving a total weight less than 1 and thus an incorrect output.
  1156. }
  1157. /************************************************************************************************************************/
  1158. }
  1159. /************************************************************************************************************************/
  1160. #endregion
  1161. /************************************************************************************************************************/
  1162. #endregion
  1163. /************************************************************************************************************************/
  1164. #region Editor
  1165. #if UNITY_EDITOR
  1166. /************************************************************************************************************************/
  1167. private static List<AnimancerPlayable> _AllInstances;
  1168. /// <summary>[Editor-Only]
  1169. /// Registers this object in the list of things that need to be cleaned up in Edit Mode.
  1170. /// </summary>
  1171. private void RegisterInstance()
  1172. {
  1173. if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
  1174. return;
  1175. if (_AllInstances == null)
  1176. {
  1177. _AllInstances = new List<AnimancerPlayable>();
  1178. UnityEditor.AssemblyReloadEvents.beforeAssemblyReload += () =>
  1179. {
  1180. for (int i = _AllInstances.Count - 1; i >= 0; i--)
  1181. {
  1182. var playable = _AllInstances[i];
  1183. if (playable.IsValid)
  1184. playable.DestroyGraph();
  1185. }
  1186. _AllInstances.Clear();
  1187. };
  1188. }
  1189. else// Clear out any old instances.
  1190. {
  1191. for (int i = _AllInstances.Count - 1; i >= 0; i--)
  1192. {
  1193. var playable = _AllInstances[i];
  1194. if (!playable.ShouldStayAlive())
  1195. {
  1196. if (playable.IsValid)
  1197. playable.DestroyGraph();
  1198. _AllInstances.RemoveAt(i);
  1199. }
  1200. }
  1201. }
  1202. _AllInstances.Add(this);
  1203. }
  1204. /************************************************************************************************************************/
  1205. /// <summary>Should this playable should stay alive instead of being destroyed?</summary>
  1206. private bool ShouldStayAlive()
  1207. {
  1208. if (!IsValid)
  1209. return false;
  1210. if (Component == null)
  1211. return true;
  1212. if (Component is Object obj && obj == null)
  1213. return false;
  1214. if (Component.Animator == null)
  1215. return false;
  1216. return true;
  1217. }
  1218. /************************************************************************************************************************/
  1219. /// <summary>[Editor-Only]
  1220. /// Returns true if the `initial` mode was <see cref="AnimatorUpdateMode.AnimatePhysics"/> and the `current`
  1221. /// has changed to another mode or if the `initial` mode was something else and the `current` has changed to
  1222. /// <see cref="AnimatorUpdateMode.AnimatePhysics"/>.
  1223. /// </summary>
  1224. public static bool HasChangedToOrFromAnimatePhysics(AnimatorUpdateMode? initial, AnimatorUpdateMode current)
  1225. {
  1226. if (initial == null)
  1227. return false;
  1228. var wasAnimatePhysics = initial.Value == AnimatorUpdateMode.AnimatePhysics;
  1229. var isAnimatePhysics = current == AnimatorUpdateMode.AnimatePhysics;
  1230. return wasAnimatePhysics != isAnimatePhysics;
  1231. }
  1232. /************************************************************************************************************************/
  1233. #endif
  1234. #endregion
  1235. /************************************************************************************************************************/
  1236. }
  1237. }