using UnityEngine; using System.Collections; namespace RootMotion { /// /// Manages solver initiation and updating /// public class SolverManager: MonoBehaviour { #region Main Interface /// /// 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. /// [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.")] public bool fixTransforms = true; /// /// [DEPRECATED] Use "enabled = false" instead. /// public void Disable() { Debug.Log("IK.Disable() is deprecated. Use enabled = false instead", transform); enabled = false; } #endregion Main protected virtual void InitiateSolver() {} protected virtual void UpdateSolver() {} protected virtual void FixTransforms() {} private Animator animator; private Animation legacy; private bool updateFrame; private bool componentInitiated; void OnDisable() { if (!Application.isPlaying) return; Initiate(); } void Start() { Initiate(); } private bool animatePhysics { get { if (animator != null) return animator.updateMode == AnimatorUpdateMode.AnimatePhysics; if (legacy != null) return legacy.animatePhysics; return false; } } private void Initiate() { if (componentInitiated) return; FindAnimatorRecursive(transform, true); InitiateSolver(); componentInitiated = true; } void Update() { if (skipSolverUpdate) return; if (animatePhysics) return; if (fixTransforms) FixTransforms(); } // Finds the first Animator/Animation up the hierarchy private void FindAnimatorRecursive(Transform t, bool findInChildren) { if (isAnimated) return; animator = t.GetComponent(); legacy = t.GetComponent(); if (isAnimated) return; if (animator == null && findInChildren) animator = t.GetComponentInChildren(); if (legacy == null && findInChildren) legacy = t.GetComponentInChildren(); if (!isAnimated && t.parent != null) FindAnimatorRecursive(t.parent, false); } private bool isAnimated { get { return animator != null || legacy != null; } } // Workaround hack for the solver to work with animatePhysics void FixedUpdate() { if (skipSolverUpdate) { skipSolverUpdate = false; } updateFrame = true; if (animatePhysics && fixTransforms) FixTransforms(); } // Updating void LateUpdate() { if (skipSolverUpdate) return; // Check if either animatePhysics is false or FixedUpdate has been called if (!animatePhysics) updateFrame = true; if (!updateFrame) return; updateFrame = false; UpdateSolver(); } // This enables other scripts to update the Animator on in FixedUpdate and the solvers with it private bool skipSolverUpdate; public void UpdateSolverExternal() { if (!enabled) return; skipSolverUpdate = true; UpdateSolver(); } } }