包含了鼠标控制照相机旋转等功能
开始本部分之前,你可以先创建一个unity3d项目,并创建一个除了主摄像机之外额外的camera。让两个摄像机位于不同位置,使他们景象不同
创建照相机之后你应该会看到以下内容:
- 1、Transform
- 2、Camera(摄像机选项)
1、Transform
由于摄像机本质上也是gameobject,因此其transform本质上和我们第二节讲的没有任何区别。如果没有学好的小伙伴可以回到第二课:从Cube看GameObject再康康。
虽然如此,我们本节也会加入一些适合摄像机的内容,也就是更多的移动方式,以及鼠标控制摄像机旋转。
1.1 Input.GetAxis(渐变轴获取)
在你了解了前一个部分的移动之后,我们在这里提供一种直接由键盘键入/鼠标移动产生的移动,也就是要讲的Input.GetAxis函数。
该函数需要一个string参数,返回一个float值,这样说很难弄懂,我们直接来举个例子。
Vector3 veca;
veca.x += Input.GetAxis("Vertical");
对于该函数,我们用一个表格来说明输入的内容,做出的动作和输出的内容。
string | 介绍 |
---|---|
Vertical | 对应键盘上下箭头,当我们在键盘上按下上箭头时,它会从0逐渐增加到1.0,反之逐渐减少到-1.0 |
Horizontal | 对应左右箭头,当我们在键盘上按下右箭头时,它会从0逐渐增加到1.0,反之会逐渐减少到-1.0 |
Mouse X | 鼠标沿屏幕X轴移动时,会触发,同上两个,区间从-1.0~1.0 |
Mouse Y | 鼠标沿屏幕Y轴移动时,会触发,同上,区间从-1.0~1.0 |
Mouse ScrollWheel | 当鼠标滚动轮滚动时触发,同上,区间从-1.0~1.0 |
简单看完之后,我们可以知道,GetAxis函数可以返回给我们一个-1~1的值,而且它并不是一个瞬间完成,而是在短时间内逐渐从0增加或缩减到1和-1。
1.2 Input.GetAxisRaw(瞬间轴获取)
该函数和GetAxis在输入上没有区别,都可以使用类似
float a = Input.GetAxis("Vertical");
float a = Input.GetAxisRaw("Vertical");
float b = Input.GetAxis("Mouse Y");
float b = Input.GetAxisRaw("Mouse Y");
来完成。
不同的是,GetAxis获取是一个渐变过程。比如你在按着右箭头的情况下,返回值是从0逐渐变为1的。
而GetAxisRaw则是一个瞬间过程,在你按下右箭头的瞬间,返回值就直接成为了1,左箭头就直接成为-1,没有过程。
1.3鼠标旋转摄像机视角
弄懂了这两个函数,我们就可以用这两个函数的特性来制作一个“通过移动鼠标来旋转视角”的功能了。
this.transform.Rotate(new Vector3(-Input.GetAxis("Mouse Y"), Input.GetAxisRaw("Mouse X"),0),Space.Self);
这是一个最简单的鼠标旋转控制摄像机视角的代码,简单来说就是用鼠标的Y轴移动控制我们摄像机的X轴移动,鼠标的X轴移动控制我们摄像机的Y轴移动。(这一部分请自行打开unity实验)
但是这个代码实际上有着很多的问题,比如由于自身坐标系改变的原因,我们在移动之后会导致摄像机的z轴乱晃。因此我们更多的,会选择额外声明一个Vector3来储存我们“正确的位置”,然后通过我们之前讲过的欧拉旋转来准确到达目标位置,这样就能解决z轴乱晃导致的问题。
因此我们改进之后,代码如下:
private Vector3 veca;
...
veca.x -= Input.GetAxis("Mouse Y");
veca.y += Input.GetAxis("Mouse X");
this.transform.localEulerAngles = veca;
这样,我们将其挂在摄像机上,就可以实现简单的鼠标控制旋转功能了。
2、Camera(摄像机选项)
该选项包括了摄像机的各个功能。
2.1 Clear Flags(清除缓冲区)
首先你要了解camera的工作机制:camera工作时,每个照相机分别渲染其范围内的颜色和深度信息,然后将空白部分填充为我们的Clear Flags的内容,在一般情况下,空白部分将会被渲染为skybox(天空盒),关于天空盒,我们马上会给一个简短的解释。
选项 | 简介 |
---|---|
Skybox | 屏幕的任何空白部分都将显示当前摄像机的skybox(天空盒)。如果当前摄像机没有设置skybox(天空盒),它将使用默认skybox(天空盒)。 |
Solid color | 屏幕的任何空白部分都将显示当前摄像机的Background属性的颜色 |
Depth only | 保留到下一层级,该选项会将当前camera的所有空白部分取消填充,但是会将已经渲染的部分保留到下一层级。一般在fps游戏中,玩家持枪就是使用该功能完成的。我们会在Depth中详细讲。 |
Don’t clear | 此模式不会清除颜色或深度缓冲区。结果是将每帧绘制在下一帧之上,从而产生涂抹效果。我们可以用一张图来说明它的效果 |
四种不同的选项本质上对应着不同的功能,但实际上Don’t clear很少用在游戏制作之中。Depth only则大量用于第一人称游戏中。
2.1.1 Skybox(天空盒)
天空盒是一种由多个面组成的立体图像,保证你向各个方向看去,都可以形成一个完整的立体空间,比如我们新建unity项目的自带背景,就是默认天空盒。
你可以在商店下载到各式各样的天空盒——包括星空,宇宙,地狱等等等等,他们会使你游戏的天空更加漂亮。
如果你想要修改默认天空盒,你可以打开Window > Rendering > Lighting,修改Skybox Material(将你制作的,或者在商店下载的天空盒拖入),来完成修改默认天空盒。
当然,你也可以直接将下载的天空盒拖入到相机来完成对单个相机的天空盒设置。
2.2 Background(背景颜色)
只要你是个正常人,应该就能很轻松的和上面的选项链接起来弄懂这玩意是什么东西吧。
如果你弄懂了这个设置,那你可真是个小聪明哦!
但是我们在这里要讲的并不是这个,而是另一个很重要的东西——如何使用代码改变。
2.2.1 color(颜色)
一般意义上,如果你想创建一个Color的话,按如下定义
Color co = new Color(1, 1, 1, 1);
括号中的四个数值,分别代表着:
R:red,红色值,范围0~1
G:green,绿色值,范围0~1
B:blue,蓝色值,范围0~1
A:Alpha,灰度值,范围0~1
一些unity中常用的颜色属性:
颜色 | 代码 |
---|---|
black | (0, 0, 0, 1). |
blue | (0, 0, 1, 1). |
clear | (0, 0, 0, 0). |
cyan | (0, 1, 1, 1). |
gray | (0.5, 0.5, 0.5, 1). |
green | (0, 1, 0, 1). |
grey | (0.5, 0.5, 0.5, 1). |
magenta | (1, 0, 1, 1). |
red | (1, 0, 0, 1). |
white | (1, 1, 1, 1). |
yellow | (1, 0.92, 0.016, 1) |
2.2.2 GetComponent<>(获取物体组件)
当我们想要改变物体camera的时候,会发现一个问题:类似之前更改transform来做的话
this.transform.translate(new ...);
this.came......??????
为什么this没有camera这个选项???
这里我们就要简单提一下,camera本质上其实也是gameobject,和一般不同的是,它增加了一个camera组件,也就是这玩意:
也就是说,本质上来说,camera其实并不是这个gameobject自己的东西,只是一个“组件”而已。
因此,我们就有了一个全新的方式,去获取这个gameobject的组件:GetComponent<组件名>
。
this.GetComponent<Camera>().backgroundColor;
哈哈,这样就可以了。
紧接着,我们使用刚才定义的颜色,赋值之后就是:
this.GetComponent<Camera>().backgroundColor = co;
//或者
this.GetComponent<Camera>().backgroundColor = new Color(1, 1, 1, 1);
同样的,这个函数可以帮助我们修改gameobject下的各个组件的各个具体值,或者调用各个函数,用到就是赚到。
紧接着加个按键设置,就可以判断我们是否成功了。
if(Input.GetKey(KeyCode.G))
{
this.GetComponent<Camera>().backgroundColor = new Color(1, 1, 1, 1);
}
(别忘了把Clear Flags设置为Solid color哦,你也可以试试在代码中使用相同原理去设置它。)
2.3 Culling Mask(剔除遮罩)
当我们需要选择性渲染对象组的时候,可更改该部分的选项。
在这个选项卡中,我们可以找到不同的Layers(层)选项,取消勾选,便表示——这一层的东西我们将不会再让它出现在我们的摄像机中。
关于Layer,我们会放在碰撞那边,和Tag一起讲。
2.4 Projection(透视功能设置)
Perspective:完整的角度渲染,也就是说我们的摄像机将会是一个正常的角度去对观察物体。
Orthographic:均匀的角度渲染,话不多说,一张图让你明白:
那是真的均匀。
2.5相机视角大小
相机视角大小并不是单纯的大小,需要根据你选择的Projection(透视功能设置)来具体决定。
2.5.1 Perspective下的大小(FOV Axis和Field of view)
FOV Axis:相机使用的是水平还是垂直视场轴,一般默认为水平。
Field of view:视场大小。
2.5.2 Orthographic下的大小(size)
这个太好懂了,我都不想讲了。简单来说就是在Orthographic模式下,相机的可视范围大小。
2.6 Physical Camera(物理摄像机)
模拟真实摄像机格式,开启后,可以直接从一些3d建模所使用的真实计算机中导入信息。关于物理摄像机的说明,官方文档已经有了很详细的介绍,限于篇幅,我在这里不加以赘述。
如果有需要的话,我也会在第二部分教程中专门做一个教程。
2.7 Clipping Planes(绘制点)
相机本质上有着一个视野范围,其中 Near表示最近视野范围, Far表示最远视野范围,在代码中,我们可以使用:
this.GetComponent<Camera>().farClipPlane = 1000;
this.GetComponent<Camera>().nearClipPlane = 0.1f;
来改变其视野范围。
2.8 Viewport Rect(绘制视图范围)
简单来说,就是我们的摄像机在显示的时候占领我们屏幕多大,它有四个元素。
X:X轴哪里开始绘制
Y:Y轴哪里开始绘制
W:X宽度
H:Y高度
2.8.1 利用Viewport Rect进行分屏
我们这里要用到之前的两个摄像机。我们想要它们实现分屏,那么本质上只要改变他们的Viewport Rect范围就可以了。
对于摄像机1,我们将其改为
对于摄像机2,我们将其改为
这样,整个显示就成了
当然,除了分屏外,很多地方都可以用到整个,请自由发挥。
2.9 Depth(深度)
深度的数据决定着多个摄像机显示的先后顺序。
假设我们有着3个摄像机,它们的Depth分别是-1,2和4
那么,我们屏幕上显示的镜头,首先是4的镜头,然后我们关闭4,就会变成2的镜头,关闭2才是-1摄像机的镜头。
我们在之前Clear Flags(清除缓冲区)中讲到了Depth Only,我们简单说明一下这是什么。
我们已经知道其实摄像机在屏幕上是一层一层显示的,那么如果我们有以下两个摄像头:
摄像头1,深度2,是玩家的持枪画面,除了枪械都是空白。
摄像头2,深度1,是玩家的场景画面,没有枪械。
我们将摄像头1设置成Depth Only,就会发现:摄像头1只留下了枪械,空白的画面被删去了。因此,背景成为了玩家实际所在的场景。
2.10 Rendering Path(渲染方法)
定义摄像机将使用的渲染方法的选项。
选项 | 描述 |
---|---|
Use Player Settings | 此摄像机将使用 Player Settings 中设置的任何渲染路径 (Rendering Path)。 |
Vertex Lit | 此摄像机渲染的所有对象都将渲染为顶点光照对象。 |
Forward | 每种材质采用一个通道渲染所有对象。 |
Deferred Lighting | 将在没有光照的情况下一次性绘制所有对象,然后在渲染队列末尾一起渲染所有对象的光照。 |
对于该部分,新手水友可以直接跳过
2.11 Render Texture(渲染纹理)
简单来说,就是将此摄像机的画面,作为纹理放在某个物件上。我们可以用这个来制作监控摄像头、直播动作、传送门等功能。