Skip to main content
Reading time: ~30 minutes
The Unreal system is CORP’s game packaging and management framework. It provides a modular approach to organizing your game through Gamepacks - self-contained packages of assets, components, macros, and scripts.

Table of Contents

What is Unreal?

The Unreal system is CORP’s solution for:
  • Modular Game Organization: Package features into independent Gamepacks
  • Asset Management: Centralized asset loading and validation
  • Component Registration: Automatic component discovery and mapping
  • Script Management: Organized client and server script execution
  • Game Configuration: Flexible authority and boot configuration

Key Features

  • 📦 Gamepack System: Modular package organization
  • 🎮 Authority Models: Client or server-authoritative games
  • 🔧 Export Mappings: Components, Macros, and ScriptableObjects
  • 📜 Script Management: Automatic client/server script placement
  • 🚀 Bootstrap System: Configurable game initialization

Gamepacks

Gamepacks are the fundamental building blocks of the Unreal system. Each Gamepack is a self-contained module that can export:
  • Components
  • Macros
  • ScriptableObjects
  • Assets
  • Client Scripts
  • Server Scripts
  • Boot Configuration

Gamepack Structure

MyGamepack/
├── metadata.ts          # Gamepack configuration
├── exports/
│   ├── components.ts    # Component mappings
│   ├── macros.ts        # Macro mappings
│   ├── scriptableobjects.ts  # ScriptableObject mappings
│   ├── bootconfig.ts    # Boot configuration
│   └── scripts/
│       ├── client/      # Client scripts
│       └── server/      # Server scripts
├── assets/              # Asset folder
└── src/                 # Source code

Project Structure

Typical CORP Project with Unreal

your-game/
├── CORP/               # Git submodule (must be named "CORP")
├── GAMECONFIG/
│   └── gameinfo.ts    # Game configuration
├── GAMEPACKS/
│   ├── CorePack/      # Git submodule - core game systems
│   │   ├── metadata.ts
│   │   ├── exports/
│   │   └── assets/
│   ├── PlayerPack/    # Git submodule - player systems
│   │   ├── metadata.ts
│   │   └── exports/
│   └── EnemyPack/     # Git submodule - enemy systems
│       ├── metadata.ts
│       └── exports/
└── src/
    ├── client/
    ├── server/
    └── shared/
Important: The CORP source code must be a git submodule named “CORP” in your repository. Each Gamepack should also be a git submodule for modularity and version control.

Setting Up Submodules

# Add CORP as a submodule
git submodule add <CORP-repo-url> CORP

# Add Gamepacks as submodules
git submodule add <gamepack-repo-url> GAMEPACKS/CorePack
git submodule add <gamepack-repo-url> GAMEPACKS/PlayerPack

Configuration

Game Info Configuration

Create GAMECONFIG/gameinfo.ts:
import { Unreal } from "CORP/shared/unreal";

const gameinfo: Unreal.Gameinfo = {
    rootPack: "CorePack",  // Root Gamepack to boot
    authority: Unreal.Authority.SERVER  // Authority model
};

export = gameinfo;

Authority Models

// Server-Authoritative (recommended for multiplayer)
authority: Unreal.Authority.SERVER

// Client-Authoritative (for single-player experiences)
authority: Unreal.Authority.CLIENT
Important: Workspace.StreamingEnabled should be disabled for client-authoritative games to ensure all game content is loaded immediately.

Gamepack Metadata

Create metadata.ts in your Gamepack:
import { Gamepacks } from "CORP/shared/unreal/gamepacks";

const metadata: Gamepacks.Config.Metadata = {
    name: "MyGamepack",
    
    // Development options
    development: {
        npm: {
            includeLockfile: true,
            includePackageJson: true
        }
    },
    
    // Packaging options
    packaging: {
        npm: {
            packageDependencies: true
        },
        obfuscation: {
            engine: "luraph"
        }
    },
    
    // Gamepack structure
    options: {
        assets: {},              // Include assets folder
        source: {},              // Include source code
        exports: {
            components: {},       // Export components
            macros: {},          // Export macros
            scriptableObjects: {}, // Export ScriptableObjects
            scripts: {
                client: {},      // Export client scripts
                server: {}       // Export server scripts
            },
            boot: {}             // Export boot config
        }
    }
};

export = metadata;

Bootstrap Process

How Unreal Bootstraps Your Game

  1. Load Game Info: Reads GAMECONFIG/gameinfo.ts
  2. Parse Gamepacks: Discovers and parses all Gamepacks in GAMEPACKS/
  3. Build Manifest: Creates game manifest with all exports
  4. Setup Assets: Organizes assets into centralized location
  5. Register Scripts: Places client/server scripts
  6. Execute Boot Config: Runs root Gamepack’s boot configuration

Using Bootstrap

In your client and server entry points:
// client/index.client.ts
import { Unreal } from "CORP/shared/unreal";

Unreal.bootstrap();
// server/index.server.ts
import { Unreal } from "CORP/shared/unreal";

Unreal.bootstrap();

Boot Configuration

Create exports/bootconfig.ts in your root Gamepack:
import { Boot } from "CORP/shared/unreal/gamepacks/boot";

const bootConfig: Boot.Config = {
    // Start game from existing workspace instances
    startFromWorkspace: true
};

export = bootConfig;
Boot Options:
  • startFromWorkspace: Load GameObjects from workspace with tags:
    • GameObjectSceneRoot: Main scene container
    • GameObjectContainer: Additional containers

Exports System

Exporting Components

Create exports/components.ts:
import { Config } from "CORP/shared/unreal/gamepacks/config";
import { PlayerController } from "../src/components/PlayerController";
import { EnemyAI } from "../src/components/EnemyAI";
import { HealthSystem } from "../src/components/HealthSystem";
import { NetworkObject } from "CORP/shared/networking/network-object";

const components: Config.Components = {
    mappings: {
        // Use snake_case for mapping names
        "player_controller": PlayerController,
        "enemy_ai": EnemyAI,
        "health_system": HealthSystem,
        
        // Core CORP components use $ prefix
        "$network_object": NetworkObject
    }
};

export = components;
Naming Convention: Use snake_case for all mapping names (components, macros, ScriptableObjects). Core CORP components are prefixed with $ (e.g., $network_object).

Exporting Macros

Create exports/macros.ts:
import { Config } from "CORP/shared/unreal/gamepacks/config";
import { PlayerMacro } from "../src/macros/PlayerMacro";
import { SpawnPointMacro } from "../src/macros/SpawnPointMacro";

const macros: Config.Macros = {
    mappings: {
        // Use snake_case for macro names
        "player_macro": PlayerMacro,
        "spawn_point_macro": SpawnPointMacro
    }
};

export = macros;
Note: See Macros for detailed information about creating and using macros.

Exporting ScriptableObjects

Create exports/scriptableobjects.ts:
import { Config } from "CORP/shared/unreal/gamepacks/config";
import { WeaponData } from "../src/scriptableobjects/WeaponData";
import { EnemyData } from "../src/scriptableobjects/EnemyData";

const scriptableObjects: Config.ScriptableObjects = {
    mappings: {
        // Use snake_case for ScriptableObject names
        "weapon_data": WeaponData,
        "enemy_data": EnemyData
    }
};

export = scriptableObjects;
Note: See ScriptableObjects for detailed information about creating and using ScriptableObjects.

Authority Models

Server-Authoritative

Best for multiplayer games where server controls game state.
// GAMECONFIG/gameinfo.ts
authority: Unreal.Authority.SERVER
Characteristics:
  • Server spawns and manages NetworkObjects
  • Server validates all game logic
  • Clients replicate server state
  • Ideal for competitive multiplayer
Example:
export class GameManager extends Behavior {
    public onStart(): void {
        if (Unreal.isAuthority()) {
            // Server-side initialization
            this.spawnEnemies();
            this.setupGameLogic();
        } else {
            // Client-side initialization
            this.setupUI();
        }
    }

    protected getSourceScript(): ModuleScript {
        return script as ModuleScript;
    }

    public willRemove(): void {}
}

Client-Authoritative

Best for single-player or cooperative games.
// GAMECONFIG/gameinfo.ts
authority: Unreal.Authority.CLIENT
Characteristics:
  • Client controls game state
  • Reduced server validation
  • Lower network overhead
  • Ideal for single-player or trusted environments
Warning: Set Workspace.StreamingEnabled = false for client-authoritative games.

Checking Authority

import { Unreal } from "CORP/shared/unreal";

export class GameController extends Behavior {
    public onStart(): void {
        if (Unreal.isAuthority()) {
            // Authority (server or client based on config)
            this.initializeGameState();
        } else {
            // Non-authority
            this.waitForReplication();
        }
    }

    protected getSourceScript(): ModuleScript {
        return script as ModuleScript;
    }

    public willRemove(): void {}
}

Working with the Manifest

Accessing the Game Manifest

import { Unreal } from "CORP/shared/unreal";

// Get the complete manifest
const manifest = Unreal.getManifest();

// Access component mappings
const components = manifest.components;

// Access macro mappings
const macros = manifest.macros;

// Access ScriptableObject mappings
const scriptableObjects = manifest.scriptableObjects;

// Access game info
const gameinfo = manifest.gameinfo;

Getting Registered Classes

import { Unreal } from "CORP/shared/unreal";

// Get a component class by name
const PlayerClass = Unreal.getComponentClass("PlayerController");

// Get a macro class by name
const SpawnMacro = Unreal.getMacroClass("SpawnPointMacro");

// Get a ScriptableObject class by name
const WeaponDataClass = Unreal.getScriptableObjectClass("WeaponData");

Managing Scripts

Client Scripts

Place client scripts in exports/scripts/client/:
// exports/scripts/client/ClientSetup.client.ts
import { Players } from "@rbxts/services";

print("Client script loaded!");

Players.LocalPlayer.CharacterAdded.Connect((character) => {
    print("Character spawned!");
});
These scripts are automatically placed in PlayerScripts.

Server Scripts

Place server scripts in exports/scripts/server/:
// exports/scripts/server/ServerSetup.server.ts
import { Players } from "@rbxts/services";

print("Server script loaded!");

Players.PlayerAdded.Connect((player) => {
    print(`Player ${player.Name} joined!`);
});
These scripts are automatically placed in ServerScriptService.

Asset Management

Adding Assets to a Gamepack

  1. Create an assets/ folder in your Gamepack
  2. Enable assets in metadata:
options: {
    assets: {}
}
  1. Place asset folders in assets/:
MyGamepack/
├── assets/
│   ├── Models/
│   │   ├── Player.rbxm
│   │   └── Enemy.rbxm
│   ├── Sounds/
│   └── UI/
  1. During bootstrap, assets are collapsed - all Gamepack assets are collected and organized into a centralized location in the game for easy access

Accessing Assets

Assets are accessed through the Virtual File System (VFS), which provides a unified path interface:
import { vfs } from "CORP/shared/utilities/vfs";

// Read an asset using the %assets% shorthand
const model = vfs.read<Model>("%assets%/Models/Player", {
    classname: "Model"
});

// %assets% is equivalent to $collapsed/$assets in the VFS
// Both paths reference the same centralized asset location
VFS Path Convention: Use %assets% as a shorthand for the collapsed assets directory. The VFS automatically resolves this to the actual location where all Gamepack assets are stored.

Complete Example

Example Gamepack Setup

1. Game Configuration

// GAMECONFIG/gameinfo.ts
import { Unreal } from "CORP/shared/unreal";

const gameinfo: Unreal.Gameinfo = {
    rootPack: "CoreGamepack",
    authority: Unreal.Authority.SERVER
};

export = gameinfo;

2. Gamepack Metadata

// GAMEPACKS/CoreGamepack/metadata.ts
import { Gamepacks } from "CORP/shared/unreal/gamepacks";

const metadata: Gamepacks.Config.Metadata = {
    name: "CoreGamepack",
    options: {
        assets: {},
        exports: {
            components: {},
            boot: {}
        }
    }
};

export = metadata;

3. Component Exports

// GAMEPACKS/CoreGamepack/exports/components.ts
import { Config } from "CORP/shared/unreal/gamepacks/config";
import { PlayerController } from "../src/PlayerController";
import { GameManager } from "../src/GameManager";

const components: Config.Components = {
    mappings: {
        "PlayerController": PlayerController,
        "GameManager": GameManager
    }
};

export = components;

4. Boot Configuration

// GAMEPACKS/CoreGamepack/exports/bootconfig.ts
import { Boot } from "CORP/shared/unreal/gamepacks/boot";

const bootConfig: Boot.Config = {
    startFromWorkspace: true
};

export = bootConfig;

5. Bootstrap

// client/index.client.ts & server/index.server.ts
import { Unreal } from "CORP/shared/unreal";

Unreal.bootstrap();

Best Practices

1. Organize by Feature

Create separate Gamepacks for major features:
GAMEPACKS/
├── CorePack/       # Core systems
├── PlayerPack/     # Player mechanics
├── CombatPack/     # Combat systems
├── UIPack/         # UI components
└── MapPack/        # Level assets

2. Use snake_case for Mapping Names

// ✓ Good - snake_case, clear and descriptive
mappings: {
    "player_controller": PlayerController,
    "enemy_ai": EnemyAI,
    "health_system": HealthSystem,
    "$network_object": NetworkObject  // Core CORP components use $ prefix
}

// ✗ Bad - inconsistent casing
mappings: {
    "PlayerController": PlayerController,
    "enemyAI": EnemyAI
}

// ✗ Bad - unclear abbreviations
mappings: {
    "pc": PlayerController,
    "ai": EnemyAI
}

3. Choose Appropriate Authority

// ✓ Good for multiplayer
authority: Unreal.Authority.SERVER

// ✓ Good for single-player
authority: Unreal.Authority.CLIENT

// Note: Consider security and game type

4. Validate Gamepack Structure

Ensure your Gamepack has proper metadata before adding exports:
// Always include name
name: "MyGamepack",

// Enable options you use
options: {
    assets: {},     // Only if you have assets
    exports: {
        components: {},  // Only if exporting components
        // etc.
    }
}

5. Keep Root Gamepack Minimal

The root Gamepack should primarily handle bootstrapping:
// Root Gamepack - minimal boot config
const bootConfig: Boot.Config = {
    startFromWorkspace: true
};

// Other Gamepacks - feature implementation

6. Use Authority Checks

export class MyComponent extends Behavior {
    public onStart(): void {
        if (Unreal.isAuthority()) {
            // Authority-only logic
        } else {
            // Replication logic
        }
    }
}

Troubleshooting

Common Issues

“Root gamepack not found”
  • Ensure rootPack name matches a Gamepack’s metadata name
  • Check Gamepack is in GAMEPACKS/ folder
“No scene root found in workspace”
  • Tag a container with GameObjectSceneRoot
  • Ensure startFromWorkspace: true in boot config
“Component mapping conflict”
  • Different Gamepacks export same component name
  • Use unique names across Gamepacks
Streaming warning with client authority
  • Set Workspace.StreamingEnabled = false in Roblox Studio
  • This ensures all content loads immediately for client authority
  • Or switch to Unreal.Authority.SERVER

Next Steps


Master the Unreal system for modular, scalable game organization! 📦