/// <summary> /// Update is called once per frame /// </summary> public override void UpdateCameraPosition(float lookHorizontal, float lookVertical) { desiredPosition = GetCameraDesiredPosition(lookHorizontal, lookVertical); if (movementSpringDampingEnabled) { transform.position = Damping.SpringDamping(transform.position, desiredPosition, ref movementVelocity, movementSpringStiffness, movementSpringDamping); } else { transform.position = desiredPosition; } }
/** * This is the optimal camera position that the camera moves towards */ public Vector3 GetCameraDesiredPosition(float lookHorizontal, float lookVertical) { if (target == null) { return(lastCameraTargetPosition); } if (cameraType == ChaseCameraType.StayBehind) { Vector3 rotation = target.transform.rotation.eulerAngles; idealSpherical.polar = -rotation.y * Mathf.Deg2Rad - (Mathf.PI * 0.5f); if (lookHorizontalSpringDamped) { lookHorizontalActual = Damping.SpringDamping(lookHorizontalActual, lookHorizontal, ref lookHorizontalVelocity, lookHorizontalSpringStiffness, lookHorizontalSpringDamping); idealSpherical.polar += lookHorizontalActual * (Mathf.PI * 0.99f); } if (lookVerticalSpringDamped) { lookVerticalActual = Damping.SpringDamping(lookVerticalActual, lookVertical, ref lookVerticalVelocity, lookVerticalSpringStiffness, lookVerticalSpringDamping); idealSpherical.elevation = Mathf.Clamp(cameraPitch + lookVerticalActual * Mathf.PI, -Mathf.PI * 0.45f, Mathf.PI * 0.45f); } Quaternion q = Quaternion.FromToRotation(transform.TransformDirection(Vector3.up), target.position); transform.rotation = q * transform.rotation; } else { if (cameraType == ChaseCameraType.LooseAllowMovementUnderCamera) { Vector3 displacement = transform.position - target.position; if (displacement.sqrMagnitude < distance * distance) { return(lastCameraTargetPosition); } } idealSpherical.polar = Mathf.Atan2(transform.position.z - target.position.z, transform.position.x - target.position.x); } Vector3 direction = idealSpherical.ToCartesian(); lastCameraTargetPosition = target.position + direction; if (virtualCameraCollisionTest) { raycastCounter++; if (raycastCounter > 2) { raycastCounter = 0; } raycastResult[raycastCounter] = Physics.Raycast(target.position + raycastOffset[raycastCounter], direction, distance); RaycastHit[] hitInfo = Physics.SphereCastAll(target.position, virtualCameraCollisionRadius, direction, distance); float newCameraDistance = distance; bool partialOcclusion = !raycastResult[0] || !raycastResult[1] || !raycastResult[2]; // allow partially occluded object if hit distance is less than 25% of pref. distance if (hitInfo.Length > 0) { for (int i = 0; i < hitInfo.Length; i++) { bool partiallyOcclusionDistance = hitInfo[i].distance < distance * 0.25f; if (!partiallyOcclusionDistance || !partialOcclusion) { newCameraDistance = hitInfo[i].distance; break; } } } float currentDistance = idealSpherical.radius; if (newCameraDistance < currentDistance || newCameraDistance - currentDistance <= Mathf.Epsilon) // don't damp if target is reached { idealSpherical.radius = newCameraDistance; vccMoveBackVelocity = 0; } else { idealSpherical.radius = Damping.SpringDamping(idealSpherical.radius, newCameraDistance, ref vccMoveBackVelocity, vccMoveBackSpringStiffness, vccMoveBackSpringDamping); } // if distance was updated, then recalculate position if (currentDistance != idealSpherical.radius) { direction = idealSpherical.ToCartesian(); lastCameraTargetPosition = target.position + direction; } } return(lastCameraTargetPosition); }