feature: 添加旋转、平移、缩放摄像头功能

This commit is contained in:
jackfiled 2023-02-12 16:45:51 +08:00
parent fc9d401cb7
commit 2290812228
3 changed files with 170 additions and 0 deletions

145
Assets/CameraBehaviour.cs Normal file
View File

@ -0,0 +1,145 @@
using UnityEngine;
public class CameraBehaviour : MonoBehaviour
{
public Transform target;
private const int MouseWheelSensitivity = 1; //滚轮灵敏度设置
private const int MouseZoomMin = 1; //相机距离最小值
private const int MouseZoomMax = 20; //相机距离最大值
private const float XSpeed = 250.0f;
private const float YSpeed = 120.0f;
private const int YMinLimit = -360;
private const int YMaxLimit = 360;
private float _eulerX; //存储相机的euler角
private float _eulerY; //存储相机的euler角
private float _distance = 5; //相机和target之间的距离因为相机的Z轴总是指向target也就是相机z轴方向上的距离
private Vector3 _targetOnScreenPosition; //目标的屏幕坐标第三个值为z轴距离
private Quaternion _cameraRotation; //存储相机的姿态四元数
private Vector3 _targetPosition; //target的位置
private Vector3 _initPosition; //平移时用于存储平移的起点位置
private Vector3 _cameraX; //相机的x轴方向向量
private Vector3 _cameraY; //相机的y轴方向向量
private Vector3 _cameraZ; //相机的z轴方向向量
private Vector3 _initScreenPosition; //中键刚按下时鼠标的屏幕坐标(第三个值其实没什么用)
private Vector3 _cursorScreenPosition; //当前鼠标的屏幕坐标(第三个值其实没什么用)
private void Start()
{
//这里就是设置一下初始的相机视角以及一些其他变量这里的x和y。。。是和下面getAxis的mouse x与mouse y对应
var angles = transform.eulerAngles;
_eulerX = angles.y;
_eulerY = angles.x;
_targetPosition = target.position;
_cameraRotation = Quaternion.Euler(_eulerY + 60, _eulerX, 0);
// 引入中间变量 提高代码效率
var transform1 = transform;
transform1.rotation = _cameraRotation; //设置相机姿态
/*var position =
_cameraRotation * new Vector3(0.0F, 0.0F, -_distance) +
_targetPosition; //四元数表示一个旋转,四元数乘以向量相当于把向量旋转对应角度,然后加上目标物体的位置就是相机位置了*/
transform1.position = _cameraRotation * new Vector3(0, 0, -_distance) + _targetPosition; //设置相机位置
}
private void Update()
{
//鼠标右键旋转功能
if (Input.GetMouseButton(1))
{
_eulerX += Input.GetAxis("Mouse X") * XSpeed * 0.02f;
_eulerY -= Input.GetAxis("Mouse Y") * YSpeed * 0.02f;
_eulerY = ClampAngle(_eulerY, YMinLimit, YMaxLimit);
_cameraRotation = Quaternion.Euler(_eulerY + 60, _eulerX, 0);
var position = _cameraRotation * new Vector3(0.0f, 0.0f, -_distance) + _targetPosition;
// 引入中间变量 提高代码效率
var transform1 = transform;
transform1.rotation = _cameraRotation;
transform1.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;
}
transform.position = _cameraRotation * new Vector3(0.0F, 0.0F, -_distance) + _targetPosition;
}
//鼠标中键平移
if (Input.GetMouseButtonDown(2))
{
// 添加中间变量
// 提高代码效率
var transform1 = transform;
_cameraX = transform1.right;
_cameraY = transform1.up;
_cameraZ = transform1.forward;
_initScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _targetOnScreenPosition.z);
//targetOnScreenPosition.z为目标物体到相机平面的法线距离
_targetOnScreenPosition = Camera.main!.WorldToScreenPoint(_targetPosition);
_initPosition = _targetPosition;
}
if (Input.GetMouseButton(2))
{
_cursorScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _targetOnScreenPosition.z);
//0.01这个系数是控制平移的速度要根据相机和目标物体的distance来灵活选择
target.position = _initPosition - 0.01f * ((_cursorScreenPosition.x - _initScreenPosition.x) * _cameraX +
(_cursorScreenPosition.y - _initScreenPosition.y) * _cameraY);
//重新计算位置
var mPosition = _cameraRotation * new Vector3(0.0F, 0.0F, -_distance) + target.position;
transform.position = mPosition;
// //用这个会让相机的平移变得更平滑但是可能在你ButtonUp时未使相机移动到应到的位置导致再进行旋转与缩放操作时出现短暂抖动
//transform.position=Vector3.Lerp(transform.position,mPosition,Time.deltaTime*moveSpeed);
}
if (Input.GetMouseButtonUp(2))
{
Debug.Log("upOnce");
//平移结束把cameraTargetPosition的位置更新一下不然会影响缩放与旋转功能
_targetPosition = target.position;
}
}
//将angle限制在min~max之间
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);
}
/*void testScreenToWorldPoint()
{
//第三个坐标指的是在相机z轴指向方向上的距离
Vector3 screenPoint = Camera.main.WorldToScreenPoint(_targetPosition);
Debug.Log("ScreenPoint: " + screenPoint);
// var worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(1,1,10));
// Debug.Log("worldPosition: "+worldPosition);
}*/
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9189b565e8ba9bfc3bdaa38149e3e13f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -339,6 +339,7 @@ GameObject:
- component: {fileID: 963194228} - component: {fileID: 963194228}
- component: {fileID: 963194227} - component: {fileID: 963194227}
- component: {fileID: 963194226} - component: {fileID: 963194226}
- component: {fileID: 963194229}
m_Layer: 0 m_Layer: 0
m_Name: Main Camera m_Name: Main Camera
m_TagString: MainCamera m_TagString: MainCamera
@ -412,6 +413,19 @@ Transform:
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 0 m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &963194229
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9189b565e8ba9bfc3bdaa38149e3e13f, type: 3}
m_Name:
m_EditorClassIdentifier:
target: {fileID: 320693310}
--- !u!1 &1880773849 --- !u!1 &1880773849
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0