/// <summary> /// Called every frame to perform processing. We only use /// this function if it's not called by another component. /// </summary> protected void Update() { if (mAnimator == null) { return; } if (mCameraRig == null) { return; } if (Time.deltaTime == 0f) { return; } // Store the state we're in mStateInfo = mAnimator.GetCurrentAnimatorStateInfo(0); mTransitionInfo = mAnimator.GetAnimatorTransitionInfo(0); if (mCameraRig.Mode == 2) { if (mStance != 2) { mPrevStance = mStance; mStance = 2; } } else { if (mStance == 2) { mStance = mPrevStance; } } // Determine the stance we're in if (mInputSource != null && mInputSource.IsPressed(KeyCode.LeftControl)) { //if (mStance != 2) //{ // mPrevStance = mStance; // mStance = 2; // mPrevRigMode = CameraRigMode; // // Start the transition process // //_CameraRig.TransitionToMode(EnumCameraMode.FIRST_PERSON); // CameraRigMode = EnumCameraMode.FIRST_PERSON; //} } else if (mStance == 2) { //mStance = mPrevStance; ////_CameraRig.TransitionToMode(mPrevRigMode); //CameraRigMode = mPrevRigMode; } else if (mInputSource != null && mInputSource.IsJustPressed(KeyCode.T)) { mPrevStance = mStance; if (mStance == 0) { mStance = 1; ((AdventureRig)mCameraRig).AnchorOrbitsCamera = false; } else if (mStance == 1) { mStance = 0; ((AdventureRig)mCameraRig).AnchorOrbitsCamera = true; } mCameraRig.Mode = 0; } // Grab the direction and speed of the input relative to our current heading StickToWorldspace(this.transform, _CameraRig.transform, ref mTempState); // Ensure some of the other values are set correctly mTempState.Acceleration = mState.Acceleration; mTempState.InitialHeading = mState.InitialHeading; // Ranged movement allows for slow forward, backwards, and strafing if (mStance == 2) { //CameraRigMode = EnumCameraMode.FIRST_PERSON; mTempState.Speed *= _TargetingStanceMovementSpeedMultiplier; // Change our heading if needed if (mTempState.Speed == 0) { if (IsInBackwardsState) { mTempState.InitialHeading = 2; } else { mTempState.InitialHeading = 0; } } else if (mTempState.Speed != 0 && mState.Speed == 0) { float lInitialAngle = Mathf.Abs(mTempState.FromCameraAngle); if (lInitialAngle < mForwardHeadingLimit) { mTempState.InitialHeading = 0; } else if (lInitialAngle > 180f - mBackwardsHeadingLimit) { mTempState.InitialHeading = 2; } else { mTempState.InitialHeading = 1; } } // Ensure we're always facing forward //mYAxisRotationAngle = NumberHelper.GetHorizontalAngle(transform.forward, _CameraRig.transform.forward); //mTempState.FromAvatarAngle = 0f; } // Combat movement allows for forward, backwards, strafing, and pivoting else if (mStance == 1) { // Determine our initial heading if (mTempState.Speed == 0) { if (IsInBackwardsState) { mTempState.InitialHeading = 2; } else { mTempState.InitialHeading = 0; } } else if (mTempState.Speed != 0 && mState.Speed == 0) { float lInitialAngle = Mathf.Abs(mTempState.FromCameraAngle); if (lInitialAngle < mForwardHeadingLimit) { mTempState.InitialHeading = 0; } else if (lInitialAngle > 180f - mBackwardsHeadingLimit) { mTempState.InitialHeading = 2; } else { mTempState.InitialHeading = 1; } } // Ensure if we've been heading forward that we don't allow the // avatar to rotate back facing the player if (mTempState.InitialHeading == 0) { //CameraRigMode = EnumCameraMode.THIRD_PERSON_FOLLOW; // Force the input to make us go forwards if (mTempState.Speed > 0.1f && (mTempState.FromCameraAngle < -90 || mTempState.FromCameraAngle > 90)) { mTempState.InputY = 1; } // If no forward rotation is allowed, this is easy if (mForwardHeadingLimit == 0f) { mTempState.FromAvatarAngle = 0f; } // Respect the foward rotation limits else { // Test if our rotation reaches the max from the camera. We use the camera since // the avatar itself rotates and this limit is relative. if (mTempState.FromCameraAngle < -mForwardHeadingLimit) { mTempState.FromCameraAngle = -mForwardHeadingLimit; } else if (mTempState.FromCameraAngle > mForwardHeadingLimit) { mTempState.FromCameraAngle = mForwardHeadingLimit; } // If we have reached a limit, we need to adjust the avatar angle if (Mathf.Abs(mTempState.FromCameraAngle) == mForwardHeadingLimit) { // Flip the angle if we're crossing over the axis if (Mathf.Sign(mTempState.FromCameraAngle) != Mathf.Sign(mState.FromCameraAngle)) { mTempState.FromCameraAngle = -mTempState.FromCameraAngle; } // Only allow the avatar to rotate the heading limit, taking into account the angular // difference between the camera and the avatar mTempState.FromAvatarAngle = mTempState.FromCameraAngle + NumberHelper.GetHorizontalAngle(transform.forward, _CameraRig.transform.forward); } } } else if (mTempState.InitialHeading == 2) { //CameraRigMode = EnumCameraMode.THIRD_PERSON_FIXED; // Force the input to make us go backwards if (mTempState.Speed > 0.1f && (mTempState.FromCameraAngle > -90 && mTempState.FromCameraAngle < 90)) { mTempState.InputY = -1; } // Ensure we don't go beyond our boundry if (mBackwardsHeadingLimit != 0f) { float lBackwardsHeadingLimit = 180f - mBackwardsHeadingLimit; // Test if our rotation reaches the max from the camera. We use the camera since // the avatar itself rotates and this limit is relative. if (mTempState.FromCameraAngle <= 0 && mTempState.FromCameraAngle > -lBackwardsHeadingLimit) { mTempState.FromCameraAngle = -lBackwardsHeadingLimit; } else if (mTempState.FromCameraAngle >= 0 && mTempState.FromCameraAngle < lBackwardsHeadingLimit) { mTempState.FromCameraAngle = lBackwardsHeadingLimit; } // If we have reached a limit, we need to adjust the avatar angle if (Mathf.Abs(mTempState.FromCameraAngle) == lBackwardsHeadingLimit) { // Only allow the avatar to rotate the heading limit, taking into account the angular // difference between the camera and the avatar mTempState.FromAvatarAngle = mTempState.FromCameraAngle + NumberHelper.GetHorizontalAngle(transform.forward, _CameraRig.transform.forward); } // Since we're moving backwards, we need to flip the movement angle. // If we're not moving and simply finishing an animation, we don't // want to rotate at all. if (mTempState.Speed == 0) { mTempState.FromAvatarAngle = 0f; } else if (mTempState.FromAvatarAngle <= 0) { mTempState.FromAvatarAngle += 180f; } else if (mTempState.FromAvatarAngle > 0) { mTempState.FromAvatarAngle -= 180f; } } } else if (mTempState.InitialHeading == 1) { //CameraRigMode = EnumCameraMode.THIRD_PERSON_FIXED; // Move out of the sidestep if needed if (mTempState.InputY > 0.1) { mTempState.InitialHeading = 0; } else if (mTempState.InputY < -0.1) { mTempState.InitialHeading = 2; } // We need to be able to rotate our avatar so it's facing // in the direction of the camera if (mTempState.InitialHeading == 1) { mTempState.FromCameraAngle = 0f; mTempState.FromAvatarAngle = mTempState.FromCameraAngle + NumberHelper.GetHorizontalAngle(transform.forward, _CameraRig.transform.forward); } } } // Determine the acceleration. We test this agains the 'last-last' speed so // that we are averaging out one frame. //mLastAcceleration = mAcceleration; mPrevState.Acceleration = mState.Acceleration; // Determine the trend so we can figure out acceleration if (mTempState.Speed == mState.Speed) { if (mSpeedTrendDirection != 0) { mSpeedTrendDirection = 0; } } else if (mTempState.Speed < mState.Speed) { if (mSpeedTrendDirection != 1) { mSpeedTrendDirection = 1; if (mMecanimUpdateDelay <= 0f) { mMecanimUpdateDelay = 0.2f; } } // Acceleration needs to stay consistant for mecanim mTempState.Acceleration = mTempState.Speed - mSpeedTrendStart; } else if (mTempState.Speed > mState.Speed) { if (mSpeedTrendDirection != 2) { mSpeedTrendDirection = 2; if (mMecanimUpdateDelay <= 0f) { mMecanimUpdateDelay = 0.2f; } } // Acceleration needs to stay consistant for mecanim mTempState.Acceleration = mTempState.Speed - mSpeedTrendStart; } // Shuffle the states to keep us from having to reallocated AdventureControllerState lTempState = mPrevState; mPrevState = mState; mState = mTempState; mTempState = lTempState; // Apply the movement and rotation ApplyMovement(); ApplyRotation(); // Delay a bit before we update the speed if we're accelerating // or decelerating. mMecanimUpdateDelay -= Time.deltaTime; if (mMecanimUpdateDelay <= 0f) { mAnimator.SetFloat("Speed", mState.Speed); //, 0.05f, Time.deltaTime); mSpeedTrendStart = mState.Speed; } // Update the direction relative to the avatar mAnimator.SetFloat("Avatar Direction", mState.FromAvatarAngle); // At this point, we never use angular speed. Rotation is done // in the ApplyRotation() function. Angular speed currently only effects // locomotion. mAnimator.SetFloat("Angular Speed", 0f); // The stance determins if we're in exploration or combat mode. mAnimator.SetInteger("Stance", mStance); // The direction from the camera mAnimator.SetFloat("Camera Direction", mState.FromCameraAngle); //, 0.05f, Time.deltaTime); // The raw input from the UI mAnimator.SetFloat("Input X", mState.InputX); //, 0.25f, Time.deltaTime); mAnimator.SetFloat("Input Y", mState.InputY); //, 0.25f, Time.deltaTime); }
/// <summary> /// This function is used to convert the game control stick value to /// speed and direction values for the player. /// </summary> protected void StickToWorldspace(Transform rController, Transform rCamera, ref AdventureControllerState rState) { if (mInputSource == null) { return; } // Grab the movement, but create a bit of a dead zone float lHInput = mInputSource.MovementX; float lVInput = mInputSource.MovementY; // Get out early if we can simply this if (lVInput == 0f && lHInput == 0f) { rState.Speed = 0f; rState.FromAvatarAngle = 0f; rState.InputX = 0f; rState.InputY = 0f; return; } // Determine the relative speed rState.Speed = Mathf.Sqrt((lHInput * lHInput) + (lVInput * lVInput)); // Create a simple vector off of our stick input and get the speed sVector3A.x = lHInput; sVector3A.y = 0f; sVector3A.z = lVInput; // Direction of the avatar Vector3 lControllerForward = rController.forward; lControllerForward.y = 0f; lControllerForward.Normalize(); // Direction of the camera Vector3 lCameraForward = rCamera.forward; lCameraForward.y = 0f; lCameraForward.Normalize(); // Create a quaternion that gets us from our world-forward to our 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 rToCamera = Quaternion.FromToRotation(Vector3.forward, Vector3.Normalize(lCameraForward)); Quaternion rToCamera = Quaternion.LookRotation(lCameraForward); // Transform joystick from world space to camera space. Now the input is relative // to how the camera is facing. Vector3 lMoveDirection = rToCamera * sVector3A; rState.FromCameraAngle = NumberHelper.GetHorizontalAngle(lCameraForward, lMoveDirection); rState.FromAvatarAngle = NumberHelper.GetHorizontalAngle(lControllerForward, lMoveDirection); // Set the direction of the movement in ranges of -1 to 1 rState.InputX = lHInput; rState.InputY = lVInput; //Debug.DrawRay(new Vector3(rController.position.x, rController.position.y + 2f, rController.position.z), lControllerForward, Color.gray); //Debug.DrawRay(new Vector3(rController.position.x, rController.position.y + 2f, rController.position.z), lMoveDirection, Color.green); }