独立游戏开发中的物理系统
2020-06-10 11:22:55 作者:佚名
作者:王寅寅 注:本文选自机械工业出版社出版的《独立游戏开发:基础、实践与创收》一书的小节,略有改动。经出版社授权刊登于此。 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轴旋转 |
相关文章
-
游戏开发中 实现炸掉一堵墙有多难?
3 02020-05-22 -
《暗黑破坏神4》官推:计划于6月底公布游戏开发新情报
3 02020-05-10 -
捕鱼游戏开发未来前景如何?
7 02020-05-09 -
GameJam 48小时游戏开发技巧与十法则
5 02020-05-07 -
游戏开发那些不能说的秘密
3 02020-05-07 -
游戏开发物语新手问答汇总
9 02020-04-22 -
中国式人生游戏开发教程 游戏开发搭配推荐
5 02020-04-11 -
中国式人生游戏开发教程游戏开发搭配推荐
7 02020-04-11 -
传《使命召唤6:现代战争2重制版》多人游戏开发中
7 02020-04-06 -
网页游戏开发制作需要多少钱?影响开发价格的因素是什么_团队
10 02020-03-25 -
游戏开发框架设计规则!_RegEvent
4 02020-02-28 -
《坎巴拉太空计划2》由T2新工作室接手将专注游戏开发
12 02020-02-21 -
《仁王2》官宣游戏开发完成已进场压盘,3月12日发售
11 02020-02-13 -
这游戏开发6年,耗资上亿美元,如今被玩家和公司彻底放弃?_团队
7 02020-02-10 -
开发感悟:4000小时的独立游戏开发总结《奇幻与砍杀》_steam
9 02019-12-30 -
独立游戏开发入门指南_引擎
24 02019-12-07 -
《黑色未来88》向A9VG的网友们问好 介绍游戏开发历程
13 02019-11-21 -
棋棋俱乐部官方:独特的棋牌游戏开发都具备哪些特点?_玩家
5 02019-10-10 -
腾讯发布《宝可梦》招聘3年以上3A游戏开发经验
18 02019-10-04 -
PS VR问世三年,索尼公布用户行为趋势、游戏开发经验
3 02019-10-01 -
育碧在越南开设手游工作室,将关注H5小游戏开发
11 02019-09-28 -
育碧在越南开设新工作室专注移动端游戏开发工作
8 02019-09-27 -
十分钟看完!干货满满的腾讯游戏开发者大会今年都说了啥?
8 02019-09-27 -
育碧在越南开设新工作室 专注移动端游戏开发工作
6 02019-09-27 -
智能手机不好卖了,游戏开发商跑去做新兴市场的生意
1 02019-09-26 -
2019腾讯游戏开发者大会:What'sNew?
19 02019-09-25 -
《星战绝地:陨落的武士团》制作人:游戏开发即将完工
19 02019-09-24 -
腾讯云、腾讯游戏学院发起“源+联盟”扶持游戏开发者
26 02019-09-23 -
悠闲时刻,关于游戏开发的书籍——四网通(物联卡)
19 02019-09-21 -
区块狗现成源码搭建,区块猫区块猪,区块宠物养成游戏开发可换UI页面
11 02019-09-20 -
君子剑科技浅谈棋牌游戏开发趋势及未来走向
3 02019-09-15 -
棋牌游戏开发需要哪些技术支持
6 02019-09-14 -
这款游戏开发了4年,现放出实机试玩,看懵现场上千名玩家
20 02019-09-12 -
迪士尼宣布将出售旗下最后一家大型游戏开发商
25 02019-09-11 -
晓风棋牌游戏开发的几大优势
2 02019-09-10 -
地方棋牌游戏开发要做好产品的差异化
3 02019-09-09 -
地方棋牌游戏开发要做好产品的差异化
10 02019-09-09 -
在棋牌游戏开发技术中不可缺少的元素有哪些?
18 02019-09-09 -
做棋牌游戏需要注意什么?什么样的棋牌游戏开发公司靠谱?
4 02019-09-09 -
棋牌游戏开发行业有哪些你想不到的猫腻
2 02019-09-08 -
棋牌游戏开发要做到哪些才能吸引客户?
21 02019-09-08 -
棋牌游戏开发的准备工作
4 02019-09-08 -
棋牌游戏开发的详细步骤
2 02019-09-08 -
定制棋牌游戏开发
0 02019-09-08 -
想找到有实力的棋牌游戏开发公司?这三点一定要知道!
3 02019-09-07 -
棋牌游戏开发哪家好
2 02019-09-07 -
决定棋牌游戏开发价格的因素有哪些?
2 02019-09-07 -
棋牌类游戏开发和运营,有必要做前期“市场调研”吗?您知道吗?
1 02019-09-06 -
游戏开发巨头汉化版
0 02019-09-06 -
中央棋牌游戏开发是你的选择之一
4 02019-09-06
234游戏网站地图
子站导航 |
|||