using UnityEngine; using System.Collections; using System; namespace RootMotion.Dynamics { // Switching and blending between Modes public partial class PuppetMaster: MonoBehaviour { /// /// Switches this PuppetMaster to PuppetMaster.Mode.Active. /// public void SwitchToActiveMode() { mode = Mode.Active; } /// /// Switches this PuppetMaster to PuppetMaster.Mode.Kinematic. /// public void SwitchToKinematicMode() { mode = Mode.Kinematic; } /// /// Switches this PuppetMaster to PuppetMaster.Mode.Disabled. /// public void SwitchToDisabledMode() { mode = Mode.Disabled; } /// /// Returns true if the PuppetMaster is in the middle of blending from a mode to mode. /// public bool isSwitchingMode { get; private set; } private Mode activeMode; private Mode lastMode; private float mappingBlend = 1f; /// /// Disables the Puppet immediately without waiting for normal mode switching procedures. /// public void DisableImmediately() { mappingBlend = 0f; isSwitchingMode = false; mode = Mode.Disabled; activeMode = mode; lastMode = mode; foreach (Muscle m in muscles) { m.rigidbody.gameObject.SetActive(false); } } // Master controller for switching modes. Mode switching is done by simply changing PuppetMaster.mode and can not be interrupted. protected virtual void SwitchModes() { if (!initiated) return; if (isKilling) mode = Mode.Active; if (!isAlive) mode = Mode.Active; foreach (BehaviourBase behaviour in behaviours) { if (behaviour.forceActive) { mode = Mode.Active; break; } } if (mode == lastMode) return; if (isSwitchingMode) return; if (isKilling && mode != Mode.Active) return; if (state != State.Alive && mode != Mode.Active) return; // Enable state switching here or else mapping won't be blended correctly isSwitchingMode = true; if (lastMode == Mode.Disabled) { if (mode == Mode.Kinematic) DisabledToKinematic(); else if (mode == Mode.Active) StartCoroutine(DisabledToActive()); } else if (lastMode == Mode.Kinematic) { if (mode == Mode.Disabled) KinematicToDisabled(); else if (mode == Mode.Active) StartCoroutine(KinematicToActive()); } else if (lastMode == Mode.Active) { if (mode == Mode.Disabled) StartCoroutine(ActiveToDisabled()); else if (mode == Mode.Kinematic) StartCoroutine(ActiveToKinematic()); } lastMode = mode; } // Switch from Disabled to Kinematic mode private void DisabledToKinematic() { foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.Reset(); } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) { m.rigidbody.gameObject.SetActive(true); m.SetKinematic(true); } } FlagInternalCollisionsForUpdate(); foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.MoveToTarget(); } activeMode = Mode.Kinematic; isSwitchingMode = false; } // Blend from Disabled to Active mode private IEnumerator DisabledToActive() { foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.Reset(); } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) { m.rigidbody.gameObject.SetActive(true); m.SetKinematic(false); m.rigidbody.WakeUp(); m.rigidbody.velocity = m.mappedVelocity; m.rigidbody.angularVelocity = m.mappedAngularVelocity; } } FlagInternalCollisionsForUpdate(); foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.MoveToTarget(); } Read(); if (blendTime > 0f) { while (mappingBlend < 1f) { mappingBlend = Mathf.Clamp(mappingBlend + Time.deltaTime / blendTime, 0f, 1f); yield return null; } } else { mappingBlend = 1f; } activeMode = Mode.Active; isSwitchingMode = false; } // Switch from Kinematic to Disabled private void KinematicToDisabled() { foreach (Muscle m in muscles) { if (!m.state.isDisconnected) { m.rigidbody.gameObject.SetActive(false); } } activeMode = Mode.Disabled; isSwitchingMode = false; } // Blend from Kinematic to Active mode private IEnumerator KinematicToActive() { foreach (Muscle m in muscles) { if (!m.state.isDisconnected) { m.SetKinematic(false); m.rigidbody.WakeUp(); m.rigidbody.velocity = m.mappedVelocity; m.rigidbody.angularVelocity = m.mappedAngularVelocity; } } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.MoveToTarget(); } Read(); if (blendTime > 0f) { while (mappingBlend < 1f) { mappingBlend = Mathf.Clamp(mappingBlend + Time.deltaTime / blendTime, 0f, 1f); yield return null; } } else { mappingBlend = 1f; } activeMode = Mode.Active; isSwitchingMode = false; } // Blend from Active to Disabled mode private IEnumerator ActiveToDisabled() { if (blendTime > 0f) { while (mappingBlend > 0f) { mappingBlend = Mathf.Max(mappingBlend - Time.deltaTime / blendTime, 0f); yield return null; } } else { mappingBlend = 0f; } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) { m.rigidbody.gameObject.SetActive(false); } } activeMode = Mode.Disabled; isSwitchingMode = false; } // Blend from Active to Kinematic mode private IEnumerator ActiveToKinematic() { if (blendTime > 0f) { while (mappingBlend > 0f) { mappingBlend = Mathf.Max(mappingBlend - Time.deltaTime / blendTime, 0f); yield return null; } } else { mappingBlend = 0f; } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.SetKinematic(true); } foreach (Muscle m in muscles) { if (!m.state.isDisconnected) m.MoveToTarget(); } activeMode = Mode.Kinematic; isSwitchingMode = false; } } }