Skip to main content

Inspector extensions

Guide

Add serialized project fields to all six Workbench modes through derived content types

To add a field such as Required Level, derive a project type from one of the six GCS content types and declare a Unity-serialized field. Then create an asset of the derived type in a GCS database. Edit its fields in Workbench or in the Unity Inspector. To add the field to existing assets, migrate them to the derived type.

Download the Inspector extension samples

Download GCS-Samples.zip and extract it outside Unity. Copy the Runtime and Editor directories you need from Samples~/InspectorExtensions/ into the corresponding project assemblies.

Keep the content type in a runtime assembly​

Place derived content classes and option providers in a player-available assembly that references TinyGiants.GCS.Runtime:

{
"name": "YourGame.GCS.Content",
"references": [
"TinyGiants.GCS.Runtime"
]
}

Declare a top-level public, concrete, non-generic class. Give the .cs file the same name as the class so Unity can associate its MonoScript and Workbench can list it for creation.

Workbench modeDerive fromStored byRuntime enumeration
CardGameCardGameCardDatabase.CardsGCSApi.Cards()
DeckGameDeckGameDeckDatabase.DecksGCSApi.Decks()
PlayerGamePlayerUnitGamePlayerUnitDatabase.PlayerUnitsGCSApi.PlayerUnits()
EnemyGameEnemyUnitGameEnemyUnitDatabase.EnemyUnitsGCSApi.EnemyUnits()
StatusGameStatusGameStatusDatabase.StatusesGCSApi.Statuses()
EncounterGameEncounterGameEncounterDatabase.EncountersGCSApi.Encounters()

The following class adds one RequiredLevel field to SampleCard

using TinyGiants.GCS.Runtime;

public sealed class SampleCard : GameCard
{
public int RequiredLevel;
}

After Unity compiles, open Card and click +. When multiple types are available, the menu lists GameCard first and sorts project types by display name, with assembly names shown for duplicates. Choose SampleCard to create a sub-asset in the selected Card Database. Its fields, including Required Level, are editable in Workbench and the Unity Inspector. The other five modes support derived types in the same way, using their own GCS base types.

Declare fields with Unity serialization rules​

Workbench uses Unity's visible serialized fields. Declare a public instance field or apply [SerializeField] to a private field. Use a type Unity can serialize, such as a primitive, enum, Unity object reference, serializable class or struct, array, or supported list. Apply [HideInInspector] when a serialized field should stay out of both inspectors.

using System;
using System.Collections.Generic;
using TinyGiants.GCS.Runtime;
using UnityEngine;

public sealed class SampleCard : GameCard
{
[GCSSection("Basic")]
[Min(1)]
[Tooltip("Minimum character level required to play this card.")]
public int RequiredLevel = 1;

[GCSSection("Visual")]
[Tooltip("Optional voice line used by project presentation code.")]
public AudioClip VoiceLine;

[GCSSection("Extension Data", "◆")]
[Range(0, 100)]
public int Power = 10;

[TextArea(2, 5)]
public string Lore;
}

Required Level appears in Basic, Voice Line in Visual, and Power and Lore in the Extension Data foldout with the ◆ icon

Control section placement with declaration order​

Sections follow their first appearance in the class. Fields appear in declaration order, and reusing a section appends the field to that section.

DeclarationResult
[Header("Extension Data")]Selects or creates the Extension Data foldout starting with this field
[GCSSection("Basic")]Selects the existing Basic foldout, or creates it when it does not exist
A following field without either attributeContinues in the current section for the same declaring type
First field of a derived declaring type without either attributeEnters the Additional foldout
Another [Header] or [GCSSection]Changes the current section from that field onward
tip

Use the exact names Basic, Visual, or Behavior to add fields to those foldouts. Derived fields appear after the base-class fields.

GCSSectionAttribute accepts either a glyph or a project-relative Assets/ or Packages/ icon path. A supplied icon overrides the built-in icon for a section with the same name:

[GCSSection("Progression", "★")]
public int RequiredLevel;

[GCSSection(
"Presentation",
"Assets/YourGame/GCS/Editor/Icons/presentation.png")]
public Color PresentationTint;

Asset paths can reference an imported Sprite or Texture2D. An invalid path falls back to the section's built-in icon and writes one warning for that path to the Console.

The following standard Unity attributes have explicit Workbench behavior:

AttributeWorkbench behavior
[Header]Starts or reuses a foldout and makes it current
[Tooltip]Applies the tooltip to the field row and control
[Space]Adds vertical space before the field
[Min]Clamps an edited integer or float to the declared minimum
[Range]Uses an integer or float slider with an input field
[TextArea], [Multiline]Uses a multiline text field
[Delayed]Commits string, integer, or float input after editing finishes
[InspectorName]Replaces the nicified field label or enum-option label
[SerializeField], [HideInInspector]Follow normal Unity visibility rules
tip

[GCSLabel] takes precedence over [InspectorName], registered controls and GCS attributes such as [GCSOptions] select controls before Unity CustomPropertyDrawer

Without a GCS control, Workbench uses Unity PropertyField, preserving project PropertyAttribute and CustomPropertyDrawer behavior, register a custom UI Toolkit control through Inspector controls

Supply single-choice options​

GCSOptionsAttribute applies to a serialized string. It accepts one of three sources:

[GCSOptions(
"Physical", "Fire", "Frost", "Lightning", "Arcane",
Editable = true)]
public string DamageSchool = "Physical";

[GCSOptions(typeof(SampleFactionOptionProvider))]
public string Faction = "alliance.kingdom";

Editable = false uses a selection-only field. Editable = true also accepts values outside the current option list. Workbench adds non-empty values stored in the same field across the current database to later dropdowns. Set EmptyValue to define the value stored when the field is cleared; the built-in Rarity, Enemy Tier, and Encounter Difficulty fields use Common, Normal, and Normal respectively.

In this sample, DamageSchool accepts either a preset or a new value. Faction stores the value returned by SampleFactionOptionProvider while showing the provider's label in the dropdown.

Built-in sourceValues supplied by GCS
NoneNo built-in single-choice values
CardTypeBuilt-in and authored card types
CardRarityBuilt-in and authored card rarities
CardTagAuthored card tags
CardKeywordRegistered CardTag IDs with their display labels
EnemyTierBuilt-in and authored enemy tiers
EncounterDifficultyBuilt-in and authored encounter difficulties

Dynamic providers implement the Runtime interface IGCSInspectorOptionProvider and provide a public parameterless constructor, Workbench creates the provider when rebuilding options and passes the current content object to GetOptions

using System.Collections.Generic;
using TinyGiants.GCS.Runtime;
using UnityEngine;

public sealed class SampleFactionOptionProvider : IGCSInspectorOptionProvider
{
public IEnumerable<GCSInspectorOption> GetOptions(Object target)
{
yield return new GCSInspectorOption(
"alliance.kingdom",
"Kingdom Alliance",
new[] { "World", "Alliance", "Kingdom" },
"Human kingdoms joined under one banner.");

yield return new GCSInspectorOption(
"horde.ashen",
"Ashen Horde",
new[] { "World", "Horde", "Ashen Marches" },
"Raiders from the volcanic frontier.");
}
}

Each option returned by the provider contains four values

Provider memberPurpose
ValueValue written to the serialized field
LabelText shown to the author in the dropdown
GroupPathExplicit page path with any depth, one segment can contain /
TooltipHover description for the option
tip

Workbench ignores case when removing duplicate Value entries, use stable, unique values

Supply multiple-choice values​

GCSMultiSelectAttribute applies to List<string> or string[]. It accepts the same fixed-option, provider-type, and built-in-source constructors as GCSOptionsAttribute.

[GCSMultiSelect(
"Humanoid", "Construct", "Undead", "Beast", "Quest",
Mode = GCSMultiSelectMode.Freeform)]
public List<string> Traits = new List<string>();

[GCSMultiSelect(
typeof(SampleSpellOptionProvider),
Mode = GCSMultiSelectMode.OptionsOnly)]
public List<string> GrantedSpells = new List<string>();
ModeAuthoring behavior
FreeformAccepts comma-delimited project values and also exposes the available values in a multiple-selection dropdown
OptionsOnlyShows ordered removable chips and only adds values through the supplied option dropdown

Traits uses Freeform, so it accepts typed values and dropdown selections. Workbench adds values already stored in SampleCard.Traits to the dropdown for later use.

GrantedSpells uses OptionsOnly, so it accepts only values returned by SampleSpellOptionProvider and displays selected values as removable chips.

Select other GCS content​

GCSSubAssetAttribute replaces an ordinary ScriptableObject reference with the GCS content picker. The picker searches registered databases, accepts derived instances of the requested base type, and can render a compact row or a summary card.

[GCSSubAsset(
typeof(SampleStatus),
Style = GCSSubAssetStyle.Card)]
public SampleStatus SignatureStatus;

SampleCard.SignatureStatus accepts only SampleStatus assets. Use GCSSubAssetListAttribute on an array or list when a field stores multiple GCS content references:

[GCSSubAssetList(typeof(GameEnemyUnit), Required = true)]
public List<GameEnemyUnit> Reinforcements = new List<GameEnemyUnit>();
tip

Required shows an inline warning when a reference is empty or a required list has no entries. Register a project validator to surface the missing reference as an Issue Badge. Create the content in its database first so it appears in the picker.

Flatten serializable settings with GCSInline​

GCSInlineAttribute exposes the direct visible children of a serializable class or struct in the current section without adding another nested property box.

using System;
using TinyGiants.GCS.Runtime;
using UnityEngine;

[Serializable]
public sealed class SampleCardStats
{
[Min(0)]
public int BaseDamage = 6;

[Range(0f, 1f)]
public float CriticalChance = 0.1f;
}

public sealed class SampleCard : GameCard
{
[GCSInline]
public SampleCardStats Stats = new SampleCardStats();
}
tip

Inspector initializes a null field when its type is concrete and has a parameterless constructor, inline data must follow Unity serialization rules

Put fields with GCSFlowGraphAttribute directly on the content class so the FlowGraph Editor can resolve their paths. For inline data, use the full path, such as Stats.BaseDamage. For top-level fields, use nameof(SampleCard.RequiredLevel). Workbench checks PropertyPath first and falls back to FieldLabel. See Inspector controls.

Edit lists with GCSList​

Apply [GCSList] to an array or List<T> field when an asset needs multiple sets of values. Workbench and the GCS content Inspector show the item count, an Add Item button, and controls for each item. Visible child fields of ordinary serialized objects use the standard GCS field controls.

public sealed class SampleCard : GameCard
{
[GCSList]
public List<SampleCardStats> BonusStats = new List<SampleCardStats>();
}

Click Add Item, then fill in Base Damage, Critical Chance, and Armor Penetration. Drag the handle on the left or use the up and down arrows on the right to reorder items. Click the minus button to remove an item. Edits are saved to the original list field and support Unity Undo/Redo.

New ordinary elements start with zero for numeric values, empty strings, and None for object references. For classes with a parameterless constructor, the constructor supplies initial field values. You can also use [GCSList] on a nested list in a [GCSInline] object or list element.

Element typeEditor behavior
int, float, string, bool, and ordinary enumsUses GCS field controls and displays ordinary enums in a dropdown
Serializable class or structExpands visible child fields and preserves supported GCS attributes, ranges, and tooltips
Unity object referenceUses an object picker. Apply [GCSSubAssetList] to select content from a GCS database
[SerializeReference] listLets you select a compatible, concrete, serializable, non-generic class or None for each item
Element with a custom PropertyDrawerUses the custom drawer for the element and GCS styling for the surrounding list

New items in a [SerializeReference] list start as None. Choosing a concrete type creates an instance. Changing the type replaces the item's data, and Undo restores it. Fields without a dedicated GCS control use Unity's property controls.

tip

[GCSInline] expands a single nested object. [GCSList] handles list layout and item operations, and existing custom drawers still handle their own rendering.

To control field visibility with project rules, define the condition in your drawer or a registered Inspector control. The GCS content Inspector recognizes these attributes.

Add a FlowGraph editing field​

GCSFlowGraphAttribute applies to a direct GameEffectFlowGraph field and adds Edit FlowGraph plus a static summary.

public sealed class ProjectCard : GameCard
{
[GCSFlowGraph(GCSFlowGraphSummary.Entries)]
public GameEffectFlowGraph AlternateBehavior = new GameEffectFlowGraph();
}

Entries summarizes entry nodes. EnemyIntents summarizes patterns, leaf intents, and action nodes.

tip

Declare graph fields directly on a derived Card, Status, or Enemy, FlowGraph Editor checks nodes using that content type

The built-in Behavior runs in battle and receives built-in Workbench validation. To execute and check AlternateBehavior, call it from project code and register a validator.

Reuse other built-in field controls​

The following Runtime attributes select built-in GCS field controls

AttributeRequired fieldResult
[GCSAssetName]stringEdits the value and renames the content sub-asset when the value is non-empty
[GCSDescription]stringUses the GCS description editor with token and semantic-reference support
[GCSLabel("Label")]Any serialized fieldOverrides the displayed label
[GCSSegmentedBool("Off", "On")]boolUses a two-segment Boolean picker
[GCSDeckEntries]GameDeck.EntriesUses the card count picker and deck summary UI
[GCSSection("Name", "Glyph or asset path")]Any serialized fieldSelects a named Workbench section from this field onward and optionally supplies its icon

If an attribute and field type are incompatible, Workbench displays the standard serialized field control.

Read the same typed data at runtime​

Databases and GCSApi expose the base types, so use normal C# type checks or OfType<T>() to reach project fields:

using System.Linq;
using TinyGiants.GCS.Runtime;

SampleCard firstSampleCard = GCSApi.Cards()
.OfType<SampleCard>()
.FirstOrDefault();

if (firstSampleCard != null)
{
int requiredLevel = firstSampleCard.RequiredLevel;
}

if (cardInstance.GetActiveCard() is SampleCard activeSampleCard)
{
PlayVoice(activeSampleCard.VoiceLine);
}

if (unitState.Source is SampleEnemy sampleEnemy)
{
ApplyEnemyRules(sampleEnemy);
}
tip

The same pattern works with GCSApi.Decks(), PlayerUnits(), EnemyUnits(), Statuses(), and Encounters(). These methods enumerate active databases and allocate a fresh list, so cache a result that is read repeatedly.

Use derived fields for authored values. Store temporary card or unit values on their runtime state or in supported battle variables.

Preserve data through authoring operations​

Workbench saves derived fields through Unity serialization. Duplicate and Paste preserve the concrete type and serialized fields and assign a unique name and GCS ID. Paste into a mode that accepts the source type. Workbench Clipboard stores object references in the current Unity Editor domain, so copy again after restarting the editor or after a domain reload.

Built-in field edits, creation, duplication, deletion, and database membership changes support Unity Undo, custom controls also support Undo/Redo when saving through GCSInspectorFieldContext.Modify, see Inspector controls

Preserve data references when changing saved types or fields

  • Use [FormerlySerializedAs] when renaming a serialized field.

  • Keep derived type names and assembly ownership stable, or provide an explicit asset migration.

  • Create a project migration tool when existing base assets must become a new derived type.

tip

To show a derived field in your card face or runtime presentation, read that field from your project's UI code.