本文へスキップ
SheetForge

シート構文

SheetForge のシートは自己記述的です。列 A はマーカー専用に予約されており、実際のデータは列 B から始まります。行はその位置ではなくマーカーによって識別されるため、コメント行をどこに挿入しても壊れることはありません。

既存のスプレッドシートを流用するには、データの手前にマーカー列を一つ挿入し、三つのマーカー行を追加してください。既存のデータ列はそのままで構いません。

マーカー(列 A)

列 A意味
#コメント行 — 完全に無視され、ラウンドトリップ時にはそのまま保持されます。
@nameフィールド名の行(列ごとに一つの名前)。
@typeフィールドの型の行。
@desc説明の行 — コード生成がこれを XML ドキュメントコメントとインスペクターのツールチップに焼き込みます。
@overlap(任意) 列ごとの重複ポリシー — true(許可、デフォルト) / false(値の一意性を強制)。
@style(任意) シート表示メタデータ — このシートのグループラベルと色。下記参照。
@enum(任意) シート全体をデータテーブルではなく enum 定義 としてマークします。下記参照。
@loc(任意) シートを ローカライズシート としてマークします——各列のセルが、その列のロケールコードを指定します。下記参照。
@yourMarker(任意、プラグインによる登録) カスタム構造マーカー — 下記参照。
(空)データ行。
  • @name@type@desc必須 です。@overlap@style、および任意のカスタムマーカーは任意です。
  • マーカー行は、データ行より上にある限り、どの順序で並んでいても構いません
  • 未知の @markerエラー となり、最も近い候補が提案されます(「@desc の間違いではありませんか?」)。登録済みのカスタムマーカーも、この提案の候補に加わります。
  • @name/@type のヘッダーがない列にデータがあるのは エラー です(孤立データガード — サイレントなデータ損失は決して許されません)。

例(列 A | B | C | D として表示):

#        | Item definitions — hand-edited by design team
@name    | codeName      | displayName | price
@type    | RecordId      | string      | int=10
@desc    | unique key    | shown in UI | shop price (gold)
         | item.sword    | Sword       | 120
         | item.potion   | Potion      |

(item.potion の空の price セルは、明示的なデフォルト値 10 として実体化されます。)

型システム

どの型も自己記述的です——読み手は @type セルだけを見れば、その列が何を保持しているかが分かります。

表記意味
int float bool string組み込みのスカラー型。
Enum<DamageType>C# の enum — enum シートで定義する(下記参照、コード不要)か、プラグインが登録します(EnumRegistry)。メンバー名が検証され、タイプミスには最も近い候補が提案されます。
List<T>リスト — 要素の区切りは ;、各要素はトリムされ、空の要素 はエラー、空のセル は空のリストになります。
RecordIdこのタブのキー列 — 文字列による自己識別子(例: item.sword)。常に必須のスカラーです。推奨される列名: codeName
IntIdこのタブの副次的な整数キー — タブごとに最大一つ、必須のスカラーで、ランタイム/セーブデータ/バックエンドの id 用です。推奨される列名: id。タブは RecordIdIntId、またはその両方をキーにできます。
RecordId@EffectsEffects タブ内のレコードへの参照 — 整合性が検証されます(対象タブが存在するか、キー列を持つか、id が解決できるか。タイプミスには提案が出ます)。
IntId@EffectsEffects タブ内のレコードへの 整数キーによる 参照 — RecordId@Effects と完全に対等です。同じ方式で整合性が検証され(対象タブが存在するか、IntId 列を持つか、id が解決できるか)、見つからない場合は最も近い 整数 の候補が提案されます。値は int.ToString で正規化されるため、手入力の 0077 として解決されます。
AssetRef@IconsAddressables グループ Icons 内のアセットへの参照 — カタログに対して存在が検証されます。サブアセット(テクスチャ内のスプライトや、フォント内のマテリアルなど)は parent[sub] としてアドレス指定されます——これは Addressables がサブオブジェクトエントリに与えるアドレスで、例えば atlas[sword] のようになります——そしてこのキーによって検証・ベイク(SubObjectName)・エクスポートが行われます。
AssetRef@Icons<Sprite>同じ参照を 一つのアセットタイプに制限した もの: アドレスは、そのアセット自体——またはそのサブアセットのいずれか——が Sprite として読み込める場合にのみ通過します。タイプ名には、プロジェクトが認識している UnityEngine.Object 派生のアセットタイプ(エンジン組み込み・自作を問わない)を書けます: 該当するタイプが一つだけなら短縮名を、それ以外はフルネーム(MyGame.ItemData)を書きます。コード生成は AssetReferenceT<Sprite> を出力します。<…> を付けない AssetRef@Icons は無制限のままで、AssetRef<Sprite>@Icons は正しい綴りの候補付きで却下されます。詳しくは下記の型付きアセット参照を参照してください。
LocRef@Stringsローカライズシート Strings 内の ローカライズキー への参照——RecordId@Tab と同じように整合性が検証され(存在確認、最も近い候補の提案、リネーム時の伝播、ピッカー、ドロップダウン)、そのエントリのソースロケールのテキストをインラインでプレビューします。対象タブは @loc を持っていなければならず(そうでなければ LocRefTargetNotLocalizationSheet)、@Target を伴わない素の LocRef は却下されます。List<LocRef@Strings>LocRef@Strings? はいつもどおり組み合わせられます。コード生成は素の LocRef 構造体を出力します——ローカライズシート を参照してください。
Color · AnimationCurve · Gradient組み込みの 視覚的な値の型。それぞれがコンパクトなテキスト形式(下記)を持ち、Data Studio とウェブアプリはそれを生のテキストではなくネイティブのカラー・カーブ・グラデーションエディターで編集します。コード生成は UnityEngine.Color / AnimationCurve / Gradient フィールドを出力します。
Modifier (例)プラグインが登録するカスタムセルタイプ(プラグイン作成 を参照)— 例えば、サンプルの stat:op:value というミニ文法。CustomType@Target も登録だけで機能します。プラグインが IReferencingCellType を実装すると、その列は RecordId@Target とまったく同じように振る舞います——検証、候補提案、名前変更への追従、描画、選択のすべてが同じ方式になります。
Pair<T> (例)プラグインが登録する ラッパー型 — 複数の内側の T 値を一つのセルに詰め込む汎用の値の形 MyWrapper<T>(例: Pair<int> = 1~2)。内側の型は再帰的に解決されるため、Pair<RecordId@Effects>Pair<Enum<DamageType>>、入れ子の Box<Pair<int>> はすべて動作します。プラグイン作成 を参照してください。

<>@ は異なる意味を持ち、共存します。<> = 種類/ラッパー(組み込みの List、またはプラグインの MyWrapper<T>)、@ = 参照先です。したがって List<RecordId@Effects> は参照のリストであり、Pair<RecordId@Effects> は二つの参照を詰め込みます——どちらも Effects タブへの参照です。整数キーも同じように組み合わさります: List<IntId@Effects> は整数キー参照のリストです。

ラッパー型(MyWrapper<T>)

プラグインは ラッパー を登録できます——外側の構文(区切り文字、要素数)を自身が持ち、内側の型は Core に委ねる、汎用の値の形です。ラッパーはどんな内側の型とも組み合わせることができます。その内部にある参照も、検証、キー名変更時の伝播、タブ名変更時の書き換えが行われます(完全なパススルー)。

却下ルール(List と整合しています):

表記許可される?理由
Pair<RecordId@Effects> · Pair<Enum<E>> · Box<Pair<int>>はいスカラー、参照、enum、または別のラッパーに対するラッパー。
List<Pair<int>>はい複合値のリスト。ラッパー自身の区切り文字は ;(リストの区切り文字)とは異なる必要があります — これはプラグイン作成側の責任です。
Pair<List<int>>いいえリストはラッパーの 内側 に置くことはできません(List は常にフラットかつ最も外側にあります。List<List<T>> と同じルールです)。
Pair<int>@Effectsいいえラッパーは値の形です。@ は代わりに内側の末端に置いてください(Pair<RecordId@Effects>)。
Pair<int?> · Pair<int=1>いいえ省略可否/デフォルト値はフィールドレベルの表記であり、内側の型の一部ではありません。

必須・任意・デフォルト値

表記意味
float(無印)必須 — 空のセルはエラーになります(サイレントな汚染は入口でブロックされます)。
float?任意 — 空のセルは 型のデフォルト値(0)として実体化され、IsDefaulted フラグが立ちます。対象は四つのスカラー(int / float / bool / string)、および三つの視覚型です: Color? → 透明な黒 #00000000AnimationCurve? → キーを持たないカーブ、Gradient? → 白いグラデーション `#FFFFFF@0,#FFFFFF@1
RecordId@Effects? · IntId@Effects? · AssetRef@Icons?任意の参照 — 空のセルは 空参照(「何も指さない」状態)として実体化され、対象タブ/グループは保持されたまま、セルには IsDefaulted フラグが立ちます。これは壊れた参照ではありません——参照整合性とアセットキーの検証はこれをスキップし、キャンバスはワイヤーを描画せず、@overlap も二つの空参照を重複として数えません。値が 入っている セルは、これまでどおり検証されるため、任意列でのタイプミスも引き続き検出されます。
RecordId@Effects=同じことを明示的に書いたものです: 空の 明示的デフォルトは、上記の素の ? と等価です。空でない デフォルト(RecordId@Effects=fire)は、引き続き解決され、整合性チェックも受けます。
int=1明示的なデフォルト値 を持つ任意 — 空のセルは 1 として実体化されます。
List<T>空のセルは常に許可されます(空リスト)。

?受け付けられない 理由は常に同じです: Core は無から値を作り出すことができないため、そうした型には明示的な =default が必要になります。これには次が該当します:

  • Enum<T>?
  • プラグインのカスタム型 — Modifier?(Modifier@Tab? を含む)
  • ラッパー — Pair<int>?

キー列が除外されているのは別の理由からです——空のキーは重複を生んでしまうためです。そのため RecordId?(キーなしの自己識別子形式)と IntId? も同様に却下されます。

その他、意図的に却下されている表記:

  • int?=1RecordId@Effects?=fire?= はどちらも「任意」を意味するため、どちらか一方を選んでください。
  • List<T>? — リストはすでに空を許容しています。
  • List<List<T>> — リストの入れ子は不可です。
  • Pair<int?> — 省略可否はフィールドレベルの表記であり、内側の型の一部ではありません。

値のルール

  • bool: true / false のみで、入力は大文字小文字を区別しません。正規形は小文字です。
  • 数値: 小数点区切りは常に . です(ロケールに依存しません)。カンマ区切りの小数、NaNInfinity は入口で却下されます。
  • 浮動小数点数のラウンドトリップ: エクスポートは最短のラウンドトリップ形式で描画するため、1.01 として戻ってくることがあります—— そのものは正確に保持されます(意味的なラウンドトリップ)。
  • マーカーと enum の比較は Ordinal です(ロケールによる予期しない挙動はありません)。

型付きアセット参照(AssetRef@Group<Type>)

AssetRef@Icons はグループ内のどのアドレスも受け付けます。AssetRef@Icons<Sprite> はそれを一つの アセットタイプ に絞り込み、その絞り込みは三箇所——検証、コード生成、オーサリングサーフェス——でチェックされます。

  • 解決されるタイプ名。 タイプ名には、プロジェクトが読み込めるあらゆる UnityEngine.Object 派生のアセットタイプを書けます——エンジン組み込みのタイプ(SpriteTexture2DAudioClipTexture のような抽象基底クラス)も、自作の ScriptableObject も同様で、許可リストはありません。コンポーネントとエディター専用タイプは候補になりません。該当するタイプが一つだけの場合は 短縮名 を、それ以外は名前空間を含む フルネーム を書きます。曖昧な名前(AmbiguousAssetType — 該当する候補がすべて列挙されます)と未知の名前(UnknownAssetType — 最も近い候補が提案されます)は、列ごとに一度、@type の行で報告されます。
  • 通過する条件。 そのアドレスにあるアセット自体、またはそのサブアセットのいずれか が、そのタイプとして読み込める場合に、制限を満たします——そのため Sprite モードでインポートされたテクスチャは <Sprite> を通過し、通常のテクスチャはセルごとに AssetTypeMismatch として報告されます。サブアセット自体は parent[sub] としてアドレス指定可能で、そのキーは自分自身のタイプに対してのみチェックされます。
  • 生成されたコードから参照できないタイプは却下されます。 定義済みアセンブリ(Assembly-CSharp とその仲間——アセンブリ定義を持たないスクリプトフォルダすべて)に属するタイプは見つかりはしますが、AssetTypeNotReferenceable として報告されます。生成されるコンパニオンアセンブリはそれらのアセンブリを参照できず、AssetReferenceT<T> がコンパイルできなくなるためです。タイプをアセンブリ定義の中に移動するか、<…> を外してください。
  • コード生成が出力するもの。 解決済みのタイプには AssetReferenceT<global::UnityEngine.Sprite> を、無制限の列には AssetReference を出力します。コンパニオンアセンブリ定義は、そのタイプが属するアセンブリを自動的に参照し、解決済みのフルネームはスキーマフィンガープリントの一部になるため、名前のマッピングを変更するとコードが再生成されます。
  • 他の型と同じように組み合わせられます: AssetRef@Icons<Sprite>?List<AssetRef@Icons<Sprite>>、そして Pair<AssetRef@Icons<Sprite>> のようなラッパーもすべて動作します。一方、AssetRef@Icons<>(空)、AssetRef@Ic<ons(グループ名の中に山括弧がある)、RecordId@Skills<X>(この制限は AssetRef にのみ適用されます)は構文エラーです。
  • Data Studio の列フォームには、候補タイプを一覧表示して @type セルを書き換えてくれる タイプ… ボタンがあります——Data Studio を参照してください。

視覚的な値の型(ColorAnimationCurveGradient)

三つの組み込み型は、生のテキストのままでは読み取れない値を保持します。そのテキスト形式は、人が手で短い版を入力できるように設計されている一方で、エディター・Export・Push・ウェブアプリを含むあらゆるツールは常に 正規の完全な形式 を書き込みます。値は シート → Unity → シート という往復を、失われることなく生き延びます。

区切り文字は三つの型すべてで共有され、リスト区切りより一段下の階層にあります: 値の中で、要素(item), で、要素内の フィールド: で、セクション| で区切られ、キーの 時間@ で付加されます。List<> の要素は引き続き ; で区切られ、この三つの記法はいずれも ; を含むことがないため——List<AnimationCurve> = 0:0,1:1;0:1,1:0 はきれいに分割できます。数値の小数点はどこでも . を使います(ロケール依存のカンマは、サイレントに間違った値になるのではなく、フィールド数の食い違いとして現れます)。区切り文字の前後の空白はトリムされ、ラウンドトリップ parse(render(parse(x))) == parse(x) はすべての受理可能な入力について成立します。

受け入れられる入力正規形
Color#RGB#RGBA#RRGGBB#RRGGBBAA(大文字小文字を区別せず、# は必須)不透明な場合は大文字の #RRGGBB、それ以外は #RRGGBBAA#FF8800#FF880080
AnimationCurve`key,key,…[pre:post]の形式で、キーはt:vt:v:in:outt:v:in:out:inW:outW:wm、または t:v:in:out:inW:outW:wm:tm`(2, 4, 7 または 8 フィールド — 3, 5 と 6 はエラー)
Gradient`colorKeys[alphaKeys[

カラー: 値は四バイトとして保存されます。HDR(1 を超えるチャンネル)はサポートされません——ベイクされたカラーは Export 時に 0…1 にクランプされます。型のデフォルト値は透明な黒、#00000000 です。

カーブ: wm は重み付きタンジェントのフラグ(0 = なし・1 = イン・2 = アウト・3 = 両方)、tm はタンジェントの モード ペア Left/Right で、任意で /broken が続きます——各辺は FreeAutoLinearConstantClampedAuto のいずれかで、これは Unity のカーブエディターが使うのと同じ名前です。短い形式は残りを補います: 2 フィールドのキーは、隣接するキーへの傾きをタンジェントとして採用し(Linear/Linear)、重みは 0.33333334、重み付けなしになります。4 フィールドのキーは入力したタンジェントをそのまま保持します(Free/Free)。7 フィールドのキーは重みを追加します。タンジェントのフィールドには Infinity または -Infinity(Constant のステップ)を指定できます。時間・値・重みは有限でなければならず、キーの時間はそれぞれ異なっていなければならず(キーはインポート時に時間順に並べ替えられるため、入力する順序は関係ありません)、キーの数に上限はありません。モードが数値に優先します: Free 以外の辺では、タンジェントの値はインポート時にモードから再計算されます——Unity が行うのと同じ計算です——そのため、モードと矛盾する手入力の数値は置き換えられ、シート・エディター・ゲームのすべてが同じ一本のカーブを表示します。ラップモードは ClampForeverLoopPingPongDefault です。OnceClampForever のエイリアスとして受け付けられ(Unity が正規化します)、書き戻されることはありません。キーを持たない カーブにはテキスト形式が存在しません: それは任意列の空セルとしてのみ存在し、Export はそれを空セルとして描画します。

グラデーション: カラーキーはアルファを持ちません(カラーのセクションに #RRGGBBAA を書くとエラーになります——アルファには専用のセクションがあります)。セクション内では @t の時間はすべて指定されているか、すべて省略されているかのどちらかで、省略された場合はキーが均等に配置されます(n = 10n ≥ 2i/(n−1))。アルファセクションが省略された場合は 1@0,1@1 を、モードが省略された場合は Blend を意味します。モードは BlendFixed(ステップ)、PerceptualBlend です。任意の色空間(Gamma または Linear)は PerceptualBlend の補間方法だけを変えます。時間とアルファは 0…1 の範囲です。時間はインポート時に 16 ビットに量子化されます——これは Unity が値を保存する方式そのものであるため、表示される値がそのままエンジンが保持する値になります。単一のキーを持つグラデーションは、Unity を経由すると同一の二つのキーとしてラウンドトリップします——見た目は変わらず、キーの数だけが増えます。

リスト: List<Color> = #F00;#0F0List<Gradient> = #F00,#00F;#0F0,#000 — リストの区切り文字は変わりません。

Data Studio はこれらのセルをネイティブのカラー・カーブ・グラデーションフィールドとして表示し、ウェブアプリは完全なエディターを備えたプレビューとして表示します——Data StudioSheetForge Web を参照してください。どちらも正規形を書き込みます。最小限の表記は人間のためのものです。

キーと一意性

  • RecordId(@ なし)がキー列です: タブごとに最大一つ。
    • キー列がゼロというのも有効です——他のタブがこのタブを参照するまでは(TargetTabHasNoKey)。
    • 二つ以上あるとエラーになります(MultipleKeyColumns)。
    • 重複したキー値(DuplicateRecordId)や空のキーセルもエラーです。
  • IntId は副次的な整数キーです。一意性は独立して強制され、他のタブは IntId@Tab を通じてこれを参照 できます
    • 整数キー参照は、RecordId@Tab と同じ整合性検証・最近傍候補の提案・リネーム時の伝播・グラフ/キャンバスでの対応を受けます。
  • タブは RecordId のみ、IntId のみ、あるいはその両方をキーにできます。この三つのケースは、あらゆる場面で対称的に振る舞います。
    • タブが 両方 を持つ場合、RecordId が表示用/識別用の値となり、整数キーはその隣に表示されます。
    • 他のタブは、どちらの方法でも同じレコードを指せます: 文字列キーによる RecordId@ThisTab、または整数キーによる IntId@ThisTab
  • @overlap: 通常の列は、デフォルトで値の重複を許可します。列の @overlap セルに false を入れると、値ベース の一意性が強制されます。
    • 1.01 は同じ値として扱われ、すべての要素とその順序が一致する二つのリストは重複と見なされます。
    • 二つの 空参照 は互いに重複と見なされることは決してありません(空のスカラーのデフォルト値は、それでも通常の値として扱われます)。
    • キー列は常に一意なので、キー列に @overlap true を書くと矛盾エラーになります。

シート表示メタデータ(@style)

@style を使うと、シートが自分の属するグループと色を自ら宣言できます——そのためグルーピングと色分けは、エディターの中だけでなく シートの中 に存在します。これは列ではなく シート そのものを記述する唯一のマーカーであるため、そのセルは列に対応づけられません——列 B から始まる、自由な key=value ペアの並びです。

@style   | title=Combat  | color=#4D8FF0
@name    | codeName      | displayName | power
@type    | RecordId      | string      | int
@desc    | unique key    | shown in UI | attack power
         | skill.fire    | Fireball    | 12
キー効果
title任意のテキスト同じ title を持つシートは、Data Studio のサイドバーでその見出しの下にまとめられます。セクションは初出順に表示され、シートはセクション内で自身の順序を保ちます。title のないシートはデフォルトのセクションにとどまります。
color#RRGGBB(六桁)このシートが現れるあらゆる場所に色を付けます: サイドバーのドット、キャンバス上のノードの枠線、そしてこのシートを指す すべて のポートとワイヤーです。
  • 両方のキーは任意で、順序も問いません——一方だけ、両方、あるいはどちらも書かなくて構いません。空のセルは無視されます(埋め合わせのセルがあっても問題ありません)。
  • 検証エラーは、すべてセル座標と具体的な修正案とともに MarkerCellInvalid として報告されます:
    • 未知のキー(最も近い候補の提案付き)
    • キーの重複
    • 値の欠落
    • #RRGGBB 形式でない色
  • 三桁の短縮形(#4AF)や色の名前は意図的に却下されます。これにより、値は常に一つの表記でラウンドトリップします。
  • 表示専用: コード生成・ベイク・スキーマフィンガープリントは @style を一切読み取りません。シートの色を変更しても、コードの再生成や ScriptableObject の再ベイクは発生しません。
  • ラウンドトリップ安全: @style の行は、コメント行と同じように保持されます。列の追加・削除・移動・名前変更があっても、そのセルは列に属していないため影響を受けません。編集は Group & color フォーム(Data Studio のサイドバーでシートを右クリック)を経由し、行を正規形で書き直します。
  • @style だけを持つシート(コメントを除く)は「まだテーブルがない」扱いになります: インポートは、必須の三つのマーカーが欠けているとしてエラーにする代わりに、警告付きでこれをスキップします。@name/@type/@desc を追加すればすぐに通常どおりパースされます。機能と制限 を参照してください。
  • style は予約済みのマーカー名です——これを登録しようとするプラグインは拒否され、@styl のようなタイプミスには @style が候補として提案されます。

enum 定義シート(@enum)

Enum<T> 列には T が必要です。プラグインの C# から登録することもできますが(EnumRegistry)、コードもプラグインも不要で、シートに書くだけ でも定義できます。次のいずれかが成り立つとき、シートは enum 定義として読み取られます:

  • @enum マーカー行を持っている(タブ名は何でも構いません)、または
  • タブ名がちょうど Enum(大文字小文字を区別)であり、かつ @type 行を持たない場合。

二つ目のルールは、@type が意図的に欠けていることを要求します: データテーブルには常にこれがあるため、たまたま Enum という名前になっている既存のテーブルは、そのままテーブルとして扱われ続けます。@enum@type両方 を持つシートは矛盾しており、推測で処理されるのではなく EnumSheetMarkerConflict として報告されます。

@desc はこの判定に関与しません——どちらの種類のシートでも使用でき、enum シートではその列の enum を説明します(詳細は下記)。

enum シートには テーブルがありません——スキーマもキー列もレコードもありません。一つの列が一つの enum です: @name セルが enum の名前を保持し、その下の各行(列 A は空欄)がそれぞれ一つのメンバーになります。

@enum    | byte       |
@desc    | Damage kind| Elemental affinity
@name    | DamageType | Element
         | Physical   | Fire
         | Magical=10 | Ice
         | True       | Lightning

このシートは二つの enum を定義しており、Enum<DamageType> / Enum<Element> は、以後どの @type セルでも解決されるようになります——列の構文自体は変わりません。上記に示した三つの追加要素はすべて任意です——素の @name 行とメンバーだけでも、完全な enum シートとして成立します。

このひな形を自分で入力する必要はありません: Create sheet には、シートのレイアウトを自動的に用意してくれる Enum definitions テンプレートが同梱されています。これは二つの組み込みテンプレートの一つです(Data Studio ▸ Sheet create / delete を参照)。

  • 順序が値そのものであり、Name=value で固定できます。 メンバーセルは、プレーンな名前か、明示的な整数を伴う Name=value のいずれかです——これは C# の enum のルールそのものです: 番号のないメンバーは直前の値より一つ大きい値になり、最初のメンバーは 0 です。
    • Normal / Rare=10 / Epic0 / 10 / 11 にコンパイルされます。コード生成は、あなたが書いた箇所にのみ = value を出力します。
    • データセルとドロップダウンは常に 名前 を使います(Rare であり、Rare=10 ではありません)。
    • プレーンな整数ではない値、または(自動採番によるものも含め)underlying type の範囲外に落ちる値は InvalidEnumMemberValue になります。
    • これが、Data Studio がメンバーの並べ替えを決して行わず、途中の穴を埋めることもない理由でもあります: メンバーをずらしてしまうと、すでにアセットに焼き込まれ、セーブデータに保存されている値が、気づかぬうちに変わってしまうからです。
  • @desc は enum を説明します。 列の @desc セルは、生成コードにおけるその enum の XML <summary>(IDE 上のツールチップ)になります——データテーブルのフィールド @desc と同じ考え方です。空のセル = 説明なし。マーカー行自体も任意です。
  • @enum セルは underlying type を指定します。 列の @enum 行のセルには、その enum の C# underlying type を指定できます——bytesbyteshortushortintuintlongulong のいずれかです。
    • 空のセル(またはタブ名が Enum@enum 行自体がない場合)は int を意味します。それ以外は InvalidEnumUnderlyingType になります。
    • コード生成は public enum Grade : byte { … } のように出力します。
    • ulong の場合、long.MaxValue を超える明示値はシートからはサポートされません——そのような enum はプラグイン C# から登録してください。
  • 空欄のセルはスキップされ、メンバーとしては読み取られません。そのため列ごとに長さが異なっていても構わず、途中の空白は単に読み飛ばされます。
  • コメント行(#)は、シート内のどこにあっても無視されます。一つのシートに多数の enum を置くことも、enum シートを複数用意することも、どちらも問題ありません。名前はそれらすべてを通じて一意でなければならず、プラグインが C# からすでに登録している名前が優先されます(シート側の定義は DuplicateEnumName として却下されます)。
  • 名前とメンバーは C# の識別子として使える必要があります: ASCII の英字・数字・_ のみで、数字から始まらず、予約語でもないこと(InvalidEnumIdentifier)。
    • 非 ASCII 文字は意図的に却下されます。見た目がそっくりな Unicode 識別子は、他と見分けのつかない型を生んでしまうためです。
    • 宣言された名前の下にメンバーが一つもない場合は EnumSheetEmptyColumn になります。
    • 一つの列の中でいずれかのメンバーが失敗した場合、その enum 全体が、中途半端に登録されるのではなく、丸ごと除外されます。
  • インポートが生成するもの。 プロジェクト全体でただ一つの SheetForgeEnums.cs——enum はタブ単位ではなく、プロジェクト単位の出力です——が、設定にある生成コードフォルダーへ、生成されるタブ型と同じ名前空間で書き出されます。最初のインポートでこの型が作成され、コンパイルされ、ドメインリロード後にベイクが完了します。追加のクリックは不要です。
  • シートを開かずにメンバーを追加する: Data Studio 内の Enum<T> セルのドロップダウンには 「Add a new member…」 があり、これを使うとメンバーが一つの undo ステップとして enum シートにステージングされます。プラグイン C# から登録された enum では、この行は提供されません——コードがその enum を所有しているためです。
  • enum シートにはレコードがないため、ScriptableObject にベイクされることは決してなく、Export/Push もそのテキストに触れません。インポートは、これらをスキップされたタブとは別に報告します。
  • 二つの境界については 機能と制限 を参照してください: プラグインが登録した enum はシートから拡張できないこと、そして生成される enum ファイルは常に設定フォルダーに置かれることです。

ローカライズシート(@loc)

@loc マーカー行は、シートを ローカライズシート に変えます: 行がキーに、列がロケールになり、各ロケール列の @loc セルがそのロケールコードを指定します。

  • RecordId キー列が必須です——そのキーの値がローカライズキーになります。
  • 最初のロケール列が ソースロケール です。
  • ロケール列は文字列型の列です。string? が推奨される形です: そうすれば、空のセルはエラーではなく翻訳漏れとして扱われます。
  • 名前で予約された二つの任意列があります: smart(bool)と comment(string)。
@loc     |            | en          | ko    |
@name    | codeName   | en          | ko    | comment
@type    | RecordId   | string?     | string? | string?
@desc    | key        | source text |       |
         | ui.ok      | OK          | 확인  | Confirm button

シートは、編集・Export・Push・xlsx・ウェブアプリにとって、引き続き通常のテーブルのままです。変わるのは 出力 です: レコードクラスも Database SO も生成されなくなる代わりに、タブごとのキー定数が生成され——Unity Localization パッケージがインストールされていれば——StringTable の同期も行われます。同じシートに @enum@loc が両方あると矛盾エラーになります。

LocRef 参照・ミンティング・ブリッジ・翻訳ワークフローという全体像は、ローカライズシート にあります。

カスタム構造マーカー(プラグインによる登録)

@overlap は、列単位のマーカー の組み込みの例です。マーカー行の各セルは列ごとに一つの値を持ち、列ごとに検証されます。プラグインも同じ方法で独自のマーカーを登録できます——例えば、各数値列がどのように補間されるかを注釈する @curve マーカーなど。

その値は、バリデーター・エッジコントリビューター・オーサリングウィンドウの列ヘッダーツールチップが読み取れる、ドメインに依存しないメタデータ(FieldSchema.MarkerValues)として保存されます。Core はその値自体を決して解釈しません——検証はマーカー定義に委譲されます。

  • 登録済みのカスタムマーカーは、@overlap とまったく同じように受け入れられます。データより上であればどの順序でもよく、重複は却下され、データより下にあるマーカーはエラーです。
  • 各マーカーが持つのは、列ごとの値の検証(空のセルが何を意味するかを含む)だけです——行全体のパースを乗っ取ることは ありません。データの「形」は、正規化(参照、List<T>type 列)の領域にとどまります。
  • カスタムマーカーは 列レベルのメタデータ のためのものであり、新しいデータの形のためのものではありません。登録例については プラグイン作成 §4.5 を参照してください。
  • @style は、列単位ではない唯一の組み込みマーカーです(シートそのものを記述するため)。したがって、手本にすべきなのはそれではなく @overlap です。

複雑なデータを組み立てる: まず正規化

複雑な構造を表現する上で推奨される方法は、参照による組み立てです(「スクリプトを書くのではなく、組み立てる」)。

  • 原子的な要素は、それぞれ専用のタブの行として存在します。
  • 組み合わせは参照のリストです: List<RecordId@Effects>
  • type 列(enum)は、データ行をコードの原子的な要素に結び付けます——あなたのランタイムはそれを switch して振る舞いをディスパッチします。組み込みのスクリプト言語は不要です。

ミニ文法(attack:add:10 のようなカスタムセルタイプ)は 小さなタプル のためのものです——Core は ;: という慣習を提供しますが、使いすぎないようにしてください。

本当に手続き的な一回限りのロジックには、画像を参照するのと同じ方法でスクリプトアセットを参照してください: List<AssetRef@Scripts>。SheetForge が参照を検証し、アドレス可能な形でベイクします。スクリプトの実行はあなたのゲームの仕事です。

特殊なデータの「形」: 一見扱いにくく見えるデータ(レベルカーブなど)でも、きれいに正規化できます(List<float>、参照による組み立て)。カスタム構造マーカーが追加するのは、(列ごとに検証される)列レベルのメタデータ であり、新しいデータの形ではありません——まずデータを正規化し、本当に冗長な列ごとの注釈が必要な場合にのみカスタムマーカーに頼ってください。プラグイン作成 を参照してください。

関連ページ