I’m posting this partially to help other people, and partially to document my findings for my future self.
**IMPORTANT EDIT: Since this post, Unity’s Content Management has replaced these approaches. Skip to this post to see discussions since: Spawning prefabs in DOTS - subscenes vs addressables - Unity Engine - Unity Discussions **
When spawning prefabs such as bullets, enemies, buildings, abilities, etc, the most obvious approach would be to place a generated authoring component on a spawner containing a list of entities to spawn such as:
public struct ThingsToSpawnData : IComponentData
{
public FixedList128Bytes<Entity> spawnList;
}
This works just fine in the editor, but when you try to build a release version, it will likely fail if you are using subscenes because the resources for those prefabs probably won’t be loaded.
There are four ways to handle the situation that I know of:
1. The Resources folder approach is outdated and I believe that it is at or near end-of-life.
2. The custom authoring approach described here Spawn and Move Prefabs | (v0.50) DOTS Tutorial - Build a Multiplayer AR app probably works okay for small projects. The main problem is that doesn’t really provide a mapping, so it’s not particular useful when you have lots of different prefabs that you want to assign in the inspector and spawn.
3. The addressables package approach involves checking the addressable checkbox in the inspector on the prefabs that need to be spawned, and then using the addressables package for async loading those prefabs at the beginning of the scene. It is possible to build a map, but it is rather difficult because there is no easy way to fetch unique ids/keys for assets or asset references. I found an approach using the PrimaryKey with AssetReference and FixedString32Bytes to setup an ID mapping system that seems to work okay.
- Advantage: It’s possible to display subsets of prefabs in the inspector for the game designer via AssetReferenceUILabelRestriction.
- Disadvantage: Addressables and subscenes don’t play very nicely together so assets can get duplicated.
- Disadvantage: There currently is no way to load a subscene with Addressables.
- Advantage: There’s a prebuilt way to download new assets/DLC from remote servers.
- Advantage: It’s easy to add new assets - just check the checkbox and assign a label or two.
- Disadvantage: Loading is slower than subscenes and building for release is extremely slow.
- Advantage: Addressables can be used to store all kinds of resources other than prefabs - like AudioClip, ParticleSystem, and Sprite. They can all be easily organized and viewed in the group window.
- Disadvantage: fetching unique ids and/or labels at runtime is a pain in the butt and hacky. A Unity rep said they have no plans to remedy this.
- Advantage: textures get compressed which saves disk space and reduces download sizes on mobile platforms.
After a lot of trial and error, I got this approach working.
@eizenhorn wrote about his scriptable-object + global map + addressables approach in a couple of places, although I wasn’t completely able to understand all the details. @WAYNGames used SOs + an asset GUID. I have seen some people talk about making a map via UnityEditor.AssetDatabase.AssetPathToGUID within the unity editor’s OnValidate() function.
4. The subcene+map approach seems to be pretty common in these forums. Some threads that discuss this approach can be found here:
One structure that I have seen people use for storing the map is a permanently allocated NativeHashmap. I opted to use a BlobHashMap in a singleton which makes it easy to access, fast, and easy to check if the map is ready or not via RequireSingletonForUpdate() ( GitHub - bartofzo/BlobHashMaps: Blob asset compatible hashmap and multihashmap for Unity's ECS ).
When I first started with the map method, I tried creating and filling the map during the conversion step (either via inheriting IConvertGameObjectToEntity or GameObjectConversionSystem). This had a huge problem - the IDs of entities (Entity.Index) change twice throughout the conversion process. See my post here: Need Help Understanding SubScenes . Fortunately, @Arnold_2013 tipped me off that the map needs to be built at runtime instead of conversion, which resolved the issue. I had to do some voodoo with making sure all assets were loaded first before building the map, but other than that, it’s working pretty well now.
- Advantage: There are no duplicate items.
- Advantage: Everything is self contained in subscenes which are super fast. Building is very fast.
- Disadvantage: The main disadvantage is that the designer’s work is more difficult because whenever a new item needs to be added, the designer must remember to add an ID/key component to each prefab and he/she must also add the prefab to the list in the subscene. - Edit: I found out that it’s possible to add the prefab/key component automatically, so now the designer only has to add something in one place. It’s still more clumsy then checking the “is addressable” checkbox, but it’s not horrible.
- Disadvantage: For packaging DLC one would need to develop a custom downloading/remote host mechanism. Maybe this will improve someday?
- Disadvantage: I wasn’t able to find an easy way to display a subset of available prefabs for the designer to choose from in the inspector - for example: just the bullet prefabs, or only enemy prefabs. I believe that one would have to build a custom inspector to properly filter types for display in the inspector window like with AssetReferenceUILabelRestriction . Edit: I figured out that I can do it with Odin Attributes via [ValueDropdown] or [AssetSelector]. It works okay, but it requires a third party paid asset.
- Disadvantage: Subscenes can only store prefabs and component types that are on prefabs, so for AudioClips, Sprites, and other types that aren’t normally placed on a prefab, you have to use addressables or find some other way to address them.
- Disadvantage: There is no handy groups window to manage spawnable assets.
- Disadvantage: If you want labels like with addressables, you have to build them yourself. I was able to build in labels that can even be accessed at runtime (unlike addressables), but it was rather difficult to do. Mine are more restricted because labels can’t be added or deleted in the editor - they are a mask type in code.
- Disadvantage: textures don’t get compressed so package file sizes can be very large for mobile platforms.
My implementation with an example can be found here: https://gitlab.com/lclemens/buggy
** compile error can be solved via fixing Unity’s blob asset template bug via the instructions here: Entities 0.17 changelog page-4#post-8267412 .
Conclusion - Overall I think both the addressables and subscene+map approaches are reasonable and I don’t see any massive advantage to one over the other. It does seem like addressables is more mature and feature-complete than subscenes. Ultimately, it will be nice when addressables works with subscenes so both solutions could be combined to get the best of both worlds.