/// <summary> /// Updates the motions tied to this layer at the variable /// time step (ie Update() not FixedUpdate(). /// </summary> /// <param name="rDeltaTime">Time since the last frame (or fixed update call)</param> /// <param name="rUpdateIndex">Index of the update to help manage dynamic/fixed updates. [0: Invalid update, >=1: Valid update]</param> public void UpdateMotions(float rDeltaTime, int rUpdateIndex) { int lPriorityIndex = -1; float lPriorityValue = float.MinValue; MotionControllerMotion lPrevActiveMotion = mActiveMotion; // Grab the current state info for the layer _AnimatorStateID = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].StateInfo.fullPathHash; _AnimatorStateNormalizedTime = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].StateInfo.normalizedTime; _AnimatorTransitionID = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].TransitionInfo.fullPathHash; _AnimatorTransitionNormalizedTime = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].TransitionInfo.normalizedTime; // Track how long the motion has been playing mActiveMotionDuration += Time.deltaTime; // Clean up the active motion's flag and ensure it's still valid if (mActiveMotion != null) { mActiveMotion.IsActivatedFrame = false; // If we have a current motion, test if it can continue if (!mActiveMotion.TestUpdate()) { mRunDeactivatedUpdate = true; mPrevActiveMotion = mActiveMotion; mActiveMotion.Deactivate(); mActiveMotion = null; } } // First, check if our current motion is interruptible. // If it's not, we know we are simply running it. if (rUpdateIndex == 1 && (mActiveMotion == null || mActiveMotion.IsInterruptible)) { bool lIsQueued = false; // Cycle through the motions to determine which ones were not // active and should be. We'll take the motion with the highest priority for (int i = 0; i < Motions.Count; i++) { MotionControllerMotion lMotion = Motions[i]; // Clean up the activation flag lMotion.IsActivatedFrame = false; // Don't test if the motion is not enabled if (!lMotion.IsEnabled) { continue; } // Don't reactivate this frame if (Time.time - lMotion.DeactivationTime < 0.001f) { continue; } // If we haven't gone past the reactivation delay, move one if (lMotion.ReactivationDelay > 0f && (lMotion.DeactivationTime + lMotion.ReactivationDelay) > Time.time) { continue; } // If we're to force the motion, don't check others if (lMotion.QueueActivation && (mActiveMotion == null || mActiveMotion.TestInterruption(Motions[i]))) { if (_AnimatorTransitionID == 0) { lIsQueued = true; lPriorityIndex = i; lPriorityValue = lMotion.Priority; lMotion.QueueActivation = false; } break; } // If we're dealing with the current motion, test if we continue else if (lMotion == mActiveMotion) { //if (mActiveMotion.TestUpdate()) //{ if (mActiveMotion.Priority >= lPriorityValue) { lPriorityIndex = i; lPriorityValue = mActiveMotion.Priority; } //} //else //{ // mActiveMotion.Deactivate(); //} } // For new motions, check for activation else if (lMotion.IsStartable) { bool lActivate = lMotion.TestActivate(); // Test if we should activate the motion if (lActivate && mMotionController.MotionActivatedEvent != null) { MotionMessage lMessage = MotionMessage.Allocate(); lMessage.ID = EnumMessageID.MSG_MOTION_TEST; lMessage.Motion = lMotion; lMessage.Continue = true; lMessage.Data = lPrevActiveMotion; mMotionController.MotionTestActivateEvent.Invoke(lMessage); lActivate = lMessage.Continue; MotionMessage.Release(lMessage); } // Test if we should activate the motion if (lActivate && mMotionController._ActorCore != null) { MotionMessage lMessage = MotionMessage.Allocate(); lMessage.ID = EnumMessageID.MSG_MOTION_TEST; lMessage.Motion = lMotion; lMessage.Continue = true; lMessage.Data = lPrevActiveMotion; mMotionController._ActorCore.SendMessage(lMessage); lActivate = lMessage.Continue; MotionMessage.Release(lMessage); } //#if USE_MESSAGE_DISPATCHER || OOTII_MD // // Send the message // if (lActivate) // { // MotionMessage lMessage = MotionMessage.Allocate(); // lMessage.ID = EnumMessageID.MSG_MOTION_TEST; // lMessage.Motion = lMotion; // lMessage.Continue = true; // lMessage.Data = lPrevActiveMotion; // MessageDispatcher.SendMessage(lMessage); // lActivate = lMessage.Continue; // MotionMessage.Release(lMessage); // } //#endif if (lActivate) { if (lMotion.Priority >= lPriorityValue) { lPriorityIndex = i; lPriorityValue = lMotion.Priority; } } } } // If we have a newly chosen motion, we need to activate it if (lPriorityIndex >= 0 && lPriorityIndex < Motions.Count) { // Ensure our new motion is valid. if (!lIsQueued && mActiveMotion != null) { // If the "new" motion is the current motion, move on if (mActiveMotion == Motions[lPriorityIndex]) { lPriorityIndex = -1; } // If the current motion has a higher priority (lower value), move on else if (mActiveMotion.Priority > lPriorityValue) { lPriorityIndex = -1; } // If we can't interrupt the current motion, move on else if (mActiveMotion.IsActive && !mActiveMotion.TestInterruption(Motions[lPriorityIndex])) { lPriorityIndex = -1; } } // Look to start the new motion (if we have one) if (lPriorityIndex >= 0) { if (mActiveMotion != null && mActiveMotion.IsActive && mActiveMotion != Motions[lPriorityIndex]) { mRunDeactivatedUpdate = true; mPrevActiveMotion = mActiveMotion; mActiveMotion.Deactivate(); } if (mActiveMotion != Motions[lPriorityIndex]) { Motions[lPriorityIndex].Activate(lPrevActiveMotion); } mActiveMotion = Motions[lPriorityIndex]; mActiveMotionDuration = 0f; } } } // Process any shutdown procedures for motions that are deactivated. if (mRunDeactivatedUpdate && mPrevActiveMotion != null) { mRunDeactivatedUpdate = mPrevActiveMotion.DeactivatedUpdate(rDeltaTime, rUpdateIndex); } // Process any motions that are active. They will die out on thier own for (int i = 0; i < Motions.Count; i++) { if (Motions[i].IsActive) { Motions[i].UpdateMotion(rDeltaTime, rUpdateIndex); // As a safetly, test and set the active motion if (mActiveMotion == null && Motions[i].IsActive) { mActiveMotion = Motions[i]; mActiveMotionDuration = 0f; } } } // Check if we've deactivated the current motion. If so, we // need to remove our reference to it if (mActiveMotion != null && !mActiveMotion.IsActive) { mActiveMotion = null; mActiveMotionDuration = 0f; } // Calculate the velocities of the active motions mAngularVelocity = Vector3.zero; mRotation = Quaternion.identity; mTilt = Quaternion.identity; mVelocity = Vector3.zero; mMovement = Vector3.zero; for (int i = 0; i < Motions.Count; i++) { if (Motions[i].IsActive) { mAngularVelocity += Motions[i].AngularVelocity; mRotation = mRotation * Motions[i].Rotation; mTilt = mTilt * Motions[i].Tilt; mVelocity += Motions[i].Velocity; mMovement += Motions[i].Movement; } } }