说明
上一篇记录了PC端鼠标控制摄像机的移动和缩放,这一篇写的是在安卓机上实现手势控制摄像机围绕一个物体进行旋转和缩放,两篇的代码逻辑基本一样只是输入检测有区别,这里我是分开记录,没有整合【Unity实现PC端鼠标控制摄像机的移动和缩放】,使用的方式也很简单,将脚本挂载到主摄像机中。
这里还用到了DoTween
的插件和UniRx
,需要自己导入一下,如果不想使用插件,可以把以下代码简单修改一下。
using UnityEngine;
using DG.Tweening;
using UnityEngine.EventSystems;
using QFramework;
using UniRx;
using UniRx.Triggers;
/// <summary>
/// 摄像机控制管理
/// </summary>
public class CameraController : MonoBehaviour
{
static CameraController _instance;
public static CameraController Ins
{
get { return _instance; }
}
Transform cam_TF;
// 是否可以控制摄像机
public bool isCanControlCam = true;
[Header("旋转的目标点:")]
public Transform rotTarget;
[Header("相机点击UI前进和返回的速度")]
public float cameraMoveSpeed = 400f;
[Header("旋转速度和缩放速度:")]
public float rotateSpeed = 1.25f;
public float wheelSpeed = 100f;
[Header("摄像机的最远距离和最近距离:")]
public float minDist = 3;
public float maxDist = 60;
[Header("最大俯仰角:")]
public float maxAngle;
[Header("最小俯仰角:")]
public float minAngle;
// 当前摄像机俯仰角
public float nowCamEulerX;
Vector3 initPos;
void Awake()
{
_instance = this;
cam_TF = Camera.main.transform;
}
void Start()
{
cam_TF.LookAt(rotTarget);
initPos = cam_TF.localPosition;
nowCamEulerX = cam_TF.localEulerAngles.x;
this.LateUpdateAsObservable().Subscribe(_ => {
if (!isCanControlCam)
return;
CameraRotate();
CameraFOV();
});
}
/// <summary>
/// 摄像机的初始位置
/// </summary>
public void CamMoveInitPos()
{
if (!isCanControlCam)
return;
this.Sequence()
.Event(() =>
{
isCanControlCam = false;
mouseLerpPos = Vector2.zero;
cam_TF.DORotate(new Vector3(25, -44, 0), 1f);
cam_TF.DOMove(initPos, 1f);
})
.Delay(1.05f)
.Event(() =>
{
isCanControlCam = true;
nowCamEulerX = cam_TF.localEulerAngles.x;
})
.Begin();
}
#region 鼠标操作
Vector2 mousePos;
Vector2 mouseLerpPos;
/// <summary>
/// 摄像机旋转
/// </summary>
void CameraRotate()
{
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved&& !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
mousePos.x = Input.GetAxis("Mouse X");
mousePos.y = Input.GetAxis("Mouse Y");
if (Input.touchCount==1 && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
mouseLerpPos.x = Mathf.Lerp(mouseLerpPos.x, mousePos.x, 5 * Time.deltaTime);
mouseLerpPos.y = Mathf.Lerp(mouseLerpPos.y, mousePos.y, 5 * Time.deltaTime);
}
else
{
mouseLerpPos.x = Mathf.Lerp(mouseLerpPos.x, 0, 5 * Time.deltaTime);
mouseLerpPos.y = Mathf.Lerp(mouseLerpPos.y, 0, 5 * Time.deltaTime);
}
cam_TF.RotateAround(rotTarget.position, Vector3.up, mouseLerpPos.x * rotateSpeed);
nowCamEulerX -= mouseLerpPos.y * rotateSpeed;
if (nowCamEulerX > maxAngle || nowCamEulerX < minAngle)
{
nowCamEulerX += mouseLerpPos.y * rotateSpeed;
mouseLerpPos.y = 0;
return;
}
if (Mathf.Abs(-mouseLerpPos.y * rotateSpeed) < 0.02f)
return;
cam_TF.RotateAround(rotTarget.position, cam_TF.right, -mouseLerpPos.y * rotateSpeed * 0.5f);
}
}
float wheelValue;
float wheelTargetValue;
Touch oldTouch1;
Touch oldTouch2;
/// <summary>
/// 摄像机缩放
/// </summary>
void CameraFOV()
{
if (Input.touchCount>1)
{
Touch newTouch1 = Input.GetTouch(0);
Touch newTouch2 = Input.GetTouch(1);
if (newTouch2.phase== TouchPhase.Began)
{
oldTouch1 = newTouch1;
oldTouch2 = newTouch2;
wheelTargetValue = 0;
return;
}
if (newTouch1.phase==TouchPhase.Moved||newTouch2.phase==TouchPhase.Moved)
{
float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);
float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);
if ((newDistance - oldDistance) < 0)
wheelValue = -0.15f;
else if ((newDistance - oldDistance) > 0)
wheelValue = 0.15f;
if (Vector3.Distance(cam_TF.position, rotTarget.position) < minDist && wheelValue > 0)
return;
if (Vector3.Distance(cam_TF.position, rotTarget.position) > maxDist && wheelValue < 0)
return;
wheelTargetValue = Mathf.Lerp(wheelTargetValue, wheelValue, 5 * Time.deltaTime);
cam_TF.Translate(Vector3.forward * wheelTargetValue * wheelSpeed);
}
}
}
#endregion
}