//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); }
//Rotate the camera toward a look vector in the scene; public void RotateTowardDirection(Vector3 _direction, float _lookSpeed) { //Normalize direction; _direction.Normalize(); //Transform target look vector to this transform's local space; _direction = tr.parent.InverseTransformDirection(_direction); //Calculate (local) current look vector; Vector3 _currentLookVector = GetAimingDirection(); _currentLookVector = tr.parent.InverseTransformDirection(_currentLookVector); //Calculate x angle difference; float _xAngleDifference = VectorMath.GetAngle(new Vector3(0f, _currentLookVector.y, 1f), new Vector3(0f, _direction.y, 1f), Vector3.right); //Calculate y angle difference; _currentLookVector.y = 0f; _direction.y = 0f; float _yAngleDifference = VectorMath.GetAngle(_currentLookVector, _direction, Vector3.up); //Turn angle values into Vector2 variables for better clamping; Vector2 _currentAngles = new Vector2(currentXAngle, currentYAngle); Vector2 _angleDifference = new Vector2(_xAngleDifference, _yAngleDifference); //Calculate normalized direction; float _angleDifferenceMagnitude = _angleDifference.magnitude; if (_angleDifferenceMagnitude == 0f) { return; } Vector2 _angleDifferenceDirection = _angleDifference / _angleDifferenceMagnitude; //Check for overshooting; if (_lookSpeed * Time.deltaTime > _angleDifferenceMagnitude) { _currentAngles += _angleDifferenceDirection * _angleDifferenceMagnitude; } else { _currentAngles += _angleDifferenceDirection * _lookSpeed * Time.deltaTime; } //Set new angles; currentYAngle = _currentAngles.y; //Clamp vertical rotation; currentXAngle = Mathf.Clamp(_currentAngles.x, -upperVerticalLimit, lowerVerticalLimit); UpdateRotation(); }
void LateUpdate() { //Get controller velocity; Vector3 _velocity; if (ignoreControllerMomentum) { _velocity = controller.GetMovementVelocity(); } else { _velocity = controller.GetVelocity(); } //Project velocity onto a plane defined by the 'up' direction of the parent transform; _velocity = Vector3.ProjectOnPlane(_velocity, parentTransform.up); float _magnitudeThreshold = 0.001f; //If the velocity's magnitude is smaller than the threshold, return; if (_velocity.magnitude < _magnitudeThreshold) { return; } //Normalize velocity direction; _velocity.Normalize(); //Get current 'forward' vector; Vector3 _currentForward = tr.forward; //Calculate (signed) angle between velocity and forward direction; float _angleDifference = VectorMath.GetAngle(_currentForward, _velocity, parentTransform.up); //Calculate angle factor; float _factor = Mathf.InverseLerp(0f, fallOffAngle, Mathf.Abs(_angleDifference)); //Calculate this frame's step; float _step = Mathf.Sign(_angleDifference) * _factor * Time.deltaTime * turnSpeed; //Clamp step; if (_angleDifference < 0f && _step < _angleDifference) { _step = _angleDifference; } else if (_angleDifference > 0f && _step > _angleDifference) { _step = _angleDifference; } //Add step to current y angle; currentYRotation += _step; //Clamp y angle; if (currentYRotation > 360f) { currentYRotation -= 360f; } if (currentYRotation < -360f) { currentYRotation += 360f; } //Set transform rotation using Quaternion.Euler; tr.localRotation = Quaternion.Euler(0f, currentYRotation, 0f); }