void HandleCharacterMovement() { // horizontal character rotation { // rotate the transform with the input speed around its local Y axis transform.Rotate(new Vector3(0f, (m_InputHandler.GetLookInputsHorizontal() * rotationSpeed * RotationMultiplier), 0f), Space.Self); } // vertical camera rotation { // add vertical inputs to the camera's vertical angle m_CameraVerticalAngle += m_InputHandler.GetLookInputsVertical() * rotationSpeed * RotationMultiplier; // limit the camera's vertical angle to min/max m_CameraVerticalAngle = Mathf.Clamp(m_CameraVerticalAngle, -89f, 89f); // apply the vertical angle as a local rotation to the camera transform along its right axis (makes it pivot up and down) if (wallRunComponent != null) { playerCamera.transform.localEulerAngles = new Vector3(m_CameraVerticalAngle, 0, wallRunComponent.GetCameraRoll()); } else { playerCamera.transform.localEulerAngles = new Vector3(m_CameraVerticalAngle, 0, 0); } } // character movement handling bool isSprinting = m_InputHandler.GetSprintInputHeld(); { if (isSprinting) { isSprinting = SetCrouchingState(false, false); } float speedModifier = isSprinting ? sprintSpeedModifier : 1f; // converts move input to a worldspace vector based on our character's transform orientation Vector3 worldspaceMoveInput = transform.TransformVector(m_InputHandler.GetMoveInput()); // handle grounded movement if (isGrounded || (wallRunComponent != null && wallRunComponent.IsWallRunning())) { if (isGrounded) { // calculate the desired velocity from inputs, max speed, and current slope Vector3 targetVelocity = worldspaceMoveInput * maxSpeedOnGround * speedModifier; // reduce speed if crouching by crouch speed ratio if (isCrouching) { targetVelocity *= maxSpeedCrouchedRatio; } targetVelocity = GetDirectionReorientedOnSlope(targetVelocity.normalized, m_GroundNormal) * targetVelocity.magnitude; // smoothly interpolate between our current velocity and the target velocity based on acceleration speed characterVelocity = Vector3.Lerp(characterVelocity, targetVelocity, movementSharpnessOnGround * Time.deltaTime); } // jumping if ((isGrounded || (wallRunComponent != null && wallRunComponent.IsWallRunning())) && m_InputHandler.GetJumpInputDown()) { // force the crouch state to false if (SetCrouchingState(false, false)) { if (isGrounded) { // start by canceling out the vertical component of our velocity characterVelocity = new Vector3(characterVelocity.x, 0f, characterVelocity.z); // then, add the jumpSpeed value upwards characterVelocity += Vector3.up * jumpForce; } else { characterVelocity = new Vector3(characterVelocity.x, 0f, characterVelocity.z); // then, add the jumpSpeed value upwards characterVelocity += wallRunComponent.GetWallJumpDirection() * jumpForce; } // play sound audioSource.PlayOneShot(jumpSFX); // remember last time we jumped because we need to prevent snapping to ground for a short time m_LastTimeJumped = Time.time; hasJumpedThisFrame = true; // Force grounding to false isGrounded = false; m_GroundNormal = Vector3.up; } } // footsteps sound float chosenFootstepSFXFrequency = (isSprinting ? footstepSFXFrequencyWhileSprinting : footstepSFXFrequency); if (m_footstepDistanceCounter >= 1f / chosenFootstepSFXFrequency) { m_footstepDistanceCounter = 0f; audioSource.PlayOneShot(footstepSFX); } // keep track of distance traveled for footsteps sound m_footstepDistanceCounter += characterVelocity.magnitude * Time.deltaTime; } // handle air movement else { if (wallRunComponent == null || (wallRunComponent != null && !wallRunComponent.IsWallRunning())) { // add air acceleration characterVelocity += worldspaceMoveInput * accelerationSpeedInAir * Time.deltaTime; // limit air speed to a maximum, but only horizontally float verticalVelocity = characterVelocity.y; Vector3 horizontalVelocity = Vector3.ProjectOnPlane(characterVelocity, Vector3.up); horizontalVelocity = Vector3.ClampMagnitude(horizontalVelocity, maxSpeedInAir * speedModifier); characterVelocity = horizontalVelocity + (Vector3.up * verticalVelocity); // apply the gravity to the velocity characterVelocity += Vector3.down * gravityDownForce * Time.deltaTime; } } } // apply the final calculated velocity value as a character movement Vector3 capsuleBottomBeforeMove = GetCapsuleBottomHemisphere(); Vector3 capsuleTopBeforeMove = GetCapsuleTopHemisphere(m_Controller.height); m_Controller.Move(characterVelocity * Time.deltaTime); // detect obstructions to adjust velocity accordingly m_LatestImpactSpeed = Vector3.zero; if (Physics.CapsuleCast(capsuleBottomBeforeMove, capsuleTopBeforeMove, m_Controller.radius, characterVelocity.normalized, out RaycastHit hit, characterVelocity.magnitude * Time.deltaTime, -1, QueryTriggerInteraction.Ignore)) { // We remember the last impact speed because the fall damage logic might need it m_LatestImpactSpeed = characterVelocity; characterVelocity = Vector3.ProjectOnPlane(characterVelocity, hit.normal); } }
// Updates the weapon bob animation based on character speed void UpdateWeaponBob() { if (Time.deltaTime > 0f) { Vector3 playerCharacterVelocity = (m_PlayerCharacterController.transform.position - m_LastCharacterPosition) / Time.deltaTime; // calculate a smoothed weapon bob amount based on how close to our max grounded movement velocity we are float characterMovementFactor = 0f; if (m_PlayerCharacterController.isGrounded || (wallRunComponent != null && wallRunComponent.IsWallRunning())) { characterMovementFactor = Mathf.Clamp01(playerCharacterVelocity.magnitude / (m_PlayerCharacterController.maxSpeedOnGround * m_PlayerCharacterController.sprintSpeedModifier)); } m_WeaponBobFactor = Mathf.Lerp(m_WeaponBobFactor, characterMovementFactor, bobSharpness * Time.deltaTime); // Calculate vertical and horizontal weapon bob values based on a sine function float bobAmount = isAiming ? aimingBobAmount : defaultBobAmount; float frequency = bobFrequency; float hBobValue = Mathf.Sin(Time.time * frequency) * bobAmount * m_WeaponBobFactor; float vBobValue = ((Mathf.Sin(Time.time * frequency * 2f) * 0.5f) + 0.5f) * bobAmount * m_WeaponBobFactor; // Apply weapon bob m_WeaponBobLocalPosition.x = hBobValue; m_WeaponBobLocalPosition.y = Mathf.Abs(vBobValue); m_LastCharacterPosition = m_PlayerCharacterController.transform.position; } }