private void Update() { Cursor.lockState = CursorLockMode.Locked; // Keep doing this. We don't want cursor anywhere just yet var dt = Time.deltaTime; // We use GetAxisRaw, since we need it to feel as responsive as possible _moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized; if (Input.GetKeyDown(KeyCode.Space) && !_isGonnaJump) { _isGonnaJump = true; } else if (Input.GetKeyUp(KeyCode.Space)) { _isGonnaJump = false; } MouseLook(ref _pitch, dt, _isInverted); _transform.rotation *= Quaternion.Euler(Input.GetAxis("Mouse X") * Sensitivity * dt * Vector3.up); if (Input.GetKeyDown(KeyCode.I)) { _isInverted = !_isInverted; } _fov.ExternalUpdate(_velocity); _hook.ExternalUpdate(dt, _transform.position); // Reset player -- makes testing much easier if (Input.GetKeyDown(KeyCode.R)) { _transform.position = new Vector3(0, 5, 0); _velocity = Vector3.forward; _hook.ResetHook(); } //////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// MOVEMENT /////////////////////////////////////////////// var wishDir = _camFollow.TransformDirectionHorizontal(_moveInput); // We want to go in this direction _wishDirDebug = wishDir.ToHorizontal(); Vector3 groundNormal; var isGrounded = IsGrounded(out groundNormal); _footsteps.ExternalUpdate(_isGonnaJump, isGrounded, isGrounded && !_isGroundedInPrevFrame); if (isGrounded) // Ground move { // Don't apply friction if just landed or about to jump if (_isGroundedInPrevFrame && !_isGonnaJump) { ApplyFriction(ref _velocity, dt); } Accelerate(ref _velocity, wishDir, GroundAccelerationCoeff, dt); // Crop up horizontal velocity component _velocity = Vector3.ProjectOnPlane(_velocity, groundNormal); if (_isGonnaJump) { // Jump away _velocity += Vector3.up * JumpStrength; } } else // Air move { // If the input doesn't have the same facing with the current velocity // then slow down instead of speeding up var coeff = Vector3.Dot(_velocity, wishDir) > 0 ? AirAccelCoeff : AirDecelCoeff; Accelerate(ref _velocity, wishDir, coeff, dt); if (Mathf.Abs(_moveInput.z) > 0.0001) // Pure side velocity doesn't allow air control { ApplyAirControl(ref _velocity, wishDir, dt); } _velocity += Vector3.down * (GravityAmount * dt); } _hook.ApplyHookAcceleration(ref _velocity, _transform, _moveInput); var displacement = _velocity * dt; // If we're moving too fast, make sure we don't hollow through any collider if (displacement.magnitude > _collisionVolume.radius) { ClampDisplacement(ref _velocity, ref displacement, _transform.position); } _transform.position += displacement; var collisionDisplacement = ResolveCollisions(ref _velocity); _hook.ApplyHookDisplacement(ref _velocity, ref collisionDisplacement, _transform.position - Vector3.up * 0.4f); _transform.position += collisionDisplacement; _isGroundedInPrevFrame = isGrounded; _hook.Draw(); _animator.SetBool("OnGround", isGrounded); _animator.SetFloat("Forward", Mathf.Lerp(0, 1, _velocity.WithY(0).magnitude / MaxSpeedAlongOneDimension)); _animator.SetFloat("Turn", Mathf.Clamp(_moveInput.x, -0.4f, 0.4f)); _animator.SetFloat("JumpLeg", _moveInput.x); _animator.SetFloat("Jump", Mathf.Lerp(-5, 5, Lerp(_velocity.y, -8f, 8f))); }