10 相机控制
本节主要学习如何控制相机自动调整位置和焦距,使两个坦克一直同时在视野内.
在Hierarchy点击右键
点击 Create Empty,生成空对象,改名为CameraRig
设置CameraRig rotation为(40,60,0)
将MainCamera拖拽到CameraRig中,使之成为CameraRig的子对象
设置MainCamera的position为(0,0,-65),rotation为(0,0,0)
Orthographic Camera
Orthographic size
通过设置size实现缩放
Aspect宽高比
相机要做到事情有两个:跟随坦克和通过缩放实现坦克一直在屏幕内.
在wm/Scripts文件夹新建脚本CameraRig ,挂载到CameraRig上面
下面我们首先实现跟随坦克
跟随坦克首先找到坦克坐标的中间坐标,然后把cameraRig移动过去
先计算中间坐标
public Transform[] targets; // tanks
private Vector3 targetPos; // 计算出来的目标点
void FindAveragePos(){ // 计算平均坐标
Vector3 avg = new Vector3 (); // 计算平均坐标的临时变量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍历一遍 avg += targets [i].position; // 所有坐标都加起来 } avg /= targets.Length; // 除以坦克个数,得到坐标的平均值 avg.y = transform.position.y; // 坐标的y轴保持不变 targetPos = avg; // 更新目标点 }
然后使用 Vector3.SmoothDamp 平滑阻尼是相机移动过去
还需要声明两个变量
private Vector3 moveSpeed; // 移动速度,SmoothDamp里面使用的
private float dampTime = 0.2f;// 到达目标的大约时间,SmoothDamp里面使用的
然后再Update()里面添加
transform.position = Vector3.SmoothDamp (transform.position, targetPos, moveSpeed, dampTime);
就可以缓动运动过去了.
CameraRig代码:
using UnityEngine;
using System.Collections;
public class CameraRig: MonoBehaviour {
public Transform[] targets; // tanks private Vector3 targetPos; // 计算出来的目标点 private Vector3 moveSpeed; // 移动速度,SmoothDamp里面使用的 private float dampTime = 0.2f;// 到达目标的大约时间,SmoothDamp里面使用的 // Use this for initialization void Start () { } // Update is called once per frame void Update () { FindAveragePos (); // 计算平均坐标 transform.position = Vector3.SmoothDamp (transform.position, targetPos,ref moveSpeed, dampTime);// 缓动效果 } void FindAveragePos(){ // 计算平均坐标 Vector3 avg = new Vector3 (); // 计算平均坐标的临时变量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍历一遍 avg += targets [i].position; // 所有坐标都加起来 } avg /= targets.Length; // 除以坦克个数,得到坐标的平均值 avg.y = transform.position.y; // 坐标的y轴保持不变 targetPos = avg; // 更新目标点 }
}
回到unity,将两个坦克放到Targets里面
点击Play运行,就可以看到无论两个坦克怎么移动,此时相机一直会在两个坦克之间.
但是不一定总能看到两个坦克.
下面来计算一下size实现正确的缩放.
中间的点为targetPos,就是我们上面计算出来的那个坐标.
Y轴 size = distance.y
X轴 size = distance.x / aspect
取大的
最终版本代码截图
CameraRig最终代码:
using UnityEngine;
using System.Collections;
public class CameraRig: MonoBehaviour {
public Transform[] targets; // tanks private Vector3 targetPos; // 计算出来的目标点 private Vector3 moveSpeed; // 移动速度,SmoothDamp里面使用的 private float dampTime = 0.2f;// 到达目标的大约时间,SmoothDamp里面使用的 private Camera camera; // 相机 private float screenEdgeBuffer = 4f; // 边缘缓冲 private float minZoom = 6.5f; // 最小缩放值 private float zoomSpeed ;// 缩放速度 SmoothDamp里面使用 // Use this for initialization void Start () { camera = GetComponentInChildren<Camera> (); } // Update is called once per frame void Update () { FindAveragePos (); // 计算平均坐标 transform.position = Vector3.SmoothDamp (transform.position, targetPos,ref moveSpeed, dampTime);// 缓动移动 float zoom = FindZoomSize (); // 计算缩放值 camera.orthographicSize = Mathf.SmoothDamp (camera.orthographicSize, zoom, ref zoomSpeed, dampTime);// 缓动缩放 } void FindAveragePos(){ // 计算平均坐标 Vector3 avg = new Vector3 (); // 计算平均坐标的临时变量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍历一遍 avg += targets [i].position; // 所有坐标都加起来 } avg /= targets.Length; // 除以坦克个数,得到坐标的平均值 avg.y = transform.position.y; // 坐标的y轴保持不变 targetPos = avg; // 更新目标点 } float FindZoomSize(){ // 计算缩放大小 float size = 0; // 临时缩放值变量 Vector3 localTargetPos = transform.InverseTransformPoint (targetPos);// 将目标点转换为相对于当前transform的本地坐标 for (int i = 0; i < targets.Length; i++) { // 变量所有坦克 Vector3 tankLocalPos = transform.InverseTransformPoint ( targets [i].position); // 坦克本地坐标 Vector3 distance = targetPos - tankLocalPos; // 和当前坦克的距离 size = Mathf.Max (size, Mathf.Abs (distance.y)); // y轴距离,取大的 size = Mathf.Max (size, Mathf.Abs (distance.x) / camera.aspect ) ; // x轴距离/aspect,取大的 } size += screenEdgeBuffer; // 加上屏幕边缘缓冲值 size = Mathf.Max (size, minZoom); // 不能小于最小缩放值 return size; }
}
---------------------------我是目录分割线---------------------------
《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转
《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力
《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制
---------------------------我是目录分割线---------------------------