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

程序员有二十年 2024-09-18 10:35:01

前言:本文章教程,结合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项目

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

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

把Ruby图片拉到Art文件夹下

可以拖动到场景内

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

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

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

进入项目配置项里面

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

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

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

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

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

把步长距离设为1

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

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

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

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

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

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

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

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

打开调色板

新建的调色板进行命名

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

把前面的Tile拖入调色板

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

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

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

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

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

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

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

选择3*3

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

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

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

快速选择、移动操作。

快速平铺操作

快速填充

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

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

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

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

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

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

引入一个立方体

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

打开项目设置

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

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

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

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

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

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

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

最终效果

立方体场景内的也设为Pivot

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

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

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

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

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

然后把Ruby也设为预制体。

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

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

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

给Ruby也提供碰撞器

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

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

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

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

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

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

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

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

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

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

现在配点场景

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Clamp方法说明:

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

Mathf.Clamp 方法有三个参数:

value: 需要被限制的值。

min: 允许的最小值。

max: 允许的最大值。

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

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

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

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

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

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

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

Health控制器当前代码如下

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

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

然后新增碰撞器和触发器

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

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

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

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

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

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

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

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

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

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

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

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

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

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

设置轴心点等调整

修改碰撞器大小

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

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

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

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

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

0 阅读:0

程序员有二十年

简介:感谢大家的关注