ControllerState.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.CompilerServices;
  5. using UnityEngine;
  6. using UnityEngine.Animations;
  7. using UnityEngine.Playables;
  8. using Object = UnityEngine.Object;
  9. namespace Animancer
  10. {
  11. /// <summary>[Pro-Only]
  12. /// An <see cref="AnimancerState"/> which plays a <see cref="RuntimeAnimatorController"/>.
  13. /// </summary>
  14. /// <remarks>
  15. /// This state can be controlled very similarly to an <see cref="Animator"/>
  16. /// via its <see cref="Playable"/> property.
  17. /// <para></para>
  18. /// <strong>Documentation:</strong>
  19. /// <see href="https://kybernetik.com.au/animancer/docs/manual/animator-controllers">
  20. /// Animator Controllers</see>
  21. /// </remarks>
  22. /// https://kybernetik.com.au/animancer/api/Animancer/ControllerState
  23. ///
  24. public partial class ControllerState : AnimancerState,
  25. ICopyable<ControllerState>,
  26. IParametizedState,
  27. IUpdatable
  28. {
  29. /************************************************************************************************************************/
  30. #region Fields and Properties
  31. /************************************************************************************************************************/
  32. private RuntimeAnimatorController _Controller;
  33. /// <summary>The <see cref="RuntimeAnimatorController"/> which this state plays.</summary>
  34. public RuntimeAnimatorController Controller
  35. {
  36. get => _Controller;
  37. set => ChangeMainObject(ref _Controller, value);
  38. }
  39. /// <summary>The <see cref="RuntimeAnimatorController"/> which this state plays.</summary>
  40. public override Object MainObject
  41. {
  42. get => Controller;
  43. set => Controller = (RuntimeAnimatorController)value;
  44. }
  45. #if UNITY_EDITOR
  46. /// <inheritdoc/>
  47. public override Type MainObjectType
  48. => typeof(RuntimeAnimatorController);
  49. #endif
  50. /************************************************************************************************************************/
  51. private new AnimatorControllerPlayable _Playable;
  52. /// <summary>The internal system which plays the <see cref="RuntimeAnimatorController"/>.</summary>
  53. public new AnimatorControllerPlayable Playable
  54. {
  55. get
  56. {
  57. Validate.AssertPlayable(this);
  58. return _Playable;
  59. }
  60. }
  61. /************************************************************************************************************************/
  62. /// <summary>Determines what a layer does when <see cref="AnimancerNode.Stop"/> is called.</summary>
  63. public enum ActionOnStop
  64. {
  65. /// <summary>Reset the layer to the first state it was in.</summary>
  66. DefaultState,
  67. /// <summary>Rewind the current state's time to 0.</summary>
  68. RewindTime,
  69. /// <summary>Allow the current state to stay at its current time.</summary>
  70. Continue,
  71. }
  72. /// <summary>Determines what each layer does when <see cref="AnimancerNode.Stop"/> is called.</summary>
  73. /// <remarks>
  74. /// If empty, all layers will reset to their <see cref="ActionOnStop.DefaultState"/>.
  75. /// <para></para>
  76. /// If this array is smaller than the <see cref="AnimatorControllerPlayable.GetLayerCount"/>,
  77. /// any additional layers will use the last value in this array.
  78. /// </remarks>
  79. public ActionOnStop[] ActionsOnStop { get; set; }
  80. /// <summary>
  81. /// The <see cref="AnimatorStateInfo.shortNameHash"/> of the default state on each layer,
  82. /// used to reset to those states when <see cref="ApplyActionsOnStop"/>
  83. /// is called for layers using <see cref="ActionOnStop.DefaultState"/>.
  84. /// </summary>
  85. /// <remarks>Gathered automatically by <see cref="GatherDefaultStates"/>.</remarks>
  86. public int[] DefaultStateHashes { get; set; }
  87. /************************************************************************************************************************/
  88. #if UNITY_ASSERTIONS
  89. /************************************************************************************************************************/
  90. /// <summary>[Assert-Only] Animancer Events work badly on <see cref="ControllerState"/>s.</summary>
  91. protected internal override string UnsupportedEventsMessage =>
  92. "Animancer Events on " + nameof(ControllerState) + "s will probably not work as expected." +
  93. " The events will be associated with the entire Animator Controller and be triggered by any of the" +
  94. " states inside it. If you want to use events in an Animator Controller you will likely need to use" +
  95. " Unity's regular Animation Event system.";
  96. /************************************************************************************************************************/
  97. #endif
  98. /************************************************************************************************************************/
  99. /// <summary>[Assert-Conditional] Asserts that the `value` is valid for a parameter.</summary>
  100. /// <exception cref="ArgumentOutOfRangeException">The `value` is NaN or Infinity.</exception>
  101. [System.Diagnostics.Conditional(Strings.Assertions)]
  102. public void AssertParameterValue(float value, [CallerMemberName] string parameterName = null)
  103. {
  104. if (!value.IsFinite())
  105. {
  106. MarkAsUsed(this);
  107. throw new ArgumentOutOfRangeException(parameterName, Strings.MustBeFinite);
  108. }
  109. }
  110. /************************************************************************************************************************/
  111. /// <summary>IK cannot be dynamically enabled on a <see cref="ControllerState"/>.</summary>
  112. public override void CopyIKFlags(AnimancerNodeBase copyFrom) { }
  113. /************************************************************************************************************************/
  114. /// <summary>IK cannot be dynamically enabled on a <see cref="ControllerState"/>.</summary>
  115. public override bool ApplyAnimatorIK
  116. {
  117. get => false;
  118. set
  119. {
  120. #if UNITY_ASSERTIONS
  121. if (value)
  122. OptionalWarning.UnsupportedIK.Log(
  123. $"IK cannot be dynamically enabled on a {nameof(ControllerState)}." +
  124. " You must instead enable it on the desired layer inside the Animator Controller.",
  125. _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(
  139. $"IK cannot be dynamically enabled on a {nameof(ControllerState)}." +
  140. " You must instead enable it on the desired state inside the Animator Controller.",
  141. _Controller);
  142. #endif
  143. }
  144. }
  145. /************************************************************************************************************************/
  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)
  149. {
  150. MarkAsUsed(this);
  151. throw new NotSupportedException();
  152. }
  153. /************************************************************************************************************************/
  154. /// <inheritdoc/>
  155. public virtual void GetParameters(List<StateParameterDetails> parameters) { }
  156. /// <inheritdoc/>
  157. public virtual void SetParameters(List<StateParameterDetails> parameters) { }
  158. /************************************************************************************************************************/
  159. #endregion
  160. /************************************************************************************************************************/
  161. #region Public API
  162. /************************************************************************************************************************/
  163. /// <summary>Creates a new <see cref="ControllerState"/> to play the `controller`.</summary>
  164. public ControllerState(RuntimeAnimatorController controller)
  165. {
  166. _Controller = controller != null
  167. ? controller
  168. : throw new ArgumentNullException(nameof(controller));
  169. }
  170. /// <summary>Creates a new <see cref="ControllerState"/> to play the `controller`.</summary>
  171. public ControllerState(RuntimeAnimatorController controller, params ActionOnStop[] actionsOnStop)
  172. : this(controller)
  173. {
  174. ActionsOnStop = actionsOnStop;
  175. }
  176. /************************************************************************************************************************/
  177. /// <summary>Creates and assigns the <see cref="AnimatorControllerPlayable"/> managed by this state.</summary>
  178. protected override void CreatePlayable(out Playable playable)
  179. {
  180. playable = _Playable = AnimatorControllerPlayable.Create(Graph._PlayableGraph, _Controller);
  181. GatherDefaultStates();
  182. DeserializeParameterBindings();
  183. }
  184. /************************************************************************************************************************/
  185. /// <summary>
  186. /// Stores the values of all parameters and calls <see cref="AnimancerNode.RecreatePlayable"/>,
  187. /// then restores the parameter values.
  188. /// </summary>
  189. public override void RecreatePlayable()
  190. {
  191. if (!_Playable.IsValid())
  192. {
  193. CreatePlayable();
  194. return;
  195. }
  196. var parameterCount = _Playable.GetParameterCount();
  197. var values = new object[parameterCount];
  198. for (int i = 0; i < parameterCount; i++)
  199. {
  200. values[i] = AnimancerUtilities.GetParameterValue(_Playable, _Playable.GetParameter(i));
  201. }
  202. base.RecreatePlayable();
  203. for (int i = 0; i < parameterCount; i++)
  204. {
  205. AnimancerUtilities.SetParameterValue(_Playable, _Playable.GetParameter(i), values[i]);
  206. }
  207. }
  208. /************************************************************************************************************************/
  209. /// <summary>
  210. /// Returns the current state on the specified `layer`,
  211. /// or the next state if it is currently in a transition.
  212. /// </summary>
  213. public AnimatorStateInfo GetStateInfo(int layerIndex)
  214. {
  215. if (!_Playable.IsValid())
  216. return default;
  217. Validate.AssertPlayable(this);
  218. return _Playable.IsInTransition(layerIndex)
  219. ? _Playable.GetNextAnimatorStateInfo(layerIndex)
  220. : _Playable.GetCurrentAnimatorStateInfo(layerIndex);
  221. }
  222. /************************************************************************************************************************/
  223. /// <summary>
  224. /// The <see cref="AnimatorStateInfo.normalizedTime"/> * <see cref="AnimatorStateInfo.length"/> of layer 0.
  225. /// </summary>
  226. public override double RawTime
  227. {
  228. get
  229. {
  230. var info = GetStateInfo(0);
  231. return info.normalizedTime * info.length;
  232. }
  233. set
  234. {
  235. Validate.AssertPlayable(this);
  236. _Playable.PlayInFixedTime(0, 0, (float)value);
  237. // Setting the time requires it to be playing.
  238. // This will leave it at the specified time.
  239. if (!IsPlaying)
  240. {
  241. _Playable.Play();
  242. Graph.RequirePostUpdate(this);
  243. }
  244. }
  245. }
  246. /************************************************************************************************************************/
  247. /// <inheritdoc/>
  248. int IUpdatable.UpdatableIndex { get; set; } = IUpdatable.List.NotInList;
  249. /************************************************************************************************************************/
  250. /// <summary>Pauses the <see cref="Playable"/> if necessary after <see cref="RawTime"/> was set.</summary>
  251. void IUpdatable.Update()
  252. {
  253. if (!IsPlaying)
  254. _Playable.Pause();
  255. AnimancerGraph.Current.CancelPostUpdate(this);
  256. }
  257. /************************************************************************************************************************/
  258. /// <inheritdoc/>
  259. public override void SetGraph(AnimancerGraph graph)
  260. {
  261. if (Graph == graph)
  262. return;
  263. Graph?.CancelPostUpdate(this);
  264. base.SetGraph(graph);
  265. }
  266. /************************************************************************************************************************/
  267. /// <summary>The current <see cref="AnimatorStateInfo.length"/> of layer 0.</summary>
  268. public override float Length => GetStateInfo(0).length;
  269. /************************************************************************************************************************/
  270. /// <summary>The current <see cref="AnimatorStateInfo.loop"/> of layer 0.</summary>
  271. public override bool IsLooping => GetStateInfo(0).loop;
  272. /************************************************************************************************************************/
  273. /// <inheritdoc/>
  274. public override void GetEventDispatchInfo(
  275. out float length,
  276. out float normalizedTime,
  277. out bool isLooping)
  278. {
  279. var state = GetStateInfo(0);
  280. length = state.length;
  281. normalizedTime = state.normalizedTime;
  282. isLooping = state.loop;
  283. }
  284. /************************************************************************************************************************/
  285. /// <summary>Gathers the <see cref="DefaultStateHashes"/> from the current states on each layer.</summary>
  286. /// <remarks>This is called by <see cref="CreatePlayable(out UnityEngine.Playables.Playable)"/>.</remarks>
  287. public void GatherDefaultStates()
  288. {
  289. Validate.AssertPlayable(this);
  290. var layerCount = _Playable.GetLayerCount();
  291. if (DefaultStateHashes == null || DefaultStateHashes.Length != layerCount)
  292. DefaultStateHashes = new int[layerCount];
  293. while (--layerCount >= 0)
  294. DefaultStateHashes[layerCount] = _Playable.GetCurrentAnimatorStateInfo(layerCount).shortNameHash;
  295. }
  296. /************************************************************************************************************************/
  297. /// <summary>
  298. /// Stops the animation and makes it inactive immediately so it no longer affects the output.
  299. /// Also calls <see cref="ApplyActionsOnStop"/>.
  300. /// </summary>
  301. protected internal override void StopWithoutWeight()
  302. {
  303. // Don't call base.StopWithoutWeight(); because it sets Time = 0;
  304. // which uses PlayInFixedTime and interferes with resetting to the default states.
  305. SetIsPlaying(false);
  306. UpdateIsActive();
  307. ApplyActionsOnStop();
  308. _SmoothingVelocities?.Clear();
  309. }
  310. /// <summary>Applies the <see cref="ActionsOnStop"/> to their corresponding layers.</summary>
  311. /// <exception cref="NullReferenceException"><see cref="DefaultStateHashes"/> is null.</exception>
  312. public void ApplyActionsOnStop()
  313. {
  314. Validate.AssertPlayable(this);
  315. var layerCount = Math.Min(DefaultStateHashes.Length, _Playable.GetLayerCount());
  316. if (ActionsOnStop == null || ActionsOnStop.Length == 0)
  317. {
  318. for (int i = layerCount - 1; i >= 0; i--)
  319. _Playable.Play(DefaultStateHashes[i], i, 0);
  320. }
  321. else
  322. {
  323. for (int i = layerCount - 1; i >= 0; i--)
  324. {
  325. var index = i < ActionsOnStop.Length
  326. ? i
  327. : ActionsOnStop.Length - 1;
  328. switch (ActionsOnStop[index])
  329. {
  330. case ActionOnStop.DefaultState:
  331. _Playable.Play(DefaultStateHashes[i], i, 0);
  332. break;
  333. case ActionOnStop.RewindTime:
  334. _Playable.Play(0, i, 0);
  335. break;
  336. case ActionOnStop.Continue:
  337. break;
  338. }
  339. }
  340. }
  341. }
  342. /************************************************************************************************************************/
  343. /// <inheritdoc/>
  344. public override void GatherAnimationClips(ICollection<AnimationClip> clips)
  345. {
  346. if (_Controller != null)
  347. clips.Gather(_Controller.animationClips);
  348. }
  349. /************************************************************************************************************************/
  350. /// <inheritdoc/>
  351. public override void Destroy()
  352. {
  353. _Controller = null;
  354. DisposeParameterBindings();
  355. base.Destroy();
  356. }
  357. /************************************************************************************************************************/
  358. /// <inheritdoc/>
  359. public override AnimancerState Clone(CloneContext context)
  360. {
  361. var clone = new ControllerState(_Controller);
  362. clone.CopyFrom(this, context);
  363. return clone;
  364. }
  365. /************************************************************************************************************************/
  366. /// <inheritdoc/>
  367. public sealed override void CopyFrom(AnimancerState copyFrom, CloneContext context)
  368. => this.CopyFromBase(copyFrom, context);
  369. /// <inheritdoc/>
  370. public virtual void CopyFrom(ControllerState copyFrom, CloneContext context)
  371. {
  372. ActionsOnStop = copyFrom.ActionsOnStop;
  373. if (copyFrom.Graph != null &&
  374. Graph != null)
  375. {
  376. var layerCount = copyFrom._Playable.GetLayerCount();
  377. for (int i = 0; i < layerCount; i++)
  378. {
  379. var info = copyFrom._Playable.GetCurrentAnimatorStateInfo(i);
  380. _Playable.Play(info.shortNameHash, i, info.normalizedTime);
  381. }
  382. var parameterCount = copyFrom._Playable.GetParameterCount();
  383. for (int i = 0; i < parameterCount; i++)
  384. {
  385. AnimancerUtilities.CopyParameterValue(
  386. copyFrom._Playable,
  387. _Playable,
  388. copyFrom._Playable.GetParameter(i));
  389. }
  390. }
  391. CopySmoothingVelocitiesFrom(copyFrom);
  392. base.CopyFrom(copyFrom, context);
  393. }
  394. /************************************************************************************************************************/
  395. #endregion
  396. /************************************************************************************************************************/
  397. #region Animator Controller Wrappers
  398. /************************************************************************************************************************/
  399. #region Cross Fade
  400. /************************************************************************************************************************/
  401. /// <summary>
  402. /// The default constant for fade duration parameters which causes it to use the
  403. /// <see cref="AnimancerGraph.DefaultFadeDuration"/> instead.
  404. /// </summary>
  405. public const float DefaultFadeDuration = -1;
  406. /************************************************************************************************************************/
  407. /// <summary>
  408. /// Returns the `fadeDuration` if it is zero or positive.
  409. /// Otherwise returns the <see cref="AnimancerGraph.DefaultFadeDuration"/>.
  410. /// </summary>
  411. public static float GetFadeDuration(float fadeDuration)
  412. => fadeDuration >= 0
  413. ? fadeDuration
  414. : AnimancerGraph.DefaultFadeDuration;
  415. /************************************************************************************************************************/
  416. /// <summary>Starts a transition from the current state to the specified state using normalized times.</summary>
  417. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerGraph.DefaultFadeDuration"/>.</remarks>
  418. public void CrossFade(
  419. int stateNameHash,
  420. float fadeDuration = DefaultFadeDuration,
  421. int layer = -1,
  422. float normalizedTime = float.NegativeInfinity)
  423. => Playable.CrossFade(stateNameHash, GetFadeDuration(fadeDuration), layer, normalizedTime);
  424. /************************************************************************************************************************/
  425. /// <summary>Starts a transition from the current state to the specified state using normalized times.</summary>
  426. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerGraph.DefaultFadeDuration"/>.</remarks>
  427. public void CrossFade(
  428. string stateName,
  429. float fadeDuration = DefaultFadeDuration,
  430. int layer = -1,
  431. float normalizedTime = float.NegativeInfinity)
  432. => Playable.CrossFade(stateName, GetFadeDuration(fadeDuration), layer, normalizedTime);
  433. /************************************************************************************************************************/
  434. /// <summary>Starts a transition from the current state to the specified state using times in seconds.</summary>
  435. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerGraph.DefaultFadeDuration"/>.</remarks>
  436. public void CrossFadeInFixedTime(
  437. int stateNameHash,
  438. float fadeDuration = DefaultFadeDuration,
  439. int layer = -1,
  440. float fixedTime = 0)
  441. => Playable.CrossFadeInFixedTime(stateNameHash, GetFadeDuration(fadeDuration), layer, fixedTime);
  442. /************************************************************************************************************************/
  443. /// <summary>Starts a transition from the current state to the specified state using times in seconds.</summary>
  444. /// <remarks>If `fadeDuration` is negative, it uses the <see cref="AnimancerGraph.DefaultFadeDuration"/>.</remarks>
  445. public void CrossFadeInFixedTime(
  446. string stateName,
  447. float fadeDuration = DefaultFadeDuration,
  448. int layer = -1,
  449. float fixedTime = 0)
  450. => Playable.CrossFadeInFixedTime(stateName, GetFadeDuration(fadeDuration), layer, fixedTime);
  451. /************************************************************************************************************************/
  452. #endregion
  453. /************************************************************************************************************************/
  454. #region Play
  455. /************************************************************************************************************************/
  456. /// <summary>Plays the specified state immediately, starting from a particular normalized time.</summary>
  457. public void Play(
  458. int stateNameHash,
  459. int layer = -1,
  460. float normalizedTime = float.NegativeInfinity)
  461. => Playable.Play(stateNameHash, layer, normalizedTime);
  462. /************************************************************************************************************************/
  463. /// <summary>Plays the specified state immediately, starting from a particular normalized time.</summary>
  464. public void Play(
  465. string stateName,
  466. int layer = -1,
  467. float normalizedTime = float.NegativeInfinity)
  468. => Playable.Play(stateName, layer, normalizedTime);
  469. /************************************************************************************************************************/
  470. /// <summary>Plays the specified state immediately, starting from a particular time (in seconds).</summary>
  471. public void PlayInFixedTime(
  472. int stateNameHash,
  473. int layer = -1,
  474. float fixedTime = 0)
  475. => Playable.PlayInFixedTime(stateNameHash, layer, fixedTime);
  476. /************************************************************************************************************************/
  477. /// <summary>Plays the specified state immediately, starting from a particular time (in seconds).</summary>
  478. public void PlayInFixedTime(
  479. string stateName,
  480. int layer = -1,
  481. float fixedTime = 0)
  482. => Playable.PlayInFixedTime(stateName, layer, fixedTime);
  483. /************************************************************************************************************************/
  484. #endregion
  485. /************************************************************************************************************************/
  486. #region Parameters
  487. /************************************************************************************************************************/
  488. /// <summary>Gets the value of the specified boolean parameter.</summary>
  489. public bool GetBool(int id)
  490. => Playable.GetBool(id);
  491. /// <summary>Gets the value of the specified boolean parameter.</summary>
  492. public bool GetBool(string name)
  493. => Playable.GetBool(name);
  494. /// <summary>Sets the value of the specified boolean parameter.</summary>
  495. public void SetBool(int id, bool value)
  496. => Playable.SetBool(id, value);
  497. /// <summary>Sets the value of the specified boolean parameter.</summary>
  498. public void SetBool(string name, bool value)
  499. => Playable.SetBool(name, value);
  500. /// <summary>Gets the value of the specified float parameter.</summary>
  501. public float GetFloat(int id)
  502. => Playable.GetFloat(id);
  503. /// <summary>Gets the value of the specified float parameter.</summary>
  504. public float GetFloat(string name)
  505. => Playable.GetFloat(name);
  506. /// <summary>Sets the value of the specified float parameter.</summary>
  507. public void SetFloat(int id, float value)
  508. => Playable.SetFloat(id, value);
  509. /// <summary>Sets the value of the specified float parameter.</summary>
  510. public void SetFloat(string name, float value)
  511. => Playable.SetFloat(name, value);
  512. /// <summary>Gets the value of the specified integer parameter.</summary>
  513. public int GetInteger(int id)
  514. => Playable.GetInteger(id);
  515. /// <summary>Gets the value of the specified integer parameter.</summary>
  516. public int GetInteger(string name)
  517. => Playable.GetInteger(name);
  518. /// <summary>Sets the value of the specified integer parameter.</summary>
  519. public void SetInteger(int id, int value)
  520. => Playable.SetInteger(id, value);
  521. /// <summary>Sets the value of the specified integer parameter.</summary>
  522. public void SetInteger(string name, int value)
  523. => Playable.SetInteger(name, value);
  524. /// <summary>Sets the specified trigger parameter to true.</summary>
  525. public void SetTrigger(int id)
  526. => Playable.SetTrigger(id);
  527. /// <summary>Sets the specified trigger parameter to true.</summary>
  528. ///
  529. public void SetTrigger(string name)
  530. => Playable.SetTrigger(name);
  531. /// <summary>Resets the specified trigger parameter to false.</summary>
  532. ///
  533. public void ResetTrigger(int id)
  534. => Playable.ResetTrigger(id);
  535. /// <summary>Resets the specified trigger parameter to false.</summary>
  536. ///
  537. public void ResetTrigger(string name)
  538. => Playable.ResetTrigger(name);
  539. /// <summary>Indicates whether the specified parameter is controlled by an <see cref="AnimationClip"/>.</summary>
  540. public bool IsParameterControlledByCurve(int id)
  541. => Playable.IsParameterControlledByCurve(id);
  542. /// <summary>Indicates whether the specified parameter is controlled by an <see cref="AnimationClip"/>.</summary>
  543. public bool IsParameterControlledByCurve(string name)
  544. => Playable.IsParameterControlledByCurve(name);
  545. /// <summary>Gets the details of one of the <see cref="Controller"/>'s parameters.</summary>
  546. public AnimatorControllerParameter GetParameter(int index)
  547. => Playable.GetParameter(index);
  548. /// <summary>Gets the number of parameters in the <see cref="Controller"/>.</summary>
  549. public int GetParameterCount()
  550. => Playable.GetParameterCount();
  551. /************************************************************************************************************************/
  552. /// <summary>The number of parameters in the <see cref="Controller"/>.</summary>
  553. public int parameterCount => Playable.GetParameterCount();
  554. /************************************************************************************************************************/
  555. private AnimatorControllerParameter[] _Parameters;
  556. /// <summary>The parameters in the <see cref="Controller"/>.</summary>
  557. /// <remarks>
  558. /// This property allocates a new array when first accessed. To avoid that, you can use
  559. /// <see cref="GetParameterCount"/> and <see cref="GetParameter"/> instead.
  560. /// </remarks>
  561. public AnimatorControllerParameter[] parameters
  562. {
  563. get
  564. {
  565. if (_Parameters == null)
  566. {
  567. var count = GetParameterCount();
  568. _Parameters = new AnimatorControllerParameter[count];
  569. for (int i = 0; i < count; i++)
  570. _Parameters[i] = GetParameter(i);
  571. }
  572. return _Parameters;
  573. }
  574. }
  575. /************************************************************************************************************************/
  576. #endregion
  577. /************************************************************************************************************************/
  578. #region Smoothed Set Float
  579. /************************************************************************************************************************/
  580. private Dictionary<int, float> _SmoothingVelocities;
  581. /************************************************************************************************************************/
  582. /// <summary>Sets the value of the specified float parameter with smoothing.</summary>
  583. /// <remarks>Consider using a <see cref="SmoothedFloatParameter"/> instead.</remarks>
  584. public float SetFloat(
  585. string name,
  586. float value,
  587. float dampTime,
  588. float deltaTime,
  589. float maxSpeed = float.PositiveInfinity)
  590. => SetFloat(Animator.StringToHash(name), value, dampTime, deltaTime, maxSpeed);
  591. /// <summary>Sets the value of the specified float parameter with smoothing.</summary>
  592. /// <remarks>Consider using a <see cref="SmoothedFloatParameter"/> instead.</remarks>
  593. public float SetFloat(
  594. int id,
  595. float value,
  596. float dampTime,
  597. float deltaTime,
  598. float maxSpeed = float.PositiveInfinity)
  599. {
  600. _SmoothingVelocities ??= new();
  601. _SmoothingVelocities.TryGetValue(id, out var velocity);
  602. value = Mathf.SmoothDamp(GetFloat(id), value, ref velocity, dampTime, maxSpeed, deltaTime);
  603. SetFloat(id, value);
  604. _SmoothingVelocities[id] = velocity;
  605. return value;
  606. }
  607. /************************************************************************************************************************/
  608. /// <summary>Copies the smoothing velocities.</summary>
  609. private void CopySmoothingVelocitiesFrom(ControllerState copyFrom)
  610. {
  611. if (copyFrom._SmoothingVelocities != null)
  612. {
  613. if (_SmoothingVelocities == null)
  614. _SmoothingVelocities = new();
  615. else
  616. _SmoothingVelocities.Clear();
  617. foreach (var item in copyFrom._SmoothingVelocities)
  618. _SmoothingVelocities[item.Key] = item.Value;
  619. }
  620. else
  621. {
  622. _SmoothingVelocities?.Clear();
  623. }
  624. }
  625. /************************************************************************************************************************/
  626. #endregion
  627. /************************************************************************************************************************/
  628. #region Misc
  629. /************************************************************************************************************************/
  630. // Layers.
  631. /************************************************************************************************************************/
  632. /// <summary>Gets the weight of the layer at the specified index.</summary>
  633. public float GetLayerWeight(int layerIndex)
  634. => Playable.GetLayerWeight(layerIndex);
  635. /// <summary>Sets the weight of the layer at the specified index.</summary>
  636. public void SetLayerWeight(int layerIndex, float weight)
  637. => Playable.SetLayerWeight(layerIndex, weight);
  638. /// <summary>Gets the number of layers in the <see cref="Controller"/>.</summary>
  639. public int GetLayerCount()
  640. => Playable.GetLayerCount();
  641. /// <summary>The number of layers in the <see cref="Controller"/>.</summary>
  642. public int layerCount
  643. => Playable.GetLayerCount();
  644. /// <summary>Gets the index of the layer with the specified name.</summary>
  645. public int GetLayerIndex(string layerName)
  646. => Playable.GetLayerIndex(layerName);
  647. /// <summary>Gets the name of the layer with the specified index.</summary>
  648. public string GetLayerName(int layerIndex)
  649. => Playable.GetLayerName(layerIndex);
  650. /************************************************************************************************************************/
  651. // States.
  652. /************************************************************************************************************************/
  653. /// <summary>Returns information about the current state.</summary>
  654. public AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex = 0)
  655. => Playable.GetCurrentAnimatorStateInfo(layerIndex);
  656. /// <summary>Returns information about the next state being transitioned towards.</summary>
  657. public AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex = 0)
  658. => Playable.GetNextAnimatorStateInfo(layerIndex);
  659. /// <summary>Indicates whether the specified layer contains the specified state.</summary>
  660. public bool HasState(int layerIndex, int stateID)
  661. => Playable.HasState(layerIndex, stateID);
  662. /************************************************************************************************************************/
  663. // Transitions.
  664. /************************************************************************************************************************/
  665. /// <summary>Indicates whether the specified layer is currently executing a transition.</summary>
  666. public bool IsInTransition(int layerIndex = 0)
  667. => Playable.IsInTransition(layerIndex);
  668. /// <summary>Gets information about the current transition.</summary>
  669. public AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex = 0)
  670. => Playable.GetAnimatorTransitionInfo(layerIndex);
  671. /************************************************************************************************************************/
  672. // Clips.
  673. /************************************************************************************************************************/
  674. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being played.</summary>
  675. public AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex = 0)
  676. => Playable.GetCurrentAnimatorClipInfo(layerIndex);
  677. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being played.</summary>
  678. public void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips)
  679. => Playable.GetCurrentAnimatorClipInfo(layerIndex, clips);
  680. /// <summary>Gets the number of <see cref="AnimationClip"/>s currently being played.</summary>
  681. ///
  682. public int GetCurrentAnimatorClipInfoCount(int layerIndex = 0)
  683. => Playable.GetCurrentAnimatorClipInfoCount(layerIndex);
  684. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  685. public AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex = 0)
  686. => Playable.GetNextAnimatorClipInfo(layerIndex);
  687. /// <summary>Gets information about the <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  688. public void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips)
  689. => Playable.GetNextAnimatorClipInfo(layerIndex, clips);
  690. /// <summary>Gets the number of <see cref="AnimationClip"/>s currently being transitioned towards.</summary>
  691. public int GetNextAnimatorClipInfoCount(int layerIndex = 0)
  692. => Playable.GetNextAnimatorClipInfoCount(layerIndex);
  693. /************************************************************************************************************************/
  694. #endregion
  695. /************************************************************************************************************************/
  696. #endregion
  697. /************************************************************************************************************************/
  698. }
  699. }