Unity手游制作记-制作通用镜头控制器

今天又来搞(zuo)事(you)情(xi)了,今天做什么呢?今天来做一个镜头控制器,用来控制镜头操作。

镜头控制器(摄像机控制器)

所谓镜头,就是我们玩游戏的时候,显示的画面,统称为镜头(也就是摄像机拍到的画面),这里又分为2d,3d,2.5d(又分为伪3d和固定视角),什么叫伪3d呢,就是3d的贴图,其实是2d方法显示,这样减少了很多运算量,固定视角的话,视角是固定的,因游戏或开发要求,而采取的3d画面但是固定视角(其实可以归到3d中去)。

功能

首先,我们要依次制作的以下功能

  1. 简单移动(这里指直接移动,类似瞬移,没有过程)
  2. 匀速运动
  3. 变速运动
  4. 简单旋转(这里指直接旋转,没有过程)
  5. 匀速旋转
  6. 变速旋转
  7. 跟随目标
  8. 根据路径来移动
  9. 以及相应的触发事件
移动

首先我们要获取摄像机对象(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);
    }
}

今天写得快,人形大宝宝可能看不到直播了- -

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值