在上一篇文章中,小编为您详细介绍了关于《steam每日特惠:《欧陆风云4》今日史低22元》相关知识。本篇中小编将再为您讲解标题独立游戏开发中的物理系统。
作者:王寅寅 注:本文选自机械工业出版社出版的《独立游戏开发:基础、实践与创收》一书的小节,略有改动。经出版社授权刊登于此。 ![]() 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展示了调整后的运行效果。 ![]() 图4 错误的渲染顺序 ![]() 图5 修正的渲染顺序 基于物理系统的移动 这里我们修改PlayerController脚本,将当前基于Transform组件的移动替换为基于物理系统功能的移动,如代码1所示。 代码1 PlayerController.cs
上述代码中的GetComponent是一个泛型方法,用于获取已附加组件,尖括号内为该组件的具体类型,这里我们获取Player的Rigidbody 2D组件,并由body变量引用。velocity是Rigidbody 2D组件中一个属性,代表当前刚体的移动速度,我们把一个匿名二维矢量赋值给它,即可实现刚体速度驱动游戏对象的移动。在这个匿名二维矢量中,X维度值即左右方向键输入值与speed变量的积,Y维度值则对应刚体当前在该维度应有的速度(也就是说,我们仅控制水平速度,而不直接控制垂直速度,垂直速度将由外力实现,例如,下落时由物理系统重力产生向下的速度;跳跃时由人物跳跃力产生向上的速度)。 注:对精准名词解释一下,velocity表示速度,speed表示速率。速度是有方向和大小的矢量,而速率是没有方向的值。在没有特别说明时,本书把两者都称为速度。 基于物理系统的跳跃与碰撞 我们继续编写PlayerController脚本代码,为主角添加跳跃能力,并使用更复杂的碰撞检测来判定其是否站立在地面上,如代码2所示。 代码2 PlayerController.cs
在上述代码中,我们新增了onGround与jumpPower变量,并使用了OnCollisionStay2D与OnCollisionExit2D方法。onGround变量是一个布尔值,用于说明主角是否站立在地面上(或其他可站立物体上),当该值为真时,我们使用GetAxis("Vertical")获取上下方向键输入值,并在输入值大于0时(向上的方向)调用AddForce方法在刚体上增加一个瞬时的力,该力是一个匿名二维矢量,作为参数传递给AddForce方法,我们这里只需要一个向上的力以产生向上的速度,因此该二维矢量的X维度值设为0,Y维度值则设为代表跳跃力大小的jumpPower变量。 OnCollisionStay2D方法会在Player始终与碰撞对象接触时连续执行,我们使用它检测主角是否站立在地面上,其中,contactCount属性保存了Player与某个碰撞对象之间碰撞点的数量(多数情况下为1),我们用cnum变量保存该数量,并结合for循环与GetContact方法遍历所有的碰撞点;contact变量则用于依次保存遍历结果,每一个碰撞点都有一个normal属性,该属性是一个法线向量(这里该向量是一个长度为1,并与Player碰撞点切线垂直的二维向量),当该向量Y维度值为1时,Player的碰撞点必然在正下方,即站立在地面上。这里我们将该值的判定标准设为0.8,以考虑碰撞点稍稍偏离正下方的情况。OnCollisionExit2D方法会在Player脱离任意碰撞时执行,我们直接在其中将onGround变量赋值为假,即说明Player处于悬空状态。 若此时运行游戏,主角将会以滚动方式移动,这不是我们想要的效果。可在Rigidbody 2D组件中展开Constraints选项并勾选Freeze Rotation Z属性以解决此问题,如图6所示。最后在检视窗口的Player Controller脚本组件中,为Speed与Jump Power属性分别设定一个合适的值(这里我们设定为3和150),即可运行游戏测试最终效果。 ![]() 图6 在Rigidbody 2D组件中锁定Z轴旋转 |
编后语:关于《独立游戏开发中的物理系统》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《幸福工厂Steam版存档在哪里 存档转移方法介绍》,感兴趣的同学可以点击进去看看。
小鹿湾阅读 惠尔仕健康伙伴 阿淘券 南湖人大 铛铛赚 惠加油卡 oppo通 萤石互联 588qp棋牌官网版 兔牙棋牌3最新版 领跑娱乐棋牌官方版 A6娱乐 唯一棋牌官方版 679棋牌 588qp棋牌旧版本 燕晋麻将 蓝月娱乐棋牌官方版 889棋牌官方版 口袋棋牌2933 虎牙棋牌官网版 太阳棋牌旧版 291娱乐棋牌官网版 济南震东棋牌最新版 盛世棋牌娱乐棋牌 虎牙棋牌手机版 889棋牌4.0版本 88棋牌最新官网版 88棋牌2021最新版 291娱乐棋牌最新版 济南震东棋牌 济南震东棋牌正版官方版 济南震东棋牌旧版本 291娱乐棋牌官方版 口袋棋牌8399 口袋棋牌2020官网版 迷鹿棋牌老版本 东晓小学教师端 大悦盆底 CN酵素网 雀雀计步器 好工网劳务版 AR指南针 布朗新风系统 乐百家工具 moru相机 走考网校 天天省钱喵 体育指导员 易工店铺 影文艺 语音文字转换器