はじめに
自己紹介
初投稿です。
はじめまして、Unityなどで個人開発をしているHIROHIRO(@HIROHIRO1224)と申します。
「rhycol(リコル)」というチームでプログラマーを担当しています。
現在、譜面を作って遊べる音楽ゲーム「Re:Beat」 を開発しています。今後もさまざまな情報を発信していく予定ですので、ぜひチェックしてみてください。
またCAMPFIREにて、クラウドファンディングを2025年7月1日〜8月31日まで実施しております。もし応援したいと思って頂けましたら、ご支援のほどよろしくお願いします!!
(2025/07/01 1:00追記)
㊗️早くも当初の目標金額である100万円突破しました!!ありがとうございます!!!🎉🎉🎉🎉
(2025/07/01 21:00追記)
㊗️なんと!!当初の目標金額の倍になります200万円を突破しました!!ありがとうございます!!!🎉🎉🎉🎉🎉🎉🎉
ストレッチゴールの追加についても現在考えておりますので、今後も皆様のご支援お待ちしております!!
(2025/07/26 20:00追記)
㊗️なんとなんとなんと!!!ストレッチゴールとして用意しておりました、当初の目標金額の3倍になります300万円を突破しました!!ご支援いただきました皆様ありがとうございます!!!🎉🎉🎉🎉🎉🎉🎉
引き続き募集しておりますので今後も皆様のご支援&拡散よろしくお願いします!!!
概要
今回作成したプラグインは、OpenAPI GeneratorをUnityエディタから直接呼び出すことで、API仕様書からC#クライアントコードの生成を自動化するものです。これにより、開発者はUnityエディタを離れることなく、数クリックでAPI連携に必要なコードを手に入れることができます。
作成した背景
以前、 TypeScriptのフレームワーク(Next.jsやNest.js)を使用していた際に、「openapi2aspida」などでOpenAPIに触れる機会があり、その便利さに感銘を受けました。
普段Unityを使っている身として、「どうにかUnityでもOpenAPIを活用できないか」 と考えていました。
そんな中、とりすーぷさん(GitHub)が公開されていたこちらの動画と出会い、入門する上で大変参考にさせていただきました。
ただ、動画を拝見する中で、生成したファイルを手動で移動させたり、Unity上で作業が完結しなかったりと、使用するまでの手順がやや複雑に感じました。
そこで今回は、それらの課題を解決するべく、 自己研鑽も兼ねてパッケージを作成・公開しましたので、ご紹介します。
導入手順
2024年6月現在、 プレリリースのため、うまくインストールできなかったり、動作が不安定だったりする場合があります。
その際は、お気軽にIssueやPull Requestを送っていただけたら大変嬉しいです。
動作環境
- Unity 2021.3 以上
- Docker 28.1.1 以上
インストール方法
GitHubからのインストール方法
1. 「ウィンドウ」→「パッケージマネージャー」を開く
2. 以下のURLをコピーする
https://github.com/rebeat-jp/UnityOpenApiCodeGen.git?path=/Packages/OpenApiCodeGen
3. 左上の+ボタンから「Git URLからパッケージを加える」を選択する
4. 先ほどコピーしたURLを入力して「追加」ボタンを押す
5. インストールされるまで待つ
OpenUPMからのインストール方法
1. 「プロジェクト設定」→「パッケージマネージャー」を開く
2. 以下の画像のようにスコープを登録する
3. 「ウィンドウ」→「パッケージマネージャー」を開く
4. +ボタン横のドロップダウンで「マイレジストリ」を選択し、右上の検索窓に「OpenAPI」と入力して「OpenApiCodeGen」というパッケージを検索する
5. インストールボタンをクリックしてインストールを行う
使用方法
使用前にセットアップが必要ですので、まずはそこから始めましょう。
初期設定
1. 「ウィンドウ」→「OpenAPI Code Generator」→「Setup」を開く
2. 「Provider」で使用するジェネレーターを選択し、Dockerのパスを入力する
Dockerのパス入力欄の下にある「click to check path」ボタンで、Dockerのパスが通っているか確認できます。
ここで使用できるパスかどうかをお試しください。
3. 「Setup」ボタンを押して初期設定を完了させる
もし正常に動作しなくなった場合は、再度初期設定を行うと改善することがありますのでお試しください。
これで下準備は完了です。
それでは、いよいよコードを生成してみましょう。
コード生成
「ウィンドウ」→「OpenAPI Code Generator」→「Generate」を開きます。
すると、画像のようなコード生成用ウィンドウが表示されます。
ここには、生成に必要なAPI仕様書のURLと、それを元に生成されたC#ファイルを配置するディレクトリのパスを指定します。
また、設定画面からデフォルトのURLとパスをあらかじめ設定しておくことで、毎回入力する手間を省くことも出来ます。
ウィンドウのGenerateボタンを押すと…
こんな感じで生成されます!!👏👏👏
また、生成時の細かな構成は設定画面から変更でき、シチュエーションに合わせてカスタマイズすることも可能です。
詳しくはOpenAPI Generatorの公式サイトも合わせてご覧ください。
OpenAPI Generator 公式 C# 生成ドキュメント
制作にあたってのポイント
今回プラグインを作るにあたって、工夫した点をいくつかご紹介します。
1. Editor拡張・UI ToolkitにおけるMVPパターンの採用
今回初めてUnityプラグインを作るにあたり、Editor拡張のUI ToolkitでUI部分の保守性をいかに高めるかを考えました。
Unityのランタイムであれば、UniRxやR3、ZenjectやVContainerなどを用いてMVPパターンを組むのが一般的かなと思います。
ただ、今回はEditor拡張での実装となるため、これらのメジャーなライブラリは用途としてあまり想定されていないのか、簡単には組み込むことができませんでした。(もし知見のある方がいらっしゃいましたら、ぜひ教えてください…)
また、ライブラリを使用すると依存関係が生まれ、柔軟なプラグイン管理を妨げる恐れがあるため、今回はC#の標準ライブラリとUnityのAPIのみで実装することにしました。
実際にUI部分のコードを例にご説明します。
(可読性のため、一部省略している箇所があります。ご了承ください。)
SetupMenu
はUI ToolkitのViewを操作するためのクラスです。
ここでは主に、UIの表示更新やユーザー操作への応答を実装しています。
それに加え、Presenterの初期化とPresenterへのUI登録も行なっています。
public class SetupMenu : EditorWindow
{
[SerializeField]
private VisualTreeAsset? _visualTreeAsset = default;
readonly ISetupPresenter _presenter;
public SetupMenu()
{
_presenter = new SetupPresenter();
}
[MenuItem("Window/OpenAPI Code Generator/Setup")]
public static void ShowExample()
{
SetupMenu wnd = GetWindow<SetupMenu>();
wnd.titleContent = new GUIContent("SetupMenu");
}
public void CreateGUI()
{
// Each editor window contains a root VisualElement object
VisualElement root = rootVisualElement;
if (_visualTreeAsset == null)
{
Debug.LogError("Unset Visual Tree Asset");
return;
}
// Instantiate UXML
VisualElement labelFromUXML = _visualTreeAsset.Instantiate();
root.Add(labelFromUXML);
// UIのフィールドを取得処理
// プレゼンターにインスタンスを渡して登録する
_presenter.Bind(this);
}
void OnSetup()
{
_presenter.Setup();
}
}
ISetupPresenter
はSetupMenu
で使用するPresenterの インターフェース です。
SetupMenuに必要な機能をここで宣言しておくことで、実装クラスを少ないコード変更で差し替えることができます。
interface ISetupPresenter
{
void Bind(SetupMenu setupMenu);
void Setup();
bool CheckRunnableDockerPath();
}
SetupPresenter
ではISetupPresenter
を実装し、ModelとViewの橋渡しを行います。
コンストラクタでModelクラスを初期化し、Bind
メソッドでイベントハンドラの登録などを行なっています。
ModelとViewの橋渡し役として処理を分離させることで、クラスごとの役割がより明確になります。
internal class SetupPresenter : ISetupPresenter
{
readonly SetupModel _setupModel;
SetupMenu? _setupMenu;
public SetupPresenter()
{
_setupModel = new();
}
public void Bind(SetupMenu setupMenu)
{
_setupMenu = setupMenu;
_setupMenu.SetOnChangeHandler((dto) => _setupModel.SetupMenuDto = dto);
_setupModel.OnChangeStatus += (s) => _setupMenu.SetProgressStatus(s);
}
public bool CheckRunnableDockerPath()
{
return _setupModel.CheckRunnableDockerPath();
}
public void Setup()
{
_setupModel.Setup();
}
}
SetupModel
では、入力・変更された値の実体を保持し、ビジネスロジックを実行します。
SetupPresenter
を介するおかげで、Viewを意識することなくロジックの記述に集中できました。
internal class SetupModel
{
public SetupMenuDto SetupMenuDto
{
get => _setupMenuDto;
set
{
_setupMenuDto = value;
OnChangeDto?.Invoke(_setupMenuDto);
}
}
public SetupStatus Status
{
get => _status;
private set
{
_status = value;
OnChangeStatus?.Invoke(_status);
}
}
public Action<SetupMenuDto>? OnChangeDto;
public Action<SetupStatus>? OnChangeStatus;
SetupMenuDto _setupMenuDto = new(GenerateProvider.OpenApi, "");
SetupStatus _status = new(SetupStatusType.None);
readonly IRepository<GeneralConfigSchema> _generalSettingsRepository;
readonly IRepository<OpenApiCsharpOption> _openApiSettingsRepository;
public SetupModel()
{
// プロパティなどの初期化処理
}
public bool CheckRunnableDockerPath()
{
// Dockerのパスが使用可能か確認する処理
}
public void Setup()
{
// プラグインのセットアップを行う
}
}
詳細な処理は省略しましたが、このような流れでUI部分を作成しました。
もしこれよりも良い手法をご存じでしたら、ご教授いただけると幸いです。
2. null安全
C#ではcsproj
ファイルやスクリプトの先頭に#nullable enable
を記載することで、null安全なコーディングが可能になります。
#nullable enable
class Test{
public string? Title
{
get => _title;
set
{
_title = value;
// OnChangedTitleがnullじゃない場合のみ処理が実行される
// また、引数に入れる_titleがnullの場合は”無名”が入る
OnChangedTitle?.Invoke(_title ?? "無名");
}
};
public Action<string>? OnChangedTitle;
string? _title;
}
参照する変数や戻り値でnullの可能性がある場合、コンパイラがそれを通知し、nullだった場合の対処をプログラマーに促します。
これにより、忌まわしき親の顔より見たNullReferenceException
から解放されるのです。
ただし注意点として、VSCodeなどのエディタでは、Null許容参照型に対してオプショナルチェーン(?.)を使い忘れた場合、コンパイルエラーではなく警告として表示されます。
そのため、Kotlinのようにコンパイラレベルでnull安全性が保証されている言語と比較すると強制力は弱く、プログラマーはより一層ログやエディタの警告表示を意識して開発する必要があります。
個人的には、Microsoftさんには今後のアップデートでNull安全性や型安全性をさらに高めていただけると嬉しいですね。(Kotlinのsealed classのような機能も実装してほしいです。)
3. OpenUPMでの公開
今回、GitHubだけでなくOpenUPMでもプラグインを公開しましたが、特に躓くこともなくスムーズに公開できました。
README
やpackage.json
を適切に記載すれば、OpenUPMに自動的にデプロイ・反映されました。
OpenUPMへのプラグイン公開方法については、また別の記事で詳しく書こうと思います。
今後の展望
現段階ではありますが、今後次のような機能追加や改善を考えています。
- Swagger Codegenによるコード生成への対応
- メニュー画面の視認性改善
- Docker以外の生成手段の提供
今後、「Re:Beat」の開発でもこのプラグインを活用し、そこで発見した改善点なども含め、逐次アップデートしていく予定です。
よろしければ皆さんも「Unity OpenAPI Code Generator」をお試しいただき、バグ報告や要望を頂けると嬉しいです。
GitHubでスターを押して頂けると大変励みになります。
まとめ
Unityを数年ほど触れてきた中で、今回初めて触る機能やツールがたくさんあり、私自身にとって非常に学びの多い開発となりました。
これからも自己研鑽を怠らず、「Re:Beat」を筆頭により良いものを作っていけるよう精進します。