• 《杜增强讲Unity之Tanks坦克大战》10-相机控制


    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坦克大战》1-准备工作

    《杜增强讲Unity之Tanks坦克大战》2-场景设置

    《杜增强讲Unity之Tanks坦克大战》3-添加坦克

    《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转

    《杜增强讲Unity之Tanks坦克大战》5-子弹

    《杜增强讲Unity之Tanks坦克大战》6-发射子弹

    《杜增强讲Unity之Tanks坦克大战》7-坦克血条

    《杜增强讲Unity之Tanks坦克大战》8-子弹碰撞处理

    《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力

    《杜增强讲Unity之Tanks坦克大战》10-相机控制

    《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制

    ---------------------------我是目录分割线---------------------------


    /// <-----------summary----------->
    /// < ---------杜增强的博客--------->
    /// < -专注于Unity游戏,VR/AR开发->
    /// <-----------summary----------->
  • 相关阅读:
    adb 常用命令及操作
    服务器被黑检查命令
    linux总结
    mysql数据库常用操作
    Python字符串所有操作函数
    Python提示信息表示内容
    Linux基础命令wget(如何联网下载?)
    Linux基础命令sz
    Linux基础命令rz
    Linux基础命令find
  • 原文地址:https://www.cnblogs.com/duzq/p/9832200.html
Copyright © 2020-2023  润新知