本节书摘来异步社区《Unity 4 3D开发实战详解》一书中的第6章,第6.7节,作者: 吴亚峰 , 杜化美 , 张月霞 , 索依娜 责编: 张涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。
6.7 物理引擎综合案例
Unity 4 3D开发实战详解
前面已经详细介绍了Unity中物理引擎的基础知识,同时,通过一些小案例来具体介绍了物理引擎的相关应用。本小节将通过一个综合案例,使读者对Unity中的物理引擎有进一步的理解。
1.案例的构思
开发案例首先要有一个明确的思路,倘若思路混乱,就会导致案例的整体不协调。接下来介绍一下本案例的设计思路。
(1)首先要明确案例要达到的目的。本案例是为了演示物理引擎模拟现实的特性。
(2)接着要明确案例场景的周边环境,要确定场景的天气。本案例中,为了使用粒子系统,决定将情景设定为大雪纷飞的环境,所以天空盒要选择阴天。
(3)接着就是对案例的核心主题部分进行设计。在本案例中,将要搭建一个足球门,门前采用预制件技术产生5×5×5整齐堆放的立方体堆。
(4)关于界面的触控事件,本案例中采用每次触控都产生一个向前飞出的足球,以撞击方块堆,然后射入足球门中。此处也要采用预制件技术。
2.案例场景的设计
关于场景环境的设计首先是天空盒的选择,接着是大雪场景的制造。具体的操作过程如下。
(1)新建一个场景,在菜单栏中选择File,打开文件操作按钮。选择New Scene,创建一个场景。按快捷键Ctrl+S保存该场景,命名为“football”。
(2)新建一个平面。在菜单栏中单击GameObject→Create Other→Plane菜单,将此平面拖曳到摄像机视野之内,然后将地板纹理图拖曳到此平面上,其参数如图6-166所示。
(3)选择摄像机“MainCamera”对象,在菜单栏中选择“Component”选项,在“组件添加”菜单中选择“Rendering”,在弹出的渲染菜单中选择“Skybox”,如图6-167所示。
(4)导入天空盒资源,在资源列表中的空白处单击鼠标右键,弹出资源操作列表,选择“Import Package”,如图6-168所示。在弹出的资源包列表中选择“Skyboxes”,如图6-169所示。经过此操作导入了天空盒资源。
(5)为摄像机的天空盒指定类型,选中摄像机,在属性查看器中,单击Skybox的属性Custom Skybox的右边的属性框,此时会弹出天空盒选择框,选择Eerie Skybox,如图6-170所示。
(6)添加大雪效果,这就需要粒子系统技术了。在菜单栏中单击GameObject选项,在弹出的游戏对象操作菜单中选择Create Other,此时会弹出“创建其他”菜单,选择Particle System选项,如图6-171所示。
(7)将粒子系统的Shape组件的Shape属性设置为Sphere,如图6-172所示。在场景设计面板中将粒子系统拖曳到摄像机的斜上方,使喷射器在摄像机视野内部不可见,即可达到大雪效果。
3.案例主体部分设计——足球门
(1)导入足球门的FBX模型。本案例中需要用到足球门的模型,模型的导入在后面的章节中会有详细的介绍。模型的资源文件“soccer_goal.FBX”位于随书光盘中源代码/第6章/资源包目录下。
(2)单击GameObject→Create Empty菜单,创建一个空游戏对象。然后单击Gameobject→Create Empty再次创建空游戏对象,命名为Structure,并将Structure拖曳到Gameobject下成为其子对象。
(3)选中Structure对象,单击Component→Mesh→Mesh Filter菜单,为Structure对象添加网格过滤器,如图6-173所示。然后在属性查看器中选择Mesh为前面导入的goal_metal_structure,如图6-174所示。
(4)选中Structure对象,单击Component→Mesh→Mesh Renderer菜单,为Structure对象添加网格渲染器,如图6-175所示。然后在属性查看器中可以更改渲染器的设置,如图6-176所示。
提示
读者应该注意的是Mesh必须添加渲染器以后才会在场景中显现出来。
(5)选中Structure对象,单击Component→Physics→Mesh Collider菜单,为Structure对象添加网格碰撞组件,如图6-177所示。然后在属性查看器中可以看到添加的Mesh Collider,如图6-178所示。
(6)调整属性查看器中Structure的Transform属性,使其大小和位置符合场景的需要,具体参数设置如图6-179所示。同时调整摄像机的Transform参数,使其能够完全看到场景中的对象,具体参数如图6-180所示。
(7)接下来为球门添加门柱。单击GameObject→Create Empty菜单创建空对象,重命名为Liang。然后将其拖曳到GameObject对象下,使其成为子对象。重复第(3)步、第(4)步操作,为对象添加组件,然后单击Component为对象添加Box Collider组件。最终Liang对象在属性查看器中的参数如图6-181所示。
(8)重复上述第(7)步操作,再次添加两个对象,使其分别位于球门的左右两侧充当门柱。其在属性查看器中的设置如图6-182和图6-183所示。
(9)经过上述操作,球门的基本框架已经搭建完成,其在Hierarchy面板的对应位置如图6-184所示。其在Scene面板中的场景如图6-185所示。
(10)接下来为球门添加球网。单击GameObject→Create Other→Cloth菜单,添加一个布料,如图6-186所示。
(11)调整查看器中布料的大小,并在布料的Attached Collider属性中设置Size为4,使每个Collider分别对应刚才创建的球门Structure以及门柱对象,如图6-187所示。然后在Cloth Renderer属性下为布料添加材质(实质是为球网贴一个球网的贴图),具体设置如图6-188所示。
提示
球网的材质是使用一张透明的球网贴图制作的,材质制作的知识前面已经讲解过,贴图资源文件“net_01.png”位于随书光盘中源代码/第6章/资源包目录下。
经过以上的操作,案例中关于球门的部分已经搭建完成。点击Unity游戏播放按钮,可以在Game窗口中看到球门以及球网,如图6-189所示。
4.案例主体部分设计——发射足球及碰撞
本案例游戏的另外一个主体部分是可交互的。在此部分中包括堆叠的方块和发射的足球,在此部分中使用的是脚本和预制件技术。具体的开发过程如下。
(1)创建预制件,在资源列表中的空白处单击鼠标右键,在弹出的资源菜单中选择“Create”,在创建菜单中选择“Prefab”,如图6-190所示。接着重复操作创建一个名为“soccerBallRigidbody”的预制件。
(2)单击GameObject→Create Other→Cube菜单,创建一个Cube对象。选择此对象,单击Component→Physics→Rigidbody选项,为Cube对象添加刚体。
(3)将刚刚创建的cube游戏对象拖曳到第(1)步创建的预制件“cube”,以设置预制件。
(4)按照顺序GameObject→CreateOther→Sphere进行操作,创建一个球体。
(5)选中球体(Sphere)游戏对象,在菜单栏中点击“Component”选项,在弹出的组件添加菜单中分别为对象添加Mesh Filter、Mesh Renderer、Sphere Collider以及Rigidbody,如图6-191所示。
(6)将刚刚创建的球体游戏对象拖曳到第(1)步中创建的预制件“soccerBallRidibody”上,以设置足球预制件。
(7)为摄像机添加脚本。首先右击资源列表空白处,在资源列表中,选择“Create”选项,在弹出的创建菜单中选择“JavaScript”,则创建了一个Javascript脚本,如图6-192所示。选中刚创建的脚本,然后再次单击为其重命名为“initCube”。
(8)编写摄像机脚本。双击刚创建的脚本,等待片刻,则会进入脚本编辑器,在脚本编辑器中进行代码编写。摄像机需要完成方块堆的初始化工作,其具体代码如下所示。
1 var cube:Transform; //定义cube对象
2 var zeroP:Vector3; //定义坐标
3 function Start ()
4 {
5 zeroP=this.transform.position; //获取当前摄像机位置
6 for(var i:int=0;i<5;i++)
7 {
8 for(var j:int=0;j<6;j++)
9 {
10 for(var k:int=0;k<5;k++)
11 {
12 GameObject.Instantiate(cube,Vector3((14.5+zeroP.x+i*0.3), (j*0.3+0.5),
13 (zeroP.z+k*0.3+35)), Quaternion.identity); //循环产生方块,并设置方块位
14 }}}}
- 第1-2行为变量的定义,非私有变量都可以在属性查看器中看到并且予以赋值。
- 第3-13行为Start方法的重写,主要是为了程序开始时在场景的某个固定的地方产生一堆立方体。
(9)关闭脚本编辑器,将资源列表中的脚本拖曳到游戏对象列表中的摄像机对象“MainCamera”上。选中摄像机对象,则可见摄像机中被添加了一个脚本组件“initCube”,如图6-193所示。
(10)将资源列表中的Cube预制件,拖曳到Init Cube脚本组件中的Cube属性的右侧属性框中,完成对脚本的属性赋值,如图6-194所示。
(11)单击GameObject→Create Empty选项,新建一个空对象,重命名为FaQiu。为对象添加脚本控制足球的发射。首先在资源列表空白处单击鼠标右键,在资源列表中,选择“Create”选项,在弹出的创建菜单中选择“JavaScript”,则创建了一个Javascript脚本,重命名为“FaQiu”。
(12)编写FaQiu对象脚本。双击刚创建的脚本,等待片刻,则会进入脚本编辑器,在脚本编辑中进行代码编写。脚本需要控制完成发射足球的工作,其具体代码如下所示。
1 var rocket; //定义变量
2 var soccerBall : Rigidbody; //定义足球刚体
3 var speed = 30.0; //定义速度变量
4 function Start ()
5 {
6 rocket = soccerBall; //初始化rocket变量
7 }
8 function FireRocket () //定义发射球的方法
9 {
10 var rocketClone:Rigidbody; //定义刚体
11 rocketClone = Instantiate(rocket, Vector3(7,1.7,-10),
12 transform.rotation); //产生预制件的坐标
13 rocketClone.velocity = transform.forward * speed; //设置足球发射的初始方向及速度
14 }
15 function Update ()
16 {
17 if (Input.GetButtonDown("Fire1"))
18 {
19 FireRocket(); //调用方法
20 }
21 transform.position.z = Mathf.Clamp (transform.position.z, -6.0, 6.0);
22 }
- 第1-3行为变量的定义,非私有变量都可以在属性查看器中看到并且予以赋值。
- 第4-7行为Start方法的重写,主要是初始化rocket变量。
- 第8-14行为定义FireRocket方法,主要是当调用该方法时生成一个rocket足球对象,然后给予该对象一个初速度。
第15-22行为Update方法的重写,主要是当触发“Fire1”事件时,就调用FireRocket方法发射出一个球。
(13)关闭脚本编辑器,将脚本拖曳到FaQiu对象上,并将资源列表中的soccerBallRigidbody预制件,拖曳到FaQiu脚本组件中的Soccer Ball属性的右侧属性框中,完成对脚本的属性赋值,如图6-195所示。
点击游戏运行按钮,观看案例运行效果,如图6-196所示。
5.案例运行效果
至此案例的开发基本都完成了,本案例可以发布成exe可执行文件在PC上运行,也可以点击Unity引擎里的运行按钮直接观看和体验运行效果。当然,也可以发布到Android设备上运行,运行效果如图6-197所示。
6.案例开发总结
至此本案例的开发已经结束,细心的读者应该注意到了,在开发过程中有多处对参数的设置,这些修改都是凭借经验来进行的。没有经验的初学者可以在特定范围内进行尝试,以体验不同的取值带来的不同视觉感受,这一阶段对于初学者是必不可少的。
在本案例的开发过程中,同时使用了刚体、粒子系统和交互布料。将多种技术用在同一个场景中在案例开发过程中是很常见的,初学者要提高综合运用能力,才能对各种技术的理解更加深入,开发的思路也更加开阔。