Odin でコンテキストエディター作ってみた
Odin でプランナー向けのコンテキストエディターを作った話
こんにちは!パン君です。
インディーズのプロジェクトで Odin Inspector を使用して、
プランナーが Unity の知見をあまり持っていなくても触れるような プロジェクト専用の「コンテキストエディター」 を作成しました。
ここでいう「コンテキストエディター」は、
「ゲーム内の◯◯に関係するデータを、ひとつの画面でまとめて編集できるツール」
のイメージです。
- キャラやステージのパラメータ
- 掲載テキストや説明文
- 報酬テーブルやフラグ設定
など まとまりとして扱いたい情報を、一箇所から編集できるようにした という話になります。
概要
もともとプロジェクトでは、データ構造を ScriptableObject や CSV で管理していましたが、
- 「どのデータがどこにあるのか」が分かりづらい
- パラメータを変えるために 何個もアセットを開く必要がある
- プランナーが Unity の Project ウィンドウを漁るのに時間がかかる
という課題がありました。
そこで、
「◯◯の仕様を触るときは、とりあえずこのウィンドウを開けばいい」
という 専用の編集画面(コンテキストエディター) をOdinで作りました。
やったことをざっくりまとめると:
- Odin の
OdinEditorWindowを使って 専用ウィンドウを作成 - プランナーが触る想定の ScriptableObject をまとめてバインド
- 絞り込み・検索・ボタン操作などを Odin の属性でサクッと実装
- 「触ってはいけない項目」は ReadOnly / Foldout / Box などでガード
という構成です。
やりたかったこと
このコンテキストエディターでは、主に次のような体験を目指しました。
1. 「どこを触ればいいか」が一目で分かる
- プランナーが Unity に詳しくなくても、
- 左側にカテゴリー
- 右側に編集する内容
- という形で、「エクセルを開く感覚」でパラメータを触れるようにしました。
具体的には:
- セクションごとに
FoldoutやTitle属性で区切る - 「ゲーム内に表示される文言」だけをまとめた枠を用意
- 管理用の ID や内部フラグは ReadOnly で表示のみ
など、Odin の装飾系属性をフル活用しています。
2. 関連データを横断して編集できる
たとえば「◯◯イベント」のコンテキストだったら、
- イベント全体の基本設定
- 各ステージの難易度テーブル
- 報酬テーブル
- ガイド用のテキスト
など、別々の ScriptableObject に分かれている情報を、 1つのウィンドウに並べて編集 できるようにしました。
Odin の InlineEditor や TableList を使うことで、
- 参照先の ScriptableObject を、その場で展開して編集
- 配列・リストをテーブル形式で編集
といった UI を、カスタム EditorWindow 側に貼り付けることができました。
3. 安全な範囲だけ触れるようにする
- プランナーには見えてほしいが、触ってほしくないフィールド
- 開発途中で変更すると危険なフラグ
こういったものは、
ReadOnly属性でロックHideIf/ShowIfでそもそも見せないInfoBoxで注意書きを出す
などの工夫を入れて、 「自由度は残しつつ、壊れにくい UI」にする ことを意識しました。
実装構成
技術的な構成は、おおよそこんな感じです。
1. ベースとなる Window クラス
OdinEditorWindowを継承したContextEditorWindowを用意MenuItem属性でメニューから開けるようにする
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEngine;
public class ContextEditorWindow : OdinEditorWindow
{
[MenuItem("Tools/Context Editor")]
private static void Open()
{
GetWindow<ContextEditorWindow>("Context Editor");
}
// プランナーが触る対象をここに並べる
[Title("イベント基本設定")]
[InlineEditor(Expanded = true)]
public EventConfig eventConfig;
[Title("ステージ設定")]
[TableList]
public StageConfig[] stages;
[Title("報酬設定")]
[TableList]
public RewardConfig[] rewards;
// 必要なら、検索・フィルタ用のフィールドもここに置く
}ウィンドウを開くだけで
- 指定したScriptableObjectの中身が 同じ画面 に展開される
- その場で値を編集、ほぞんが 反映される
という状態にできます。
2. ScriptableObject側の設計
もともとのデータ構造をScriptableObject化しておけば
- プロジェクト全体では通常通りScriptableObjectとして利用
- 編集時だけコンテキストエディターのウィンドウからアクセス
という二重の使い方ができます。
例えば :
[CreateAssetMenu(menuName = "Game/Event")]
public class EventConfig : ScriptableObject
{
[LabelText("イベント名")]
public string eventName;
[LabelText("開催期間")]
public string durationText;
[LabelText("説明文")]
public string description;
[LabelText("有効フラグ")]
public bool isEnabled;
}これを先ほどのContextEditorWindowのフィールドとして参照しておけば、
ウィンドウ側でInlineEditorしたときに、 Odinのデコレーション込みで表示されます 。
3. ちょっとしたUX改善
例:
- 「選択中のステージだけテストシーンを起動する」ボタン
- 「報酬テーブルをデフォルト値で初期化する」ボタン
- 「特定 ID のデータを検索してフォーカス」ボタン
Odin の Button 属性を使えば、EditorWindow 内にメソッドをそのままボタンとして出せるので、 ちょっとしたツール感を簡単に足せます
実際に運用してみて
実際にプランナーに使ってもらって感じたメリットはこんな感じでした。
- 「この仕様を触りたいときは、このウィンドウを開けばいい」という入口が固定された
- Unity の Project ウィンドウや Inspector をさまよう時間が減った
- パラメータの更新とコミュニケーションのログが取りやすくなった(「この画面のここを変えました」と言いやすい)
- 誤操作されると困る部分は最初からロックしておけるので、事故が減った
一方で、課題としては:
- コンテキストエディター自体のメンテナンスコストが発生する
- データ構造を弄るときは、Editor 側の反映も忘れないようにする必要がある
- UI を作り込みすぎると「専用ツール」になりすぎて、柔軟性が落ちる
といった点もありました。
最後に
Odin を使ったコンテキストエディターは、
- 「プランナーが直接触れる Unity ツール」を作りたいとき
- 「プロジェクト専用の編集画面」をサクッと用意したいとき
にかなり相性がいいと感じました。
Inspector 拡張だけでは足りないけれど、EditorWindow をフルスクラッチするのは大変
というケースでは、Odin の属性と EditorWindow を組み合わせるだけで、
「ちょうどいいライン」のツールが作りやすいです。
今後は、
- もう少し UI/UX を整理したバージョン
- 別プロジェクトでも使い回せるような抽象化
にもチャレンジしてみたいと思っています。
興味があれば、別の記事で具体的なコードや属性の使い方も掘り下げていくので、また読んでもらえたら嬉しいです。
コメントを読み込み中...