自作音ゲーの譜面データについて悩む


結論

とりあえず今回はテキストデータと譜面データとして使用したいので↓の中から知っていて使いやすそうなcsvで対応させることにしました

.txt
.html
.htm
.xml
.bytes
.json
.csv
.yaml
.fnt
Unity テキストアセット

前提

音ゲーはノーツと呼ばれる判定を音楽を聴きながらリズム良く押すことによって得点が加算されていきます

ノーツを呼び出すタイミングを記したファイルを譜面データと言います
譜面データにはノーツのタイミングの他にノーツの種類や、速度などを埋め込んだりします

タイミングについて

タイミングを呼び出す方法は2種類あると思います
時間指定か小節指定です
※他にもありそうだったらコメントください

小節指定のjson

最初は小節指定のjsonファイルを作ろうと考えていました

notes{
[[ノーツの種類,ノーツのレーン,速度][ノーツの種類,ノーツのレーン,速度]]//1小節目
[ノーツの種類,ノーツのレーン,速度]...//2小節目
}

のように生成しようとしていました

メリット

・小節ごとの管理が楽

デメリット

・bpmが変わる曲は作りにくい

何故使わなかったか

jsonファイルをforやforeachで回すのが難しかった

jsonは[key:value]のように値が存在しており

{notus:
[key:value,key:value],
[key:value,key:value],
[key:value,key:value]}

のように作ることができます
valueを取り出してノーツを生成します

//jsonファイルの読み込み
var textAsset = Resources.Load("譜面.json") as TextAsset;

var jsonText = textAsset.text;
JsonNode json = JsonNode.Parse(jsonText)

//jsonを辞書に入れる
Dictionary<string,object> dic_json = json["notes"].Get<Dictionary<string,object>>();
foreach (var notes in json["notes"])
{
    long note = notes["note"].Get<long>();
    for (int i = 0; note > i; i++)
       //インスタンスからノーツを生成
    }
}

※うろ覚え
これの悪い点はnoteに入っている総ノーツ数がずれるとノーツの呼び出しがされなくなること
また、foreachで変数に追加して呼び出すと

[0:1,1:1,2:2]

のようにリストで出てくるので割とめんどくさい
そして、ここではJsonNodeを使ってますが、Unity標準のJsonUtilityを使うと型を作らないといけないので音ゲーのようなデータの最大量が変わるものには向いてません

時間指定のCSV

csvは0行目に曲情報、その後ろにノーツ情報を追加しました
ノーツの情報の詳細は

ノーツの種類(番号),ノーツのレーン,ノーツが来る時間,ノーツの速度(元bpm* 基本的に1)

です

メリット

・実装が簡単
・拡張性がある

デメリット

・譜面制作の難易度が激ムズ

//ファイル読み込み
csv_read("../譜面.csv");

music_name = csvDatas[0][0];
bpm = float.Parse(csvDatas[0][1]);
all_notes = int.Parse(csvDatas[0][2]);
offset = double.Parse(csvDatas[0][3]);
//インスタンスをリストに追加
GameObject_all_notes.Add(new GameObject[]{ notes1, notes2, notes3, notes4, notes5 });
for (int i = 1; i < csvDatas.Count; i++)
{
    _type = int.Parse(csvDatas[i][0]);
    _lane = int.Parse(csvDatas[i][1]);
    _time = float.Parse(csvDatas[i][2]);
    _speed = float.Parse(csvDatas[i][3]);
    Generate =  GameObject_all_notes[int.Parse(csvDatas[i][0])][int.Parse(csvDatas[i][1])];

    Generate.GetComponent<notes>().set_up_notes(_time, _speed);
    Instantiate(Generate, new Vector3(Generate.transform.position.x, Generate.transform.position.y, Generate.transform.position.z + (_speed * public_speed * 10) * _time), Quaternion.identity);
}

これは現在使っているコード(の簡略版)
こちらは割と拡張性もあり簡単のノーツを生成することができるのでよき
ただし、インスタンスを生成する際にノーツのスピードとタイミングを計算しないといけないのでそこだけ注意

ついでにオブジェクトの加速度を切らないとだんだんズレます