//Update; void Update() { //Get controller velocity; Vector3 _velocity = controller.GetVelocity(); //Split up velocity; Vector3 _horizontalVelocity = VectorMath.RemoveDotVector(_velocity, tr.up); Vector3 _verticalVelocity = _velocity - _horizontalVelocity; //Smooth horizontal velocity for fluid animation; _horizontalVelocity = Vector3.Lerp(oldMovementVelocity, _horizontalVelocity, smoothingFactor); oldMovementVelocity = _horizontalVelocity; animator.SetFloat("VerticalSpeed", _verticalVelocity.magnitude * VectorMath.GetDotProduct(_verticalVelocity.normalized, tr.up)); animator.SetFloat("HorizontalSpeed", _horizontalVelocity.magnitude); //If animator is strafing, split up horizontal velocity; if (useStrafeAnimations) { Vector3 _localVelocity = animatorTransform.InverseTransformVector(_horizontalVelocity); animator.SetFloat("ForwardSpeed", _localVelocity.z); animator.SetFloat("StrafeSpeed", _localVelocity.x); } //Pass values to animator; animator.SetBool("IsGrounded", controller.IsGrounded()); animator.SetBool("IsStrafing", useStrafeAnimations); }
//Rotate camera toward '_direction', at the rate of '_speed', around the upwards vector of this gameobject; public void RotateTowardsVelocity(Vector3 _velocity, float _speed) { //Remove any unwanted components of direction; _velocity = VectorMath.RemoveDotVector(_velocity, GetUpDirection()); //Calculate angle difference of current direction and new direction; float _angle = VectorMath.GetAngle(GetFacingDirection(), _velocity, GetUpDirection()); //Calculate sign of angle; float _sign = Mathf.Sign(_angle); //Calculate final angle difference; float _finalAngle = Time.deltaTime * _speed * _sign * Mathf.Abs(_angle / 90f); //If angle is greater than 90 degrees, recalculate final angle difference; if (Mathf.Abs(_angle) > 90f) { _finalAngle = Time.deltaTime * _speed * _sign * ((Mathf.Abs(180f - Mathf.Abs(_angle))) / 90f); } //Check if calculated angle overshoots; if (Mathf.Abs(_finalAngle) > Mathf.Abs(_angle)) { _finalAngle = _angle; } //Take movement speed into account by comparing it to 'maximumMovementSpeed'; _finalAngle *= Mathf.InverseLerp(0f, maximumMovementSpeed, _velocity.magnitude); SetRotationAngles(GetCurrentXAngle(), GetCurrentYAngle() + _finalAngle); }
//Update; private void Update() { //Get controller velocity; Vector3 _velocity = controller.GetVelocity(); //Calculate horizontal velocity; Vector3 _horizontalVelocity = VectorMath.RemoveDotVector(_velocity, tr.up); FootStepUpdate(_horizontalVelocity.magnitude); }
//This function is called when the controller has collided with a ceiling while jumping or moving upwards; void OnCeilingContact() { //If local momentum is used, transform momentum into world coordinates first; if (useLocalMomentum) { momentum = tr.localToWorldMatrix * momentum; } //Remove all vertical parts of momentum; momentum = VectorMath.RemoveDotVector(momentum, tr.up); if (useLocalMomentum) { momentum = tr.worldToLocalMatrix * momentum; } }
//This function is called when the controller has lost ground contact, i.e. is either falling or rising, or generally in the air; void OnGroundContactLost() { //Calculate current velocity; //If velocity would exceed the controller's movement speed, decrease movement velocity appropriately; //This prevents unwanted accumulation of velocity; float _horizontalMomentumSpeed = VectorMath.RemoveDotVector(GetMomentum(), tr.up).magnitude; Vector3 _currentVelocity = GetMomentum() + Vector3.ClampMagnitude(savedMovementVelocity, Mathf.Clamp(movementSpeed - _horizontalMomentumSpeed, 0f, movementSpeed)); //Calculate length and direction from '_currentVelocity'; float _length = _currentVelocity.magnitude; //Calculate velocity direction; Vector3 _velocityDirection = Vector3.zero; if (_length != 0f) { _velocityDirection = _currentVelocity / _length; } //Subtract from '_length', based on 'movementSpeed' and 'airControl', check for overshooting; if (_length >= movementSpeed * airControl) { _length -= movementSpeed * airControl; } else { _length = 0f; } //If local momentum is used, transform momentum into world coordinates first; if (useLocalMomentum) { momentum = tr.localToWorldMatrix * momentum; } momentum = _velocityDirection * _length; if (useLocalMomentum) { momentum = tr.worldToLocalMatrix * momentum; } }
//Apply friction to both vertical and horizontal momentum based on 'friction' and 'gravity'; //Handle sliding down steep slopes; void HandleMomentum() { //If local momentum is used, transform momentum into world coordinates first; if (useLocalMomentum) { momentum = tr.localToWorldMatrix * momentum; } Vector3 _verticalMomentum = Vector3.zero; Vector3 _horizontalMomentum = Vector3.zero; //Split momentum into vertical and horizontal components; if (momentum != Vector3.zero) { _verticalMomentum = VectorMath.ExtractDotVector(momentum, tr.up); _horizontalMomentum = momentum - _verticalMomentum; } //Add gravity to vertical momentum; _verticalMomentum -= tr.up * gravity * Time.deltaTime; //Remove any downward force if the controller is grounded; if (currentControllerState == ControllerState.Grounded) { _verticalMomentum = Vector3.zero; } //Apply friction to horizontal momentum based on whether the controller is grounded; if (currentControllerState == ControllerState.Grounded) { _horizontalMomentum = VectorMath.IncrementVectorLengthTowardTargetLength(_horizontalMomentum, groundFriction, Time.deltaTime, 0f); } else { _horizontalMomentum = VectorMath.IncrementVectorLengthTowardTargetLength(_horizontalMomentum, airFriction, Time.deltaTime, 0f); } //Add horizontal and vertical momentum back together; momentum = _horizontalMomentum + _verticalMomentum; //Project the current momentum onto the current ground normal if the controller is sliding down a slope; if (currentControllerState == ControllerState.Sliding) { momentum = Vector3.ProjectOnPlane(momentum, mover.GetGroundNormal()); } //Apply slide gravity along ground normal, if controller is sliding; if (currentControllerState == ControllerState.Sliding) { Vector3 _slideDirection = Vector3.ProjectOnPlane(-tr.up, mover.GetGroundNormal()).normalized; momentum += _slideDirection * slideGravity * Time.deltaTime; } //If controller is jumping, override vertical velocity with jumpSpeed; if (currentControllerState == ControllerState.Jumping) { momentum = VectorMath.RemoveDotVector(momentum, tr.up); momentum += tr.up * jumpSpeed; } if (useLocalMomentum) { momentum = tr.worldToLocalMatrix * momentum; } }