10 相機(jī)控制
本節(jié)主要學(xué)習(xí)如何控制相機(jī)自動調(diào)整位置和焦距,使兩個坦克一直同時在視野內(nèi).
在Hierarchy點擊右鍵
點擊 Create Empty,生成空對象,改名為CameraRig
設(shè)置CameraRig rotation為(40,60,0)
將MainCamera拖拽到CameraRig中,使之成為CameraRig的子對象
設(shè)置MainCamera的position為(0,0,-65),rotation為(0,0,0)
Orthographic Camera
Orthographic size
通過設(shè)置size實現(xiàn)縮放
Aspect寬高比
相機(jī)要做到事情有兩個:跟隨坦克和通過縮放實現(xiàn)坦克一直在屏幕內(nèi).
在wm/Scripts文件夾新建腳本CameraRig ,掛載到CameraRig上面
下面我們首先實現(xiàn)跟隨坦克
跟隨坦克首先找到坦克坐標(biāo)的中間坐標(biāo),然后把cameraRig移動過去
先計算中間坐標(biāo)
public Transform[] targets; // tanks
private Vector3 targetPos; // 計算出來的目標(biāo)點
void FindAveragePos(){ // 計算平均坐標(biāo)
Vector3 avg = new Vector3 (); // 計算平均坐標(biāo)的臨時變量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍歷一遍 avg += targets [i].position; // 所有坐標(biāo)都加起來 } avg /= targets.Length; // 除以坦克個數(shù),得到坐標(biāo)的平均值 avg.y = transform.position.y; // 坐標(biāo)的y軸保持不變 targetPos = avg; // 更新目標(biāo)點 }
然后使用 Vector3.SmoothDamp 平滑阻尼是相機(jī)移動過去
還需要聲明兩個變量
private Vector3 moveSpeed; // 移動速度,SmoothDamp里面使用的
private float dampTime = 0.2f;// 到達(dá)目標(biāo)的大約時間,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; // 計算出來的目標(biāo)點 private Vector3 moveSpeed; // 移動速度,SmoothDamp里面使用的 private float dampTime = 0.2f;// 到達(dá)目標(biāo)的大約時間,SmoothDamp里面使用的 // Use this for initialization void Start () { } // Update is called once per frame void Update () { FindAveragePos (); // 計算平均坐標(biāo) transform.position = Vector3.SmoothDamp (transform.position, targetPos,ref moveSpeed, dampTime);// 緩動效果 } void FindAveragePos(){ // 計算平均坐標(biāo) Vector3 avg = new Vector3 (); // 計算平均坐標(biāo)的臨時變量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍歷一遍 avg += targets [i].position; // 所有坐標(biāo)都加起來 } avg /= targets.Length; // 除以坦克個數(shù),得到坐標(biāo)的平均值 avg.y = transform.position.y; // 坐標(biāo)的y軸保持不變 targetPos = avg; // 更新目標(biāo)點 }
}
回到unity,將兩個坦克放到Targets里面
點擊Play運行,就可以看到無論兩個坦克怎么移動,此時相機(jī)一直會在兩個坦克之間.
但是不一定總能看到兩個坦克.
下面來計算一下size實現(xiàn)正確的縮放.
中間的點為targetPos,就是我們上面計算出來的那個坐標(biāo).
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; // 計算出來的目標(biāo)點 private Vector3 moveSpeed; // 移動速度,SmoothDamp里面使用的 private float dampTime = 0.2f;// 到達(dá)目標(biāo)的大約時間,SmoothDamp里面使用的 private Camera camera; // 相機(jī) 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 (); // 計算平均坐標(biāo) 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(){ // 計算平均坐標(biāo) Vector3 avg = new Vector3 (); // 計算平均坐標(biāo)的臨時變量 for (int i = 0; i < targets.Length; i++) { // 所有tank遍歷一遍 avg += targets [i].position; // 所有坐標(biāo)都加起來 } avg /= targets.Length; // 除以坦克個數(shù),得到坐標(biāo)的平均值 avg.y = transform.position.y; // 坐標(biāo)的y軸保持不變 targetPos = avg; // 更新目標(biāo)點 } float FindZoomSize(){ // 計算縮放大小 float size = 0; // 臨時縮放值變量 Vector3 localTargetPos = transform.InverseTransformPoint (targetPos);// 將目標(biāo)點轉(zhuǎn)換為相對于當(dāng)前transform的本地坐標(biāo) for (int i = 0; i < targets.Length; i++) { // 變量所有坦克 Vector3 tankLocalPos = transform.InverseTransformPoint ( targets [i].position); // 坦克本地坐標(biāo) Vector3 distance = targetPos - tankLocalPos; // 和當(dāng)前坦克的距離 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; }
}