"A custom asset extension can lose a registration race against an engine type"
▸ SYMPTOM
- A custom
[AssetType]resource type stops resolving.ResourceLibrary.GetAll<T>()returns an empty sequence. - There is no error, no warning, and no console line. The registration just does not take.
- The same commit on the same engine build behaves differently between launches. One session has the custom type fully live. The next has it completely dark.
▸ CAUSE
The engine registers its own type on some extensions out of the box. One example is [AssetType(Name = "Ammo Type", Extension = "ammo", Category = "Game")], which ships with a stock asset to match. A project-defined resource type that claims the same letters collides with the engine type.
The collision is a race, and which side wins is decided per editor launch, not fixed by the commit. The same commit on the same engine build produced opposite outcomes across two launches ten minutes apart. One launch had the custom type live. The next had it dark.
The losing type is silent. ResourceLibrary.GetAll<T>() for that type returns an empty sequence with no diagnostic. Worse, every file on that extension then deserializes as the engine's type instead. A consumer that treats "empty result" as "nothing of mine exists" can instead receive a foreign asset with every field at its C# default, silently reachable wherever the empty-list case was assumed harmless.
▸ FIX
Audit the extension before you commit to a custom asset type.
- Open
asset_typesin a live editor. - Find every registration that claims your extension. Two registrations can share the same display
Name, so check theCategoryand which one actually claims theExtension. Never match on the name string alone. - If the engine or a base addon already claims those letters, choose a different extension. An extension collision is blocking, not cosmetic.
- In code, make any path that calls
GetAll<T>()for a type that shares an extension with an engine asset detect the empty or foreign-data case explicitly, then degrade instead of reporting green.
▸ WHY IT WORKS
The registration outcome is session-scoped luck, so a green result on one launch is not evidence the type is safe. Reading asset_types in a live editor shows which type actually holds the extension this session. Ruling out any letters the engine or a base addon already claims removes the race entirely, because there is no second registrant to lose to.
- Published