236 lines
9.2 KiB
C#
236 lines
9.2 KiB
C#
using DG.Tweening;
|
||
using UnityEngine;
|
||
using NaughtyAttributes;
|
||
using UnityEngine.EventSystems;
|
||
|
||
namespace Framework.Scripts.Runtime.Engine.Engine.Camera.CameraControl
|
||
{
|
||
public class CameraControlComponent : ICameraController
|
||
{
|
||
public enum CameraEnum
|
||
{
|
||
TopView,
|
||
FrontView
|
||
}
|
||
|
||
//相机跟随的目标物体,一般是一个空物体
|
||
[SerializeField] private GameObject target;
|
||
|
||
[HorizontalLine(color: EColor.Blue)] [SerializeField] [Label("启用旋转")]
|
||
private bool enableMouseFunctions = true;
|
||
|
||
[SerializeField] [Label("启用鼠标碰到UI禁用脚本")]
|
||
private bool enableMouseOverUI = true;
|
||
|
||
[SerializeField] private CameraEnum cameraEnum;
|
||
|
||
private float middleSpeed = 2;
|
||
|
||
private int MouseWheelSensitivity = 1; //滚轮灵敏度设置
|
||
|
||
private int MouseZoomMin = 10; //相机距离最小值
|
||
|
||
private int MouseZoomMax = 9999; //相机距离最大值
|
||
|
||
private float xSpeed = 250.0f; //旋转视角时相机x轴转速
|
||
|
||
private float ySpeed = 120.0f; //旋转视角时相机y轴转速
|
||
|
||
private float Distance = 20; //相机和target之间的距离,因为相机的Z轴总是指向target,也就是相机z轴方向上的距离
|
||
|
||
//[BoxGroup("参数")][SerializeField][Label("角度最小限制")] private int yMinLimit = -360;
|
||
//[BoxGroup("参数")][SerializeField][Label("角度最大限制")] private int yMaxLimit = 360;
|
||
|
||
private Vector2 minMaxSlider;
|
||
|
||
private float x = 0.0f; //存储相机的euler角
|
||
private float y = 0.0f; //存储相机的euler角
|
||
private Vector3 targetOnScreenPosition; //目标的屏幕坐标,第三个值为z轴距离
|
||
|
||
private Quaternion storeRotation; //存储相机的姿态四元数
|
||
private Vector3 CameraTargetPosition; //target的位置
|
||
private Vector3 initPosition; //平移时用于存储平移的起点位置
|
||
private Vector3 cameraX; //相机的x轴方向向量
|
||
private Vector3 cameraY; //相机的y轴方向向量
|
||
private Vector3 cameraZ; //相机的z轴方向向量
|
||
|
||
private Vector3 initScreenPos; //中键刚按下时鼠标的屏幕坐标(第三个值其实没什么用)
|
||
private Vector3 curScreenPos; //当前鼠标的屏幕坐标(第三个值其实没什么用)
|
||
|
||
|
||
private Vector2 jilu;
|
||
|
||
private Transform cameraTransform;
|
||
|
||
public void Init(Transform cam, Transform target)
|
||
{
|
||
cameraTransform = cam;
|
||
this.target = target.gameObject;
|
||
|
||
cameraEnum = CameraEnum.FrontView;
|
||
Vector3 angles = cameraTransform.eulerAngles;
|
||
x = angles.y;
|
||
y = angles.x;
|
||
CameraTargetPosition = target.transform.position;
|
||
|
||
Distance = Vector3.Distance(cameraTransform.position, target.transform.position);
|
||
|
||
// 给摄像机一个初始的位置和角度
|
||
SetCameraPositionAndRotation();
|
||
}
|
||
|
||
public void MoveTargetTo(Vector3 newPosition, float newfloat)
|
||
{
|
||
target.transform.DOMove(newPosition, 2).OnUpdate(() =>
|
||
{
|
||
Vector3 mPosition = storeRotation * new Vector3(0.0F, 0.0F, -Distance) + target.transform.position;
|
||
cameraTransform.position = mPosition;
|
||
CameraTargetPosition = target.transform.position;
|
||
}
|
||
);
|
||
}
|
||
|
||
void SetCameraPositionAndRotation()
|
||
{
|
||
//Vector3 position = rotation * new Vector3(0.0f, 0.0f, -11) + target.transform.position;
|
||
|
||
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
|
||
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
|
||
|
||
y = ClampAngle(y, minMaxSlider.x, minMaxSlider.y);
|
||
|
||
storeRotation = Quaternion.Euler(y, x, 0);
|
||
var position = storeRotation * new Vector3(0.0f, 0.0f, -Distance) + CameraTargetPosition;
|
||
|
||
cameraTransform.rotation = storeRotation;
|
||
cameraTransform.position = position;
|
||
}
|
||
|
||
|
||
//将angle限制在min~max之间
|
||
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);
|
||
}
|
||
|
||
|
||
public GameObject GetTarget()
|
||
{
|
||
return target;
|
||
}
|
||
|
||
public void UpdateValue(Vector2 minMax)
|
||
{
|
||
minMaxSlider = minMax;
|
||
}
|
||
|
||
|
||
public void ControlCamera()
|
||
{
|
||
if (enableMouseOverUI)
|
||
{
|
||
if (EventSystem.current.IsPointerOverGameObject())
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (enableMouseFunctions)
|
||
{
|
||
//鼠标右键旋转功能
|
||
if (Input.GetMouseButton(1))
|
||
{
|
||
//如果是顶视图,只能左右旋转,不能上下
|
||
if (cameraEnum == CameraEnum.FrontView)
|
||
{
|
||
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
|
||
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
|
||
|
||
y = ClampAngle(y, minMaxSlider.x, minMaxSlider.y);
|
||
|
||
storeRotation = Quaternion.Euler(y, x, 0);
|
||
var position = storeRotation * new Vector3(0.0f, 0.0f, -Distance) + CameraTargetPosition;
|
||
|
||
Debug.Log(storeRotation);
|
||
cameraTransform.rotation = storeRotation;
|
||
cameraTransform.position = position;
|
||
}
|
||
else
|
||
{
|
||
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
|
||
//y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
|
||
|
||
//y = ClampAngle(y, minMaxSlider.x, minMaxSlider.y);
|
||
|
||
storeRotation = Quaternion.Euler(90, x, 0);
|
||
var position = storeRotation * new Vector3(0.0f, 0.0f, -Distance) + CameraTargetPosition;
|
||
|
||
cameraTransform.rotation = storeRotation;
|
||
cameraTransform.position = position;
|
||
}
|
||
}
|
||
else if (Input.GetAxis("Mouse ScrollWheel") != 0) //鼠标滚轮缩放功能
|
||
{
|
||
if (Distance >= MouseZoomMin && Distance <= MouseZoomMax)
|
||
{
|
||
Distance -= Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity;
|
||
}
|
||
|
||
if (Distance < MouseZoomMin)
|
||
{
|
||
Distance = MouseZoomMin;
|
||
}
|
||
|
||
if (Distance > MouseZoomMax)
|
||
{
|
||
Distance = MouseZoomMax;
|
||
}
|
||
|
||
cameraTransform.position = storeRotation * new Vector3(0.0F, 0.0F, -Distance) + CameraTargetPosition;
|
||
}
|
||
|
||
//鼠标中键平移
|
||
if (Input.GetMouseButtonDown(2))
|
||
{
|
||
cameraX = cameraTransform.right;
|
||
cameraY = cameraTransform.up;
|
||
cameraZ = cameraTransform.forward;
|
||
|
||
initScreenPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetOnScreenPosition.z);
|
||
Debug.Log("downOnce");
|
||
|
||
//targetOnScreenPosition.z为目标物体到相机xmidbuttonDownPositiony平面的法线距离
|
||
if (UnityEngine.Camera.main != null) targetOnScreenPosition = UnityEngine.Camera.main.WorldToScreenPoint(CameraTargetPosition);
|
||
initPosition = CameraTargetPosition;
|
||
}
|
||
|
||
if (Input.GetMouseButton(2))
|
||
{
|
||
curScreenPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetOnScreenPosition.z);
|
||
//0.01这个系数是控制平移的速度,要根据相机和目标物体的distance来灵活选择
|
||
Vector3 vv = initPosition - (0.01f * middleSpeed) * ((curScreenPos.x - initScreenPos.x) * cameraX +
|
||
(curScreenPos.y - initScreenPos.y) * cameraY);
|
||
target.transform.position = new Vector3(vv.x, vv.y, vv.z);
|
||
|
||
//重新计算位置
|
||
Vector3 mPosition = storeRotation * new Vector3(0.0F, 0.0F, -Distance) + target.transform.position;
|
||
cameraTransform.position = mPosition;
|
||
|
||
// //用这个会让相机的平移变得更平滑,但是可能在你buttonup时未使相机移动到应到的位置,导致再进行旋转与缩放操作时出现短暂抖动
|
||
//transform.position=Vector3.Lerp(transform.position,mPosition,Time.deltaTime*moveSpeed);
|
||
}
|
||
|
||
if (Input.GetMouseButtonUp(2))
|
||
{
|
||
Debug.Log("upOnce");
|
||
//平移结束把cameraTargetPosition的位置更新一下,不然会影响缩放与旋转功能
|
||
CameraTargetPosition = target.transform.position;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |