Extend card types, tags, and description tokens
Add project-specific card types, tags, and description tokens that appear in the existing authoring controls and runtime text
Newly registered entries go directly into the corresponding fields in Game Card Editor and FlowGraph; the Type, Rarity, and Tags fields in the Card-mode Inspector all receive their options from registries

The image above shows where registration results enter the content-authoring interface; Card Type provides the primary classification and color, Card Tag provides reusable keywords, and Description Token turns runtime values into player-facing text inside Description
Card types
A card type is a card's primary classification, such as Basic, Skill, or Curse; projects can also add their own primary categories; the type participates in card filtering, type-matching cost rules, card-frame color, and the type dropdowns in Game Card Editor and FlowGraph
Inherit CardType and add [CardType]
using TinyGiants.GCS.Runtime;
using UnityEngine;
[CardType]
public sealed class PowerCardType : CardType
{
public override string Id => "Power";
public override string DisplayName => "Power";
public override Color UIColor => new Color(0.2f, 0.7f, 0.4f);
public override Color NumberAccent => new Color(0.45f, 1f, 0.65f);
}
| Property | Meaning |
|---|---|
Id | The stable stored value used for rule matching; it must be unique and non-empty, and must not change after cards reference it |
DisplayName | The label shown in editors and on cards |
UIColor | The card frame and theme color |
NumberAccent | Optional accent for cost and value numbers, defaulting to UIColor |
GCS includes five types: Basic, Skill, Curse, Support, and Burst; custom types appear beside them in the corresponding dropdowns
Card tags
A card tag marks a reusable rule or trait outside the primary type; several cards can share the same tag; GCS includes Ethereal, Exhaust, Innate, Retain, and Unplayable, while a project can add tags such as Volatile, Combo, or Bloodbound
Inherit CardTag and add [CardTag]
using TinyGiants.GCS.Runtime;
[CardTag]
public sealed class VolatileCardTag : CardTag
{
public override string Id => "Volatile";
public override string DisplayName => "Volatile";
}
| Property | Meaning |
|---|---|
Id | The stable stored value and rule-matching key, which must be unique and non-empty |
DisplayName | The keyword label shown in Game Card Editor |
Icon | Optional badge Sprite for the keyword, left empty by default |
Use a tag when several cards share a trait; use a type when a card needs a primary classification with its own visual identity
Description tokens
Description Tokens let card text update with runtime values; a card description can contain {name} or {name:args}, and the Formatter calls the Token registered under that name to produce replacement text; use {{ and }} when the text needs literal braces
GCS includes 21 Tokens, and the Demo provides 4 more that depend on preset status names; confirm that the existing entries do not already cover the required value before creating a project extension
| Built-in token | Names |
|---|---|
| Card values | {Damage}, {Block}, {Heal}, {DrawCount}, {EnergyCost}, {EffectiveCost}, {X} |
| Status stacks | {Stacks}, {StackOf} |
| Unit values | {HP}, {MaxHP}, {Armor}, {MissingHP} |
| Battle counters | {TurnNumber}, {HandSize}, {DrawSize}, {DiscardSize}, {ExhaustSize} |
| Conditional text | {IfUpgraded}, {IfHasStatus}, {IfPlayerTurn} |
When a project needs new dynamic text, implement IDescriptionToken and add [DescriptionToken("name")]
using TinyGiants.GCS.Runtime;
[DescriptionToken("Rage", Description = "Bonus damage from the caster's missing HP.")]
public sealed class RageToken : IDescriptionToken
{
public string Resolve(CardDescriptionContext ctx, string args)
{
var source = ctx?.Source;
if (source == null) return "0";
return ((source.MaxHp - source.CurrentHp) / 5).ToString();
}
}
Card text:
Deal 6 damage, plus {Rage} for your missing HP.
CardDescriptionContext carries:
| Field | Meaning |
|---|---|
Card | The card definition being described |
Instance | The card instance when the description is evaluated during battle |
Source | The source unit when known |
Target | The current target when known |
Battle | The battle state when a battle is active |
Outside battle, Instance, Source, Target, and Battle may all be null; the Token must handle these cases so the card still renders correctly in editor lists and previews
Read registration results
GCS scans loaded assemblies that reference TinyGiants.GCS.Runtime, registers every concrete class with the corresponding attribute, and exposes the results through the public API
var types = GCSApi.CardTypes();
var tags = GCSApi.CardTags();
var tokens = GCSApi.DescriptionTokens();
var nodes = GCSApi.NodeTypes();
The dropdowns in Game Card Editor and FlowGraph read the same registries, so new entries appear after compilation and Domain Reload finish
Keep IDs stable
Registry IDs and Token names are stable contracts in saved content
| Extension | Stable key |
|---|---|
| Card type | CardType.Id |
| Card tag | CardTag.Id |
| Description token | DescriptionTokenAttribute.Name |
A Display Name can change; an ID or Token name must not be changed directly after a saved card, filter, Description, or FlowGraph references it
Design options around the authoring workflow
-
Use card types for primary classifications, with an easy-to-distinguish color for each type
-
Use card tags for reusable keyword behavior and filtering
-
Use Description Tokens for text that must update with runtime state
-
Keep choices that can be expressed with dropdowns out of manually typed fixed IDs
-
Keep Display Names short enough to fit fully on cards and nodes
Troubleshoot registration
When a custom type, tag, or Token does not appear, check these items in order:
- Confirm that the class belongs to a runtime assembly that references
TinyGiants.GCS.Runtime - Confirm that the class is concrete, not abstract
- Confirm that
[CardType],[CardTag], or[DescriptionToken("name")]is present - Wait for Unity to finish compilation and Domain Reload
- Check the Console; an empty
Idis skipped with a warning, while a duplicateIdreplaces the entry registered earlier, so the project must guarantee uniqueness