using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
///
/// [RequireComponent(typeof(Camera))]
public class AroundCamera : MonoBehaviour
{
#region Field and Property
///
/// Around center.
///
public Transform target;
///
/// Settings of mouse button, pointer and scrollwheel.
///
public MouseSettings mouseSettings = new MouseSettings(1, 10, 10);
///
/// Range limit of angle.
///
public Range angleRange = new Range(-90, 90);
///
/// Range limit of distance.
///
public Range distanceRange = new Range(1, 10);
///
/// Damper for move and rotate.
///
[Range(0, 10)]
public float damper = 5;
///
/// Camera current angls.
///
public Vector2 CurrentAngles { set; get; }
///
/// Current distance from camera to target.
///
public float CurrentDistance { set; get; }
///
/// Camera target angls.
///
public Vector2 targetAngles;
///
/// Target distance from camera to target.
///
public float targetDistance;
public int mLayer;
public bool mIsMovableDetection = true;
public bool mRotateEnable = true;
public static bool mIsTouchedUI = false;
#endregion
#region Protected Method
protected virtual void Start()
{
Initialize();
}
private void Update()
{
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
{
if (EventSystem.current.IsPointerOverGameObject())
{
mIsTouchedUI = true;
}
}
if(Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1))
{
mIsTouchedUI = false;
}
}
public static bool IsTouchedUI()
{
return mIsTouchedUI;
}
public float mCameraDistance = 0.0f;
protected virtual void LateUpdate()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, float.MaxValue))
{
float cameraDistance = Vector3.Distance(Camera.main.transform.position, hit.point);
mouseSettings.wheelSensitivity = cameraDistance / 4;
mCameraDistance = cameraDistance;
}
AroundByMouse();
}
///
/// Initialize component.
///
public virtual void Initialize()
{
CurrentAngles = targetAngles = transform.eulerAngles;
CurrentDistance = targetDistance = Vector3.Distance(transform.position, target.position);
}
///
/// Camera around target by mouse.
///
public void AroundByMouse()
{
if (IsTouchedUI()) return;
float preDistance = targetDistance;
Vector2 preAngle = targetAngles;
bool mouseOperate = false;
#if !UNITY_ANDROID
if (Input.GetMouseButton(mouseSettings.mouseButtonID) && !IsTouchedUI())
{
//Mouse pointer.
targetAngles.y += Input.GetAxis("Mouse X") * mouseSettings.pointerSensitivity;
targetAngles.x -= Input.GetAxis("Mouse Y") * mouseSettings.pointerSensitivity;
//Range.
targetAngles.x = Mathf.Clamp(targetAngles.x, angleRange.min, angleRange.max);
mouseOperate = true;
}
if (Input.GetAxis("Mouse ScrollWheel") != 0f)
{
//Mouse scrollwheel.
targetDistance -= Input.GetAxis("Mouse ScrollWheel") * mouseSettings.wheelSensitivity;
targetDistance = Mathf.Clamp(targetDistance, distanceRange.min, distanceRange.max);
mouseOperate = true;
}
#else
if (Input.touchCount == 2)
{
Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
if (touch0.phase == TouchPhase.Moved && touch1.phase == TouchPhase.Moved)
{
Vector2 lastDelta = (touch0.position - touch0.deltaPosition) - (touch1.position - touch1.deltaPosition);
Vector2 currDelta = touch0.position - touch1.position;
float deltaMagnitude = currDelta.magnitude - lastDelta.magnitude;
targetDistance -= deltaMagnitude * mouseSettings.wheelSensitivity * 0.02f;
targetDistance = Mathf.Clamp(targetDistance, distanceRange.min, distanceRange.max);
CurrentDistance = targetDistance;
mouseOperate = true;
}
}
if (Input.touchCount == 1 && mRotateEnable)
{
//Mouse pointer.
targetAngles.y += Input.GetAxis("Mouse X") * mouseSettings.pointerSensitivity * 0.2f; ;
targetAngles.x -= Input.GetAxis("Mouse Y") * mouseSettings.pointerSensitivity * 0.2f; ;
//Range.
targetAngles.x = Mathf.Clamp(targetAngles.x, angleRange.min, angleRange.max);
CurrentAngles = targetAngles;
mouseOperate = true;
}
#endif
if (mouseOperate && !MovableDetection())
{
targetDistance = preDistance;
targetAngles = preAngle;
return;
}
#if !UNITY_ANDROID
//Lerp.
CurrentAngles = Vector2.Lerp(CurrentAngles, targetAngles, damper * Time.deltaTime);
CurrentDistance = Mathf.Lerp(CurrentDistance, targetDistance, damper * Time.deltaTime);
//Not Lerp
//CurrentAngles = targetAngles;
//CurrentDistance = targetDistance;
#endif
//Update transform position and rotation.
transform.rotation = Quaternion.Euler(CurrentAngles);
transform.position = target.position - transform.forward * CurrentDistance;
#region
#if !UNITY_ANDROID
if (Vector2.Distance(CurrentAngles, targetAngles) > 1.0f)
PlayerPrefs.SetInt("CameraRotating", 1);
else
PlayerPrefs.SetInt("CameraRotating", 0);
if (Mathf.Abs(CurrentDistance - targetDistance) > 1.0f)
PlayerPrefs.SetInt("CameraZooming", 1);
else
PlayerPrefs.SetInt("CameraZooming", 0);
#endif
#endregion
}
public bool MovableDetection()
{
if (!mIsMovableDetection) return true;
Quaternion preRot = transform.rotation;
Vector3 prePos = transform.position;
transform.rotation = Quaternion.Euler(targetAngles);
transform.position = target.position - transform.forward * targetDistance;
if (Physics.Linecast(prePos, transform.position))
{
transform.rotation = preRot;
transform.position = prePos;
return false;
}
return true;
}
#endregion
}