Esempio n. 1
0
        /// <summary>
        /// We smooth the input so that we don't start and stop immediately in the blend tree. That can create pops.
        /// </summary>
        protected void SmoothInput()
        {
            MotionState lState = mMotionController.State;

            // Convert the input to radial so we deal with keyboard and gamepad input the same.
            float lInputMax = (IsRunActive ? 1f : 0.5f);

            float lInputX         = Mathf.Clamp(lState.InputX, -lInputMax, lInputMax);
            float lInputY         = Mathf.Clamp(lState.InputY, -lInputMax, lInputMax);
            float lInputMagnitude = Mathf.Clamp(lState.InputMagnitudeTrend.Value, 0f, lInputMax);

            InputManagerHelper.ConvertToRadialInput(ref lInputX, ref lInputY, ref lInputMagnitude);

            // Smooth the input
            mInputX.Add(lInputX);
            mInputY.Add(lInputY);
            mInputMagnitude.Add(lInputMagnitude);

            // Modify the input values to add some lag
            mMotionController.State.InputX = mInputX.Average;
            mMotionController.State.InputY = mInputY.Average;
            mMotionController.State.InputMagnitudeTrend.Replace(mInputMagnitude.Average);
        }
Esempio n. 2
0
        /// <summary>
        /// Updates the motion over time. This is called by the controller
        /// every update cycle so animations and stages can be updated.
        /// </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 override void Update(float rDeltaTime, int rUpdateIndex)
        {
            mRotation = Quaternion.identity;

            // Grab the state info
            MotionState lState = mMotionController.State;

            // Convert the input to radial so we deal with keyboard and gamepad input the same.
            float lInputX   = lState.InputX;
            float lInputY   = lState.InputY;
            float lInputMag = lState.InputMagnitudeTrend.Value;

            InputManagerHelper.ConvertToRadialInput(ref lInputX, ref lInputY, ref lInputMag); //, (IsRunActive ? 1f : 0.5f));

            // Ensure we support the stop delay. This way, we can get out
            // of the blend tree with a nice transition
            if (lState.InputMagnitudeTrend.Value < 0.4f)
            {
                // Only set the timer if it's not set yet
                if (mStopTime == 0f)
                {
                    mStopInput.x = mInputX.Average;
                    mStopInput.y = mInputY.Average;
                    mStopTime    = Time.time + _StopDelay;

                    mInputX.Clear(mStopInput.x);
                    mInputY.Clear(mStopInput.y);
                    mInputMagnitude.Clear(Mathf.Sqrt((mInputX.Value * mInputX.Value) + (mInputY.Value * mInputY.Value)));
                }
            }
            // Clear the timer
            else
            {
                mStopTime = 0f;
            }

            // When we're processing normally, update all the input values
            if (mStopTime == 0f)
            {
                mInputX.Add(lInputX);
                mInputY.Add(lInputY);
                mInputMagnitude.Add(lInputMag);
            }
            // If we've reached our stop time, it's time to stop
            else if (Time.time > mStopTime)
            {
                // Determine how we'll stop based on the direction
                if (!(mMotionLayer._AnimatorStateID == STATE_IdlePoseOut))
                {
                    mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, PHASE_STOP, 0, true);
                }
                // If we're already stopping, we can clear our movement info. We don't want
                // to clear the movement before the transition our our blend tree will drop to idle
                else
                {
                    mStopTime = 0f;
                    mInputX.Clear();
                    mInputY.Clear();
                    mInputMagnitude.Clear();

                    lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].MotionPhase     = 0;
                    lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].MotionParameter = 0;
                }
            }

            // Modify the input values to add some lag
            lState.InputX = mInputX.Average;
            lState.InputY = mInputY.Average;
            lState.InputMagnitudeTrend.Replace(mInputMagnitude.Average);

            // Finally, set the state value
            mMotionController.State = lState;

            // If we're not dealing with an ootii camera rig, we need to rotate to the camera here
            if (_RotateWithCamera && !(mMotionController.CameraRig is BaseCameraRig))
            {
                OnCameraUpdated(rDeltaTime, rUpdateIndex, null);
            }

            if (!_RotateWithCamera && _RotateWithInput)
            {
                RotateUsingInput(rDeltaTime, ref mRotation);
            }

            // Allow the base class to render debug info
            base.Update(rDeltaTime, rUpdateIndex);
        }
Esempio n. 3
0
        /// <summary>
        /// Updates the motion over time. This is called by the controller
        /// every update cycle so animations and stages can be updated.
        /// </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 override void Update(float rDeltaTime, int rUpdateIndex)
        {
            mMovement = Vector3.zero;
            mRotation = Quaternion.identity;

            mNoInputElapsed = mNoInputElapsed + rDeltaTime;

            // If we're at the surface and grounded, we can't be going fast
            bool lAllowRunning = (!mSwimmerInfo.IsInShallowWater(mActorController.GroundingLayers)) && IsRunning;

            // Grab the state info
            MotionState lState = mMotionController.State;

            // Convert the input to radial so we deal with keyboard and gamepad input the same.
            float lInputX         = lState.InputX;
            float lInputY         = lState.InputY;
            float lInputMagnitude = lState.InputMagnitudeTrend.Value;

            InputManagerHelper.ConvertToRadialInput(ref lInputX, ref lInputY, ref lInputMagnitude, (lAllowRunning ? 1f : 0.5f));

            // If input stops, we're going to keep our current value
            // and have the motion come to a smooth stop as needed
            if (lInputMagnitude > 0f)
            {
                mInputX.Add(lInputX);
                mInputY.Add(lInputY);
                mInputMagnitude.Add(lInputMagnitude);

                mNoInputElapsed = 0f;
            }

            // Use the averaged values for input
            lState.InputX = mInputX.Average;
            lState.InputY = mInputY.Average;
            lState.InputMagnitudeTrend.Replace(mInputMagnitude.Average);
            mMotionController.State = lState;

            // Determine how we'll stop based on the direction
            if (mMotionLayer._AnimatorStateID == STATE_SwimTree && mNoInputElapsed > 0.15f)
            {
                mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, PHASE_STOP_SWIM, 0, true);
            }

            // We do this so we can re-enter the movement if needed
            if (mMotionLayer._AnimatorTransitionID == TRANS_SwimTree_TreadIdlePose)
            {
                mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, 0, 0, true);
            }

            // Do a surface check to see if we're exiting the water
            float lWaterMovement = mSwimmerInfo.WaterSurface.position.y - mSwimmerInfo.WaterSurfaceLastPosition.y;

            if (mSwimmerInfo.TestExitWater(lWaterMovement))
            {
                mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, PHASE_STOP_IDLE, 0, true);
                return;
            }

            // If we're at the surface, we may need to move with the surface
            if (mSwimmerInfo.IsAtWaterSurface(0.5f))
            {
                mMovement.y = mMovement.y + lWaterMovement;
                mSwimmerInfo.CreateRipples(mMotionController._Transform.position);
            }
            else
            {
                mSwimmerInfo.CreateUnderwaterEffect(mMotionController.Animator, HumanBodyBones.Head);
            }

            mSwimmerInfo.WaterSurfaceLastPosition = mSwimmerInfo.WaterSurface.position;

            // Move based on the buoyancy
            mMovement = mMovement + mSwimmerInfo.GetBuoyancy(rDeltaTime);

            // Move vertically
            float lAngle = 0f;

            if (mMotionController._InputSource != null)
            {
                float lUpSpeed = mMotionController._InputSource.GetValue(_UpAlias) * _VerticalSpeed;
                if (lUpSpeed != 0f)
                {
                    lAngle = _MaxPitch;
                }
                if (mSwimmerInfo.IsAtWaterSurface(0f))
                {
                    lUpSpeed = 0f;
                }

                float lDownSpeed = mMotionController._InputSource.GetValue(_DownAlias) * -_VerticalSpeed;
                if (lDownSpeed != 0f)
                {
                    lAngle = -_MaxPitch;
                }
                if (mActorController.IsGrounded)
                {
                    lDownSpeed = 0f;
                }

                mMovement.y = mMovement.y + ((lUpSpeed + lDownSpeed) * rDeltaTime);
            }

            // If we're not using the keys, we may use the mouse
            if (_DiveWithCamera && lAngle == 0f)
            {
                float lUpSpeed          = 0f;
                float lDownSpeed        = 0f;
                float lAdjustedMaxPitch = _MaxPitch - 5f;

                float lCameraAngle = NumberHelper.GetHorizontalAngle(mMotionController._CameraTransform.forward, mMotionController._Transform.forward, mMotionController._CameraTransform.right);
                if (lCameraAngle > 5f)
                {
                    lCameraAngle = lCameraAngle - 5f;
                    lUpSpeed     = (Mathf.Min(lCameraAngle, lAdjustedMaxPitch) / lAdjustedMaxPitch) * _VerticalSpeed;
                    if (mSwimmerInfo.IsAtWaterSurface(0f))
                    {
                        lUpSpeed = 0f; lCameraAngle = 0f;
                    }
                }
                else if (lCameraAngle < -5f)
                {
                    lCameraAngle = lCameraAngle + 5f;
                    lDownSpeed   = (Mathf.Max(lCameraAngle, -lAdjustedMaxPitch) / -lAdjustedMaxPitch) * -_VerticalSpeed;
                    if (mActorController.IsGrounded)
                    {
                        lDownSpeed = 0f; lCameraAngle = 0f;
                    }
                }

                if (lCameraAngle != 0f)
                {
                    lAngle      = Mathf.Clamp(lAngle + lCameraAngle, -_MaxPitch, _MaxPitch);
                    mMovement.y = mMovement.y + ((lUpSpeed + lDownSpeed) * rDeltaTime);
                }
            }

            //Utilities.Debug.Log.ScreenWrite("Angle:" + lAngle.ToString("f3"), 14);

            // Rotate the body if we can
            RotateBody(-lAngle);

            // If we're not dealing with an ootii camera rig, we need to rotate to the camera here
            if (_RotateWithCamera && !(mMotionController.CameraRig is BaseCameraRig))
            {
                OnCameraUpdated(rDeltaTime, rUpdateIndex, null);
            }

            // Rotate as needed
            if (!_RotateWithCamera && _RotateWithInput)
            {
                RotateUsingInput(rDeltaTime, ref mRotation);
            }
        }