Unity学习记录-摄像机控制
摄像机控制:
- WASD或方向键控制
- 鼠标屏幕边缘滚动控制(如英雄联盟)
- 鼠标右键拖拽控制移动
- 鼠标中键控制摄像机焦距
关于移动转向的问题
- 如果单纯地按键盘输入来控制移动的话,会出现摄像机转向后移动混乱的情况(转向后摄像机自身的坐标系也跟着旋转)
- 使用三元数InputDir接收键盘输入,再用三元数MoveDir计算摄像机的移动
WASD控制摄像机移动
- 创建一个空物体,摆正其坐标系(方便接收键盘输入)
- 创建cinemachineVirtualCamera,使其看向空物体
- 为空物体编写脚本,键盘控制空物体移动,相当于摄像机移动
1 2 3
| private Vector3 inputDir=new Vector3(0,0,0); private Vector3 moveDir; [SerializeField] private float moveSpeed = 50f;
|
inputDir记录键盘输入,moveDir计算实际移动
1 2 3 4 5 6 7 8 9 10 11 12
| void KeybroadControl() { inputDir.Set(0, 0, 0);
if (Input.GetKey(KeyCode.W)) inputDir.z += 1f; if (Input.GetKey(KeyCode.A)) inputDir.x += -1f; if (Input.GetKey(KeyCode.S)) inputDir.z += -1f; if (Input.GetKey(KeyCode.D)) inputDir.x += 1f; }
|
每帧调用该函数,获取键盘输入
1 2 3 4
| moveDir = this.transform.forward * inputDir.z + this.transform.right * inputDir.x;
this.transform.position += moveDir * moveSpeed * Time.deltaTime;
|
在Update中应用移动:moveDir = 当前朝向 X 前后移动量+当前的右方 X 左右的移动量,并应用到position中
QE控制摄像机转向
1 2
| private float rotateDir; [SerializeField] private float rotateSpeed = 50f;
|
1 2 3 4 5 6 7 8
| void KeybroadControl() { rotateDir = 0f; if (Input.GetKey(KeyCode.Q)) rotateDir += -1f; if (Input.GetKey(KeyCode.E)) rotateDir += +1f; }
|
1
| this.transform.eulerAngles += new Vector3(0, rotateDir * rotateSpeed * Time.deltaTime, 0);
|
在Update中应用移动,沿Y轴转动
鼠标屏幕边缘控制摄像机移动(如英雄联盟)
- 和键盘控制思路类似,只不过inputDir改为接收鼠标位置
1 2
| [SerializeField] private int edgeScrollSize = 20; [SerializeField] private float moveSpeed = 50f;
|
1 2 3 4 5 6 7 8 9
| void MouseControlScroll() { if (Input.mousePosition.x < edgeScrollSize) inputDir.x = -1f; if (Input.mousePosition.x > Screen.width - edgeScrollSize) inputDir.x = 1f; if (Input.mousePosition.y < edgeScrollSize) inputDir.z = -1f; if (Input.mousePosition.y > Screen.height - edgeScrollSize) inputDir.z = 1f; }
|
每帧调用该函数
1 2 3 4
| moveDir = this.transform.forward * inputDir.z + this.transform.right * inputDir.x;
this.transform.position += moveDir * moveSpeed * Time.deltaTime;
|
同样地在Update中应用移动
鼠标右键拖拽控制摄像机移动
1 2
| private Vector3 mouseLastPosition; private bool isDrag = false;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void MouseControlDrag() { if (Input.GetMouseButtonDown(1)) { isDrag = true; mouseLastPosition = Input.mousePosition; } if (Input.GetMouseButtonUp(1)) { isDrag = false; } if (isDrag) { inputDir.x = (mouseLastPosition.x - Input.mousePosition.x) * dragSpeed * Time.deltaTime; inputDir.z = (mouseLastPosition.y - Input.mousePosition.y) * dragSpeed * Time.deltaTime; mouseLastPosition = Input.mousePosition; } }
|
每帧调用该函数,记录鼠标拖拽
1 2 3 4
| moveDir = this.transform.forward * inputDir.z + this.transform.right * inputDir.x;
this.transform.position += moveDir * moveSpeed * Time.deltaTime;
|
同样地在Update中应用移动
鼠标滚轮控制摄像机焦距
1 2
| [SerializeField] private float ScrollSpeed = 5f; [SerializeField] private CinemachineVirtualCamera cinemachineVirtualCamera;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void CameraZoomControl() { if(Input.mouseScrollDelta.y>0) { cinemachineVirtualCamera.m_Lens.FieldOfView -= ScrollSpeed; } if(Input.mouseScrollDelta.y<0) { cinemachineVirtualCamera.m_Lens.FieldOfView += ScrollSpeed; } if(Input.GetMouseButtonDown(2)) { cinemachineVirtualCamera.m_Lens.FieldOfView = 60; } }
|