using UnityEngine; using System; //移动端和PC端的绕点摄像机控制器 public class CameraController : MonoBehaviour { // 是否允许旋转 [Header("是否允许旋转轴")] public bool canRotation_X = true; public bool canRotation_Y = true; [Header("是否开启缩放")] public bool canScale = true; #region 字段和属性 /// /// 旋转中心 /// [Header("旋转中心物体Transform")] public Transform target; /// /// 关于鼠标的设置 Settings of mouse button, pointer and scrollwheel. /// [Header("鼠标设置,鼠标id,灵敏度,滚轮强度")] public MouseSettings mouseSettings = new MouseSettings(0, 10, 10); /// /// 旋转角度限制 /// [Header("旋转角限制")] public Range angleRange = new Range(-90, 90); /// /// 距离的限制 /// [Header("缩放距离限制")] public Range distanceRange = new Range(1, 10); /// /// Damper for move and rotate. /// [Header("移动和旋转的阻力")] [Range(0, 10)] public float damper = 5; /// /// 角度,摄像机 /// public Vector2 CurrentAngles { protected set; get; } /// /// 当前距离,从摄像机到物体 /// public float CurrentDistance { protected set; get; } /// /// 摄像机当前角度 /// protected Vector2 targetAngles; /// /// 目标距离,从摄像机到目标,Target distance from camera to target. /// protected float targetDistance; #endregion #region Protected Method protected virtual void Start() { //初始化当前角度目标角度和当前距离目标距离 CurrentAngles = targetAngles = transform.eulerAngles; CurrentDistance = targetDistance = Vector3.Distance(transform.position, target.position); } protected virtual void LateUpdate() { if(Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) AroundByMouseInput(); else if(Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer) AroundByMobileInput(); } //记录上一次手机触摸位置判断用户是在左放大还是缩小手势 private Vector2 oldPosition1; private Vector2 oldPosition2; //是否是单指 private bool m_IsSingleFinger; /// /// 安卓控制 /// protected void AroundByMobileInput() { //如果是单指 if (Input.touchCount == 1) { //如果是按下并且拖拽 if (Input.touches[0].phase == TouchPhase.Moved) { //改变角度 targetAngles.y += Input.GetAxis("Mouse X") * mouseSettings.pointerSensitivity; targetAngles.x -= Input.GetAxis("Mouse Y") * mouseSettings.pointerSensitivity; //限定x角度 Range. targetAngles.x = Mathf.Clamp(targetAngles.x, angleRange.min, angleRange.max); } //是单指 Mouse pointer. m_IsSingleFinger = true; } //缩放 Mouse scrollwheel. if (canScale) { //是否两指 if (Input.touchCount > 1) { //计算出当前两点触摸点的位置 if (m_IsSingleFinger) { oldPosition1 = Input.GetTouch(0).position; oldPosition2 = Input.GetTouch(1).position; } //如果双指都在移动 if (Input.touches[0].phase == TouchPhase.Moved && Input.touches[1].phase == TouchPhase.Moved) { //暂存移动后的手指位置 var tempPosition1 = Input.GetTouch(0).position; var tempPosition2 = Input.GetTouch(1).position; //当前双指距离 float currentTouchDistance = Vector3.Distance(tempPosition1, tempPosition2); //上次双指距离 float lastTouchDistance = Vector3.Distance(oldPosition1, oldPosition2); //计算上次和这次双指触摸之间的距离差距 //然后去更改摄像机的距离 targetDistance -= (currentTouchDistance - lastTouchDistance) * Time.deltaTime * mouseSettings.wheelSensitivity; //备份上一次触摸点的位置,用于对比 oldPosition1 = tempPosition1; oldPosition2 = tempPosition2; //不是单指 m_IsSingleFinger = false; } } } //把距离限制住在min和max之间 targetDistance = Mathf.Clamp(targetDistance, distanceRange.min, distanceRange.max); //差值运算 Lerp. CurrentAngles = Vector2.Lerp(CurrentAngles, targetAngles, damper * Time.deltaTime); CurrentDistance = Mathf.Lerp(CurrentDistance, targetDistance, damper * Time.deltaTime); //如果限定了摄像机的话,角度不变 if (!canRotation_X) targetAngles.y = 0; if (!canRotation_Y) targetAngles.x = 0; //更新旋转 transform.rotation = Quaternion.Euler(CurrentAngles); //更新位置 transform.position = target.position - transform.forward * CurrentDistance; // transform.position = target.position - Vector3.forward * CurrentDistance; } /// /// Camera around target by mouse input. /// protected void AroundByMouseInput() { if (Input.GetMouseButton(mouseSettings.mouseButtonID)) { //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); } //Mouse scrollwheel. if (canScale) { targetDistance -= Input.GetAxis("Mouse ScrollWheel") * mouseSettings.wheelSensitivity; } // m_debugTip.text = Input.GetAxis("Mouse ScrollWheel").ToString() + " + " + targetDistance.ToString(); targetDistance = Mathf.Clamp(targetDistance, distanceRange.min, distanceRange.max); //Lerp. CurrentAngles = Vector2.Lerp(CurrentAngles, targetAngles, damper * Time.deltaTime); CurrentDistance = Mathf.Lerp(CurrentDistance, targetDistance, damper * Time.deltaTime); if (!canRotation_X) targetAngles.y = 0; if (!canRotation_Y) targetAngles.x = 0; //Update transform position and rotation. transform.rotation = Quaternion.Euler(CurrentAngles); transform.position = target.position - transform.forward * CurrentDistance; // transform.position = target.position - Vector3.forward * CurrentDistance; } #endregion } [Serializable] public struct MouseSettings { /// /// ID of mouse button. /// public int mouseButtonID; /// /// Sensitivity of mouse pointer. /// public float pointerSensitivity; /// /// Sensitivity of mouse ScrollWheel. /// public float wheelSensitivity; /// /// Constructor. /// /// ID of mouse button. /// Sensitivity of mouse pointer. /// Sensitivity of mouse ScrollWheel. public MouseSettings(int mouseButtonID, float pointerSensitivity, float wheelSensitivity) { this.mouseButtonID = mouseButtonID; this.pointerSensitivity = pointerSensitivity; this.wheelSensitivity = wheelSensitivity; } } /// /// Range form min to max. /// [Serializable] public struct Range { /// /// Min value of range. /// public float min; /// /// Max value of range. /// public float max; /// /// Constructor. /// /// Min value of range. /// Max value of range. public Range(float min, float max) { this.min = min; this.max = max; } } /// /// Rectangle area on plane. /// [Serializable] public struct PlaneArea { /// /// Center of area. /// public Transform center; /// /// Width of area. /// public float width; /// /// Length of area. /// public float length; /// /// Constructor. /// /// Center of area. /// Width of area. /// Length of area. public PlaneArea(Transform center, float width, float length) { this.center = center; this.width = width; this.length = length; } } /// /// Target of camera align. /// [Serializable] public struct AlignTarget { /// /// Center of align target. /// public Transform center; /// /// Angles of align. /// public Vector2 angles; /// /// Distance from camera to target center. /// public float distance; /// /// Range limit of angle. /// public Range angleRange; /// /// Range limit of distance. /// public Range distanceRange; /// /// Constructor. /// /// Center of align target. /// Angles of align. /// Distance from camera to target center. /// Range limit of angle. /// Range limit of distance. public AlignTarget(Transform center, Vector2 angles, float distance, Range angleRange, Range distanceRange) { this.center = center; this.angles = angles; this.distance = distance; this.angleRange = angleRange; this.distanceRange = distanceRange; } }