前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Unity】手把手入门2D游戏开发教程——小狐狸的冒险(上)

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

作者头像
Wesky
发布2024-09-19 19:22:46
1090
发布2024-09-19 19:22:46
举报
文章被收录于专栏:Dotnet Dancer

‍前言:本文章教程,结合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 方法有三个参数:

  1. value: 需要被限制的值。
  2. min: 允许的最小值。
  3. 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、射线检测、音效、打包与发布等。

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Dotnet Dancer 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档