请扫描以上二维码-下载本节项目源文件
01 摄像机的两种类型
02 正交摄像机动态变焦的实用场景
03 摄像机对焦距离(Camera Size)的计算方法
04 如何创建C#脚本来实现正交摄像机的自动对焦
Unity中的摄像机有两种类型,分别是透视摄像机与正交摄像机。透视摄像机主要用在3D游戏中,就像人眼一样看物体;而正交摄像机主要用在2D游戏中,在一个矩形盒子内观察物体。下面介绍与Unity 2D游戏相关的正交摄像机的相关知识。
为了使手机游戏自动适应所有手机设备的屏幕分辨率,需要根据不同的设备分辨率动态调整正交摄像机的对焦距离,也就是动态调整Unity中Camera的Size值,确保游戏所有的场景元素都在摄像机的观察范围之内。
例子:对于一个800像素×640像素且单元比例(Pixels to Units)为100像素的游戏场景来说,它的比例值就是场景高度640像素除以单元比例100像素等于6.4。
因为一般设置正交相机处于游戏场景中央位置,所以它的Size值是比例值6.4的一半3.2,所以我们要设置摄像机尺寸(Size)为3.2,才可以确保场景中的所有元素正好被正交摄像机完整地观察到(也就是屏幕分辨率可以自适应)。
在学习了正交摄像机的相关知识后,下面创建第一个C#脚本来控制正交摄像机的对焦。
步骤1: 在 Assets 文件夹里单击鼠标右键,选择 Create → Folder 命令创建一个名为 scripts 的文件夹用来存放所有的C#脚本。
步骤2: 接下来在 scripts 文件夹上单击鼠标右键,创建一个C#脚本文件,将其命名为 PixelPerfect-Camera 。双击文件名就可以使用Unity自带的Mono Develop工具来打开脚本了。可以看到Unity会自动为脚本添加初始化代码,如下图所示,这是一个刚刚创建脚本的基本布局,我们可以在它的基础上添加自己的逻辑代码。
步骤3: 删除系统自动生成的Start()和Update()方法,创建一个静态的浮点数类型的变量用来存储单元格像素值,将这个变量命名为 pixelToUnity 。
步骤4: 创建一个静态的浮点数类型的变量用来存储比例值,将这个变量命名为 scale。
步骤5: 在计算摄像机比例之前,还需要添加一个公共属性,这个公共属性存储游戏默认分辨率。在其他分辨率下,游戏会根据这个分辨率的比例动态等比例缩放。现在创建一个公共Vector2类,将其命名为 nativeResolution ,并且赋值 11 36×640 。
在理想状态下,等比例缩放会保持画面不失真,但是现在设备的分辨率众多,不能保证可以适应所有的屏幕分辨率,在这里我们采用一个最简单的方法:通过对摄像机镜头的距离控制来缩放用户视角的方式保持这画面可以等比缩放。
要控制摄像机的比例,首先需要使用脚本获取它的引用,然后创建一个变量,将其和摄像机关联起来。我们可以使用GetComponent的方法,它是一个泛类,可以传入任何我们想要的类型,这里传入摄像机属性,就可以获取摄像机引用,注意在语句最后一定要加()来结束方法的调用。
我们使用Awake()来初始化摄像机程序,因为Awake()方法会在实例没有创建好之前就被调用,所以我们一般使用这个方法来预加载系统级别的组件。
步骤6: 在Awake方法中使用GetComponent方法来实例化摄像机。
步骤7: 使用if判断语句和orthographic方法来判断当前摄像机是否是正交摄像机。
步骤8: 计算当前设备分辨率高度与默认分辨率高度比例,这个比例决定着单元像素(pixelsto unit)值的比例。
步骤9: pixelToUnit值需要乘以刚刚计算出来的比例值,才是真实的值。
步骤10: 我们使用orthographicSize属性为正交摄像机赋予的比例值,等于屏幕高度的一半除以单元像素值(pixel To Unit)。
步骤11: 按Ctrl+S组合键保存代码,正交摄像机自动对焦脚本就完成了,我们现在回到Unity软件中,在 Hierarchy 面板中选择 Main Camera 选项,然后在 Inspector 面板中单击 Add Components 按钮,选择并添加 Scripts 文件夹中的 Pixel Perfect Camera ,或直接把脚本拖到main camera(主摄像机)上。
小结: 运行程序时候可以发现在不同的分辨率下,摄像机的尺寸值会自动改变,来适应新的屏幕分辨率。
这个项目中默认分辨率是iPhone 5s的4英寸屏幕分辨率。我们的游戏会以4英寸屏幕为基准适应其他设备的不同分辨率。在通常的手机游戏项目中,程序会自动根据不同的设备分辨率获取相应分辨率的美术资源。当然这只针对像素资源,对于矢量资源的处理就不需要考虑不同设备的分辨率问题了。
我们新创建出来的脚本需要导入Mono框架,并且需要继承Mono behavior类,所以之后的编码工作都需要基于Mono框架之内进行,所有会看到自动生成两个方法Start()和update(),它们分别用于程序的初始化与渲染更新。
现在我们来看看怎样处理摄像机逻辑,因为我们的游戏现在只设置了一个摄像机,所以处理起来就会比较特别。我们会在这个摄像机类中设置静态的属性来存储比例和屏幕的分辨率,这样其他的类就可以通过这个静态属性访问到了。
为了记录下美术资源的单元像素比例,这里设置一个公共的静态浮点数,并把这个变量命名为 pixelsToUnit ,然后给这个变量赋值1。为了表示这个值为浮点数,把这个值写成1.0f。以后看到这个带f标志的数字时,就知道它表示一个浮点数。
接下来,需要另外一个公共的静态属性来表示比例。假设这个比例在游戏开始的时候总是为1,现在开始计算摄像机的比例,不需要在Update方法里执行计算逻辑,在Start()方法执行之前来进行计算即可,因为摄像机的比例决定了用户的视角,所有它需要在游戏其他元素创建之前就计算好比例。为了实现这个功能,我们修改程序的Start()方法为Awake()方法,在Awake()方法里进行计算。当然这里也不需要使用Update()方法,可以把它删除,也可以修改程序自动生成的注释文字或将其删除,但是还是要写注释的,这个在中大型项目及多人合作项目中是非常重要的。