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-游戲流程控制
---------------------------我是目錄分割線---------------------------