
using UnityEngine;
using System.Collections;
public class CameraOrbit : MonoBehaviour {
public Transform target;
public Vector3 targetOffset = new Vector3(0, 1.5f, 0);
private Vector3 oldTargetPosition;
public float minAngleX = -20, maxAngleX = 60;
private Vector3 angles;
private const float minDistance = 1.0f;
private float distance;
public float maxDistance = 7.0f;
public Vector3 cameraOffset = new Vector3(1, 0, 0);
void OnEnable() {
if( !target ) return;
angles = transform.eulerAngles;
distance = maxDistance;
}
void LateUpdate () {
if( !target ) return;
angles += GetInputRotation();
angles.x = ClampAngle(angles.x, minAngleX, maxAngleX);
Vector3 targetPosition = target.TransformPoint(targetOffset);
// попытка сгладить движение камеры
//targetPosition = Vector3.Lerp(oldTargetPosition, targetPosition, 15*Time.deltaTime);
//oldTargetPosition = targetPosition;
// сглаживаем вращение камеры
Quaternion rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(angles), 20*Time.deltaTime);
ComputeTransform(targetPosition, rotation, maxDistance, cameraOffset);
distance = CollisionTest(targetPosition, distance);
}
private void ComputeTransform(Vector3 targetPosition, Quaternion rotation, float distance, Vector3 cameraOffset) {
transform.rotation = rotation;
transform.position = targetPosition;
transform.Translate(0, 0, -distance);
transform.Translate(cameraOffset * distance);
}
private float CollisionTest(Vector3 targetPosition, float oldDistance) {
Vector3 dir = transform.position - targetPosition;
float distance = Raycast(targetPosition, dir, dir.magnitude);
if(distance < 1) distance = 1;
distance = Mathf.Lerp(oldDistance, distance, 10*Time.deltaTime);
transform.position = targetPosition + dir.normalized * distance;
return distance;
}
private static float Raycast(Vector3 start, Vector3 dir, float distance) {
RaycastHit hit = new RaycastHit();
if( Physics.Raycast(start, dir, out hit, distance) ) {
return hit.distance;
}
return distance;
}
private static float ClampAngle(float angle, float min, float max) {
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
private Vector3 GetInputRotation() {
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
return MobileInput.GetRotation();
#else
if( !Input.GetMouseButton(1) ) return Vector2.zero;
float dx = Input.GetAxis( "Mouse X" )*4;
float dy = Input.GetAxis( "Mouse Y" )*4;
return new Vector2(-dy, dx);
#endif
}
void OnDrawGizmosSelected() {
if(!enabled) return;
Gizmos.color = Color.red;
Gizmos.DrawSphere( target.TransformPoint( targetOffset ), 0.05f );
}
}