【Unity3D】简单常用的功能实现2——视角的跟随、旋转、缩放
【视角的跟随、旋转、缩放实现】
首先,在实现这些功能之前,我们给Hierarchy面板中的主摄像机额外包装几层Empty Object,形成一个新的摄像机结构,如下图(当然这些空物体的命名大家按自己方便就是了):
然后调整一下CameraUpAndDown、CameraZoomContainer的几个参数(注意,调参这个步骤一定不要漏掉,调参是为了使主摄像机在旋转拉伸时能始终对准物体):
如图:
CameraUpAndDown物体rotateZ轴90°。(旋转CameraUpAndDown的Z轴是为了使主摄像机视角在旋转、拉伸时始终对准物体,)
CameraZoomContainer物体RotateY轴-90°。(旋转CameraZoomContainer的Y轴是为了使编辑器状态下视角在旋转、拉伸时始终对准物体,但不修改的话并不会影响运行时的视角)
CameraZoomContainer物体Position.X改为一个正数,(不一定是4,只要能使你的主摄像机观察到物体就行,0的话会使主摄像机距离物体太近。)
第二步,在CameraFollowAndRotate的Inspector面板下添加一个脚本(这里我把这个脚本命名为CameraCtrl),代码如下:
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4
5 public class CameraCtrl : MonoBehaviour
6 {
7 public static CameraCtrl Instance;
8
9 /// <summary>
10 /// 摄像机结构下的几个子物体, m_CameraUpAndDown控制垂直观察角度,m_CameraZoomContainer控制镜头对准方向, m_CameraContainer控制物体与镜头间距离
11 /// </summary>
12 [SerializeField]
13 private Transform m_CameraUpAndDown;
14 [SerializeField]
15 private Transform m_CameraZoomContainer;
16 [SerializeField]
17 private Transform m_CameraContainer;
18
19 private void Awake()
20 {
21 Instance = this;
22 }
23
24 //初始化函数
25 public void Init()
26 {
27 //如果Camera垂直观察角度的初始值、Camera与物体距离的初始值在限定范围外,进行矫正
28 m_CameraUpAndDown.Rotate(0, 0, 45f);
29 m_CameraUpAndDown.localEulerAngles = new Vector3(0, 0, Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z, 1f, 90f));
30 m_CameraContainer.localPosition = new Vector3(0, 0, Mathf.Clamp(m_CameraContainer.localPosition.z, -5f, 0));
31 }
32
33 //实时看向主角物体
34 public void AutoLookAt(Vector3 position)
35 {
36 m_CameraZoomContainer.LookAt(position);
37 }
38
39 /// <summary>
40 /// 控制Camera水平旋转 左=0 右=1
41 /// </summary>
42 /// <param name="type"></param>
43 public void SetCameraRotate(int type)
44 {
45 transform.Rotate(0, 20 * Time.deltaTime * (type == 0 ? 1 : -1), 0);
46 }
47
48 /// <summary>
49 /// 控制Camera垂直旋转 上=0 下=1
50 /// </summary>
51 /// <param name="type"></param>
52 public void SetCameraUpAndDown(int type)
53 {
54 m_CameraUpAndDown.Rotate(0, 0, 20 * Time.deltaTime * (type == 0 ? 1 : -1));
55 //锁定Camera垂直观察角度的范围1°至90°
56 m_CameraUpAndDown.localEulerAngles = new Vector3(0, 0, Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z, 1f, 90f));
57 }
58
59 /// <summary>
60 /// 控制Camera和物体的距离 拉近=0 拉远1
61 /// </summary>
62 /// <param name="type"></param>
63 public void SetCameraZoom(int type)
64 { //注意,虽然方法名有Zoom,但是控制镜头与物体距离的是m_CameraContainer,所以这里修改m_CameraContainer的position的Z轴
65 m_CameraContainer.Translate(Vector3.forward * 4 * Time.deltaTime * (type == 0 ? 1 : -1));
66 m_CameraContainer.localPosition = new Vector3(0, 0, Mathf.Clamp(m_CameraContainer.localPosition.z, -5f, 0));
67 }
68 }
注意! 13、15、17三个序列化字段的赋值要在CameraFollowAndRotate的Inspector面板中进行,使这些变量指向对应的组件,如下图:
第三步,在 视角要跟随的Object 的脚本中 实现对CameraCtrl脚本方法的调用,这里就简单举例了:
1 //该方法在要跟随的Object的脚本的Update()中调用即可实现视角的旋转、缩放以及视角的实时跟随
2 private void cameraAutoFollow()
3 {
4 if (CameraCtrl.Instance == null) { return; }
5 //Camera实时同步主角物体的位置并使镜头对准主角物体
6 CameraCtrl.Instance.transform.position = gameObject.transform.position;
7 CameraCtrl.Instance.AutoLookAt(gameObject.transform.position);
8
9
10 //依照按键调整镜头视角,以按Q键实现顺时针水平旋转为例子
11 if (Input.GetKey(KeyCode.Q))
12 {
13 CameraCtrl.Instance.SetCameraRotate(0); //参数为1 则为逆时针水平旋转
14 //CameraCtrl.Instance.SetCameraUpAndDown(0); //视角垂直旋转
15 //CameraCtrl.Instance.SetCameraZoom(0); //视角缩放
16 }
17 }
最后,对这个摄像机结构再总结一下:
CameraFollowAndRotate:通过修改该Object的Position,我们可以实现视角对移动物体的跟随、RotateY轴则可以实现视角对物体的水平旋转观察。
CameraUpAndDown:通过Rotate该Object的Z轴,我们可以实现视角对移动物体的垂直旋转观察。Z轴旋转要初始为90°
CameraZoomContainer:运行的时候Lookat方法会实时Rotate各个轴使摄像机镜头对准物体。Y轴旋转要初始为-90°以方便编辑器视窗下对Camera的调试,X轴设置为一个合适的正数就可以。
CameraContainer:通过修改该Object的Position.Z属性来拉近或拉远主摄像机与物体的距离,实现缩放。