独立游戏开发中的物理系统

摘 要

作者:王寅寅 注:本文选自机械工业出版社出版的《独立游戏开发:基础、实践与创收》一书的小节,略有改动。经出版社授权刊登于此。 Unity物理系统更准确的叫法应该是物理引擎

  作者:王寅寅

注:本文选自机械工业出版社出版的《独立游戏开发:基础、实践与创收》一书的小节,略有改动。经出版社授权刊登于此。

独立游戏开发中的物理系统


Unity物理系统更准确的叫法应该是物理引擎(Physics Engine),该引擎是采用NVIDIA的PhysX物理引擎实现的,为避免与游戏引擎本身的名字冲突,本书还是称其为物理系统。所谓物理系统,是指在游戏对象上实现加速度、碰撞、重力、摩擦力及各种外力作用的一系列功能集合。Unity物理系统又分为2D和3D两种类型,两者在使用上大体相似,主要区别是3D物理系统多了一个维度。

Unity物理系统没有总开关,只要在游戏对象上附加并正确设置了物理组件(如Rigidbody、Collider、Joint、Effector等组件),即使用了物理系统功能。下面我们继续开发案例游戏,并基于物理系统实现主角的移动、跳跃、自由落体及更复杂的碰撞检测等功能。

游戏对象调整

对于Road,我们需要将其调整为一个有一定距离且主角可以站立的路面。首先将Road的Sprite Renderer组件Draw Mode属性选择为Tiled(在该属性下,图像会根据游戏对象尺寸自动填充,就像连续的瓦片一样),然后在场景中拖曳Road的左右边框(需要确保工具栏中的变换工具为Rect Tool状态),适当增大其宽度后即可得到一个连续的路面。接下来调整碰撞器范围,在Box Collider 2D组件中单击Edit Collider按钮后,碰撞器范围即进入可编辑状态,调整完后再次单击Edit Collider按钮即可。我们还需要取消碰撞器的Is Trigger属性,以保证主角与路面的碰撞不可穿透,此时尽管Road并未附加Rigidbody 2D组件,但它相当于一个Static状态的刚体。另外,之前的Road脚本已经不适用了,我们将其对应脚本组件从检视窗口移除,并将该脚本文件从项目窗口删除即可。如图1和图2所示:图1展示了检视窗口中Road的相关组件情况,标注框中为相关的调整项;图2展示了Road在场景视图中的情况,注意其碰撞器范围是一个极细的矩形绿色框(图中可能不容易看出来,请读者结合实际操作查看),我们将该范围上边框调整在Road高度二分之一的位置,对应马路中央,也是游戏角色的水平落脚点。

独立游戏开发中的物理系统

图1    Road游戏对象相关组件情况


独立游戏开发中的物理系统

图2    调整后的Road游戏对象


注:在图1中,有一个三角形警告符号,其内容提示我们:当前本Sprite图像资源的导入设置可能会造成Tiled模式下的绘制错误。但很明显,我们这里并未出现绘制错误,笔者在实际工作中也尚未遇到过此类错误,忽略该警告即可。或者,可在该Sprite的图像资源导入设置中,将Mesh Type属性设置为Full Rect以消除该警告。

对于Player,我们需要让其拥有重力以及合适的碰撞范围。首先将Rigidbody 2D组件的Gravity Scale属性设置为4,以接受该值大小的重力等级。接着重新选择碰撞器,由于主角有一个近似圆形的外观,因此可用圆形的Circle Collider 2D组件替换Box Collider 2D组件,并适当调整其范围大小,如图3所示。

独立游戏开发中的物理系统

图3  调整后的Player游戏对象


对于RoadBlock,可用类似方法调整其碰撞范围并删除RoadBlock脚本即可,具体步骤这里不再赘述。

渲染顺序修正

我们先运行游戏,可以看到主角会因重力向路面下落,最终被错误地显示在马路后面,如图4所示。要修正此问题,我们需要了解下Sprite Renderer组件的Sorting Layer与Order in Layer属性:Sorting Layer属性中可添加一系列特定名称的排序分组,Unity将按照组顺序依次渲染其中的Sprite;当多个Sprite同属一个Sorting Layer分组时,则可通过Order in Layer属性的值大小来决定它们的渲染顺序。

值得注意的是,Soring Layer与Layer虽然只差一个单词,但在Unity中它们是两个不同的概念,可阅读书中第5章中有关Layer的简要介绍。另外读者应知晓,Sprite Renderer组件功能不属于物理系统功能。

下面,我们开始调整Sorting Layer与Order in Layer。首先,在Sorting Layer中添加一个Player分组:任意选择一个游戏对象,在检视窗口中单击Sorting Layer属性右侧的Default按钮,并在展开的下拉列表中选择Add Sorting Layer选项,即可打开标签与层的有关设置,其中,Sorting Layers栏下默认仅有一个Default分组,右下角的加减号(“+ -”)可增减分组,拖曳左侧的等号(“=”)则可调整组顺序,这里我们添加一个Player分组,并保持现有顺序即可。然后为Player的Sprite选择该分组:单击Player游戏对象,直接将其Sorting Layer属性右侧的选项选择为刚才添加的Player分组即可。接下来,Road与RoadBlock之间同样需要调整渲染顺序:将RoadBlock拖曳到Road上,可看到错误的前后关系,此时保持两者的Sorting Layer同属默认Default分组,我们保持Road的Order in Layer属性为0,再将RoadBlock的Order in Layer属性设为1,即可修正渲染顺序(RoadBlock为0,Road为-1也可以)。图5展示了调整后的运行效果。