【Unity】東方Projectのキャラクターを網羅したUnityパッケージを作りました

## はじめに
### 東方とは
皆さん、東方Projectをご存知ですか?
ZUN(通称：神主)さんの個人サークル「上海アリス幻樂団」の同人ゲーム、書籍、音楽CDの事です。
20年以上の歴史がある作品であり、キャラクターも150を優に超えています。

魅力について語るとなるとキリが無いですが、この記事で重要な東方Projectの魅力として`二次創作に寛容`というのがあります。
簡単に言うと、最低限のガイドラインさえ守れば東方のキャラや場所を利用して創作物を作れます。
東方二次創作ゲームも数多くあり、例えば筆者個人制作の[東方翠神廻廊](https://play.google.com/store/apps/details?id=com.TD12734.thsuijin&hl=ja)や、企業制作の[東方LostWord](https://touhoulostword.com/)が存在します。

https://play.google.com/store/apps/details?id=com.TD12734.thsuijin&hl=ja

### 東方二次創作ゲームを作る上での問題点
数人の東方キャラだけ登場するゲームは兎も角、翠神廻廊やLostWordのような原作キャラが100人以上登場するキャラゲーを制作する場合は以下の作業が大変です。

- 登場キャラ全員分の列挙型や定数の作成
   - キャラごとにレベルなどを保存する時にユニークな値が必要になります
   - 変数名をキャラの英語名にする場合、名前が英語のキャラの綴りを全員分調べる必要があります
   - 例：Wriggle Nightbug(リグル・ナイトバグ)、Maribel Hearn(マエリベリー・ハーン)
- 登場キャラ全員分の名前を間違えずに入力
   - 東方には難解な漢字を持つ子が結構居ます
   - 例：饕餮 尤魔(とうてつ ゆうま)、宇佐見 菫子(うさみ すみれこ)
- 上記の翻訳
   - 海外人気もあるので、少なくとも英語は欲しいです

上記の問題を解決するためにUnityパッケージを作成しました。

## パッケージの概要
![東方資料包裹](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318712/a8e2414e-6b16-2a6c-168f-f97659d47e37.png)

東方資料包裹(とうほうしりょうほうか)は東方Projectのキャラクターの情報を取得可能なデータパッケージです。

最新作(獣王園)、旧作、書籍のキャラクターまで網羅しています。

霊夢などの各キャラクターについて、以下の情報をソースコード上で簡単に取得可能です。

- 名前
- フルネーム
- キャラクターごとに設定されたユニークな数値と文字列
   - PlayerPrefsやswitch文での分岐などで使えます。

また、名前とフルネームは以下の言語に翻訳されています。

- 日本語
   - 読み仮名、フルネームの読み仮名も取得可能です。
- 英語
- 中国語

## 使い方
https://github.com/TD12734/TouhouDataPackage

上のGitHubのリポジトリから `TouhouDataPackage.unitypackage` パッケージをダウンロードしてください。
その後、Unityプロジェクトにインポートし、以下のusingディレクティブを追加することで `Character` クラスを使えるようになります。

```cs
using TouhouData;
```

詳細は[こちらのREADME](https://github.com/TD12734/TouhouDataPackage/blob/main/DevDocuments/README-ja.md)をご覧ください。

## 使用例

以下のようにenumに近い感覚でキャラクターの名前などの情報を取得可能です。

```cs
Character character1 = Character.Reimu; // enumに近い感覚で代入可能
Character character2 = Character.Reisen;

Character.ChangeLanguage ("ja"); // 言語を日本語に設定
Debug.Log (character1.Name); // 霊夢
Debug.Log (character2.FullName); // 鈴仙・優曇華院・イナバ

Character.ChangeLanguage ("en"); // 言語を英語に設定
Debug.Log (character1.Name); // Reimu
Debug.Log (character2.FullName); // Reisen Udongein Inaba

Character.ChangeLanguage ("zh"); // 言語を中国語に設定
Debug.Log (character1.Name); // 灵梦
Debug.Log (character2.FullName); // 铃仙·优昙华院·因幡
```

以下のように特定の言語の翻訳を直接取得することも可能です。

```cs
Character character3 = Character.Remilia;
Debug.Log (character3.Locales.Ja.Name); // レミリア
Debug.Log (character3.Locales.En.Name); // Remilia
Debug.Log (character3.Locales.Zh.Name); // 蕾米莉亚

Character character4 = Character.Marisa;
Debug.Log (character4.Locales.Ja.FullName); // 霧雨 魔理沙
Debug.Log (character4.Locales.En.FullName); // Marisa Kirisame
Debug.Log (character4.Locales.Zh.FullName); // 雾雨 魔理沙
```

日本語は平仮名の読み仮名も取得可能です。

```cs
Debug.Log (Character.Sakuya.Locales.Ja.NameKana); // さくや
Debug.Log (Character.Nitori.Locales.Ja.NameKana); // にとり
Debug.Log (Character.Alice.Locales.Ja.NameKana); // ありす

Debug.Log (Character.Komachi.Locales.Ja.FullNameKana); // おのづか こまち
Debug.Log (Character.Tewi.Locales.Ja.FullNameKana); // いなば てゐ
Debug.Log (Character.Eiki.Locales.Ja.FullNameKana); // しき えいき・やまざなどぅ
```

キャラクターごとにユニークな文字列(定数)を取得可能であり、PlayerPrefsのキーに使用できます。

```cs
Debug.Log (Character.Reisen.String); // Reisen
Debug.Log (Character.ReisenSecond.String); // ReisenSecond
PlayerPrefs.SetString(Character.Reisen.String + "_Nickname", "うどんげ");
PlayerPrefs.SetInt(Character.ReisenSecond.String + "_Power", 20);
```


ランダムなキャラクターを取得する事や、全てのキャラクターのforループを回す事も行えます。

```cs
Character randomCharacter = Character.Get (Random.Range (0, Character.length)); // ランダムなキャラクター

for (int i = 0; i < Character.length; i++)
{
   Character character = Character.Get (i);
   if (character != null)
   {
      Debug.Log (character.String); // Akyuu, Alice, Aunn, ... , Yuuma, Yuyuko, Zanmu
   }
}
```

以下のようにすればswitch文も使えます。

```cs
Character character = Character.Get (Random.Range (0, Character.length));

switch (character.String)
{
case Character.Strings.Ekisya:
case Character.Strings.Genjii:
case Character.Strings.Rinnosuke:
   Debug.Log (character.FullName + "は男です。");
   break;
case Character.Strings.Singyoku:
   Debug.Log (character.FullName + "は男だったり女だったりします。");
   break;
default:
   Debug.Log (character.FullName + "は女です。");
   break;
}
```

## 動作確認
パッケージをインポートしたらSamplesディレクトリにサンプルシーンやサンプルコードがあります。
サンプルシーンでは以下のような東方キャラの大百科を実装してあります。
![サンプル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318712/306b00b5-3ac8-ee99-0b44-5ea4e0a80c2f.png)

サンプルには以下の機能があり、パッケージの使用感が分かると思います。

- 東方キャラの名前と読み仮名の表示
- キャラ切り替え
- 翻訳切り替え
- 性別の確認(switch文を使用)
- レベルの増加や確認(PlayerPrefsを使用)
- 固定のキャラ(霊夢)のレベルの確認
- ランダムなキャラ(鈴仙)のレベルの確認

なお、東方キャラの立ち絵は規約の問題で添付していないのでご自身で用意してください。
用意しない場合はダミーの棒人間が表示されます。

## おわりに
今まで東方二次創作ゲームを3作制作し、東方キャラごとのユニークな文字列の設定や翻訳はかなり面倒でした。
なので、今回のパッケージを作りました。
これで東方二次創作ゲームの制作が楽になれば嬉しいです。

拡張性を考慮してEnumではなくclassで実装していますが、switch文なども含めて使用する上で不便さは無いと思います。
もし、問題や意見がある場合は[GitHubのIssue](https://github.com/TD12734/TouhouDataPackage/issues)に連絡してください。

<!--

規約

https://assetstore.unity.com/ja-JP/publishing/submission-guidelines

https://docs.unity3d.com/ja/2023.2/Manual/cus-document.html

-->