ControllerState.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Animations;
  6. using UnityEngine.Playables;
  7. using Object = UnityEngine.Object;
  8. using System.Runtime.CompilerServices;
  9. namespace Animancer
  10. {
  11. /// <summary>[Pro-Only] An <see cref="AnimancerState"/> which plays a <see cref="RuntimeAnimatorController"/>.</summary>
  12. /// <remarks>
  13. /// You can control this state very similarly to an <see cref="Animator"/> via its <see cref="Playable"/> property.
  14. /// <para></para>
  15. /// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/animator-controllers">Animator Controllers</see>
  16. /// </remarks>
  17. /// https://kybernetik.com.au/animancer/api/Animancer/ControllerState
  18. ///
  19. public partial class ControllerState : AnimancerState
  20. {
  21. /************************************************************************************************************************/
  22. /// <summary>An <see cref="ITransition{TState}"/> that creates a <see cref="ControllerState"/>.</summary>
  23. public interface ITransition : ITransition<ControllerState> { }
  24. /************************************************************************************************************************/
  25. #region Fields and Properties
  26. /************************************************************************************************************************/
  27. private RuntimeAnimatorController _Controller;
  28. /// <summary>The <see cref="RuntimeAnimatorController"/> which this state plays.</summary>
  29. public RuntimeAnimatorController Controller
  30. {
  31. get => _Controller;
  32. set => ChangeMainObject(ref _Controller, value);
  33. }
  34. /// <summary>The <see cref="RuntimeAnimatorController"/> which this state plays.</summary>
  35. public override Object MainObject
  36. {
  37. get => Controller;
  38. set => Controller = (RuntimeAnimatorController)value;
  39. }
  40. /// <summary>The internal system which plays the <see cref="RuntimeAnimatorController"/>.</summary>
  41. public AnimatorControllerPlayable Playable
  42. {
  43. get
  44. {
  45. Validate.AssertPlayable(this);
  46. return _Playable;
  47. }
  48. }
  49. private new AnimatorControllerPlayable _Playable;
  50. /************************************************************************************************************************/
  51. /// <summary>Determines what a layer does when <see cref="Stop"/> is called.</summary>
  52. public enum ActionOnStop
  53. {
  54. /// <summary>Reset the layer to the first state it was in.</summary>
  55. DefaultState,
  56. /// <summary>Rewind the current state's time to 0.</summary>
  57. RewindTime,
  58. /// <summary>Allow the current state to stay at its current time.</summary>
  59. Continue,
  60. }
  61. private ActionOnStop[] _ActionsOnStop;
  62. /// <summary>Determines what each layer does when <see cref="Stop"/> is called.</summary>
  63. /// <remarks>
  64. /// If empty, all layers will reset to their <see cref="ActionOnStop.DefaultState"/>.
  65. /// <para></para>
  66. /// If this array is smaller than the <see cref="AnimatorControllerPlayable.GetLayerCount"/>, any additional
  67. /// layers will use the last value in this array.
  68. /// </remarks>
  69. public ActionOnStop[] ActionsOnStop
  70. {
  71. get => _ActionsOnStop;
  72. set
  73. {
  74. _ActionsOnStop = value;
  75. if (_Playable.IsValid())
  76. GatherDefaultStates();
  77. }
  78. }
  79. /// <summary>
  80. /// The <see cref="AnimatorStateInfo.shortNameHash"/> of the default state on each layer, used to reset to
  81. /// those states when <see cref="ApplyActionsOnStop"/> is called for layers using
  82. /// <see cref="ActionOnStop.DefaultState"/>.
  83. /// </summary>
  84. /// <remarks>Gathered using <see cref="GatherDefaultStates"/>.</remarks>
  85. public int[] DefaultStateHashes { get; set; }
  86. /************************************************************************************************************************/
  87. #if UNITY_ASSERTIONS
  88. /// <summary>[Assert-Only] Animancer Events doesn't work properly on <see cref="ControllerState"/>s.</summary>
  89. protected override string UnsupportedEventsMessage =>
  90. "Animancer Events on " + nameof(ControllerState) + "s will probably not work as expected." +
  91. " The events will be associated with the entire Animator Controller and be triggered by any of the" +
  92. " states inside it. If you want to use events in an Animator Controller you will likely need to use" +
  93. " Unity's regular Animation Event system.";
  94. /// <summary>[Assert-Only]
  95. /// <see cref="PlayableExtensions.SetSpeed"/> does nothing on <see cref="ControllerState"/>s.
  96. /// </summary>
  97. protected override string UnsupportedSpeedMessage =>
  98. nameof(PlayableExtensions) + "." + nameof(PlayableExtensions.SetSpeed) + " does nothing on " + nameof(ControllerState) +
  99. "s so there is no way to directly control their speed." +
  100. " The Animator Controller Speed page explains a possible workaround for this issue:" +
  101. " https://kybernetik.com.au/animancer/docs/bugs/animator-controller-speed";
  102. #endif
  103. /************************************************************************************************************************/
  104. /// <summary>[Assert-Conditional] Asserts that the `value` is valid.</summary>
  105. /// <exception cref="ArgumentOutOfRangeException">The `value` is NaN or Infinity.</exception>
  106. [System.Diagnostics.Conditional(Strings.Assertions)]
  107. public void AssertParameterValue(float value, [CallerMemberName] string parameterName = null)
  108. {
  109. if (!value.IsFinite())
  110. throw new ArgumentOutOfRangeException(parameterName, Strings.MustBeFinite);
  111. }
  112. /************************************************************************************************************************/
  113. /// <summary>IK cannot be dynamically enabled on a <see cref="ControllerState"/>.</summary>
  114. public override void CopyIKFlags(AnimancerNode node) { }
  115. /************************************************************************************************************************/
  116. /// <summary>IK cannot be dynamically enabled on a <see cref="ControllerState"/>.</summary>
  117. public override bool ApplyAnimatorIK
  118. {
  119. get => false;
  120. set
  121. {
  122. #if UNITY_ASSERTIONS
  123. if (value)
  124. OptionalWarning.UnsupportedIK.Log($"IK cannot be dynamically enabled on a {nameof(ControllerState)}." +
  125. " You must instead enable it on the desired layer inside the Animator Controller.", _Controller);
  126. #endif
  127. }
  128. }
  129. /************************************************************************************************************************/
  130. /// <summary>IK cannot be dynamically enabled on a <see cref="ControllerState"/>.</summary>
  131. public override bool ApplyFootIK
  132. {
  133. get => false;
  134. set
  135. {
  136. #if UNITY_ASSERTIONS
  137. if (value)
  138. OptionalWarning.UnsupportedIK.Log($"IK cannot be dynamically enabled on a {nameof(ControllerState)}." +
  139. " You must instead enable it on the desired state inside the Animator Controller.", _Controller);
  140. #endif
  141. }
  142. }
  143. /************************************************************************************************************************/
  144. /// <summary>The number of parameters being wrapped by this state.</summary>
  145. public virtual int ParameterCount => 0;
  146. /// <summary>Returns the hash of a parameter being wrapped by this state.</summary>
  147. /// <exception cref="NotSupportedException">This state doesn't wrap any parameters.</exception>
  148. public virtual int GetParameterHash(int index) => throw new NotSupportedException();
  149. /************************************************************************************************************************/
  150. #endregion
  151. /************************************************************************************************************************/
  152. #region Public API
  153. /************************************************************************************************************************/
  154. /// <summary>Creates a new <see cref="ControllerState"/> to play the `controller`.</summary>
  155. public ControllerState(RuntimeAnimatorController controller)
  156. {
  157. if (controller == null)
  158. throw new ArgumentNullException(nameof(controller));
  159. _Controller = controller;
  160. }
  161. /// <summary>Creates a new <see cref="ControllerState"/> to play the `controller`.</summary>
  162. public ControllerState(RuntimeAnimatorController controller, params ActionOnStop[] actionsOnStop)
  163. : this(controller)
  164. {
  165. _ActionsOnStop = actionsOnStop;
  166. }
  167. /************************************************************************************************************************/
  168. /// <summary>Creates and assigns the <see cref="AnimatorControllerPlayable"/> managed by this state.</summary>
  169. protected override void CreatePlayable(out Playable playable)
  170. {
  171. playable = _Playable = AnimatorControllerPlayable.Create(Root._Graph, _Controller);
  172. GatherDefaultStates();
  173. }
  174. /************************************************************************************************************************/
  175. /// <summary>
  176. /// Stores the values of all parameters, calls <see cref="AnimancerNode.DestroyPlayable"/>, then restores the
  177. /// parameter values.
  178. /// </summary>
  179. public override void RecreatePlayable()
  180. {
  181. if (!_Playable.IsValid())
  182. {
  183. CreatePlayable();
  184. return;
  185. }
  186. var parameterCount = _Playable.GetParameterCount();
  187. var values = new object[parameterCount];
  188. for (int i = 0; i < parameterCount; i++)
  189. {
  190. values[i] = AnimancerUtilities.GetParameterValue(_Playable, _Playable.GetParameter(i));
  191. }
  192. base.RecreatePlayable();
  193. for (int i = 0; i < parameterCount; i++)
  194. {
  195. AnimancerUtilities.SetParameterValue(_Playable, _Playable.GetParameter(i), values[i]);
  196. }
  197. }
  198. /************************************************************************************************************************/
  199. /// <summary>
  200. /// Returns the current state on the specified `layer`, or the next state if it is currently in a transition.
  201. /// </summary>
  202. public AnimatorStateInfo GetStateInfo(int layerIndex)
  203. {
  204. Validate.AssertPlayable(this);
  205. return _Playable.IsInTransition(layerIndex) ?
  206. _Playable.GetNextAnimatorStateInfo(layerIndex) :
  207. _Playable.GetCurrentAnimatorStateInfo(layerIndex);
  208. }
  209. /************************************************************************************************************************/
  210. /// <summary>
  211. /// The <see cref="AnimatorStateInfo.normalizedTime"/> * <see cref="AnimatorStateInfo.length"/> of layer 0.
  212. /// </summary>
  213. protected override float RawTime
  214. {
  215. get
  216. {
  217. var info = GetStateInfo(0);
  218. return info.normalizedTime * info.length;
  219. }
  220. set
  221. {
  222. Validate.AssertPlayable(this);
  223. _Playable.PlayInFixedTime(0, 0, value);
  224. if (!IsPlaying)
  225. {
  226. _Playable.Play();
  227. DelayedPause.Register(this);
  228. }
  229. }
  230. }
  231. /************************************************************************************************************************/
  232. /// <summary>The current <see cref="AnimatorStateInfo.length"/> of layer 0.</summary>
  233. public override float Length => GetStateInfo(0).length;
  234. /************************************************************************************************************************/
  235. /// <summary>Indicates whether the current state on layer 0 will loop back to the start when it reaches the end.</summary>
  236. public override bool IsLooping => GetStateInfo(0).loop;
  237. /************************************************************************************************************************/
  238. /// <summary>Gathers the <see cref="DefaultStateHashes"/> from the current states on each layer.</summary>
  239. public void GatherDefaultStates()
  240. {
  241. Validate.AssertPlayable(this);
  242. var layerCount = _Playable.GetLayerCount();
  243. if (DefaultStateHashes == null || DefaultStateHashes.Length != layerCount)
  244. DefaultStateHashes = new int[layerCount];
  245. while (--layerCount >= 0)
  246. DefaultStateHashes[layerCount] = _Playable.GetCurrentAnimatorStateInfo(layerCount).shortNameHash;
  247. }
  248. /************************************************************************************************************************/
  249. /// <summary>
  250. /// Stops the animation and makes it inactive immediately so it no longer affects the output.
  251. /// Also calls <see cref="ApplyActionsOnStop"/>.
  252. /// </summary>
  253. public override void Stop()
  254. {
  255. // Don't call base.Stop(); because it sets Time = 0; which uses PlayInFixedTime and interferes with
  256. // resetting to the default states.
  257. Weight = 0;
  258. IsPlaying = false;
  259. if (AutomaticallyClearEvents)
  260. Events = null;
  261. ApplyActionsOnStop();
  262. }
  263. /// <summary>Applies the <see cref="ActionsOnStop"/> to their corresponding layers.</summary>
  264. /// <exception cref="NullReferenceException"><see cref="DefaultStateHashes"/> is null.</exception>
  265. public void ApplyActionsOnStop()
  266. {
  267. Validate.AssertPlayable(this);
  268. var layerCount = Math.Min(DefaultStateHashes.Length, _Playable.GetLayerCount());
  269. if (_ActionsOnStop == null || _ActionsOnStop.Length == 0)
  270. {
  271. for (int i = layerCount - 1; i >= 0; i--)
  272. _Playable.Play(DefaultStateHashes[i], i, 0);
  273. }
  274. else
  275. {
  276. for (int i = layerCount - 1; i >= 0; i--)
  277. {
  278. var index = i < _ActionsOnStop.Length ? i : _ActionsOnStop.Length - 1;
  279. switch (_ActionsOnStop[index])
  280. {
  281. case ActionOnStop.DefaultState:
  282. _Playable.Play(DefaultStateHashes[i], i, 0);
  283. break;
  284. case ActionOnStop.RewindTime:
  285. _Playable.Play(0, i, 0);
  286. break;
  287. case ActionOnStop.Continue:
  288. break;
  289. }
  290. }
  291. }
  292. // Allowing the RawTime to be applied prevents the default state from being played because
  293. // Animator Controllers don't properly respond to multiple Play calls in the same frame.
  294. CancelSetTime();
  295. }
  296. /************************************************************************************************************************/
  297. /// <inheritdoc/>
  298. public override void GatherAnimationClips(ICollection<AnimationClip> clips)
  299. {
  300. if (_Controller != null)
  301. clips.Gather(_Controller.animationClips);
  302. }
  303. /************************************************************************************************************************/
  304. /// <inheritdoc/>
  305. public override void Destroy()
  306. {
  307. _Controller = null;
  308. base.Destroy();
  309. }
  310. /************************************************************************************************************************/
  311. #endregion
  312. /************************************************************************************************************************/
  313. #region Animator Controller Wrappers
  314. /************************************************************************************************************************/
  315. #region Cross Fade
  316. /************************************************************************************************************************/
  317. /// <summary>
  318. /// The default constant for fade duration parameters which causes it to use the
  319. /// <see cref="AnimancerPlayable.DefaultFadeDuration"/> instead.
  320. /// </summary>
  321. public const float DefaultFadeDuration = -1;
  322. /************************************************************************************************************************/
  323. /// <summary>
  324. /// Returns the `fadeDuration` if it is zero or positive. Otherwise returns the
  325. /// <see cref="AnimancerPlayable.DefaultFadeDuration"/>.
  326. /// </summary>
  327. public static float GetFadeDuration(float fadeDuration)
  328. => fadeDuration >= 0 ? fadeDuration : AnimancerPlayable.DefaultFadeDuration;
  329. /************************************************************************************************************************/
  330. /// <summary>Starts a transition from the current state to the specified state using normalized times.</summary>
  331. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerPlayable.DefaultFadeDuration"/>.</remarks>
  332. public void CrossFade(int stateNameHash,
  333. float fadeDuration = DefaultFadeDuration,
  334. int layer = -1,
  335. float normalizedTime = float.NegativeInfinity)
  336. => Playable.CrossFade(stateNameHash, GetFadeDuration(fadeDuration), layer, normalizedTime);
  337. /************************************************************************************************************************/
  338. /// <summary>Starts a transition from the current state to the specified state using normalized times.</summary>
  339. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerPlayable.DefaultFadeDuration"/>.</remarks>
  340. public void CrossFade(string stateName,
  341. float fadeDuration = DefaultFadeDuration,
  342. int layer = -1,
  343. float normalizedTime = float.NegativeInfinity)
  344. => Playable.CrossFade(stateName, GetFadeDuration(fadeDuration), layer, normalizedTime);
  345. /************************************************************************************************************************/
  346. /// <summary>Starts a transition from the current state to the specified state using times in seconds.</summary>
  347. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerPlayable.DefaultFadeDuration"/>.</remarks>
  348. public void CrossFadeInFixedTime(int stateNameHash,
  349. float fadeDuration = DefaultFadeDuration,
  350. int layer = -1,
  351. float fixedTime = 0)
  352. => Playable.CrossFadeInFixedTime(stateNameHash, GetFadeDuration(fadeDuration), layer, fixedTime);
  353. /************************************************************************************************************************/
  354. /// <summary>Starts a transition from the current state to the specified state using times in seconds.</summary>
  355. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerPlayable.DefaultFadeDuration"/>.</remarks>
  356. public void CrossFadeInFixedTime(string stateName,
  357. float fadeDuration = DefaultFadeDuration,
  358. int layer = -1,
  359. float fixedTime = 0)
  360. => Playable.CrossFadeInFixedTime(stateName, GetFadeDuration(fadeDuration), layer, fixedTime);
  361. /************************************************************************************************************************/
  362. #endregion
  363. /************************************************************************************************************************/
  364. #region Play
  365. /************************************************************************************************************************/
  366. /// <summary>Plays the specified state immediately, starting from a particular normalized time.</summary>
  367. public void Play(int stateNameHash,
  368. int layer = -1,
  369. float normalizedTime = float.NegativeInfinity)
  370. => Playable.Play(stateNameHash, layer, normalizedTime);
  371. /************************************************************************************************************************/
  372. /// <summary>Plays the specified state immediately, starting from a particular normalized time.</summary>
  373. public void Play(string stateName,
  374. int layer = -1,
  375. float normalizedTime = float.NegativeInfinity)
  376. => Playable.Play(stateName, layer, normalizedTime);
  377. /************************************************************************************************************************/
  378. /// <summary>Plays the specified state immediately, starting from a particular time (in seconds).</summary>
  379. public void PlayInFixedTime(int stateNameHash,
  380. int layer = -1,
  381. float fixedTime = 0)
  382. => Playable.PlayInFixedTime(stateNameHash, layer, fixedTime);
  383. /************************************************************************************************************************/
  384. /// <summary>Plays the specified state immediately, starting from a particular time (in seconds).</summary>
  385. public void PlayInFixedTime(string stateName,
  386. int layer = -1,
  387. float fixedTime = 0)
  388. => Playable.PlayInFixedTime(stateName, layer, fixedTime);
  389. /************************************************************************************************************************/
  390. #endregion
  391. /************************************************************************************************************************/
  392. #region Parameters
  393. /************************************************************************************************************************/
  394. /// <summary>Gets the value of the specified boolean parameter.</summary>
  395. public bool GetBool(int id) => Playable.GetBool(id);
  396. /// <summary>Gets the value of the specified boolean parameter.</summary>
  397. public bool GetBool(string name) => Playable.GetBool(name);
  398. /// <summary>Sets the value of the specified boolean parameter.</summary>
  399. public void SetBool(int id, bool value) => Playable.SetBool(id, value);
  400. /// <summary>Sets the value of the specified boolean parameter.</summary>
  401. public void SetBool(string name, bool value) => Playable.SetBool(name, value);
  402. /// <summary>Gets the value of the specified float parameter.</summary>
  403. public float GetFloat(int id) => Playable.GetFloat(id);
  404. /// <summary>Gets the value of the specified float parameter.</summary>
  405. public float GetFloat(string name) => Playable.GetFloat(name);
  406. /// <summary>Sets the value of the specified float parameter.</summary>
  407. public void SetFloat(int id, float value) => Playable.SetFloat(id, value);
  408. /// <summary>Sets the value of the specified float parameter.</summary>
  409. public void SetFloat(string name, float value) => Playable.SetFloat(name, value);
  410. /// <summary>Gets the value of the specified integer parameter.</summary>
  411. public int GetInteger(int id) => Playable.GetInteger(id);
  412. /// <summary>Gets the value of the specified integer parameter.</summary>
  413. public int GetInteger(string name) => Playable.GetInteger(name);
  414. /// <summary>Sets the value of the specified integer parameter.</summary>
  415. public void SetInteger(int id, int value) => Playable.SetInteger(id, value);
  416. /// <summary>Sets the value of the specified integer parameter.</summary>
  417. public void SetInteger(string name, int value) => Playable.SetInteger(name, value);
  418. /// <summary>Sets the specified trigger parameter to true.</summary>
  419. public void SetTrigger(int id) => Playable.SetTrigger(id);
  420. /// <summary>Sets the specified trigger parameter to true.</summary>
  421. public void SetTrigger(string name) => Playable.SetTrigger(name);
  422. /// <summary>Resets the specified trigger parameter to false.</summary>
  423. public void ResetTrigger(int id) => Playable.ResetTrigger(id);
  424. /// <summary>Resets the specified trigger parameter to false.</summary>
  425. public void ResetTrigger(string name) => Playable.ResetTrigger(name);
  426. /// <summary>Gets the details of one of the <see cref="Controller"/>'s parameters.</summary>
  427. public AnimatorControllerParameter GetParameter(int index) => Playable.GetParameter(index);
  428. /// <summary>Gets the number of parameters in the <see cref="Controller"/>.</summary>
  429. public int GetParameterCount() => Playable.GetParameterCount();
  430. /// <summary>Indicates whether the specified parameter is controlled by an <see cref="AnimationClip"/>.</summary>
  431. public bool IsParameterControlledByCurve(int id) => Playable.IsParameterControlledByCurve(id);
  432. /// <summary>Indicates whether the specified parameter is controlled by an <see cref="AnimationClip"/>.</summary>
  433. public bool IsParameterControlledByCurve(string name) => Playable.IsParameterControlledByCurve(name);
  434. /************************************************************************************************************************/
  435. #endregion
  436. /************************************************************************************************************************/
  437. #region Misc
  438. /************************************************************************************************************************/
  439. // Layers.
  440. /************************************************************************************************************************/
  441. /// <summary>Gets the weight of the layer at the specified index.</summary>
  442. public float GetLayerWeight(int layerIndex) => Playable.GetLayerWeight(layerIndex);
  443. /// <summary>Sets the weight of the layer at the specified index.</summary>
  444. public void SetLayerWeight(int layerIndex, float weight) => Playable.SetLayerWeight(layerIndex, weight);
  445. /// <summary>Gets the number of layers in the <see cref="Controller"/>.</summary>
  446. public int GetLayerCount() => Playable.GetLayerCount();
  447. /// <summary>Gets the index of the layer with the specified name.</summary>
  448. public int GetLayerIndex(string layerName) => Playable.GetLayerIndex(layerName);
  449. /// <summary>Gets the name of the layer with the specified index.</summary>
  450. public string GetLayerName(int layerIndex) => Playable.GetLayerName(layerIndex);
  451. /************************************************************************************************************************/
  452. // States.
  453. /************************************************************************************************************************/
  454. /// <summary>Returns information about the current state.</summary>
  455. public AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex = 0) => Playable.GetCurrentAnimatorStateInfo(layerIndex);
  456. /// <summary>Returns information about the next state being transitioned towards.</summary>
  457. public AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex = 0) => Playable.GetNextAnimatorStateInfo(layerIndex);
  458. /// <summary>Indicates whether the specified layer contains the specified state.</summary>
  459. public bool HasState(int layerIndex, int stateID) => Playable.HasState(layerIndex, stateID);
  460. /************************************************************************************************************************/
  461. // Transitions.
  462. /************************************************************************************************************************/
  463. /// <summary>Indicates whether the specified layer is currently executing a transition.</summary>
  464. public bool IsInTransition(int layerIndex = 0) => Playable.IsInTransition(layerIndex);
  465. /// <summary>Gets information about the current transition.</summary>
  466. public AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex = 0) => Playable.GetAnimatorTransitionInfo(layerIndex);
  467. /************************************************************************************************************************/
  468. // Clips.
  469. /************************************************************************************************************************/
  470. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being played.</summary>
  471. public AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex = 0) => Playable.GetCurrentAnimatorClipInfo(layerIndex);
  472. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being played.</summary>
  473. public void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => Playable.GetCurrentAnimatorClipInfo(layerIndex, clips);
  474. /// <summary>Gets the number of <see cref="AnimationClip"/>s currently being played.</summary>
  475. public int GetCurrentAnimatorClipInfoCount(int layerIndex = 0) => Playable.GetCurrentAnimatorClipInfoCount(layerIndex);
  476. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  477. public AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex = 0) => Playable.GetNextAnimatorClipInfo(layerIndex);
  478. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  479. public void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => Playable.GetNextAnimatorClipInfo(layerIndex, clips);
  480. /// <summary>Gets the number of <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  481. public int GetNextAnimatorClipInfoCount(int layerIndex = 0) => Playable.GetNextAnimatorClipInfoCount(layerIndex);
  482. /************************************************************************************************************************/
  483. #endregion
  484. /************************************************************************************************************************/
  485. #endregion
  486. /************************************************************************************************************************/
  487. }
  488. }