Esempio n. 1
0
        /// <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;
                }
            }
        }