void LateUpdate()
    {
        Instance = this;

        if (!HasCamera)
        {
            return;
        }

        if (!HasTarget)
        {
            return;
        }

        bool mouseLook = RPGControllerUtils.GetButtonSafe(MouseLookButton, false);

        // This defines our "real" distance to the player
        realDistance -= RPGControllerUtils.GetAxisRawSafe(ZoomAxis, 0f) * ZoomSpeed;
        realDistance  = Mathf.Clamp(realDistance, MinDistance, MaxDistance);

        // This is the distance we want to (clamped to what is viewable)
        targetDistance  = realDistance;
        targetDistance  = Mathf.Clamp(targetDistance, currentMinDistance, currentMaxDistance);
        currentDistance = targetDistance;

        // Calculate offset vector
        Vector3 offset = new Vector3(0, 0, -currentDistance);

        // RMB
        if (mouseLook && LockCameraBehindTarget)
        {
            targetPitch -= (RPGControllerUtils.GetAxisRawSafe(PitchAxis, 0f) * 4f);
            targetPitch  = Mathf.Clamp(targetPitch, MinPitch, MaxPitch);
        }

        // Lock camera behind target, this overrides everything
        if (LockCameraBehindTarget)
        {
            targetYaw = RPGControllerUtils.SignedAngle(offset.normalized, -Target.transform.forward, Vector3.up);
        }

        // Clamp targetYaw to -180, 180
        targetYaw    = Mathf.Repeat(targetYaw + 180f, 360f) - 180f;
        currentYaw   = targetYaw;
        currentPitch = targetPitch;


        // Rotate offset vector
        offset = Quaternion.Euler(currentPitch, currentYaw, 0f) * offset;

        // Position camera holder correctly
        transform.position = TargetPosition + offset;

        Vector3 p = transform.position;

        transform.position = new Vector3(p.x, Mathf.Clamp(p.y, yClamp, float.MaxValue), p.z);

        // And then have the camera look at our target
        Camera.transform.LookAt(TargetPosition);
    }
 private void LateUpdate()
 {
     Instance = this;
     if (HasCamera && HasTarget)
     {
         bool buttonSafe = RPGControllerUtils.GetButtonSafe(MouseLookButton, false);
         realDistance   -= RPGControllerUtils.GetAxisRawSafe(ZoomAxis, 0f) * ZoomSpeed;
         realDistance    = Mathf.Clamp(realDistance, MinDistance, MaxDistance);
         targetDistance  = realDistance;
         targetDistance  = Mathf.Clamp(targetDistance, currentMinDistance, currentMaxDistance);
         currentDistance = targetDistance;
         Vector3 point = new Vector3(0f, 0f, 0f - currentDistance);
         if (buttonSafe)
         {
             targetPitch -= RPGControllerUtils.GetAxisRawSafe(PitchAxis, 0f) * 4f;
             targetPitch  = Mathf.Clamp(targetPitch, MinPitch, MaxPitch);
         }
         targetYaw               = RPGControllerUtils.SignedAngle(point.normalized, -Target.transform.forward, Vector3.up);
         targetYaw               = Mathf.Repeat(targetYaw + 180f, 360f) - 180f;
         currentYaw              = targetYaw;
         currentPitch            = targetPitch;
         point                   = Quaternion.Euler(currentPitch, currentYaw, 0f) * point;
         base.transform.position = TargetPosition + point;
         Vector3 position = base.transform.position;
         base.transform.position = new Vector3(position.x, Mathf.Clamp(position.y, yClamp, float.MaxValue), position.z);
         Camera.transform.LookAt(TargetPosition);
     }
 }
    void LateUpdate()
    {
        Instance = this;

        if (!HasCamera)
        {
            return;
        }

        if (!HasTarget)
        {
            return;
        }

        bool rotate    = RPGControllerUtils.GetButtonSafe(MouseRotateButton, false);
        bool mouseLook = RPGControllerUtils.GetButtonSafe(MouseLookButton, false);

        bool  smoothRotation      = SmoothRotation || SmoothAutoRotation;
        float smoothRotationSpeed = SmoothRotationSpeed;

        // This defines our "real" distance to the player
        realDistance -= RPGControllerUtils.GetAxisRawSafe(ZoomAxis, 0f) * ZoomSpeed;
        realDistance  = Mathf.Clamp(realDistance, MinDistance, MaxDistance);

        // This is the distance we want to (clamped to what is viewable)
        targetDistance = realDistance;
        targetDistance = Mathf.Clamp(targetDistance, currentMinDistance, currentMaxDistance);

        // This is our current distance
        if (SmoothZoom)
        {
            currentDistance = Mathf.Lerp(currentDistance, targetDistance, Time.deltaTime * SmoothZoomSpeed);
        }
        else
        {
            currentDistance = targetDistance;
        }

        // Calculate offset vector
        Vector3 offset = new Vector3(0, 0, -currentDistance);

        // LMB is not down, but we should rotate camera behind target
        if (!rotate && RotateCameraBehindTarget)
        {
            targetYaw           = RPGControllerUtils.SignedAngle(offset.normalized, -Target.forward, Vector3.up);
            smoothRotation      = SmoothAutoRotation;
            smoothRotationSpeed = SmoothAutoRotationSpeed;
        }

        // Only LMB down and no lock
        if (rotate && !mouseLook && !LockCameraBehindTarget)
        {
            targetYaw          += (RPGControllerUtils.GetAxisRawSafe(YawAxis, 0f) * RotationMouseSpeed);
            targetPitch        -= (RPGControllerUtils.GetAxisRawSafe(PitchAxis, 0f) * RotationMouseSpeed);
            targetPitch         = Mathf.Clamp(targetPitch, MinPitch, MaxPitch);
            smoothRotation      = SmoothRotation;
            smoothRotationSpeed = SmoothRotationSpeed;
        }

        // RMB
        if (mouseLook && LockCameraBehindTarget)
        {
            targetPitch -= (RPGControllerUtils.GetAxisRawSafe(PitchAxis, 0f) * RotationMouseSpeed);
            targetPitch  = Mathf.Clamp(targetPitch, MinPitch, MaxPitch);
        }

        // Lock camera behind target, this overrides everything
        if (LockCameraBehindTarget)
        {
            targetYaw      = RPGControllerUtils.SignedAngle(offset.normalized, -Target.transform.forward, Vector3.up);
            smoothRotation = false;
        }

        // Clamp targetYaw to -180, 180
        targetYaw = Mathf.Repeat(targetYaw + 180f, 360f) - 180f;

        if (!smoothRotation)
        {
            currentYaw   = targetYaw;
            currentPitch = targetPitch;
        }
        else
        {
            // Clamp smooth currentYaw to targetYaw and clamp it to -180, 180
            currentYaw = Mathf.LerpAngle(currentYaw, targetYaw, Time.deltaTime * smoothRotationSpeed);
            currentYaw = Mathf.Repeat(currentYaw + 180f, 360f) - 180f;

            // Smooth pitch
            currentPitch = Mathf.LerpAngle(currentPitch, targetPitch, Time.deltaTime * smoothRotationSpeed);
        }

        // ray hit
        RaycastHit hit = default(RaycastHit);

        // Rotate offset vector
        offset = Quaternion.Euler(currentPitch, currentYaw, 0f) * offset;

        if (Physics.Raycast(transform.position, Vector3.down, out hit, 2048f, Obstacles) && hit.transform.GetComponent <TerrainCollider>() != null)
        {
            yClamp = hit.point.y + Camera.near;
        }
        else
        {
            yClamp = float.MinValue;
        }

        // Position camera holder correctly
        transform.position = TargetPosition + offset;

        Vector3 p = transform.position;

        transform.position = new Vector3(p.x, Mathf.Clamp(p.y, yClamp, float.MaxValue), p.z);

        //float y = Mathf.Clamp(p.y, yClamp, float.MaxValue)

        // And then have the camera look at our target
        Camera.transform.LookAt(TargetPosition);

        Vector3 targetToCam = transform.position - TargetPosition;

        if (Physics.Raycast(TargetPosition, targetToCam.normalized, out hit, MaxDistance, Obstacles))
        {
            currentMinDistance = Mathf.Min(currentMinDistance, 1f);
            currentMaxDistance = Mathf.Max(currentMinDistance + 0.05f, (hit.point - Target.position).magnitude * 0.95f);
        }
        else
        {
            currentMinDistance = MinDistance;
            currentMaxDistance = MaxDistance;
        }

        // Clear this flag
        LockCameraBehindTarget   = false;
        RotateCameraBehindTarget = false;
    }