对Camera的理解一直在于棋牌游戏(2D)开发时Camera Projection的选择,其他方面的参数没有纠结过。直到有天思考LOL(英雄联盟)的英雄视角和小地图时就迷茫了,这个时候才发现,自己缺少了太多的基础知识,唉,慢慢补吧!说这段话,不仅仅是对自己的吐槽,也是个人在从事游戏开发过程中容易犯的错误:很多基础点没掌握好,大家也可以对照思考下自己的基础,哈哈!
“官方吐槽”
Camera是为玩家显示游戏场景的一种装置。通过定制和操作摄像机,可以让你的游戏外观与众不同。在一个场景中你可以拥有数量不限的摄像机。它们可以被设置为以任何顺序来渲染,在屏幕上的任何地方来渲染,或仅仅渲染屏幕的一部分。
1.Clear Flags:清除标记;决定屏幕上哪部分将被清除,一般用于使用多个摄像机绘制不同的游戏对象的情况。
说明:每个相机在渲染时会存储颜色和深度信息。屏幕的未绘制部分是空的,默认情况下会显示Skybox。当你使用多个相机时,每一个都将自己的颜色和深度信息存储在缓冲区中,还将积累大量的每个相机的渲染数据。当场景中的任何特定相机进行渲染时,你可以设定清除标记以清除缓冲区信息的不同集合。可以通过下面四个选项之一来完成:
理解:当多个Camera进行显示时,互相之间可能会造成干扰;针对不同的Camera,只需要将其需要显示的部分显示出来,其他的部分都遮挡就好。
- Skybox 天空盒,该模式是默认模式。在屏幕上空白的部分将显示当前相机的天空盒。如果当前相机没有设置天空盒,它会默认使用渲染设置(在Edit->Render Settings里)中选择的天空盒。如果渲染设置中也没有设置天空盒,则它会默认使用Background颜色。另外天空盒组件可以添加到相机上。
- Solid Color 纯色,选择该模式屏幕上的任何空白的部分将显示当前相机的Background颜色。
- Depth Only 仅深度,该模式用于游戏对象不希望被剪裁的情况。
说明:如果想绘制一个玩家的枪而不让它在环境内部得到裁剪,你要设置一个深度为0的相机来绘制环境,还要另一个深度为1的相机单独绘制武器。该武器相机的清除标记应设置为Depth Only。这将保持环境的图形显示在屏幕上,但会丢弃所有关于每个对象在三维空间中的位置的信息。当枪被绘制出来,不透明的部分将完全覆盖任何已绘制的事物,而不管枪到墙之间如何接近。
理解:当需要对gameobject A进行单独显示时,可以考虑Depth Only模式和Depth值大于其他Camera的Depth值;值得注意的是,在其他Camera里面Culling Mask的值就必须剔除掉A;至于怎么剔除掉A,涉及到Layer层级的知识,单独将A设置为一层Layer即可。 - Don't Clear 不清除;该模式不清除任何颜色或深度缓存。其结果是,每帧渲染的结果叠加在下一帧之上,造成涂片效果。一般与自定义的Shader(着色器)配合使用。
2.Background:背景;设置背景颜色;在镜头中的所有元素渲染完成且没有指定Skybox(天空盒)的情况下,将设置的颜色应用到屏幕的空白处。
3.Culling Mask:剔除遮罩;根据游戏对象所指定的层来控制摄像机所渲染的游戏对象。
说明:剔除遮罩有选择地渲染一组对象。通常好的做法,是把用户界面放到不同的层,然后用一个独立相机单独渲染UI层。为了使UI显示在其他相机视角的顶部,你还需要设置清除标记为Depth Only,并确保UI相机的深度比其他相机高。
4.Projection:投射方式;切换相机的透视的模式。
Perspective:透视摄像;犹如我们的眼睛一样,会根据距离的远近显示 大小
Orthographic:正交摄像;物体显示的大小会是一样的,和距离相机远近无关(无透视的方式均匀地渲染游戏对象)
注意:延迟渲染不支持正交模式、
5.Field of View:视野范围(Perspective模式下Camera特有),控制透视相机视角的宽度,以及纵向的角度尺寸。。
6.Size:大小(Orthographic模式下Camera特有,上图没有显示出来),设置正交相机的视口大小。
7.Clipping Planes:剪裁平面;相机开始和停止渲染之间的距离。
Near:相机开始渲染的最近点。
Far: 相机开始渲染的最远点。
8.Viewport Rect:标准视图矩形;用四个数值来控制相机的视图将绘制在屏幕的位置以及大小,使用屏幕坐标系,数值在0-1之间。
X:摄像机视图进行绘制的起始水平位置
Y:摄像机视图进行绘制的起始垂直位置
W:相机输出到屏幕上的宽度
H:相机输出到屏幕上的高度
9.Depth:深度;控制相机的渲染顺序,较大值的相机将被渲染在较小值的相机之上。
10.Rendering Path:渲染路径;指定摄像机的渲染方式。
Use Player Settings(Use Graphics Settings):使用播放器设置(使用内置着色器设置);此相机将使用玩家设置的渲染路径。
Vertex Lit(Legacy Vertex Lit):顶点光照;相机将对所有的游戏对象作为顶点光照对象来渲染。
Forward:快速渲染;相机将对所有游戏对象将按每种材质一个通道的方式来渲染。(说实话,这个我无法理解,哈哈!)
Deferred Lighting(Legacy Deferred):延迟光照; 相机对所有游戏物体进行一次无光照渲染,记录相关信息;最后所有游戏对象再次被渲染时,会叠加之前的相关信息。(Pro版本)
注意:如果相机的投影模式设置为正投影,该值将被重写,相机将始终使用Forward渲染。
11.Target Texture:目标纹理;用于将摄像机视图输出并渲染到屏幕。一般用于制作导航图或者画中画等效果。设置此引用将禁用此相机向屏幕呈现的功能。
12.Occlusion Culling:是否对物体进行遮挡剔除(这里涉及到细节优化等等,值得去深究)
13.Allow HDR:是否支持这个相机的高动态范围渲染。
14.Allow MSAA:是否使用MSAA渲染目标;只有在当前质量设置MSAA级别支持的情况下才会使用MSAA。
15.Allow Dynamic Resolution:是否使用动态分辨率缩放。
注意:动态分辨率缩放(DRS)改变了相机的分辨率。这将减少GPU工作负载。
16.Target Display:目标显示;定义要呈现的外部设备。1 - 8。
说明:终于把Camera相关属性写完了;比较重要也经常会使用到的属性有1,2,3,4,9。希望能够理解透哈!!!关于属性12-15,涉及到Unity运行时关于GPU的优化,这个后面再去学习。
“Game实战”
前面也说了之所以开始写下这个笔记,也是思考到一些具像问题时大脑一片空白了。掌握概念后就应该解决问题了,记录几个具体案例。
问题一:实践下Depth属性的作用?
创建的场景自带Main Camera,其Depth为-1;然后自己创建一个Camera,你会发现它的Depth值为0。
再在场景中创建一个Cube和Sphere作为摄像机的拍摄物体;并让两摄像机都能够拍摄到两个物体。(注意这里要将两台相机的高度设置为不同,不然后面你就不知道Game窗口显示的是哪个Camera的画面)。你会发现Game窗口将只显示Camera拍摄到的画面。
可见摄像机Depth属性设置相机绘图顺序,具有较大值的相机将被绘制在具有较小值的相机的上面,换言之,一个深度为1的相机将绘制在一个深度为0的相机之上。
问题二:能否将多个摄像机拍摄到的画面渲染到同一个屏幕上?
两台相机Main Camera和Camera,参数都是默认的。将Camera的Clear Flags(默认Skybox)设置为Depth Only;此时你可以看到Game窗口将显示Main Camera和Camera同时拍摄到的画面。(尽量将两台相机的位置区分开,这样画面就会不同,最后渲染到一起更加有对比感)。
由此可见,要想将多个相机拍摄的画面渲染到同一个画面是很简单的事情,只需要将它们的Clear Flags设置为Depth Only;但是有一个条件是,它们的Depth都需要比Clear Flags为Skybox或Solid Color的摄像机的Depth高,这样才可以将多个相机单独拍摄的画面叠加于同一个画面上。
理解:第二个问题说到底还是涉及到Depth属性的应用,可见这个小马仔对于Camera的 重要性,哈哈!
问题三:上一个问题是将多个相机拍摄的画面渲染到同一个屏幕?现在思考下怎么在一个屏幕上显示每个相机拍摄到的一部分呢?比如:Main Camera拍摄场景背景,Camera拍摄特定的物体。
1.在问题二的基础上。在场景创建一个Plane,添加材质,使其充满Main Camera画面,作为场景背景。
2.接下来,我们要为物体设置层关系。Unity的Layer的概念可以类比PS里面的图层。添加一个层,命名为other;将场景中的Cube和Sphere的Layer设置为other
3.最后设置两个摄像机的Culling Mask 属性,以使摄像机渲染指定层物体。摄像机的Culling Mask默认为Everything,表明渲染所有层的物体。
Main Camera:将Culling Mask 里面的other层勾去掉,Culling Mask将显示为Mixed… ;你将发现Main Camera的窗口将只显示背景图片,物体没有被渲染。
Camera:在Culling Mask选项里面先勾选Nothing,再勾选other层,表明该摄像机只渲染属于other层的东西,将不会拍摄到别的图层。
最后,在Game窗口看到两个摄像机叠加的画面。
小结:从上面三个问题明白了摄像机的Depth、Clear Falgs和Culling Mask的作用。如果是制作游戏,你可以创建一个界面摄像机,单独渲染界面,而别的摄像机将渲染场景。你只需要添加UI图层,将所有的界面物体的Layer设置为UI,UI摄像机的Culling Mask也只勾选UI层。
问题四:相机跟随模型问题!常常看到第一人称视角的游戏,这个实现就是相机跟随模型的操作。那么具体的操作应该是怎么样的呢?
创建一个空物体Player,然后把模型Model(这里使用一个Cube替代)和摄像机作为Player的子物体,并且务必把模型的transform重置,同player一致。然后通过代码来控制Player即可。
问题五:由问题四延伸出来的问题,第一人称视角的相机跟随处理很容易,那么怎么处理第三人称视角呢?这个应该算得上是“真正”的相机跟随了吧。
理解:这里的相机应该是固定于模型后方一定距离的位置。当模型移动时,检测模型和相机之间的距离是否大于原始距离;如果是,则移动相机相应的距离(移动后的距离 - 原始距离)
public class CameraMove : MonoBehaviour {
public Transform Target;//跟随的目标
private Vector3 Offset;//相机和目标之间的偏移量
// Use this for initialization
void Start () {
Offset = Target.position - transform.position;
}
// Update is called once per frame
void Update () {
transform.position = Vector3.Lerp(transform.position,Target.position-Offset,Time.deltaTime*5f);//插值移动位置
Quaternion rota = Quaternion.LookRotation(Target.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation,rota,Time.deltaTime*3f);//插值移动角度
}
}
这里只是距离简单的思路方式,可以观看大神的文章学习:https://blog.csdn.net/bobowang1991/article/details/54097075
问题六:创建小地图,就是文章开头我思考的那个LOL中小地图的实现问题。
创建小地图:在天空放置一个摄像机向下看,然后设置该摄像机深度值depth大于模型摄像机,然后设置成2D(orthogonality)。通过Viewport Rect属性来调节Camera视图的位置,可以表现出类似于LOL游戏中小地图的样子。
具体的关于点击小地图,角色可以在大地图上跳转到相应位置的操作后面再去研究。可以看看大神们的笔记:https://blog.csdn.net/fanfan_hongyun/article/details/77779472;https://blog.csdn.net/m_cainiaokuaifei/article/details/53649102。
问题七:对人物进行标记,
做人物标记:在人物头顶创建一个平面,然后载入三角图片。由于主摄像机不能看见三角平面标记,则给该平面设置一个层,给摄像机设置成不看见这个层。把摄像机属性skybox更改为depth only ,则只显示摄像机看得见的,其余部分会消失。(这个也暂时留着,后期再来看,哈哈!实在是写不下去了!)
“个人吐槽”
道路长且远,且行且珍惜,阿西吧!!!!!!!!