BPVM Snack Pack #6 - The CDO Mystery: Your Class's Secret Template
Every Blueprint class has a hidden template object that nobody talks about. Meet the CDO - the mysterious instance that defines what 'default' really means.
TL;DR — Every Unreal class has a Class Default Object (CDO): a real instance created automatically when the class loads that acts as the template for all future spawns. Editing “Default” values in the Blueprint editor writes directly to the CDO, spawning copies its properties, and defaults survive recompilation because the old CDO’s values are copied into the new one—never modify a CDO at runtime.
The content in this post is based on Unreal Engine 5.6.0
BPVM Snack Pack - Quick Blueprint knowledge drops! Part of the Blueprint to Bytecode series.
The Mystery Object
You’ve created a Blueprint class. You haven’t spawned any instances yet. But surprise - an instance already exists.
It’s called the Class Default Object (CDO), and it’s been quietly living in memory since your class was loaded.
What Is a CDO?
Think of the CDO as the master mold for your class:
1
2
3
4
5
// When you create BP_MyActor...
UClass* MyClass = BP_MyActor::StaticClass();
// This already exists!
AActor* CDO = MyClass->GetDefaultObject(); // The secret instance
The CDO is:
- A real instance of your class (it’s an actual object in memory!)
- Created automatically when the class loads
- Never spawned in the world (it exists in limbo)
- The template for all future instances
Why Does Every Class Need One?
Problem: When you spawn an actor, where do its default values come from?
Bad Solution: Store defaults as metadata somewhere
1
2
3
4
5
6
// Imaginary bad design
class ClassMetadata {
float DefaultHealth = 100;
FString DefaultName = "Player";
// Hundreds of properties...
};
Unreal’s Solution: Just create one “perfect” instance and copy from it!
1
2
3
4
5
6
7
// The CDO IS the defaults
AActor* CDO = GetDefault<AActor>();
CDO->Health = 100; // Set once
CDO->Name = "Player";
// Spawning copies from CDO
AActor* NewActor = SpawnActor(); // Copies all properties from CDO
The Magic Moment
When you edit “Default” values in the Blueprint editor:
You’re not editing metadata. You’re editing the CDO directly!
1
2
3
4
5
// In Blueprint Editor, when you set Health = 100
CDO->Health = 100; // You're literally setting a property on the CDO
// Later, when spawning
NewInstance->Health = CDO->Health; // Copy from CDO
CDO in Action
Here’s the lifecycle:
1. Class Creation
1
2
3
4
5
// Blueprint gets compiled
UBlueprintGeneratedClass* NewClass = CompileBlueprint();
// CDO is created immediately
UObject* CDO = NewClass->GetDefaultObject();
2. Setting Defaults
1
2
3
4
// You edit in Blueprint editor
CDO->MaxHealth = 150;
CDO->TeamColor = FColor::Red;
CDO->WeaponClass = AK47::StaticClass();
3. Instance Creation
1
2
3
4
5
6
7
// Player spawns your actor
AActor* Instance = World->SpawnActor<AActor>(BP_MyActor);
// Under the hood:
// 1. Allocate memory
// 2. Copy all properties from CDO
// 3. Run constructor
The Revert Button Mystery
Ever wondered how the “Revert to Default” button works?
![Property with revert button in editor]
It’s just comparing to the CDO:
1
2
3
4
5
6
bool IsModified = (Instance->Health != CDO->Health);
// If true, show yellow revert button
void RevertToDefault() {
Instance->Health = CDO->Health; // Just copy from CDO!
}
CDO vs Constructor Defaults
C++ Constructor:
1
2
3
AMyActor::AMyActor() {
Health = 100; // Runs EVERY spawn
}
CDO System:
1
2
3
4
5
// Set once on CDO
CDO->Health = 100;
// Spawning just copies memory (faster!)
memcpy(NewInstance, CDO, sizeof(AActor));
The CDO approach is much faster for spawning many instances!
The Hidden CDO Lifecycle
During Compilation:
1
2
3
4
5
6
7
8
9
10
11
12
13
void CompileBlueprint() {
// Old CDO still has player's configured defaults
UObject* OldCDO = OldClass->GetDefaultObject();
// Clean the class
CleanAndSanitizeClass(OldClass);
// Recompile everything
CompileClass(NewClass);
// Copy defaults from old CDO to new CDO!
CopyPropertiesFrom(OldCDO, NewCDO);
}
This is why your default values survive recompilation!
CDO Gotchas
1. CDO Exists in Editor AND Runtime
1
2
3
4
5
// In editor
CDO->SomeProperty = 10; // Editing defaults
// In packaged game
CDO->SomeProperty; // Still 10! (read-only now)
2. Never Modify CDO at Runtime
1
2
// DON'T DO THIS in gameplay code!
CDO->Health = 200; // You just changed defaults for ALL future spawns!
3. CDO and Hot Reload
1
2
3
4
// During hot reload
OldCDO->SaveDefaults();
RecompileClass();
NewCDO->RestoreDefaults(); // Your settings survived!
Quick Takeaway
- Every class has a CDO (Class Default Object) - a hidden template instance
- When you edit defaults in Blueprint, you’re editing the CDO
- Spawning actors copies properties from the CDO (fast!)
- The CDO survives recompilation (that’s why defaults persist)
- Never modify the CDO at runtime (it affects all future spawns)
The CDO Is Everywhere
Next time you:
- Set a default value in Blueprint
- Hit the revert button
- Spawn an actor
- Recompile a Blueprint
Remember: You’re interacting with the CDO, the secret template object that makes Unreal’s class system work!
Want More Details?
For the complete explanation with code:
Next up: How node handlers turn your graph into code!
🍿 BPVM Snack Pack Series
- ← #5: SuperStruct Magic
- #6: The CDO Mystery ← You are here
- #7: Node Handlers Explained →
Cite this post
Jayden Zhang. “BPVM Snack Pack #6 - The CDO Mystery: Your Class's Secret Template.” Jayden Zhang’s Blog, October 28, 2025. https://www.jaydengames.com/posts/bpvm-snack-06-cdo-mystery/
BibTeX
@misc{bpvm-snack-06-cdo-mystery2025,
author = {Jayden Zhang},
title = {BPVM Snack Pack #6 - The CDO Mystery: Your Class's Secret Template},
year = {2025},
url = {https://www.jaydengames.com/posts/bpvm-snack-06-cdo-mystery/},
note = {Jayden Zhang’s Blog}
}
