/// <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; // Test if we stop sneak due to a change in stance. We do this here to transition if (mMotionController.State.AnimatorStates[mMotionLayer._AnimatorLayerIndex].MotionPhase == 0 && mMotionController._InputSource != null && mMotionController._InputSource.IsEnabled) { //if (mMotionController._InputSource.IsJustPressed(_ActionAlias)) if (mMotionController._InputSource.IsReleased(_ActionAlias)) { // We have to use the forced value our we'll change the current blend value as we transition mMotionController.ForcedInput.x = mInputX.Average; mMotionController.ForcedInput.y = mInputY.Average; mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, PHASE_END, 0, true); } } // 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, 0.5f); // Smooth the input mInputX.Add(lInputX); mInputY.Add(lInputY); mInputMagnitude.Add(lInputMagnitude); // Use the smoothed values for input mMotionController.State.InputX = mInputX.Average; mMotionController.State.InputY = mInputY.Average; mMotionController.State.InputMagnitudeTrend.Replace(mInputMagnitude.Average); // 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); } }
/// <summary> /// Sets the value of this state with values from another /// /// Note: When the shift occurs, all intrinsict types (float, string, etc) /// have thier values copied over. Any reference types (arrays, objects) have /// thier references assigned. This includes 'child' properties. /// /// For the reference values... if we want them shared between the prev and current /// instances, we don't need to do anything. /// /// However, if we want reference values to be independant between the prev and current /// we need to grab the prev's reference, hold it, and then reset it. /// </summary> /// <param name="rSource">MotionState that has the data to copy</param> public static void Shift(ref MotionState rCurrent, ref MotionState rPrev) { // Reference objects need to be held onto otherwise our 'prev' // container will actually hold the reference in the 'current' container AnimatorLayerState[] lAnimatorStates = rPrev.AnimatorStates; // Move the current contents into the previous bucket rPrev = rCurrent; // Update the members of the states array. We have to do this // so 'prev' doesn't accidentally hold a reference sot the array in 'current' rPrev.AnimatorStates = lAnimatorStates; if (rPrev.AnimatorStates != null) { int lCount = lAnimatorStates.Length; for (int i = 0; i < lCount; i++) { //rPrev.AnimatorStates[i] = rCurrent.AnimatorStates[i]; //TT rPrev.AnimatorStates[i].SetTime = rCurrent.AnimatorStates[i].SetTime; rPrev.AnimatorStates[i].MotionPhase = rCurrent.AnimatorStates[i].MotionPhase; rPrev.AnimatorStates[i].MotionForm = rCurrent.AnimatorStates[i].MotionForm; rPrev.AnimatorStates[i].MotionParameter = rCurrent.AnimatorStates[i].MotionParameter; rPrev.AnimatorStates[i].AutoClearMotionPhase = rCurrent.AnimatorStates[i].AutoClearMotionPhase; rPrev.AnimatorStates[i].AutoClearMotionPhaseReady = rCurrent.AnimatorStates[i].AutoClearMotionPhaseReady; rPrev.AnimatorStates[i].AutoClearActiveTransitionID = rCurrent.AnimatorStates[i].AutoClearActiveTransitionID; rPrev.AnimatorStates[i].StateInfo = rCurrent.AnimatorStates[i].StateInfo; rPrev.AnimatorStates[i].TransitionInfo = rCurrent.AnimatorStates[i].TransitionInfo; } } // Initialize the object we're attached to. Don't clear // the contact position as we'll store it for future use //rCurrent.Support = null; //rCurrent.SupportPosition = Vector3.zero; //rCurrent.SupportRotation = Quaternion.identity; // Initialize the ground information //rCurrent.IsGrounded = false; //rCurrent.GroundAngle = 0f; //rCurrent.GroundNormal = Vector3.up; //rCurrent.GroundDistance = float.MaxValue; }
/// <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); }
/// <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; // Grab the state info 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); // 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); } }
/// <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) { mVelocity = Vector3.zero; mMovement = Vector3.zero; float lHipDistanceDelta = 0f; // Since we're not doing any lerping or physics based stuff here, // we'll only process once per cyle even if we're running slow. if (rUpdateIndex != 1) { return; } // If we have a hip bone, we'll adjust the jump based on the distance // that changes between the foot and the hips. This way, the jump is // "hip based" and not "foot based". if (_ConvertToHipBase && mHipBone != null) { float lHipDistance = mHipBone.position.y - mMotionController._Transform.position.y; // As the distance gets smaller, we increase the shift lHipDistanceDelta = -(lHipDistance - mLastHipDistance); mLastHipDistance = lHipDistance; } // Determine how gravity is being applied //Vector3 lWorldGravity = (mActorController._Gravity.sqrMagnitude == 0f ? UnityEngine.Physics.gravity : mActorController._Gravity); //if (mActorController._IsGravityRelative) { lWorldGravity = mActorController._Transform.rotation * lWorldGravity; } //Vector3 lGravityNormal = lWorldGravity.normalized; // Determine our velocities //mVelocity = mLaunchVelocity; //Vector3 lVelocity = mActorController.State.MovementForceAdjust / rDeltaTime; //Vector3 lVerticalVelocity = Vector3.Project(lVelocity, mActorController._Transform.up); // Grab the state info MotionState lState = mMotionController.State; //int lStateMotionPhase = lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].MotionPhase; //int lStateMotionParameter = lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].MotionParameter; //AnimatorStateInfo lStateInfo = lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].StateInfo; int lStateID = mMotionLayer._AnimatorStateID; float lStateTime = mMotionLayer._AnimatorStateNormalizedTime; //AnimatorTransitionInfo lTransitionInfo = lState.AnimatorStates[mMotionLayer._AnimatorLayerIndex].TransitionInfo; //int lTransitionID = lTransitionInfo.fullPathHash; // On launch, add the impulse if (lStateID == STATE_RunningJump) { // If we haven't applied the impulse, do it now. if (!mIsImpulseApplied) { mIsImpulseApplied = true; mActorController.AddImpulse(mActorController._Transform.up * _Impulse); } // As we come to the end, we have a couple of options if (!mIsExitTriggered && lStateTime > 0.80f) { // If we're a long way from the ground, transition to a fall if (mFall != null && mFall.IsEnabled && mActorController.State.GroundSurfaceDistance > _MinFallHeight) { mIsExitTriggered = true; mMotionController.ActivateMotion(mFall); } // If we're still getting input, keep running else if (lState.InputMagnitudeTrend.Value >= 0.1f) // && Mathf.Abs(lState.InputFromAvatarAngle) < 10f) { mIsExitTriggered = true; mMotionController.SetAnimatorMotionPhase(mMotionLayer.AnimatorLayerIndex, PHASE_LAND_RUN, true); } // Come to a quick stop else { mIsExitTriggered = true; mMotionController.SetAnimatorMotionPhase(mMotionLayer.AnimatorLayerIndex, PHASE_LAND_IDLE, true); } } // While in the jump, adjust the displacement else { mMovement = mActorController._Transform.up * lHipDistanceDelta; } } // Once we get into the run forward, we can transition to the true run else if (lStateID == STATE_RunJump_RunForward) { if (lStateTime > 1f) { // It may be time to move into the walk/run if (mWalkRunMotion != null && mWalkRunMotion.IsEnabled) { mWalkRunMotion.StartInRun = mWalkRunMotion.IsRunActive; mWalkRunMotion.StartInWalk = !mWalkRunMotion.StartInRun; mMotionController.ActivateMotion(mWalkRunMotion as MotionControllerMotion); } //if (mWalkRunPivot != null && mWalkRunPivot.IsEnabled) //{ // mWalkRunPivot.StartInRun = mWalkRunPivot.IsRunActive; // mWalkRunPivot.StartInWalk = !mWalkRunPivot.StartInRun; // mMotionController.ActivateMotion(mWalkRunPivot); //} //else if (mWalkRunPivot_v2 != null && mWalkRunPivot_v2.IsEnabled) //{ // mWalkRunPivot_v2.StartInRun = mWalkRunPivot_v2.IsRunActive; // mWalkRunPivot_v2.StartInWalk = !mWalkRunPivot_v2.StartInRun; // mMotionController.ActivateMotion(mWalkRunPivot_v2); //} //else if (mWalkRunStrafe != null && mWalkRunStrafe.IsEnabled) //{ // mWalkRunStrafe.StartInRun = mWalkRunStrafe.IsRunActive; // mWalkRunStrafe.StartInWalk = !mWalkRunStrafe.StartInRun; // mMotionController.ActivateMotion(mWalkRunStrafe); //} //else if (mWalkRunStrafe_v2 != null && mWalkRunStrafe_v2.IsEnabled) //{ // mWalkRunStrafe_v2.StartInRun = mWalkRunStrafe_v2.IsRunActive; // mWalkRunStrafe_v2.StartInWalk = !mWalkRunStrafe_v2.StartInRun; // mMotionController.ActivateMotion(mWalkRunStrafe_v2); //} //else if (mWalkRunRotate != null && mWalkRunRotate.IsEnabled) //{ // mWalkRunRotate.StartInRun = mWalkRunRotate.IsRunActive; // mWalkRunRotate.StartInWalk = !mWalkRunRotate.StartInRun; // mMotionController.ActivateMotion(mWalkRunRotate); //} //else if (mWalkRunRotate_v2 != null && mWalkRunRotate_v2.IsEnabled) //{ // mWalkRunRotate_v2.StartInRun = mWalkRunRotate_v2.IsRunActive; // mWalkRunRotate_v2.StartInWalk = !mWalkRunRotate_v2.StartInRun; // mMotionController.ActivateMotion(mWalkRunRotate_v2); //} else { Deactivate(); } } } // Once we get to the idle pose, we can deactivate else if (lStateID == STATE_IdlePose) { Deactivate(); } //Log.FileWrite("Adv_J.Update(" + rDeltaTime.ToString("f4") + ", " + rUpdateIndex + ") isAct:" + mIsActive + " " + mMotionController.AnimatorStateNames[lStateID] + " %:" + lStateInfo.normalizedTime.ToString("0.000") + " mm:" + mMovement.y.ToString("f4") + " mv:" + mVelocity.y.ToString("f4") + " pv:" + lProjectedVelocity.y.ToString("f4")); }
/// <summary> /// Returns the current velocity of the motion /// </summary> protected Vector3 DetermineVelocity(bool rAllowSlide) { Vector3 lVelocity = Vector3.zero; //int lStateID = mMotionLayer._AnimatorStateID; // TRT 11/20/15: If we're colliding with an object, we won't allow // any velocity. This helps prevent sliding while jumping // against an object. if (mActorController.State.IsColliding) { return(lVelocity); } // Determines if we allow sliding or not if (!rAllowSlide && mActorController.State.IsGrounded) { return(lVelocity); } // If were in the midst of jumping, we want to add velocity based on // the magnitude of the controller. //if ((lStateID != STATE_JumpRecoverIdle || rAllowSlide) && // (lStateID != STATE_JumpRecoverRun || rAllowSlide) && // IsInMotionState) { MotionState lState = mMotionController.State; // Speed that comes from momenum Vector3 lMomentum = mLaunchVelocity; float lMomentumSpeed = (_IsMomentumEnabled ? lMomentum.magnitude : 0f); // Speed that comes from the user float lControlSpeed = (_IsControlEnabled ? _ControlSpeed * lState.InputMagnitudeTrend.Value : 0f); // Speed we'll use as the character is jumping float lAirSpeed = Mathf.Max(lMomentumSpeed, lControlSpeed); // If we allow control, let the player determine the direction if (_IsControlEnabled) { Vector3 lBaseForward = mActorController._Transform.forward; if (mMotionController._InputSource != null && mMotionController._InputSource.IsEnabled) { if (mMotionController._CameraTransform != null) { lBaseForward = mMotionController._CameraTransform.forward; } } // Create a quaternion that gets us from our world-forward to our actor/camera direction. // FromToRotation creates a quaternion using the shortest method which can sometimes // flip the angle. LookRotation will attempt to keep the "up" direction "up". Quaternion lToBaseForward = Quaternion.LookRotation(lBaseForward, mActorController._Transform.up); // Determine the avatar displacement direction. This isn't just // normal movement forward, but includes movement to the side Vector3 lMoveDirection = lToBaseForward * lState.InputForward; // Apply the direction and speed lVelocity = lVelocity + (lMoveDirection * lAirSpeed); } // If momementum is enabled, add it to keep the player moving in the direction of the jump if (_IsMomentumEnabled) { lVelocity = lVelocity + lMomentum; } // Don't exceed our air speed if (lVelocity.magnitude > lAirSpeed) { lVelocity = lVelocity.normalized * lAirSpeed; } } return(lVelocity); }