美文网首页游戏开发案例系列教程
《Unity入门案例-Tanks坦克大战》10-相机控制

《Unity入门案例-Tanks坦克大战》10-相机控制

作者: 杜增强 | 来源:发表于2018-10-20 09:15 被阅读0次

    10 相机控制

    本节主要学习如何控制相机自动调整位置和焦距,使两个坦克一直同时在视野内.

    image

    在Hierarchy点击右键

    image

    点击 Create Empty,生成空对象,改名为CameraRig

    image

    设置CameraRig rotation为(40,60,0)

    image

    将MainCamera拖拽到CameraRig中,使之成为CameraRig的子对象

    设置MainCamera的position为(0,0,-65),rotation为(0,0,0)

    image

    Orthographic Camera

    image

    Orthographic size

    image

    通过设置size实现缩放

    Aspect宽高比

    image

    相机要做到事情有两个:跟随坦克和通过缩放实现坦克一直在屏幕内.

    在wm/Scripts文件夹新建脚本CameraRig ,挂载到CameraRig上面

    下面我们首先实现跟随坦克

    image

    跟随坦克首先找到坦克坐标的中间坐标,然后把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);

    就可以缓动运动过去了.

    image

    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里面

    image

    点击Play运行,就可以看到无论两个坦克怎么移动,此时相机一直会在两个坦克之间.

    image

    但是不一定总能看到两个坦克.

    下面来计算一下size实现正确的缩放.

    image

    中间的点为targetPos,就是我们上面计算出来的那个坐标.

    Y轴 size = distance.y

    X轴 size = distance.x / aspect

    取大的

    image

    最终版本代码截图

    image

    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坦克大战》10-相机控制

        本文链接:https://www.haomeiwen.com/subject/enppzftx.html