public void Tick(float dt) { Cursor.lockState = CursorLockMode.Locked; // Keep doing this. We don't want cursor anywhere just yet // We use GetAxisRaw, since we need it to feel as responsive as possible Vector3 moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized; #region No clip #if CHEATS_ENABLED if (Input.GetKeyDown(KeyCode.RightAlt)) { _noClipMove = !_noClipMove; } if (Input.GetMouseButtonDown(2)) { _velocity = _velocity.normalized * 20; } #endif if (_noClipMove) { float y = 0; if (Input.GetKey(KeyCode.Space)) { y = 1; } else if (Input.GetKey(KeyCode.LeftControl)) { y = -1; } moveInput.y = y; transform.position += _camTransform.TransformDirection(moveInput) * NoClipSpeed * Time.deltaTime; _velocity = Vector3.zero; return; } #endregion IsWalking = Input.GetKey(KeyCode.LeftShift); // MOVEMENT var wishDir = _camTransform.TransformDirectionHorizontal(moveInput); // We want to go in this direction _wishDirDebug = wishDir.ToHorizontal(); var isGrounded = IsGrounded(out Vector3 groundNormal); if (isGrounded) // Ground move { if (_isGroundedInPrevFrame && !_isGonnaJump) // Don't apply friction if just landed or about to jump { ApplyFriction(ref _velocity, dt); } var speedLimit = IsWalking ? WalkSpeed : MaxSpeedAlongOneDimension; Accelerate(ref _velocity, wishDir, GroundAccelerationCoeff, speedLimit, dt); // Crop up horizontal velocity component _velocity = Vector3.ProjectOnPlane(_velocity, groundNormal); if (_isGonnaJump) { // Jump away _velocity += Gravity.Up * JumpStrength; _sfx.Jump(); } } 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, MaxSpeedAlongOneDimension, dt); if (Mathf.Abs(moveInput.z) > 0.0001) // Pure side velocity doesn't allow air control { ApplyAirControl(ref _velocity, wishDir, moveInput, dt); } _velocity += Gravity.Down * (GravityAmount * dt); } 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); transform.position += collisionDisplacement; #region Footsteps if (isGrounded) { // At the moment of stopping: // - force play the sfx, it makes it sound more natural, humans usually stop with an extra step // - reset the distance, to make the footsteps ryhtym the same at start of walking every time if (_prevVelocity.ToHorizontal().magnitude > 0.01 && _velocity.ToHorizontal().magnitude < 0.01) { _footstepDistance = 0f; _sfx.Footstep(); } var totalDisplacement = displacement + collisionDisplacement; _footstepDistance += totalDisplacement.magnitude; const float stepDistance = 2f; // Play a footstep after this much of travel if (_footstepDistance > stepDistance) { _footstepDistance = 0f; _sfx.Footstep(); } } #endregion _isGroundedInPrevFrame = isGrounded; _prevVelocity = _velocity; }