4K音游制作
Foreword
Just as I mentioned last time, I need more practical experience. Therefore, based on Unity
and C#
, I have decided to create a rhythm game.
Nowadays, there are many types of rhythm games in the market. One type is no-key rhythm games, such as Phigros
and Rizline
. Another type is multiple-keys rhythm games, such as Kalpa
and Muse Dash
. There is also a type of rhythm games called emergence rhythm games, such as Cytus
and 阳春白雪
. In addition, there are many games that mix multiple elements from the above types, such as Arcaea
and maimaiDX
. Considering the difficulty and time cost, I have ultimately chosen 4K rhythm games as my goal.
介绍
顾名思义,4K(即4 keys)音游,一共包含四个轨道。在每个轨道会有音符下落,游玩者需要在音符到达判定线处点击。每次点击后会进行判定,点击越精准评级也就会越高。以我曾常玩的游戏 Malody 4k
为例,游戏游玩界面如下:
基于此,我们来对整个制作过程的思路进行梳理。
首先,音游程序可以大致分为四个部分,即谱面读取、触控输入、游戏控制器和键型四个部分。对于每个部分,我们再来进行详细的解析。
程序梳理
谱面读取
首先,在玩音游的第一步必然是谱面的读取,读取完谱面后才能有接下来的展开。对于谱面的读取,我们可以从以下三个方面来考虑:
- 读取谱面文件
- 解析数据并储存
- 初始化
于是,我们完成了谱面读取的初步分析。
键型
在这里我们先来讨论一下键型。在4k中,我们仅仅使用 tap
和 hold
。其中最主要的就是 tap
,由此我们才分生出各种叠、切、乱、锚键、多押等等键型。当然 hold
也会用到,不过就没有 tap
那么频繁,一般在恶心的面条谱里、休息段以及低dan谱中会遇到较多。因此,我们考虑这两种键型:
- tap:点击即可
- hold:点击后需长按,直至结束
触控输入
基于上面的键型,我们来讨论触控输入。我们可以分成三类,分别是输入信息、分析方法和输出信息。首先,玩家触碰屏幕时,我们就来判断触碰的位置信息和状态信息。判断位置信息即判断你是否碰到了这个音符对应的位置,状态信息即判断你是否正确打击了对应键型。
随后,我们来分析玩家的输入。分析方法分为两种,一种是点击,即手指点到屏幕那一刻的手势;一种是触摸,就是手指在屏幕上的手势。
最后就是输出了。最后判定是点击还是触摸即可。
游戏控制器
经过梳理,我们可以总结如下:
- 谱面读取(可以独立出去)——加载谱面,初始化关卡,设置游戏开始
- 每一帧都记时
- 如果到了对应的时间,就生成谱面对应的音符
- 如果游戏开始,且音乐已经播放完毕
- 结束游戏
由此,我们给出了一个大致的思路框架。我们仍需对特定对象进行细化。比如音符、判定器等。
音符
在4k中,音符(note)呈下落式。因此,我们让音符在每一帧都移动,由此来模拟下落。如果进入了自己的时间判定区域,就执行如下代码:
每一帧都检测自己是否被点击(或者对应的手势)
如果被点到,就消除自己,并且生成点击特效(也可以辅以音效
,比如でらっくす)向判定器发送被点击的时间
判定器
用来计算点击的评价,显示评价的结果、更改分数、combo数等等,可以集成在控制器里。
由此,我们的大致框架已经完成,我们来进行下一步。
Unity的使用
我这边安装了Unity
的 LTS
版本,以及 VS 2022
。接下来,就可以着手开始了~
新建项目完成后,点击右上角的灰框,切换至 2 by 3
模式。这样就能同时打开场景编辑器和游戏视角两个视窗。
随后,我们来添加背景,即创建轨道。这也是每一个note得以下落的基础。在经过一系列的调整以及摄像机位置的调整后,成功实现了背景的搭建:
随后,我们在 Assets
文件夹下,创建 Scripts
文件夹,用来存放我们的 C#
代码。
首先,我们需要处理触控输入部分。在 Unity Manual
中,我们用 touch
作为关键词进行搜索。尽管结果众多,但不难发现,Touch.phase
和 Touch.position
使我们需要的。我们可以看见,旁边写到:
Touch.phase
:描述触摸阶段Touch.position
:触摸在屏幕空间中的位置