【Unity】手把手入门2D游戏开发教程——小狐狸的冒险(上)

前言:本文章教程,结合Unity官方教程和网上其他资源教程进行整合,目的是让大家可以更快速地上手,减少大家观看比较理论的教程或者视频时长偏长的教程的时间。‍‍‍‍‍

本文章参考了以下有关文献或内容:

SIKI视频教程:Unity2D 官方入门案例 - Ruby's Adventure:

https://www.sikiedu.com/course/650

Unity官方文档教程:Ruby's Adventure:2D 初学者

https://learn.u3d.cn/tutorial/unity-ruby-adventure

如果感兴趣官方教程,或者视频教程,可以参考以上两个教程入口。如果喜欢快速上手体验,那观看我下面的亲自动手实验的部分,也许会更快捷。

本篇为前半部分基础内容,包括:控制角色的移动、脚本组件开发、Tilemap使用与地形绘制、地形碰撞器、物理系统(碰撞器、刚体组件等)、角色的回血与掉血触发、预制体等。

接下来正式开始我们的创作旅程。先创建一个2D项目

4e631cc54dbbb504dd592daa399f2c5c.png

导入有关资源包。资源包我直接在siki的免费课程里面下载。资源链接:https://www.sikiedu.com/course/650/task/53225/show

资源包内包括了官方提供的免费的Ruby狐狸以及其他有关资源内容,用于在这个项目上进行实操使用。

92fd44b18202ded722552d4998aa56dc.png

把Ruby图片拉到Art文件夹下

d1b0f7314b6b3e29887e9dae482b4629.png

可以拖动到场景内

4b334aeeed17c36dbea25842de7c2364.png

选中Ruby,可以看到图片格式自动被转换为 2D and UI 格式。

31d363899338cfd24d32abf8e2bac071.png

新建脚本文件夹 Scripts,在里面新增一个脚本 RubyController

456feb27cf49689353e2ba27eae63821.png

把脚本丢Ruby控件属性内,成为它的一个组件。

c10649b7900dc07db72259bde592bfd5.png

进入项目配置项里面

8f0a123980bd73354508a1d1ae689dba.png

输入管理器里面,可以设置一些参数。这些参数也可以被用代码进行获取,例如水平和垂直参数。

2bc4262e5a5a2c14b145ccf5ddb7f03c.png

双击前面的C# 脚本代码打开,新增一些代码,如下图。用于操作主角移动,并且使用Time.deltaTime来实现平滑移动。

8e5bd792982438a8966a010aab744906.png

deltaTime解释,可以参考GPT说明:

c92725202fa3e57793e5060fcde8fa8f.png

2D的帧率默认是60FPS,可以通过启动时候修改帧率。正常情况下不需要更改。以下只是示例。

32eec697955ff35b27b597fc8e6bf846.png

场景移动时候,可以预设步长,步长设置,在场景内工具栏,点开,有一个 Increment Snapping

d794efde81b02cb7716e806c3660a38e.png

把步长距离设为1

58224da703cda8c66e0beaff0a220958.png

测试下效果,环境里面随便拖入一个进去,然后Ctrl+d复制一个,再Ctrl+鼠标拖动,可以看到自动移动1个单位(一个格子长度),自动对齐。

71ae8e559339f176aacc9f093cfeaabb.png

移除上面的测试,新增一个Tilemap

0e315ba7e44133488c4b2311d4180101.png

会自动创建一个Grid,Grid下面自动会有一个Tilemap

Grid可以用于将游戏对象均匀分布在网格内;Timemap是网格地图,由Tile(瓦片)组成

884ca3e5726e25ad19f855ec59caf296.png

Assets下新建一个Tiles文件夹,然后在文件夹内新建一个Tile,重命名为FirstTile

a18fa448f27b56ed59ee823177f5c18b.png

d5d9d67cf2a71804d04961773bb555e1.png

把资源里面的Tile图片,拖到环境目录下

9aa2dd8c827b605ac0122b2554459aaa.png

然后给Tile设置精灵(Sprite),把Tile图片资源对象拖过去即可。

5dc7f5c879bcdcae98dc970ab5529fd1.png

选中Hierachy的Tilemap,然后在场景上面工具栏内,找到Tile Palette 来打开调色板

1bee31890486d6e3072c6e9de3585f5a.png

打开调色板

7f0055c3022e7b9241313d188075091e.png

新建的调色板进行命名

4b148c5391557049864bfd9cc6c47824.png

创建时候会提示保存路径,选择Tiles文件夹

929fcb1fa9f9fd18d5c6ff9a1b5112a3.png

把前面的Tile拖入调色板

8b992eac1b8f928014a7c03f6c9f1009.png

选中笔刷,就可以根据指定的Tile,来刷存在感,例如在上面场景内可以随意刷,例如刷个Wesky

77133093241ebac82b1c35b79953bdb7.png

资源里面的Tile属性,有一个每单位100像素点。

2e7c33514c2ecdb78bd63d779cea385d.png

但是下面的图片资源大小,是64*64的,所以上面粉刷场景时候,遇到了填充不满的情况。

d847ebc13b1d4ef0fd705b6f983d5a86.png

把每个单位100像素,改为64像素,应用以后,就可以看到场景内的空隙就没掉了,不会留下空白了。

779e1cbc100b3807ae4b9e119747993f.png

选择环境下的floor几个文件,一起选中,然后精灵模式设为Multiple

982aa153babd1615101a588cf91eba86.png

选择第一个图,打开编辑器

824977260155fa75edd6134a49d4b9e8.png

然后选择Slice,选择Grid By Cell Grid

2cc59c137a25366dd390be8a059e6289.png

选择3*3

3d7a35a77a54ddc28c53012beeaa9458.png

然后就可以发现可以展开,里面有9个图案

b9587470bfdf645ec0c3d5c115c84505.png

然后继续对其他五个进行同样的拆分。

完了以后,对所有6个资源,拖入到调色板内。如果提示保存路径,就保存到Tiles文件夹内。如果资源显示的不是填满状态,则跟上面一样的方式,修改对应的单元像素点数量。

96f7b0977779a13750105ff50fc23232.png

快速选择、移动操作。

2e1ff3f438a8728bdede67ebb4fd7bdd.png

快速平铺操作

f19d4aa7df2d656e21bd9526c97321af.png

快速填充

814148d41983855088a074ecb415bc13.png

在Tilemap进行操作,点击Edit按钮即可。没点击,只能对场景内进行操作。

bc9068bdb4857c08ff879f000d870303.png

回到Hierachy目录下,可以看到Ruby、Grid、Tilemap的属性里面,坐标也包括Z轴,虽然是2D,但是实际上Z轴是我们正视的方向。所以也存在层次。如果都是0,Unity也会存在渲染先后问题,有可能导致需要显示外面的,因为先渲染,所以就被覆盖的情况。

b007fe5814caaceba4cc259c68f9bdc4.png

取消2D勾选,可以看到实际上就是一个3D场景。只是摄像机一直保持正视。

67e0d3c213f2e7530ec36b507b026ab8.png

可以修改Z轴来显示不同层级,但是毕竟是2D项目,这样做不太友好。所以有一个层级的概念。order by layer,数值越大,渲染越晚,以此来达到分层次渲染来显示的目的。

a868711829735d2c62d572ca6413bb6f.png

例如tilemap,地面一般是最底层,此处假设设为-10

e737fe360b9ec337a9f2887bad202973.png

然后Ruby本身可能是隐藏的,现在就出现了

0374a3c2b46002b6c770aec77a73a041.png

引入一个立方体

73d2519e49aa49e71503b72aebafaa7d.png

这个时候发现,Ruby爬到箱子上面穿过,这个不太符合正常规律。

b45f6f7523dc5103fc240618471082f9.png

打开项目设置

7ad61076e0c76239aa35d72ef0d716b0.png

Graphics下面的Camera设置,把模式设为自定义

e120c7681ca950e985a0d3cdd8d28622.png

把Y轴设为1,其他为0,代表按照Y轴渲染进行排序

126497c0e9a5d536595f788d038bcd08.png

此时,可以看到Ruby不会跑到箱子上面了。

9e16a611f083b5f8438af7565cc99bcd.png

不过此时,角色穿过以后,会发现身体部位,有的在箱子一边,有的在另一边,穿模了。那就继续改。Ruby觉得属性的Sprite Sort Point把默认的Center改为Pivot.如果是center,说明轴心点是中心点,所以是以中心点进行判断的,就可能存在身首异处。

2889cc7ce05f7388053364684098d1d4.png

环境资源内,把箱子的属性Pivot也设为底部

e77c3ab18412b40e2504c318f88f44fb.png

打开Ruby资源的属性,再打开精灵编辑器

7be6c1b4a2fcdd807530e6dc6b743726.png

对Ruby进行设置,让她轴心在脚下,以及形象大小设为合适的图片,防止周边空白太多,影响后续操作。

306dfc517f689014abc3344d2373e2cf.png

最终效果

2d4b29f6906860c35afc18f06a49ba8d.png

立方体场景内的也设为Pivot

a10fbd3801b849b411c3b3dc764f4339.png

为了方便后续操作,此处把箱子作为预制体。方式:场景的箱子,拉到资源下面,就可以变成预制体了。预制体,可以用于,在预制体内修改,使用预制体的场景内容,都会同步更新。

f90197771be5a44807431e80482fbc35.png

箱子的精灵编辑器打开,也对它的轴心点进行更改

6ac292e95acc2c0076da669df92cd756.png

设置好以后,现在看Ruby,可以发现穿越自然很多了

c599dc55044b170ee7e3a4c4a6a54d2b.png

虽然穿越自由了,但是实际上的世界,是不允许穿越的。所以接下来要添加刚体组件和碰撞器来实现不穿模。

给角色添加RigidBody 2D刚体组件。

684678352f3d4f429e7a2fed98c013fd.png

然后把Ruby也设为预制体。

设为预制体完成以后,先启动看下带上刚体组件的效果。发现Ruby走向了深渊,受到重力影响。

da73b8144fe3b53d3f4687ef57cbd987.png

2D这个不需要重力,所以需要把重力系数改为0.数值指的是重力的倍数。

6409dd6d479924826ca65070bd58084e.png

对箱子新增碰撞器 Box Collider 2D,一般对运动的物体需要提供刚体组件,给静止物体只提供碰撞器。如果需要碰撞的两方,都需要有碰撞器。如果运动的物体不提供刚体组件,“可能”导致碰撞失效。

2e664108f54f1cdfdda7e47218d7f5a3.png

给Ruby也提供碰撞器

557f7a8163dfa9ef5a4e0c610e3ab17a.png

然后选中箱子,看下资源是不是存在超出碰撞范围的设置。编辑碰撞器

2fe2d26e1755f4746f04fe8c22e4c11e.png

把超出范围的部分,进行调节

87a81e8a9b8f7f532079e6ac6464126e.png

然后把场景内的更改,应用到预制体内

8f9e3c87897b7d5bbc10bee613a146c9.png

对Ruby也做同样的调整和应用

8ae16893e9855327ad67b6135a86adb8.png

现在启动程序,可以看到还有bug,存在角色抖动和旋转问题。

045bad4083cd5b1097a6a2fba19b5028.png

刚体组件内冻结角色Z轴旋转

b01b64f83796e7a919852437e1806f24.png

接下来解决Ruby抖动问题:刚体组件检测到Ruby和箱子重叠,把Ruby移出碰撞器外;但是人工按键控制Ruby移动,又会导致Ruby进入,从而导致角色抖动。修改代码,最后通过刚体.MovePosition来移动到指定位置

fcb836de30c3820704257a089285ebee.png

继续修改箱子碰撞器,把碰撞范围缩小。不然角色到达箱子边缘就会被挡住了。

2cff3d69ac74e3277dd62e4b876562a4.png

对角色也要做调整,调整到脚底区域。调整完毕记得应用到预制体进行覆盖。

bb60ad86b212c59c618d5ad0974ab7da.png

现在可以看到,角色遇到箱子可以正常了,不会抖动,也不会旋转了。

4e2b7ad7c637f2f6d1e5d29b1d9b090f.png

现在配点场景

f8aec9e1e2f215bb729bff1f980dd6ee.png

运行会发现,角色会掉河里。

2304aabf720205d9373abdb1082e3247.png

需要控制角色不掉河里,并且支持快速操作的方法,使用Tilemap碰撞器。Tilemap新增Tilemap 2D碰撞器。

6c3c413f0678c792ed7bbde45147f439.png

选中资源下面tiles文件夹内除了带河流的所有资源,然后把碰撞类型,统一设为None。原先布局看不到缩略图,所以布局可以自己调整一下。

cf8a5134087f5049963adbdb0dbb461b.png

启动测试过程省略,可以看到不会掉河里了。但是还存在一个问题是,看到河内碰撞器太多,对资源是一种浪费。

bfd8d3ac71e8288db403600cec4764e8.png

对Tilemap新增联合碰撞器组件 Composite Collider 2D

94fe313d035d59d2bcedf88068d84299.png

然后,回到tilemap的2D碰撞器,把Composite Operation设置为Merge。其他几个选项说明如下:

  • None: 不进行任何合并操作。每个Tile都将保持其单独的Collider。

  • Merge: 将相邻的或重叠的Colliders合并成一个大的Collider。这通常用来减少物理计算的复杂性和提高性能。

  • Intersect: 只保留重叠部分的Collider。这种操作较少见,但可以用于特定的碰撞检测逻辑。

  • Difference: 从一个Collider中减去与另一个Collider重叠的部分。这可以用来创建复杂的碰撞形状。

  • Flip: 这个选项并非标准的合并方式,可能用于反转Collider的合并逻辑,但在标准的Unity文档中并不常见,具体效果可能取决于具体的实现。

84bc39225783241569851b98c3a2c717.png

这个时候,可以看到场景内的碰撞器网格被合并在一起,形成一个大的碰撞器了,减少了不必要的纹路。

63475515ec14263caa53e0fa13173855.png

接着再把Tilemap的刚体组件的Body Type类型设置为静态 Static。三种状态说明如下:

  • Dynamic: 这是最常用的选项,使物体受到所有物理效果的影响,包括重力和碰撞。动态物体可以自由地移动和旋转,并且它们的行为将由力、扭矩和外部影响(如碰撞)决定。

  • Kinematic: 运动学物体不受力和碰撞的影响,但可以通过改变其位置和旋转来影响其他的动态物体。通常用于控制物体的运动,如平台或由代码驱动的物体,而不是通过物理引擎自然响应力。

  • Static: 静态物体基本上是不移动的物体。它们不会因为受力而移动或旋转,但可以用来作为场景中的不动障碍物或地面。例如,墙壁和地板通常设置为静态,因为它们不需要移动也不受重力影响。

01cce110f1bd4b49f7f53ff2f82c1b4d.png

给Ruby设置初始化的生命值、以及定义最大生命值。

37fa74773211494e4dfa2d4daf510a69.png

新增一个更新生命值的方法

10ce730471ee014fc27c1dca52339593.png

Clamp方法说明:

用于限制一个值使其保持在指定的最小值和最大值之间。这个方法确保了变量的值不会超出设定的范围,这在游戏开发中非常有用,比如控制角色的位置、设置摄像机的视角边界等。

Mathf.Clamp 方法有三个参数:

  1. value: 需要被限制的值。

  2. min: 允许的最小值。

  3. max: 允许的最大值。

带入上面的代码,如果_currentHealth+value小于0,Mathf.Clamp会返回0;如果大于_maxHealth,它会返回_maxHealth;如果在0和_maxHealth之间,它会返回_currentHealth+value的值。

继续优化其他代码,用于方便操作.

75b3b5a5420e9fe7b88fc854d44222ff.png

8c320efe10900c0e3a95d88ee0c7eaf0.png

新增草莓控件,用于给角色不满血状态下,恢复血量使用。

c7b0d3beffbb33839fe9d509bf8c9eaa.png

给草莓添加碰撞器,并且勾选触发器。

ad08d5cb647cd963ae3cc13b6cdc24f4.png

接着新建一个草莓的脚本代码,例如 HealthController.然后挂载给草莓控件,当做草莓的一个组件。

a1b819acdf4b59cd4dde3bb025394997.png

这个时候,触碰草莓应该是穿过去的,不会有效果。所以新增一个进入草莓刚体组件时候的方法,方法自带,我们只需要写内容即可。

740f9a72c6b6dd67f019aff559572d55.png

ruby里面新增一个属性,用来只能获取当前生命值的用途

a34f1234874df644a343348f6139af27.png

Health控制器当前代码如下

da780aaadfee9e6b23f4d746d75a9331.png

这个时候,如果血量不满,就可以吃掉草莓。但是如果血量是满的,就会穿透。具体演示就不放了,大佬们到这儿应该差不多都可以自己玩了。

接下来,继续添加伤害区域

ec05099fa2433e27fae45b6253340409.png

然后新增碰撞器和触发器

0e9fde1ab988e4cb6b52c096e4a2f10a.png

新增伤害区域脚本,并绑定给伤害区域控件

0441418d500ba6bd955495c8c6266d98.png

ruby里面新增一些属性和方法,用于让ruby在伤害区域内,可以持续性掉血

ea2cd092dad3a972960a4a7edca9612b.png

一些无敌时间的设定,让Ruby不会瞬间挂掉;以及定时操作的设定。

02245a7d6b632569692f5f13aece1bdf.png

现在把ruby的刚体组件休眠关闭,防止ruby休眠(导致碰撞效果失效)

aeec3c360a3562ea3f5565cdda131c99.png

伤害资源里面,把Mesh类型设置为 Full Rect

917563c7c4e491051dc2f1b34ecad284.png

然后把控件的Draw模式设置为Tiled. 三个选项含义分别是:

  • Simple - 这个选项通常表示对对象的处理保持基本和简单,没有复杂的变化或额外的图像处理。

  • Sliced - 这通常用于处理需要九宫格缩放(9-slice scaling)的图像。这种方法可以让你的图像在拉伸时保持边缘和角落的完整性,常用于UI元素如按钮和面板。

  • Tiled - 这个选项允许图像在空间中重复平铺,而不是拉伸。这适合那些需要在较大区域内保持图案一致性的纹理或图像。

719d76ff17027f1abfac3573507ca0eb.png

TileMode选择适配器模式,可以在缩放时候自适应

4fec833b97af99d3f6198d8fd6bd064b.png

Auto Tilling勾选以后,碰撞器也会自动跟随物体拉伸而同步拉伸

6005d3efa6f616e884da008e0217ee4e.png

添加机器人,并添加碰撞器

2910e4f15d7e1d1fa94ab9332d6f9a92.png

再新增刚体组件,重力0,冻结Z轴

388d90c6ff890ae0874c6cba1d2a517a.png

机器人资源,Pivot设置为自定义

be36debecb94011e0f80757658611d40.png

设置轴心点等调整

d3d775074c03d1b8a7c0c0d39e723ed4.png

修改碰撞器大小

15c1a040f7d31d390cd488202d62c0cf.png

新建机器人脚本,然后挂身上

f2bdf172c854aec455690996fb979a8a.png

机器人脚本编辑,有关具体内容如下。

2c966fcbd088dd5640230b90cae4dbc6.png

当前运行效果如下。观察当前血量,满血吃不到草莓;碰到机器人,血量-1,再返回去,就可以吃掉草莓,然后回血。

9b5f833154d297329465b8655adf090f.png

由于篇幅限制,后半部分,后续择时再发布。后半部分内容前瞻:包括动画设置、粒子效果、虚拟相机、武器开发、UGUI、射线检测、音效、打包与发布等。

如果觉得我的教程比其他教程看起来更加方便、快捷,或者对你有帮助,欢迎点赞、转发或在看。感谢各位观众捧场!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值