今天又来搞(zuo)事(you)情(xi)了,今天做什么呢?今天来做一个镜头控制器,用来控制镜头操作。
镜头控制器(摄像机控制器)
所谓镜头,就是我们玩游戏的时候,显示的画面,统称为镜头(也就是摄像机拍到的画面),这里又分为2d,3d,2.5d(又分为伪3d和固定视角),什么叫伪3d呢,就是3d的贴图,其实是2d方法显示,这样减少了很多运算量,固定视角的话,视角是固定的,因游戏或开发要求,而采取的3d画面但是固定视角(其实可以归到3d中去)。
功能
首先,我们要依次制作的以下功能
- 简单移动(这里指直接移动,类似瞬移,没有过程)
- 匀速运动
- 变速运动
- 简单旋转(这里指直接旋转,没有过程)
- 匀速旋转
- 变速旋转
- 跟随目标
- 根据路径来移动
- 以及相应的触发事件
移动
首先我们要获取摄像机对象(Camera)
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
void Awake() {
camera = this.GetComponent<Camera>();
}
void Update () {
}
}
接着就来做移动。
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
// 最大最小宽度
public float minX = 100.0f;
public float maxX = -100.0f;
// 最大最小高度
public float minY = 10.0f;
public float maxY = 50.0f;
// 最大最小深度
public float minZ = 100.0f;
public float maxZ = -100.0f;
// 当前速度
Vector3 nowSpeed;
// 加速度
Vector3 addSpeed;
void Awake() {
camera = this.GetComponent<Camera>();
addSpeed = Vector3.zero;
nowSpeed = Vector3.zero;
}
// 简单移动(瞬移)
public virtual void simpleMove(float x, float y, float z) {
camera.transform.position = check(x, y, z);
simpleMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void simpleMove(Vector3 pos) {
camera.transform.position = check(pos);
simpleMoveEvent(camera, pos);
}
protected virtual void simpleMoveEvent(Camera cam, Vector3 pos) {
}
// 匀速移动
public virtual void constantMove(float x, float y, float z) {
nowSpeed.x = x;
nowSpeed.y = y;
nowSpeed.z = z;
constantMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void constantMove(Vector3 speed) {
nowSpeed = speed;
constantMoveEvent(camera, speed);
}
protected virtual void constantMoveEvent(Camera cam, Vector3 speed) {
}
// 变速移动
public virtual void changeMove(float x, float y, float z) {
addSpeed.x = x;
addSpeed.y = y;
addSpeed.z = z;
changeMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void changeMove(Vector3 speed) {
addSpeed = speed;
changeMoveEvent(camera, speed);
}
protected virtual void changeMoveEvent(Camera cam, Vector3 speed) {
}
void Update () {
Vector3 pos = camera.transform.position;
pos += nowSpeed * Time.deltaTime;
nowSpeed += addSpeed * Time.deltaTime;
camera.transform.position = check(pos);
}
/* ***************
* 工具类函数
* 范围:public(公共)
*
* ***************/
// 检测坐标是否超出范围,并强制移动到范围内
public Vector3 check(Vector3 p) {
Vector3 pos = new Vector3(p.x, p.y, p.z);
pos.x = Mathf.Max(pos.x, minX);
pos.x = Mathf.Min(pos.x, maxX);
pos.y = Mathf.Max(pos.y, minY);
pos.y = Mathf.Min(pos.y, maxY);
pos.z = Mathf.Max(pos.z, minZ);
pos.z = Mathf.Min(pos.z, maxZ);
return pos;
}
public Vector3 check(float x, float y, float z) {
x = Mathf.Max(x, minX);
x = Mathf.Min(x, maxX);
y = Mathf.Max(y, minY);
y = Mathf.Min(y, maxY);
z = Mathf.Max(z, minZ);
z = Mathf.Min(z, maxZ);
return new Vector3(x, y, z);
}
}
旋转
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
// 当前旋转速度
Vector3 nowRotationSpeed;
// 旋转加速度
Vector3 addRotationSpeed;
void Awake() {
camera = this.GetComponent<Camera>();
addRotationSpeed = Vector3.zero;
nowRotationSpeed = Vector3.zero;
}
// 简单旋转(瞬间)
public virtual void simpleRotation(float x, float y, float z) {
camera.transform.rotation = Quaternion.Euler(x, y, z);
simpleRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void simpleRotation(Vector3 pos) {
camera.transform.rotation = Quaternion.Euler(pos);
simpleRotationEvent(camera, pos);
}
protected virtual void simpleRotationEvent(Camera cam, Vector3 pos) {
}
// 匀速旋转
public virtual void constantRotation(float x, float y, float z) {
nowRotationSpeed.x = x;
nowRotationSpeed.y = y;
nowRotationSpeed.z = z;
constantRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void constantRotation(Vector3 speed) {
nowRotationSpeed = speed;
constantRotationEvent(camera, speed);
}
protected virtual void constantRotationEvent(Camera cam, Vector3 speed) {
}
// 变速旋转
public virtual void changeRotation(float x, float y, float z) {
addRotationSpeed.x = x;
addRotationSpeed.y = y;
addRotationSpeed.z = z;
changeRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void changeRotation(Vector3 speed) {
addSpeed = speed;
changeRotationEvent(camera, speed);
}
protected virtual void changeRotationEvent(Camera cam, Vector3 speed) {
}
void Update () {
camera.transform.rotation = Quaternion.Slerp(camera.transform.rotation, Quaternion.Euler(nowRotationSpeed + camera.transform.eulerAngles), Time.deltaTime);
nowRotationSpeed += addRotationSpeed * Time.deltaTime;
}
跟随目标
只需要每帧的时候,跟踪这个目标即可。
using UnityEngine;
using System.Collections;
/* *********************************************************
* 跟踪目标时,无法进行独立的移动,需要先取消跟踪(endFlowTra)
*
*
* *********************************************************/
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
Transform tra; // 跟踪目标
Vector3 traPos; // 距离跟踪目标的距离
void Awake() {
camera = this.GetComponent<Camera>();
tra = null;
traPos = Vector3.zero;
}
// 开始跟踪目标
public virtual void startFlowTra(Transform t, Vector3 pos) {
tra = t;
traPos = pos;
startFlowTraEvent(camera, t, pos);
}
protected virtual void startFlowTraEvent(Camera cam, Transform t, Vector3 pos) {
}
// 结束跟踪目标
public virtual void endFlowTra() {
endFlowTraEvent(camera, tra, traPos);
tra = null;
traPos = Vector3.zero;
}
protected virtual void endFlowTraEvent(Camera cam, Transform t, Vector3 pos) {
}
void Update () {
if (tra != null) {
camera.transform.position = check(tra.position + traPos);
}
}
根据路径进行移动
我们只需要创建路径队列即可进行移动。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/* *********************************************************
* 跟踪目标时,无法进行独立的移动,需要先取消跟踪(endFlowTra)
*
*
* *********************************************************/
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
// 路径队列
Queue<Vector3> path;
float pathTime; // 每个点所需时间
Vector3 nowPathPos;
void Awake() {
camera = this.GetComponent<Camera>();
path = new Queue<Vector3>();
}
// 开始根据路径移动(传入一系列的点)
public virtual void startFlowPath(float time, params Vector3[] pos) {
this.nowSpeed = Vector3.zero;
this.addSpeed = Vector3.zero;
pathTime = time;
path = new Queue<Vector3>(pos);
path.Enqueue(pos[pos.Length - 1]);
nowPathPos = path.Dequeue(); // 将终点加入二次,作为终点标记
}
// 结束根据路径移动
public virtual void endFlowPath() {
this.nowSpeed = Vector3.zero;
this.addSpeed = Vector3.zero;
path = new Queue<Vector3>();
}
void Update () {
if (path.Count != 0) {
float dis = Vector3.Distance(nowPathPos, camera.transform.position);
if (dis <= 0.1f) { // 已经接近
camera.transform.position = nowPathPos;
nowPathPos = path.Dequeue();
if (path.Count == 0) { // 如果是最后一个点,则将速度变为0
nowSpeed = Vector3.zero;
addSpeed = Vector3.zero;
}
} else {
// 进行平滑移动
camera.transform.position = Vector3.SmoothDamp(camera.transform.position, nowPathPos, ref nowSpeed, pathTime);
}
}
}
总结
可以使用这个进行一系列的镜头操作,比如拉伸,移动,追随,镜头剧情等,还可以根据自己的需求进行扩展
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/* *********************************************************
* 跟踪目标时,无法进行独立的移动,需要先取消跟踪(endFlowTra)
* 一般只需要继承protected函数即可,不推荐继承public函数
* 这里将protected函定为二级函数,public函定义为一级函数(一级调用二级)
* *********************************************************/
[RequireComponent(typeof(Camera))]
public class CameraControl : MonoBehaviour {
protected Camera camera;
// 最大最小宽度
public float minX = -100.0f;
public float maxX = 100.0f;
// 最大最小高度
public float minY = -50.0f;
public float maxY = 50.0f;
// 最大最小深度
public float minZ = -100.0f;
public float maxZ = 100.0f;
// 当前速度
Vector3 nowSpeed;
// 加速度
Vector3 addSpeed;
// 当前旋转速度
Vector3 nowRotationSpeed;
// 旋转加速度
Vector3 addRotationSpeed;
Transform tra; // 跟踪目标
Vector3 traPos; // 距离跟踪目标的距离
// 路径队列
Queue<Vector3> path;
float pathTime; // 每个点所需时间
Vector3 nowPathPos;
void Awake() {
camera = this.GetComponent<Camera>();
addSpeed = Vector3.zero;
nowSpeed = Vector3.zero;
addRotationSpeed = Vector3.zero;
nowRotationSpeed = Vector3.zero;
tra = null;
traPos = Vector3.zero;
path = new Queue<Vector3>();
nowPathPos = Vector3.zero;
}
void Start() {
startFlowPath(1.0f, new Vector3(1, 1, 1), new Vector3(-1, -1, -1));
}
// 简单移动(瞬移)
public virtual void simpleMove(float x, float y, float z) {
camera.transform.position = check(x, y, z);
simpleMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void simpleMove(Vector3 pos) {
camera.transform.position = check(pos);
simpleMoveEvent(camera, pos);
}
protected virtual void simpleMoveEvent(Camera cam, Vector3 pos) {
}
// 匀速移动
public virtual void constantMove(float x, float y, float z) {
nowSpeed.x = x;
nowSpeed.y = y;
nowSpeed.z = z;
constantMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void constantMove(Vector3 speed) {
nowSpeed = speed;
constantMoveEvent(camera, speed);
}
protected virtual void constantMoveEvent(Camera cam, Vector3 speed) {
}
// 变速移动
public virtual void changeMove(float x, float y, float z) {
addSpeed.x = x;
addSpeed.y = y;
addSpeed.z = z;
changeMoveEvent(camera, new Vector3(x, y, z));
}
public virtual void changeMove(Vector3 speed) {
addSpeed = speed;
changeMoveEvent(camera, speed);
}
protected virtual void changeMoveEvent(Camera cam, Vector3 speed) {
}
// 简单旋转(瞬间)
public virtual void simpleRotation(float x, float y, float z) {
camera.transform.rotation = Quaternion.Euler(x, y, z);
simpleRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void simpleRotation(Vector3 pos) {
camera.transform.rotation = Quaternion.Euler(pos);
simpleRotationEvent(camera, pos);
}
protected virtual void simpleRotationEvent(Camera cam, Vector3 pos) {
}
// 匀速旋转
public virtual void constantRotation(float x, float y, float z) {
nowRotationSpeed.x = x;
nowRotationSpeed.y = y;
nowRotationSpeed.z = z;
constantRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void constantRotation(Vector3 speed) {
nowRotationSpeed = speed;
constantRotationEvent(camera, speed);
}
protected virtual void constantRotationEvent(Camera cam, Vector3 speed) {
}
// 变速旋转
public virtual void changeRotation(float x, float y, float z) {
addRotationSpeed.x = x;
addRotationSpeed.y = y;
addRotationSpeed.z = z;
changeRotationEvent(camera, new Vector3(x, y, z));
}
public virtual void changeRotation(Vector3 speed) {
addSpeed = speed;
changeRotationEvent(camera, speed);
}
protected virtual void changeRotationEvent(Camera cam, Vector3 speed) {
}
// 开始跟踪目标
public virtual void startFlowTra(Transform t, Vector3 pos) {
tra = t;
traPos = pos;
startFlowTraEvent(camera, t, pos);
}
protected virtual void startFlowTraEvent(Camera cam, Transform t, Vector3 pos) {
}
// 结束跟踪目标
public virtual void endFlowTra() {
endFlowTraEvent(camera, tra, traPos);
tra = null;
traPos = Vector3.zero;
}
protected virtual void endFlowTraEvent(Camera cam, Transform t, Vector3 pos) {
}
// 开始根据路径移动(传入一系列的点)
public virtual void startFlowPath(float time, params Vector3[] pos) {
this.nowSpeed = Vector3.zero;
this.addSpeed = Vector3.zero;
pathTime = time;
path = new Queue<Vector3>(pos);
path.Enqueue(pos[pos.Length - 1]);
nowPathPos = path.Dequeue(); // 将终点加入二次,作为终点标记
}
// 结束根据路径移动
public virtual void endFlowPath() {
this.nowSpeed = Vector3.zero;
this.addSpeed = Vector3.zero;
path = new Queue<Vector3>();
}
void Update () {
if (tra != null){
camera.transform.position = check(tra.position + traPos);
} else if (path.Count != 0) {
float dis = Vector3.Distance(nowPathPos, camera.transform.position);
if (dis <= 0.1f) { // 已经接近
camera.transform.position = nowPathPos;
nowPathPos = path.Dequeue();
if (path.Count == 0) { // 如果是最后一个点,则将速度变为0
nowSpeed = Vector3.zero;
addSpeed = Vector3.zero;
}
} else {
// 进行平滑移动
camera.transform.position = Vector3.SmoothDamp(camera.transform.position, nowPathPos, ref nowSpeed, pathTime);
}
} else {
Vector3 pos = camera.transform.position;
pos += nowSpeed * Time.deltaTime;
nowSpeed += addSpeed * Time.deltaTime;
camera.transform.position = check(pos);
camera.transform.rotation = Quaternion.Slerp(camera.transform.rotation, Quaternion.Euler(nowRotationSpeed + camera.transform.eulerAngles), Time.deltaTime);
nowRotationSpeed += addRotationSpeed * Time.deltaTime;
}
}
/* ***************
* 工具类函数
* 范围:public(公共)
*
* ***************/
// 检测坐标是否超出范围,并强制移动到范围内
public Vector3 check(Vector3 p) {
Vector3 pos = new Vector3(p.x, p.y, p.z);
pos.x = Mathf.Max(pos.x, minX);
pos.x = Mathf.Min(pos.x, maxX);
pos.y = Mathf.Max(pos.y, minY);
pos.y = Mathf.Min(pos.y, maxY);
pos.z = Mathf.Max(pos.z, minZ);
pos.z = Mathf.Min(pos.z, maxZ);
return pos;
}
public Vector3 check(float x, float y, float z) {
x = Mathf.Max(x, minX);
x = Mathf.Min(x, maxX);
y = Mathf.Max(y, minY);
y = Mathf.Min(y, maxY);
z = Mathf.Max(z, minZ);
z = Mathf.Min(z, maxZ);
return new Vector3(x, y, z);
}
}
今天写得快,人形大宝宝可能看不到直播了- -