RPG 游戏开发(16)文字系统 1
欢迎来到第五部分——文字系统。在这个部分,我们将会实现一个悬浮文字。大概说一下这个部分的学习内容:
对象池:这是一种设计模式,因为我们有多个文字需要显示,所以在每次显示一个文字都创建一个 Game Object 再销毁,对系统性能消耗挺高。所以我们将创建几个 Game Object,当需要显示文字的时候,就激活这个 Game Object 让它显示在屏幕上,否则就让它休眠。
文字系统需要比较多的逻辑:
需要显示的文字
被激活了没
显示在界面上的时长
显示在界面上的位置
有没有动画效果
字体颜色和字形
所以我们需要创建一个新的脚本,用于编写文字的逻辑代码。脚本名称为 FloatingText。这个脚本是专注于文字的逻辑类代码。
编辑代码,这次我们不需要继承 MonoBehavior 类。首先我们引用 UnityEngine.UI 命名空间(using 语句)。然后里边定义六个成员变量(变量用途我都写在代码注释了)。
然后我们定义两个函数,Show 和 Hide,Show 显示函数将 isActive 设置为 true,然后更新 lastShown 时间,最后再把该 gameObj ...
RPG 游戏开发(15)PlayerPrefs
上篇文章,我们写好了 GameManager 的基础架构,然后今天我们来完善 SaveState 和 LoadState 函数。
Awake 函数首先我们修改一下 Awake 函数,在 Awake 调用的时候,需要判断 instance(也就是 GameManager 对象)如果不是空的,则删除该 GameObject,然后直接跳出函数。如果是空的,则将这个 GameManager 对象指向 instance 变量(就是上章说的自己指向自己)。
为什么判断 GameManager 对象是否为空?因为如果我们回到同一场景(比如说从 Main 去到 Dungeon1 再回到 Main),这样就会出现两个 GameManager 了。所以我们需要判断,如果 instance 不为空,就代表已经有一个 GameManager 存在,那么就删掉这个新的冲突的 GameManager。
还有一种解决方式是:我们将这个 GameManager 提取出来单独放在一个 Scene 里(比如说加载界面)而这个 Scene 只会被调用一次。那么就能解决这个BUG。
引用 UnityEngine.SceneM ...
RPG 游戏开发(14)GameManager
前面三个部分,我们已经把游戏的基本内容做好了(角色移动、场景设计、碰撞触发某些功能)。现在,我们需要给游戏打上地基,让游戏可以保存玩家信息——金币、经验值、武器等……
那么我们在 Scripts 文件夹里创建一个新的脚本 GameManager,Unity 默认会将此脚本的图标变更为齿轮状。双击编辑它。首先,我们定义一个 instance 变量,类型是 GameManager(也就是我们现在创建的脚本),修饰符为 public static。修饰符是 static,这意味着这个变量是全局的。我可以在任何一个类访问 GameManager.instance 来访问到这个 GameManager
我们让游戏的 GameManager 自己获取自己,所以重写 Awake 函数,内容是 instance = this。意味着这个类的 instance 对象指向他自己。
using UnityEngine;public class GameManager : MonoBehaviour{ public static GameManager instance; private ...
RPG 游戏开发(13)传送门
哈喽大家好,还记得我们在设计第一个地图(有箱子的那个)时画了个凸起的地方吧?这次我们会在那里放置一块碰撞体,当玩家走过去之后,将会被传送到 Dungeon1 场景。
我们在 SampleScene 的 Hierarchy 面板中,右键创建一个 Game Object 并命名为 Portal(传送门),给其新增 BoxCollider2D 组件,调整它的位置。强迫症,所以我将这个 GameObject 的位置修改为 X = 0,Y = 1.36,Collider 的 Offset 设置为 0,Size 为 0.48 和 0.16,都是 8 和 16 的倍数。
创建一个新的脚本(Script),命名为 Portal,然后将其拖拽到我们刚刚创建的 Game Object(Portal)里。双击编辑该脚本。因为是传送门,我们不需要从它这儿获取到什么东西。所以它的继承应该是 Collidable。
重写 OnCollide 方法。我们要实现的逻辑是,当玩家踏入这个区域时,随机传送到一个地牢里。
定义一个字符串数组,里边保存了需要传送的场景名称。在 OnCollide 函数里,当玩家碰撞到之后, ...
RPG 游戏开发(12)触碰箱子获取金币
这篇文章我们将继续完善箱子功能。但在此之前,我们需要在 Collidable 类和 Chest 类中增加一层 Collectible 类(原先是 Chest 类继承了 Collidable 类;现在是 Chest 类继承 Collectible 类,Collectible 类继承 Collidable 类)。因为之后会有一些物体是碰撞之后,被玩家捡起来的。
添加这层继承关系是因为,假如之后我们有武器了,当武器挥动的时候,应该是碰撞(Collidable)处理而非获取(Collectible)处理。而箱子则是获取(Collectable)处理。
所以,修改之后代码如下:
Chest.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Chest : Collectable{ protected override void OnCollide(Collider2D collider) { Debug.Log(col ...
RPG 游戏开发(11)CSharp 继承
大家好啊,上个文章我们做了个基本的碰撞触发事件,但是只是输出了个 Debug.Log 那么这一章我们将详细地说怎么去实现一些效果,比如打开箱子获得物品。
那么首先我们就需要到我们的 Atlas 图块里把箱子的像素图切出来。打开 Sprite Editor,开始干活!首先,我们把之前弄好的褐色木箱子改名为 crate,而找到宝箱,他有六个图,我们选两个(一个空的,一个满的)使用即可。将满的命名为 chest_0,另一个为 1。裁剪好了之后点击 Apply。
然后将 chest_0 图块从 Project 面板拖到游戏场景 Scene 中随便一个位置(注意,不要贴着墙壁,因为墙面有 Collider 演示的时候会造成混淆),这时候你会发现只有一个框框,宝箱没看见。这是因为它的 Sorting Layer 在 Default,被地板当着了,所以我们新建一个 Sorting Layer 命名为 Interactable,将他的位置放在 Floor 和 Actor 之间,也就是在视觉效果里,看见该箱子在地板之上,在角色之下。
我们给 chest_0 添加一个 BoxCollid ...
RPG 游戏开发(10)可碰撞物体
欢迎来到第三部分。这一部分我们将设计一些可以让玩家碰撞之后与其交互的物体。在开始之前,我们打开 Scene 文件夹,然后双击开回 SampleScene 场景(记得先保存 Dungeon1 场景)
我们需要创建一个名为 Collidable 的脚本(Script),这个脚本是放在非玩家单位(如NPC,可破坏物品)的,当玩家触碰到拥有 Collidable 脚本的物体时,将会触发某些设定好的行为。
在 Scripts 文件夹里右键点击 Create / C# Script 创建脚本,将其命名为 Collidable 然后打开文件。
编程首先我们声明三个变量:
ContractFilter2D 是 public 修饰符,意味着我们可以在 Unity 的 Inspector 面板中对其进行调整。它用于过滤需要检测的游戏物品。
BoxCollider2D 用于获取当前游戏物体(也就是被挂上此脚本的物体)中的 BoxCollider2D。我们之后需要对这个 BoxCollider2D 进行操作。
Collider2D 数组用于保存 BoxCollider2D 所碰撞到的所有物体。Collide ...
RPG 游戏开发(9)创建地牢
我们需要创建一个新的场景(Scene)来创建地牢。先保存现在正在编辑的场景,然后同时按下 CTRL + N ,选择 2D 场景创建一个新的场景。然后 CTRL + S 保存场景,我将其命名为 Dungeon1,保存在 Scenes 文件夹里。
选中 Main Camera 物件,将其 Size 属性调整成 1。
创建 2D Object / Tilemap / Rectangular 物件,将其命名为 Floor,并把 Grid 的 Size 属性 改为 0.16。
这样,我们就有和上一个场景一样的设置了。
接下来,我们点击 Floor,给其绘制地板地图。绘制完成之后,效果如下:
在 Grid 物件中右键,新建 2D Object / Tilemap / Rectangular 物件,命名为 Other。这个将用作绘制地牢装饰物(如墙体之类的)。开始绘制墙壁,我们还加了个回复泉水。效果如下:
然后再用深色块吧其他位置补上,让玩家看不到蓝色的背景。修改之后如下:
然后再创建一个 2D Object / Tilemap / Rectangular ,将其命名为 Collision。L ...
RPG 游戏开发(8)绘制地图
上篇文章,我们把调色板做好了。这时候点击调色板的画笔工具(注意,不要在 Edit 模式下点击)然后将鼠标放到 Scene 面板上,可以看到图块可以被画到游戏界面上。可是很奇怪,好像画面上只能放置几个图块,然后感觉图块之间的间隔特别大。
这是因为我们导入这个图集(Atlas)的时候,设置的 Pixel Per Unit 是 100,所以代表一个方块有 100 × 100 个像素点。可是我们的图块实际上只有 16 × 16 个像素点。
在 Hierarchy 面板中,点击 Grid 然后在其 Inspector 面板中的 Cell Size 属性值里 x 和 y 分别写上 0.16(我们在设镜头设置那篇文章中有提到过)。这是因为图块定义 100PPU,可实际是 16PPU,所以 16 / 100 = 0.16。调整完之后,就可以顺利在界面上进行绘制了。
我们在 hierarchy 面板中创建的 floor 图层用于放置作为背景的图块(例如地板),我们还可以另外添加如 wall、accessories 图层。并且对某些图层设置碰撞体,使角色不能通过该碰撞体或者触发陷阱。
回到 Tile P ...
RPG 游戏开发(7)创建 Tile Palette
本来这篇文章需要推迟发布的……因为最近正在考虑入手工作机,刚刚都一直在挑选电脑。但是已经跟各位读者约定日更2篇了,只能硬着头皮冲!
上个教学,我们搞了一堆地图块,现在我们要将其转换成 Tilemap 以便我们可以用画笔的方式直接把图块画上去制作地图。
在上方菜单栏点击 Window / 2D / Tile Palette,弹出 Tile Palette 面板。因为要一直用到 Tile Palette 所以我们将他的面板固定在某个比较容易使用的位置。通过点击 Tile Palette 标签,可以直接拖动面板,将其放置在所需的位置即可,我们放在如下位置:
然后我们在 Hierarchy 面板中右键,2D Object / Tilemap / Rectangular 创建 Tilemap,然后将其命名为 floor(不是命名 Grid 而是明明 Grid 的子组件)。然后我们点击刚刚命名的 floor 组件,可以看到他有个 Tilemap Renderer 的元件。里面有个属性是 Sorting Layer。是不是感觉似曾相识?之前我们在设置角色被地板当着的时候有用到这个属性。当时我们没有 ...