BPVM Snack Pack #4 - Skeleton Classes: The Hidden Hero | ebp BPVM Snack Pack #4 - Skeleton Classes: The Hidden Hero | ebp BPVM Snack Pack #4 - Skeleton Classes: The Hidden Hero | ebp
Post

BPVM Snack Pack #4 - Skeleton Classes: The Hidden Hero

How does Blueprint A reference Blueprint B when B isn't compiled yet? The skeleton class - Blueprint's version of forward declarations.

BPVM Snack Pack #4 - Skeleton Classes: The Hidden Hero

The content in this post is based on Unreal Engine 5.4.0

BPVM Snack Pack - Bite-sized Blueprint knowledge! Part of the Blueprint to Bytecode series.

The Circular Dependency Problem

Here’s a common scenario in multiplayer games:

1
2
3
Blueprint_PlayerController references Blueprint_GameMode
Blueprint_GameMode references Blueprint_PlayerState
Blueprint_PlayerState references Blueprint_PlayerController

Classic circular dependency. How do you compile these without deadlock?

The C++ Way (Doesn’t Work Here)

In C++, you’d use forward declarations:

1
2
3
4
5
6
class AMyGameMode;  // Forward declaration

class AMyPlayerController : public APlayerController
{
    AMyGameMode* GameMode;  // Use the forward declaration
};

But Blueprints compile at runtime (or on-demand in editor). You can’t just “forward declare” a Blueprint!

The Solution: Skeleton Classes

Unreal solves this with a two-pass approach. During Stage VIII (Recompile Skeleton), it creates a “skeleton” version of each Blueprint class:

1
2
3
4
5
6
7
8
9
10
11
12
// Skeleton class: Just the structure, no implementation
class BP_PlayerController_SKEL : public APlayerController
{
    // Has all the properties
    UPROPERTY()
    ABP_GameMode* GameMode;

    // Has all the function signatures
    void DoSomething();

    // But NO bytecode yet!
};

Think of it like a header file (.h) in C++, but generated at compile-time for Blueprints.

How It Solves Circular Dependencies

Phase 1 - Create Skeletons:

1
2
3
4
// For each Blueprint, create skeleton FIRST
BP_PlayerController_SKEL  // Just the shape
BP_GameMode_SKEL          // Just the shape
BP_PlayerState_SKEL       // Just the shape

Phase 2 - Full Compile:

1
2
3
4
// Now everyone can reference the skeletons!
BP_PlayerController references BP_GameMode_SKEL 
BP_GameMode references BP_PlayerState_SKEL 
BP_PlayerState references BP_PlayerController_SKEL 

No circular dependency! Everyone has something to reference.

What’s in a Skeleton?

A skeleton class contains:

Variable declarations (with types)

1
2
3
4
5
UPROPERTY()
float Health;  // Type is known

UPROPERTY()
ABP_Enemy* Enemy;  // Type is known

Function signatures (parameters and return types)

1
2
3
4
5
UFUNCTION()
void TakeDamage(float Amount);  // Signature is known

UFUNCTION()
float GetHealth();  // Return type is known

NO bytecode (the actual function implementation)

1
2
3
4
5
// Function exists but body is empty:
void TakeDamage(float Amount)
{
    // Nothing here yet!
}

The Two-Pass Compilation

This is why Blueprint compilation happens in two major phases:

Pass 1 - Skeleton Only (Fast):

  • Create class structure
  • Add all properties
  • Add all function signatures
  • NO bytecode generation

Pass 2 - Full Compile (Slower):

  • Generate bytecode for all functions
  • Fill in the implementation details
  • Update all instances

When Do You See Skeletons?

You rarely see skeleton classes directly, but they’re working behind the scenes:

Scenario 1 - Opening a Blueprint:

1
2
3
4
OpenBlueprint(BP_MyActor);
// Quick skeleton compile happens
// → Can now see variables/functions in editor
// Full compile happens when you click "Compile"

Scenario 2 - Circular References:

1
2
3
4
5
BP_A references BP_B
BP_B references BP_A
// Both get skeleton classes first
// Then both get fully compiled
// → No deadlock!

Scenario 3 - Loading Game:

1
2
3
LoadLevel(MyLevel);
// Skeletons for all Blueprints load first
// Then full compiles happen in dependency order

The SKEL Naming Convention

If you ever see this in logs or crashes:

1
BP_MyActor_C_SKEL

That _SKEL suffix means you’re looking at a skeleton class. The _C is the generated class suffix.

Quick Takeaway

  • Skeleton Class = Class header (properties + function signatures, no implementation)
  • Created in Stage VIII of compilation
  • Solves circular dependencies by providing “something to reference”
  • Think of it as a smart forward declaration
  • Gets replaced by full class after bytecode generation

Why This Matters

Understanding skeletons helps you:

  • Debug “missing function” errors (skeleton compiled, full compile failed)
  • Understand why compilation happens in passes
  • Know why circular dependencies usually work (but can still cause issues if not careful)

Want More Details?

For the complete explanation with code examples:

Next snack: We’ll peek inside the “Clean and Sanitize” process!


🍿 BPVM Snack Pack Series

This post is licensed under CC BY 4.0 by the author.