The Half-Life Unified SDK introduces an entity dictionary that stores the complete set of entities available in a mod and exposes them for programmatic creation. Unlike the original engine dispatch table, the dictionary is a runtime structure that can be queried, iterated, and specialised by entity base class — making it possible to safely create entities by name in C++ code and to restrict creation to entities of a particular type.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/twhl-community/halflife-unified-sdk/llms.txt
Use this file to discover all available pages before exploring further.
Relevant Headers
Registering an Entity
Registering an entity with the dictionary works the same way as in the original Half-Life SDK, using theLINK_ENTITY_TO_CLASS macro:
- Inherit from
CBaseEntityor one of its derived classes. - Be a non-abstract class.
- Have a public, parameterless constructor.
Creating an Entity Instance
Via the Engine (Automatic)
The engine creates entity instances automatically in two situations:- When a new map starts and all entities defined in the map file are spawned.
- When a save game is loaded and all entities are created before restoration data is applied.
Programmatically via the Entity Dictionary
To create an entity from C++ code, useg_EntityDictionary->Create<T>():
"crossbow_bolt" and returns it as a pointer to the specified type. In debug builds the dictionary validates that the requested type is compatible and emits a warning if it is not.
Via CBaseEntity::Create
Most game code creates entities through the higher-level CBaseEntity::Create helper, which sets the origin, angles, and owner automatically:
Spawn must be called after all of an entity’s keyvalues have been set. CBaseEntity::Create handles this internally; if you call g_EntityDictionary->Create directly you are responsible for calling Spawn at the right time.Destroying an Entity
CallUTIL_Remove to destroy an entity:
UTIL_Remove is safe to call multiple times on the same entity. After calling it, ensure any pointers to that entity are cleared.
Additional (Typed) Dictionaries
In addition to the globalg_EntityDictionary (typed as EntityDictionary<CBaseEntity>), the SDK registers specialised dictionaries for entity sub-types. This allows code to create entities while restricting the result to a specific base class.
The SDK provides the following global dictionary pointers out of the box:
Order of Operations: Entity Creation
Understanding the lifecycle of an entity is important when writing entity code.Entity creation lifecycle
Entity creation lifecycle
| Step | What happens |
|---|---|
| Constructor | Called first. Do not put any logic here — pev is not yet valid. |
pev initialisation | The entity’s pev (entvars_t) pointer is set up. |
OnCreate | Called next. Set default values here (health, model, etc.). |
KeyValue calls | Called once for each keyvalue set by the level designer. Keyvalues in entvars_t are handled by DispatchKeyValue; others may be delegated to RequiredKeyValue. |
Spawn | Called by DispatchSpawn or by programmatic creation code. Finishes entity setup. |
Activate | Called during ServerActivate for all non-dormant entities when a new level starts or a save game loads. Allows entities to find each other by name. Not called for programmatically created entities. |
| First think | Entities that set an immediate think function complete any remaining setup in the first few frames after startup. |
Order of Operations: Entity Destruction
Entity destruction lifecycle
Entity destruction lifecycle
| Step | What happens |
|---|---|
UpdateOnRemove | Called when UTIL_Remove is used. Run cleanup code that only applies to programmatic removal here. |
OnDestroy | Called regardless of removal method. Put general cleanup code here. |
| Destructor | Called last. The entity is no longer valid — no logic should execute here. |