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-游戏流程控制

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

《杜增强讲Unity之Tanks坦克大战》10-相机控制的更多相关文章

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

    11 游戏流程控制 使用协程来控制游戏流程 11.1 添加MessageText 首先添加一个Text来显示文字   image 设置GameMgr   image 11.2 游戏整体流程 下面Gam ...

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

    9 发射子弹时蓄力 实现效果如下   image 按下开火键(坦克1为空格键)重置力为最小力,一直按着的时候蓄力,抬起的时候发射.如果按着的时候蓄力到最大,则自动发射,此时在抬起则不会重复发射. 首先 ...

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

    4 坦克移动和旋转 本节课的目标是实现同时wsad和上下左右控制两个坦克分别移动和旋转 4.1 本节代码预览   image 将上节课场景s2另存为s3. 4.2 添加车轮扬沙效果 从Prefabs里 ...

  4. 《杜增强讲Unity之Tanks坦克大战》1-准备工作

    0.案例介绍 0.1开始界面   点击Play Now 进入游戏界面   左边的坦克使用ws控制前后移动,ad键左右旋转,空格键开火   右边的坦克使用方向键上下控制前后移动,方向键左右键实现左右旋转 ...

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

    2  场景设置 2.1 本节效果预览   2.2 项目目录设置 点击Project面板的Create按钮,在根目录下面新建wm文件夹   Wm文件夹用于存放我们自己生成的Prefab和脚本等其他资源, ...

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

    3 添加坦克 3.1 本节效果预览   3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面.   3.3 添加坦克模型 在Model文件夹下面找到Tank模型   将Tank ...

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

    5 子弹 本节的任务是创建子弹的Prefab   image 首先从Model/Shell找到子弹的模型,拖入Hierarchy中,添加刚体组件,所有属性默认值. 添加Capsule Collider ...

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

    6 发射子弹 本节完成发射子弹的功能,最终代码如下:   image 首先,发射子弹得确定发射的位置和方向,还有发射的初始速度.具体的发射速度和按下发射按键的时间长短有关,这个关于子弹的蓄力我们在第九 ...

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

    7 坦克血条 点击菜单GameObject->UI->Slider创建Slider   选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...

随机推荐

  1. 自动代码质量分析(GitLab+JenKins+SonarQube)

    自动代码质量分析(GitLab+JenKins+SonarQube) 1.需求场景 开发提交代码自动执行代码质量分析. 2.所需应用 GitLab,JenKins,SonarQube 3.架构图 4. ...

  2. python ddt模块

    ddt模块包含了一个类的装饰器ddt和两个方法的装饰器: data:包含多个你想要传给测试用例的参数: file_data:会从json或yaml中加载数据: 通常data中包含的每一个值都会作为一个 ...

  3. win10连接外接鼠标怎么禁用触摸板

    Win10笔记本如何禁用触摸板呢?Win10笔记本如何设置“插入鼠标自动禁止触摸板功能”呢?虽然笔记本触摸板在一定程度上可以方便我们的 操作,但是在以鼠标和键盘做为重要的输入设备的情况下,笔记本触摸板 ...

  4. django中url 和 path 的区别

    django中 url 和 path 都是配置路径,有什么不同? django.urls path django.conf.urls  url path 与 url 是两个不同的模块,效果都是响应返回 ...

  5. 3、爬虫之selenium模块

    一 selenium模块 什么是selenium?selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作. selenium最初是一个自动化测试工具, ...

  6. shp转oracle spatial

    2010年12月1日  终于搞定了shp到oracle spatial,说下步骤和感受吧! 1 XP系统:转换工具的下载(shp2sdo.exe ):下载后把此文件复制到PATH变量包含的目录下(E: ...

  7. Spark项目之电商用户行为分析大数据平台之(九)表的设计

    一.概述 数据设计,往往包含两个环节: 第一个:就是我们的上游数据,就是数据调研环节看到的项目基于的基础数据,是否要针对其开发一些Hive ETL,对数据进行进一步的处理和转换,从而让我们能够更加方便 ...

  8. ubuntu 中安装 ZED SDK 及结合ROS 的使用

    双目视觉(stereo vision),由于估计深度相对容易且稠密,在姿态估计和建图时容易初始化和估计尺度,所以在三维重建,SLAM等的应用中有这广泛的应用. ZED 作为近几年出现的商业化双目传感器 ...

  9. JS日历控件优化(增加时分秒)

    JS日历控件优化      在今年7月份时候 写了一篇关于 "JS日历控件" 的文章 , 当时只支持 年月日 的日历控件,现在优化如下:      1. 在原基础上 支持 yyyy ...

  10. Android 调用手机上第三方百度地图并传值给地图

    //移动APP调起Android百度地图方式举例 Intent intent = null; try { // intent = Intent.getIntent("intent://map ...