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); }*/ }