Diagram of the Colony Upgradable Buildings System showing the flow from BP_LoadUnloadUpgrades to PCG and metadata actors.

Colony Upgradable Buildings System

01

Problem

For Colony, a mobile AI-drive simulation game uour players had the option of evolving the colony over time. Our upgradable city needed to feel alive and responsive, and we needed to do that without turning level maintenance into a full-time job.

We had:

  • A compact map with 16 core buildings
  • Each building with 4 states (empty plot → upgrade level 03)
  • Every state affecting art, activities, gameplay hooks, and backend data

The original approach relied on multiple sublevels and a lot of manual setup:

  • ❌ Duplicated sublevels per building state
  • ❌ Per-actor configuration of gameplay tags and attributes
  • ❌ Manually placed and wired activity blueprints
  • ❌ Repeated setup whenever we added a new feature or iterated on the map
  • ❌ Unreal Engine was not managing to instantiate things properly, and batching was being broken.

This resulted in roughly 240–270 manual touchpoints per pass. With even a 5–10% error rate on hand edits, the system didn’t scale for fast iteration, new features, or future maps and larger city layouts.


02

Solution

I built a PCG-driven upgrade system in Unreal Engine 5 that turns artist-authored levels into an automated pipeline, centered around a single Blueprint:

1. BP_LoadUnloadUpgrades – driving the PCG

  • A Blueprint called BP_LoadUnloadUpgrades controls which state each building should be in.
  • It reads our custom Upgrade Levels Config (a struct per building state) and:
    • Selects the PCG target slot name (which PCG Volume / graph slot to talk to).
    • Picks the correct PCG Building Data Asset for the current upgrade level.
  • It then:
    • Finds the relevant PCG Volume in the level.
    • Sets the graph object parameters (data asset, level to load, tags).
    • Calls Generate on the PCG component.

In short: the Blueprint decides “what state is this building in, and which PCG data asset should we use?” and hands that to PCG.

2. PCG graph – instancing the art

Once the PCG component is configured:

  • The PCG graph loads the assigned PCG Data Asset.
  • It uses that data to instance all meshes for the chosen building state (empty → L3) instead of manually placed actors.
  • Each building type (Barracks, Hydro, Med Bay, etc.) flows through the same PCG logic; only the data asset changes.

This keeps all visual content for each state in data assets + level instances, not scattered across sublevels.

3. PCG graph – spawning metadata actors

After the art is in place, the same PCG graph:

  • Analyzes the bounds of the loaded building level.
  • Spawns lightweight metadata actors in those bounds.
  • Passes in data from BP_LoadUnloadUpgrades via graph parameters:
    • Building gameplay tag (e.g. LocationTag.Greenhouse)
    • Upgrade level
    • Slot / building identifier

So PCG doesn’t just draw the building — it also drops in the actors that will hold all gameplay-relevant information for that location, and setting up triggers for the touch events as well as the backend events so the nameplates and other UI elements are updated.

4. PostProceduralGenerationSpawn – self-initialising actors

To keep the logic out of the graph nodes themselves, we rely on a single hook:

  • After PCG finishes, it calls PostProceduralGenerationSpawn.
  • Newly created metadata actors listen to this and configure themselves:
    • Gameplay Tags
      Building type, upgrade tier, status, and any other tags designers or engineers need.
    • Attributes / variables
      Upgrade level, building name, current status, custom flags for backend and analytics.

This means any actor spawned by PCG knows how to “boot up” correctly without manual tagging or per-actor setup.

5. Data-driven configuration

All of this is backed by a small config struct on BP_LoadUnloadUpgrades:

  • For each upgrade level we set:
    • The PCG Building Data Asset (what PCG uses to instance meshes and metadata).
  • Shared fields like the Building Tag (e.g. LocationTag.Greenhouse) live next to that config and are pushed both:
    • Into the PCG graph (for filtering/spawning logic).
    • Into the metadata actors (so they know what they represent).

Changing how a building behaves is mostly a matter of editing this config, not touching dozens of actors.


03

Outcome

  • ⏱️ From ~270 manual edits to zero per pass
    Upgrades, tags, activity actors, and level loading are now driven entirely by BP_LoadUnloadUpgrades + PCG.

  • Consistent data across disciplines
    Design, tech art, and backend all read from the same PCG-spawned metadata actors, so there’s no configuration drift between sublevels.

  • Fast, low-risk iteration
    Adding a new building feature usually means:

    • Extending the config struct and PCG graph, and
    • Updating a bit of PostProceduralGenerationSpawn logic – not re-tagging hundreds of actors.
  • 🎨 Artists stay in DCC / level land
    Artists focus on authoring the base level and per-state level instances. The system takes care of:

    • Picking the right state,
    • Instancing the meshes,
    • Spawning metadata actors,
    • And wiring all tags and attributes automatically.

Portfolio | Sergi Carrion