SolverManager.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using UnityEngine;
  2. using System.Collections;
  3. namespace RootMotion {
  4. /// <summary>
  5. /// Manages solver initiation and updating
  6. /// </summary>
  7. public class SolverManager: MonoBehaviour {
  8. #region Main Interface
  9. /// <summary>
  10. /// If true, will fix all the Transforms used by the solver to their initial state in each Update. This prevents potential problems with unanimated bones and animator culling with a small cost of performance. Not recommended for CCD and FABRIK solvers.
  11. /// </summary>
  12. [Tooltip("If true, will fix all the Transforms used by the solver to their initial state in each Update. This prevents potential problems with unanimated bones and animator culling with a small cost of performance. Not recommended for CCD and FABRIK solvers.")]
  13. public bool fixTransforms = true;
  14. /// <summary>
  15. /// [DEPRECATED] Use "enabled = false" instead.
  16. /// </summary>
  17. public void Disable() {
  18. Debug.Log("IK.Disable() is deprecated. Use enabled = false instead", transform);
  19. enabled = false;
  20. }
  21. #endregion Main
  22. protected virtual void InitiateSolver() {}
  23. protected virtual void UpdateSolver() {}
  24. protected virtual void FixTransforms() {}
  25. private Animator animator;
  26. private Animation legacy;
  27. private bool updateFrame;
  28. private bool componentInitiated;
  29. void OnDisable() {
  30. if (!Application.isPlaying) return;
  31. Initiate();
  32. }
  33. void Start() {
  34. Initiate();
  35. }
  36. private bool animatePhysics {
  37. get {
  38. if (animator != null) return animator.updateMode == AnimatorUpdateMode.AnimatePhysics;
  39. if (legacy != null) return legacy.animatePhysics;
  40. return false;
  41. }
  42. }
  43. private void Initiate() {
  44. if (componentInitiated) return;
  45. FindAnimatorRecursive(transform, true);
  46. InitiateSolver();
  47. componentInitiated = true;
  48. }
  49. void Update() {
  50. if (skipSolverUpdate) return;
  51. if (animatePhysics) return;
  52. if (fixTransforms) FixTransforms();
  53. }
  54. // Finds the first Animator/Animation up the hierarchy
  55. private void FindAnimatorRecursive(Transform t, bool findInChildren) {
  56. if (isAnimated) return;
  57. animator = t.GetComponent<Animator>();
  58. legacy = t.GetComponent<Animation>();
  59. if (isAnimated) return;
  60. if (animator == null && findInChildren) animator = t.GetComponentInChildren<Animator>();
  61. if (legacy == null && findInChildren) legacy = t.GetComponentInChildren<Animation>();
  62. if (!isAnimated && t.parent != null) FindAnimatorRecursive(t.parent, false);
  63. }
  64. private bool isAnimated {
  65. get {
  66. return animator != null || legacy != null;
  67. }
  68. }
  69. // Workaround hack for the solver to work with animatePhysics
  70. void FixedUpdate() {
  71. if (skipSolverUpdate) {
  72. skipSolverUpdate = false;
  73. }
  74. updateFrame = true;
  75. if (animatePhysics && fixTransforms) FixTransforms();
  76. }
  77. // Updating
  78. void LateUpdate() {
  79. if (skipSolverUpdate) return;
  80. // Check if either animatePhysics is false or FixedUpdate has been called
  81. if (!animatePhysics) updateFrame = true;
  82. if (!updateFrame) return;
  83. updateFrame = false;
  84. UpdateSolver();
  85. }
  86. // This enables other scripts to update the Animator on in FixedUpdate and the solvers with it
  87. private bool skipSolverUpdate;
  88. public void UpdateSolverExternal() {
  89. if (!enabled) return;
  90. skipSolverUpdate = true;
  91. UpdateSolver();
  92. }
  93. }
  94. }