华东师范大学学士学位论文 基于Unity的车辆模拟游戏的设计与实现
(二) 场景物理仿真实现
如前文提到,Unity3D内臵对Nvidia PhysX支持,其实际工作就是封装了一些游戏中常用的组件以及脚本中调用的类,只要将这些碰撞体组件赋予游戏对象,就被加入PhysX虚拟世界进行运算。下面主要介绍常用组件:
刚体(Rigid):在PhysX的基本概念中,两个碰撞体发生碰撞必须要求其中至少有一个刚体。所以对运动的物体要赋予刚体属性,刚体可设臵质量、重力计算、碰撞检测频率等属性。
网格碰撞体(Mesh Collider):根据游戏玩法,玩家通过车身前部撞击其他车的后部进行游戏,在车身前部和后部各加入一个网格碰撞体,网格碰撞体可通过网格数据定义凸体形状,比起基本碰撞体更加精确。
地形碰撞体(Terrain Collider):通过地形模块生成的地形可以选择加入地形碰撞体,就这样就可以不需要定义网格数据来定义网格碰撞体,其本质就是根据高度图生成的网格碰撞体。
轮胎碰撞体(Wheel Collider):汽车经常在陡峭的地形上行走,如果将轮胎定义为一般碰撞体则容易造成碰撞而导致车身飞起,轮胎碰撞体具有阻尼弹性和摩擦力的属性,不同类型的车辆可以使用不同的轮胎碰撞体参数,模拟出各种效果。
弹簧连接体(Spring Joint):物体之间如果通过连接有力的作用,可通过设臵连接体来实现。弹簧连接体能够模拟物体之间的阻尼作用。
如图4-11所示,场景中需要进行物理计算的主要有三种:地形、一些3D模型(如栅栏)和汽车,其中地形和3D模型为静态物体,只要为其增加静态碰撞体组件即可。而汽车的构造较为复杂,首先在游戏中前车身和后车身为不同的积分部位,因此要定义为两个网格碰撞体,并且为了得到真实的物理效果,需要将轮胎定义为车轮碰撞体并通过弹簧连接体与车身相连,如图4-12所示。
21
华东师范大学学士学位论文 基于Unity的车辆模拟游戏的设计与实现
物理仿真地形汽车栅栏地形碰撞体网格碰撞体刚体网格碰撞体车轮碰撞体弹簧连接体 图4-11 物理仿真模块实现
图4-12汽车物理仿真的构造
(三) 汽车动力学模拟
进行了汽车的物理组件装配之后,还要实现汽车动力学模型。由于汽车在驾驶过程中影响其运动情况的因素错综复杂,操纵机构对汽车的行驶存在着多输入、多藕合、非线性的控制作用,而实时渲染游戏要求动力学仿真计算快速,要在精确度与计算速度之间折中,需要简化动力学模型[11]。
为了简化模型,作如下假设:所有车辆都是刚体,不考虑多节车厢的情况。汽车在行驶过程中,因速度的变化受到引擎的驱动力和阻力(动摩擦力、空气阻力),如果汽车在转弯还会收到轮胎的侧摩擦力,汽车行驶过程中的基本受力图如4-13所示:
22
华东师范大学学士学位论文 基于Unity的车辆模拟游戏的设计与实现
图4-13 车辆行驶受力图
假设汽车当前正在转弯且速度为v,且由于转弯轮胎和车身的z轴并不重合,速
度v在轮胎x轴方向的分量为v.x,k为阻力系数,根据公式4-4可得出汽车受得的阻力f和轮胎侧摩擦力f侧:
公式4-4
汽车当前引擎提供的驱动力决定于汽车当前的档位,档位由当前速度大小决定,
不同的车辆有不同的档位设计,为了控制汽车能达到的最大速度,使用二次线性增量法,vtop表示汽车能达到的最大速度,n表示该车当前的档位, vn表示达到该档位的最低速度,Fn表示n档位收到的驱动力,k为公式4-4中的阻力系数,这样,速度、档位、驱动力之间关系可用公式4-5表示:
根据以上得出的汽车动力学模型,需要在Unity3D中通过脚本组件实现,首先为
23
公式4-5
华东师范大学学士学位论文 基于Unity的车辆模拟游戏的设计与实现
汽车对象增加一个继承自MonoBehavior的Car.js脚本,在其中重写两个更新函数Update()和FixedUpdate(),Update()函数在每帧绘制之前调用一次,FixedUpdate()通过一个计时器定时调用,时间间隔可在工程中设臵。然后在这两个更新函数进行动力学计算。以下为两个更新函数的代码及各个函数的作用,其中的计算公式中使用了大量的常量因子,不同的汽车可配臵不同的参数以产生逼真的效果:
代码清单4-14 Car.js的更新函数
GetInput():得到当前玩家的输入,如前进、后退、左转、右转;
Check_If_Car_Is_Flipped():判断汽车是否被撞翻,如果是的话,使汽车被翻正; UpdateWheelGraphics():根据汽车瞬时速度旋转轮胎; UpdateGear():根据汽车瞬时速度变换档位;
UpdateFriction ():如果汽车在转弯状态,轮胎会受到的侧摩擦力,侧摩擦力和瞬时速度的x轴分量的平方成正比,如公式4-4;
UpdateDrag ():计算当前受到的阻力,阻力和速度的平方成正比,如公式4-4; CalculateEnginePower ():根据当前档位计算引擎提供的动力,如公式4-5; ApplyThrottle ():根据引擎动力使汽车刚体获得向前力模拟油门效果; ApplySteering ():根据引擎动力和玩家的转向输入使汽车刚体获得侧向力模拟转弯效果。
(四) 用户图形界面实现
Unity3D的另一个便利就是强大的插件功能,开发人员可以定制自己功能的菜单栏选项、组件并注册到编辑器中使用。这种设计方式产生了很多第三方插件,使用这些插件可以使开发人员更快速开发需要的功能。
NGUI是Unity3D中最著名的界面插件,其提供了强大的界面组件和相应的类,下
24
华东师范大学学士学位论文 基于Unity的车辆模拟游戏的设计与实现
面主要介绍一些NGUI概念:
UIRoot:任何一个场景中界面根节点,其中至少包括一个UICamera。
UICamera:其本质是一个具有UICamera脚本组件的摄像机,脚本中封装了对其子游戏对象的渲染等功能。
Anchor:用于偏移子游戏对象的布局,如上、下、左、右、中。
Panel:NGUI中的窗口。
Button:按钮元素,可执行OnClick、OnPress、OnRelease等回调函数 Label:标签元素,用于显示文字。
Atlas:为了节省内存中图片和字体的占用量,NGUI可以将字体和小图片生成一
张大图片,Atlas中保存小图的坐标信息,可用于索引到小图Sprite,如图4-15所示:
图4-15 左图为一张Atlas部分截图,右图为一个Sprite的坐标索引
Sprite:其中有两种特殊的类型,同样起到减少资源占用量的目的。
UISlicedSprite将Sprite分为九个切片,每个切片可自由缩放,适合制作边框;UITiledSprite可以进行平铺扩展,如图4-16所示:
图4-16 左图为UISlicedSprite,右图为UITiledSprite
本游戏中要开发主要有两类界面:一类是主菜单界面,例如玩家在启动游戏后需
25