A cross-platform dialogue authoring system for games. GameScript provides a visual graph editor embedded in IDEs (VS Code, Rider), with runtime packages for Unity, Unreal, and Godot.
GameScript is a complete dialogue middleware solution that lets game developers:
- Design dialogue flows using a visual node-based graph editor
- Write game logic in native code (C#, C++, GDScript) with full IDE support
- Collaborate using PostgreSQL for team projects or SQLite for solo development
- Deploy high-performance binary snapshots to game engines
Unlike traditional dialogue tools that use embedded scripting languages, GameScript keeps all game logic in native code files. Actions and conditions are regular functions that get full IDE support: autocomplete, debugging, refactoring, and type checking.
GameScript's interface is a web-based editor embedded in your IDE (VS Code or Rider). The UI uses a dockable panel system where you can arrange panels to suit your workflow.
Click the GameScript icon in the IDE sidebar (Activity Bar in VS Code, Tool Window in Rider) to open the editor panel.
The Conversation Finder is your central hub for managing dialogue conversations.
Features:
- Search & Filter – Filter conversations by name, ID, tags, or any column
- Inline Editing – Double-click cells to edit names directly in the grid
- Multi-select – Select multiple conversations for bulk delete/restore
- Soft Delete – Deleted conversations can be restored; toggle visibility with the "Show Deleted" button
- Dynamic Tag Columns – Custom tag categories appear as filterable columns
Tag categories let you organize conversations with custom metadata. For example, create a "Status" category with values like "Draft", "In Review", and "Approved".
To create a tag category:
- Click the gear icon in the Conversation Finder toolbar to open Tag Category Settings
- Click Add Category and enter a name
- Select the category in the Inspector to add values
- A new column appears in the grid—assign values by editing cells
Property templates define custom data fields attached to conversations or nodes. Unlike tags (which are for organization), properties store game-relevant data that gets exported to your runtime.
Property types:
- String – Text values
- Integer – Whole numbers
- Decimal – Floating-point numbers
- Boolean – True/false checkboxes
To create a property template:
- Click the properties icon in the toolbar to open Property Template Settings
- Click Add Template and choose a name and type
- Optionally add predefined values (dropdown options) for non-boolean types
- Properties appear in the Inspector when editing conversations or nodes
The Graph Editor is where you design dialogue flows using a visual node-and-edge interface.
Node types:
- Root Node – The conversation entry point (auto-created, cannot be deleted)
- Dialogue Node – A line of dialogue spoken by an actor
- Logic Node – Runs conditions/actions without displaying text
Working with nodes:
- Create – Use the toolbar or right-click menu to add nodes
- Connect – Drag from an output port to an input port to create edges
- Select – Click nodes/edges or drag a selection box
- Delete – Press Delete or use the Graph menu
- Copy/Paste – Cmd/Ctrl+C and Cmd/Ctrl+V within the same conversation
Layout options:
- Auto Layout – Toggle automatic hierarchical arrangement (uses ELK layout engine)
- Vertical/Horizontal – Switch layout orientation via the Graph menu
- Manual Mode – Disable auto-layout to position nodes freely
Edge properties:
- Priority – Higher priority edges are evaluated first when multiple paths exist
- Type – "Default" (visible) or "Hidden" (internal flow, not shown to players)
Actors are the characters who speak dialogue lines.
Features:
- Create actors with auto-assigned colors
- Edit name, color, and notes inline or via Inspector
- Delete actors (nodes revert to the default actor)
- Localized names for multilingual character display names
A default "System" actor exists for narration or system messages and cannot be deleted.
Locales represent the languages your game supports.
Features:
- Create locales – Add new languages (e.g., "English", "French", "Japanese")
- Set primary locale – The primary language used as the source for translations
- Delete locales – Removes all translations for that language (cannot delete primary)
The Inspector panel (right side) shows context-sensitive properties for whatever you've selected.
Top bar buttons:
- Connection – Database connection status and configuration
- Settings – Project-wide settings (snapshot path, code output folder, auto-export)
Inspector content changes based on selection:
- Conversation – Name, notes, tags, custom properties, localizations link
- Node – Type, actor, voice text, UI response text, condition/action code toggles, custom properties
- Actor – Name, color, notes, localized name
- Locale – Name
- Tag Category – Name, list of values (add/edit/delete)
- Property Template – Name, type, predefined values
Settings panel:
- Snapshot Output Path – Where to export
.gsbbinary files - Code Output Folder – Where to generate condition/action code stubs
- Code Template – Target engine (Unity, Godot, Unreal)
- Export Now – Manually trigger snapshot export
Important: Before using GameScript, you must configure both the Snapshot Output Path and Code Output Folder in Settings. The snapshot path should point to a folder in your game project where the runtime can load
.gsbfiles (e.g.,Assets/StreamingAssets/GameScriptin Unity). The code output folder should point to where you want generated condition/action code stubs to live.
The Localization Editor lets you edit all translatable text across your project.
Grid columns:
- ID – Localization row identifier
- Conversation – Which conversation owns this text
- Name – Optional label for the localization
- Locale columns – One column per language containing the translated text
- Tag columns – Custom tag categories for organizing translations
Features:
- Inline editing – Click any cell to edit translations directly
- Search & Replace – Find and replace text across selected locales
- CSV Export – Download all translations for external editing
- CSV Import – Upload translations with validation and progress tracking
Use the table options menu (hamburger icon in the grid toolbar) to export and import localizations as CSV. This enables workflows with external translation tools:
- Export CSV – Download all localizations to a
.csvfile - Open in Google Sheets or Excel – Edit translations, send to translators, or use formulas
- Import CSV – Upload the modified file back into GameScript
The import process validates headers, reports mismatches, and lets you choose between "Update only" (existing rows) or "Upsert" (create missing rows) modes.
Similar to conversation tags, localization tags help organize your translations. Access tag settings via the gear icon in the Localization Editor toolbar.
Example use cases:
- "Voice Status" – Track which lines have been recorded
- "Review Status" – Mark translations as needing review
- "Context" – Categorize by in-game context (UI, cutscene, NPC dialogue)
GameScript can push and pull localizations directly to/from Google Sheets, enabling real-time collaboration with translators. Access these features via the Google Sheets dropdown menu in the Localization Editor toolbar.
Setup Steps:
-
Create a Google Cloud Project
- Go to Google Cloud Console
- Create a new project (or use an existing one)
-
Enable Required APIs
- Go to APIs & Services → Library
- Search for and enable:
- Google Sheets API
- Google Drive API
- Google Picker API
-
Configure OAuth Consent Screen
- Go to APIs & Services → OAuth consent screen
- Choose "External" user type (or "Internal" for Workspace accounts)
- Fill in the required fields (app name, support email)
- Add scopes:
https://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/userinfo.email
- Add your email as a test user (required for External apps in testing mode)
-
Create OAuth Client ID
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Choose "Desktop app" as the application type
- Note the Client ID and Client Secret
-
Configure GameScript
- Open GameScript Settings (gear icon in Inspector)
- In the Google Sheets section, click Configure
- Enter your Client ID and Client Secret
- Click Save Credentials
-
Sign In and Select Spreadsheet
- Click Sign In to authenticate with Google
- Click Select to choose a spreadsheet using Google Picker
- The selected spreadsheet will be used for Push/Pull operations
Using the Google Sheets Menu:
Once configured, the Google Sheets dropdown menu in the Localization Editor toolbar provides:
- Open in Browser – View the selected spreadsheet in your web browser
- Export to Sheets – Export all localizations to the spreadsheet (overwrites existing data)
- Import from Sheets – Import localizations from the spreadsheet (shows import confirmation dialog)
The spreadsheet will have columns matching your locales (ID, Name, English, French, etc.).
- Visual Graph Editor - Node-based dialogue authoring with drag-and-drop
- Multi-IDE Support - VS Code and JetBrains Rider plugins
- Native Code Integration - Conditions and actions written in C#/C++/GDScript
- Database-Backed - PostgreSQL for teams, SQLite for individuals
- Localization - Built-in multi-language support with CSV export
- Text Resolution - CLDR plural rules, grammatical gender, template substitution with typed args
- Binary Snapshots - FlatBuffers format for zero-copy runtime access
- Hot Reload - Automatic export on save, instant updates in-engine
- Undo/Redo - Full history with multiplayer resilience
- Golden Layout UI - Customizable panel arrangement
GameScript V3 includes a complete text resolution pipeline that produces identical results across all three runtimes (Unity, Unreal, Godot). The pipeline runs automatically before text is delivered to your listener callbacks.
Each localization entry can have multiple text variants indexed by plural category (Zero, One, Two, Few, Many, Other) and gender category (Masculine, Feminine, Neuter, Other). The resolver picks the best match using a three-pass fallback: exact match, gender fallback to Other, then catch-all (Other/Other).
Full Unicode CLDR cardinal and ordinal plural rules are implemented natively in each runtime. Decimal operand support (i, v, w, f, t) enables correct category selection for numbers like "1.0" vs "1" in languages that distinguish them. Pass a PluralArg with Value and Precision to drive both plural selection and numeric substitution.
Gender is resolved automatically from the snapshot: each localization can reference a subject actor whose grammatical gender (Masculine, Feminine, Neuter, Other, Dynamic) drives variant selection. Alternatively, a direct gender override on the localization entry or via TextResolutionParams.GenderOverride at runtime gives full control.
Localization text can contain {placeholder} tokens. The runner substitutes values from typed arguments:
| Arg Type | Example | Description |
|---|---|---|
| String | Arg.String("player", "Ada") |
Plain string substitution |
| Int | Arg.Int("count", 1000) |
Locale-aware integer ("1,000") |
| Decimal | Arg.Decimal("rate", 314, 2) |
Locale-aware decimal ("3.14") |
| Percent | Arg.Percent("chance", 155, 1) |
Locale-aware percentage ("15.5%") |
| Currency | Arg.Currency("price", 1999, "USD") |
Locale-aware currency ("$19.99") |
| RawInt | Arg.RawInt("id", 42) |
Unformatted integer ("42") |
Currency formatting uses ISO 4217 for decimal place lookup. The PluralArg drives both plural category selection and numeric template substitution.
The runner calls OnSpeechParams / OnDecisionParams on your listener before resolving text, giving you the opportunity to provide TextResolutionParams (gender override, plural arg, typed args). The resolved text is then delivered as a ready-to-display string via OnSpeech(node, voiceText, ...) and OnDecision(choices, ...).
gamescript/
├── core/ # Core schemas and generated code
│ ├── schema/ # FlatBuffer schemas (.fbs)
│ └── generated/ # Auto-generated code
│ ├── ts/ # TypeScript (UI, IDE plugins)
│ ├── csharp/ # C# (Unity, .NET IDEs)
│ └── cpp/ # C++ (Unreal)
│
├── shared/ # Shared TypeScript package
│ └── src/ # Types, query builders, utilities
│
├── ui/ # Svelte web UI (graph editor)
│ ├── src/
│ │ ├── lib/
│ │ │ ├── api/ # Bridge to IDE plugins
│ │ │ ├── components/ # Svelte components
│ │ │ ├── db/ # Database abstraction layer
│ │ │ └── stores/ # Svelte stores
│ │ └── routes/ # SvelteKit routes
│ └── dist/ # Built assets
│
├── plugins/
│ ├── vscode/ # VS Code extension
│ │ └── src/
│ │ ├── database.ts # SQLite/PostgreSQL connections
│ │ ├── panel.ts # Webview panel management
│ │ └── handlers/ # Message handlers
│ ├── rider/ # JetBrains Rider plugin (Kotlin)
│ │ └── src/main/kotlin/
│ └── dotnet/ # Shared .NET code (future)
│
├── runtimes/
│ ├── unity/ # Unity package
│ │ └── Packages/studio.shortsleeve.gamescript/
│ ├── csharp/ # Shared C# runtime code
│ ├── godot/ # Godot 4.x addon
│ │ ├── gdextension/ # C++ GDExtension source
│ │ └── project/addons/ # GDScript runtime
│ └── unreal/ # Unreal Engine plugin
│ ├── Source/ # C++ runtime and editor modules
│ └── ThirdParty/ # FlatBuffers library
│
└── tools/ # CLI tools (planned)
The web-based graph editor built with:
- Svelte 5 - Reactive UI framework
- SvelteKit - Build tooling and routing
- @xyflow/svelte - Node graph visualization
- Golden Layout - Dockable panel system
- ELK - Automatic graph layout
The UI is embedded in IDE plugins via webview and communicates through a message bridge.
TypeScript package containing:
- Database schema types
- SQL query builders
- FlatBuffer type definitions
- Shared utilities
Extension providing:
- Webview panel hosting the UI
- SQLite and PostgreSQL database connections
- File system access for code generation
- Binary snapshot export
Kotlin-based plugin for JetBrains Rider:
- JCEF browser hosting the UI
- Same database and file system capabilities as VS Code
- Native IDE integration
Unity package providing:
- FlatBuffer snapshot loading
- Dialogue state machine with text resolution pipeline
- Attribute-based function binding
- CLDR plural rules, gender resolution, template substitution
- Editor tooling
Godot 4.x addon providing:
- C++ GDExtension for FlatBuffer parsing
- GDScript dialogue execution engine with text resolution pipeline
- CLDR plural rules, gender resolution, template substitution
- Custom Inspector plugins for ID types
- Export validation
Unreal Engine plugin providing:
- FlatBuffer snapshot loading
- Dialogue state machine with UGameplayTask support and text resolution pipeline
- Macro-based function binding (NODE_CONDITION/NODE_ACTION)
- CLDR plural rules, gender resolution, template substitution
- Custom property drawers and picker windows
- Pre-PIE build validation
- IPC integration with GameScript IDE
Install via the Unity Package Manager using a Git URL:
- Open Window > Package Manager
- Click the + button and select Add package from git URL...
- Enter:
Replace
https://github.com/ShortSleeveStudio/GameScript.git?path=/runtimes/unity/Packages/studio.shortsleeve.gamescript#vX.Y.ZvX.Y.Zwith the desired version tag (e.g.,v3.0.0).
Godot does not have a built-in package manager with Git URL support. Install manually:
- Download the release ZIP from the Releases page
- Extract the
addons/gamescript/folder - Copy it to your project's
res://addons/directory - Enable the plugin in Project > Project Settings > Plugins
Alternatively, clone the repository and copy runtimes/godot/project/addons/gamescript/ to your project.
Unreal does not support Git URL installation for plugins. Install manually:
- Download the release ZIP from the Releases page
- Extract the plugin folder
- Copy it to your project's
Plugins/GameScript/directory (createPlugins/if it doesn't exist) - Regenerate project files (right-click
.uproject→ Generate Visual Studio project files) - Enable the plugin in Edit → Plugins, search for "GameScript"
- Restart the editor when prompted
Alternatively, build from source:
cd runtimes/unreal
./setup_flatbuffers.sh # Fetch FlatBuffers dependency
./build.sh # Build plugin to Build/ directory
# Then copy Build/ to your project's Plugins/GameScript/See runtimes/unreal/INSTALLATION.md for detailed installation and usage instructions, including VSCode IntelliSense setup for the code preview feature.
- Node.js 18+
- pnpm 8+
- JDK 17+ (for Rider plugin)
pnpm installpnpm buildBuilds in dependency order:
shared/- TypeScript utilitiesui/- Svelte web UIplugins/vscode/- VS Code extension
pnpm devRuns all packages in watch mode with hot reload.
pnpm build:riderOr manually:
cd plugins/rider
./gradlew buildPluginThe built plugin ZIP will be in plugins/rider/build/distributions/.
pnpm test# UI tests
pnpm --filter @gamescript/ui test
# Shared package tests
pnpm --filter @gamescript/shared test- Open the repository root in VS Code
- Run
pnpm build - Press F5 to launch Extension Development Host
- Click the GameScript icon in the Activity Bar
pnpm dev:riderThis builds the UI and launches a sandboxed Rider instance with the plugin.
pnpm package:vscodeCreates .vsix file in plugins/vscode/.
pnpm package:riderCreates plugin ZIP in plugins/rider/build/distributions/.
| Command | Description |
|---|---|
pnpm install |
Install all dependencies |
pnpm build |
Build all packages |
pnpm build:rider |
Build Rider plugin |
pnpm dev |
Run all packages in watch mode |
pnpm dev:rider |
Build UI and run Rider sandbox |
pnpm test |
Run all tests |
pnpm lint |
Run linters |
pnpm format |
Format code with Prettier |
pnpm clean |
Remove build artifacts |
pnpm package:vscode |
Package VS Code extension |
pnpm package:rider |
Package Rider plugin |
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Graph UI │ ──▶ │ Database │ ──▶ │ .gsb File │
│ (Svelte) │ │ (SQL/Postgres)│ │ (FlatBuffer)│
└─────────────┘ └──────────────┘ └─────────────┘
│ │
│ Messages │ Load
▼ ▼
┌─────────────┐ ┌─────────────┐
│ IDE Plugin │ │ Engine │
│(VSCode/Rider)│ │ Runtime │
└─────────────┘ └─────────────┘
Actions and conditions are written in native code with attribute markers:
// Unity C# example
[NodeCondition(456)]
public static bool HasEnoughGold(IDialogueContext ctx)
{
return GameState.PlayerGold >= 10;
}
[NodeAction(456)]
public static async Awaitable HandOverGold(IDialogueContext ctx, CancellationToken token)
{
GameState.PlayerGold -= 10;
await AnimationManager.Play("hand_over_gold", token);
}// Unreal C++ example
NODE_CONDITION(456)
bool HasEnoughGold(const IDialogueContext* Context)
{
return GameState->PlayerGold >= 10;
}
NODE_ACTION(456)
UGameplayTask* HandOverGold(const IDialogueContext* Context)
{
GameState->PlayerGold -= 10;
return UDialogueAction_PlayAnim::CreateTask(Context, HandOverGoldAnim);
}At runtime, the engine builds jump tables for O(1) function dispatch.
- SQLite - Single-user, file-based, no setup required
- PostgreSQL - Multi-user, real-time collaboration via LISTEN/NOTIFY
Both support the same schema and UI. Switch between them in the connection panel.
Export format uses FlatBuffers for:
- Zero-copy memory mapping
- O(1) random access
- Minimal memory footprint
- Per-locale bundles
If you experience slow or jerky scrolling in the Rider plugin, disable out-of-process JCEF:
- Go to Help → Find Action (or press
Ctrl+Shift+A/Cmd+Shift+A) - Search for "Registry..."
- Find
ide.browser.jcef.out-of-process.enabled - Uncheck it
- Restart Rider
See VERSIONING.md for the list of files that need version bumps.
- ARCHITECTURE.md - Overall system architecture
- ARCHITECTURE_UNITY.md - Unity runtime details
- ARCHITECTURE_GODOT.md - Godot runtime details
- ARCHITECTURE_UNREAL.md - Unreal runtime details
See LICENSE.md.










