ランダムな日本人名を作成したく、姓名データをCSVにしたものはいいものの、Unityで管理できるようにデータベース化したかったためそれをする。
データベースには前回使用したScriptableObjectを利用する。
前回の記事は以下
データベース管理
管理データのCSV化
まずは姓名データを管理するCSVを用意する
→したものがこちら。
姓データにのみ頻出度(Frequency)というパラメータを付けている。
これは有名な苗字(「佐藤」とか「鈴木」)とかは頻出度を高くして、後々名前を自動生成させるときに制御させるために任意でつけた。
構成図
構成はこんな感じ。

今回は姓名データ自体はScriptableObject化せず、CSVからインポートさせるような形式にしてみる
構築
データベース作成
まずはデータとデータベース部分を作成する。
今回は姓名データ自体はScriptableObject化しないため、同じスクリプトファイルに管理するデータ自体も書いてしまう。
NameDataBase.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
[CreateAssetMenu(menuName = "NameDataBase")]
public class NameDataBase : ScriptableObject
{
[SerializeField] public List<LastName> lastNameList = new List<LastName>();
[SerializeField] public List<FirstName> firstNameList = new List<FirstName>();
public void AddNameData(LastName _lastName)
{
this.lastNameList.Add(_lastName);
}
public void AddNameData(FirstName _firstName)
{
this.firstNameList.Add(_firstName);
}
}
[System.Serializable]
public class LastName
{
public string lastnameKanji; // 苗字(漢字)
public string lastnameReading; // 読み方
public int frequency; // 頻出度
}
[System.Serializable]
public class FirstName
{
public string firstnameKanji; // 名前(漢字)
public string firstnameReading; // 読み方
}
データを追加する関数も書いてみた。
前回のデータベースを構築した際もこうすればよかったと反省したため。
どこかのタイミングで作り直すだろうと思いつつ、それは未来の自分にまかせる
[System.Serializable]を指定しておかないとInspector上で表示されないので、ちゃんと管理するデータクラスに付与しておく。
あとはAssetオブジェクトを作成しておくこと。

データ登録スクリプトの作成
データベースを作成したので、次はそのデータベースにデータを登録するスクリプトを用意する。
機能としては
- 名前用、苗字用のCSVファイルを読み込む
- CSVファイルの中身を1行ずつ処理する
- Assetオブジェクト化させたデータベースオブジェクトに対してデータを登録する
CsvImportTool.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class CsvImportTool : MonoBehaviour
{
[SerializeField] private NameDataBase nameDataBase;
[SerializeField] private TextAsset lastNameCsv;
[SerializeField] private TextAsset firstNameCsv;
// Start is called before the first frame update
void Start()
{
SetFirstNameDataBaseFromCsv();
SetLastNameDataBaseFromCsv();
}
/// <summary>
/// CSVから苗字データをデータベースに登録する関数
/// </summary>
public void SetFirstNameDataBaseFromCsv()
{
StringReader reader = new StringReader(firstNameCsv.text);
// 処理行数を管理する変数
int lineCount = 1;
// CSVの中を1行ずつ処理
while (reader.Peek() != -1) // reader.Peekが-1になるまで
{
// 一行ずつ読み込み
string line = reader.ReadLine();
// 1行目の処理(カラム名等)は処理を飛ばす
if (lineCount == 1)
{
lineCount++;
continue;
}
// カンマで区切って配列に入れる
string[] lineArray = line.Split(",");
Debug.Log(firstNameCsv.name + "の [" + lineCount.ToString() + "] 行目を処理中... [" + lineArray[0] + "]");
// データベースに追加
FirstName fstn = new FirstName();
fstn.firstnameKanji = lineArray[0];
fstn.firstnameReading = lineArray[1];
nameDataBase.AddNameData(fstn);
lineCount++;
}
}
/// <summary>
/// CSVから名前データをデータベースに登録する関数
/// </summary>
public void SetLastNameDataBaseFromCsv()
{
StringReader reader = new StringReader(lastNameCsv.text);
// 処理行数を管理する変数
int lineCount = 1;
// CSVの中を1行ずつ処理
while (reader.Peek() != -1) // reader.Peekが-1になるまで
{
// 一行ずつ読み込み
string line = reader.ReadLine();
// 1行目の処理(カラム名等)は処理を飛ばす
if (lineCount == 1)
{
lineCount++;
continue;
}
// カンマで区切って配列に入れる
string[] lineArray = line.Split(",");
Debug.Log(lastNameCsv.name + "の [" + lineCount.ToString() + "] 行目を処理中... [" + lineArray[0] + "]");
// データベースに追加
LastName lstn = new LastName();
lstn.lastnameKanji = lineArray[0];
lstn.lastnameReading = lineArray[1];
lstn.frequency = Int32.Parse(lineArray[2]);
nameDataBase.AddNameData(lstn);
lineCount++;
}
}
}
以下でインポートするCSVと操作(データ追加)するデータベースAssetオブジェクトを指定する
[SerializeField] private NameDataBase nameDataBase;
[SerializeField] private TextAsset lastNameCsv;
[SerializeField] private TextAsset firstNameCsv;
CSVを1行ずつ読み込むのは
while (reader.Peek() != -1) // reader.Peekが-1になるまで
{
// 一行ずつ読み込み
string line = reader.ReadLine();
の部分。
reader.ReadLine()が実行されるとreader.Peekが消費され、残りの行数が0になるまで繰り返す。
あとはCSVファイルを読み込んで、区切り文字で区切ってそれぞれのパラメータをFirstNameクラスおよびLastNameクラスにセットしてデータベースに登録するだけ。
実行する際にはInspectorからCSVファイルとNameDataBaseのAssetオブジェクトを設定しておくこと。
GameObjectにアタッチ
空のGameObject(今回は「CsvImportTool」という名前)を作成して、「CsvImportTool.cs」をそのオブジェクトにアタッチする。
上記した通り、実行する際にはCSVファイルとNameDataBaseのAssetオブジェクトを設定する。
ゲームを再生するとStart()メソッドに書いてある読み込み関数が実行される。
実行結果
実行するとこんな感じ。
ScriptableObjectなので一回登録すれば恒久的に利用できる。
ので、このスクリプトを使うのは一番初めだけ(もしくは後程CSVファイルを再読み込みしたい場合)

あとがき
こういうツール系のスクリプトはStart()に書いてゲーム実行させるよりもInspectorにボタンを追加してそこで実行したほうが便利。(下図みたいに)

【TODO】Editorの作り方も後日整理する