Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion Spawning prefabs in DOTS - subscenes vs addressables

Discussion in 'Entity Component System' started by lclemens, Jul 26, 2022.

  1. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    I'm posting this partially to help other people, and partially to document my findings for my future self.

    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:

    Code (CSharp):
    1. public struct ThingsToSpawnData : IComponentData
    2. {
    3.     public FixedList128Bytes<Entity> spawnList;
    4. }
    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 https://dots-tutorial.moetsi.com/unity-ecs/spawn-and-move-prefabs-in-unity-ecs 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. @WAYN_Games 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() ( https://github.com/bartofzo/BlobHashMaps ).

    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: https://forum.unity.com/threads/need-help-understanding-subscenes.898910/#post-8303640 . 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: https://forum.unity.com/threads/entities-0-17-changelog.1020202/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.
     
    Last edited: Sep 7, 2022
    xuhuajie, ShadLady, slonoedov and 3 others like this.
  2. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Since I'm currently in the process of "evaluating" ECS and am especially struggling with this topic this helps me a ton. So many thanks for taking the time to post this.

    I think "ultimately" the best option would be if UT would develop/document/define a proper method. Since most games require prefabs/assets it's pretty useless when everyone reinvents the wheel. For such basic functionality something should be built-in IMO. The whole authoring/conversion "workflow" seems pretty bloated to me.
     
    lclemens and bb8_1 like this.
  3. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    I'm using addressable to delegate the unique id management to it. Having an asset reference game object instead of a game object also takes care of setting the prefab as addressable.
    The idea for now is at conversion time I add a component that contains hash of the guid. The at runtime I'll get all prefab with that component to built the map and discard any duplicate prefab (same hashed Id).
    For now the update of the addressable will not trigger the update of the prefab entity since I can't convert it at runtime (or rather it seems this will be deprecated in futur version, may have misunderstood though...)
    The prefab can however be updated through live link ;).
    Was planing to play with subscene but it may not be viable yet.
     
    bb8_1 likes this.
  4. Ng0ns

    Ng0ns

    Joined:
    Jun 21, 2016
    Posts:
    195
    How do ya'll get around loading the different assets without hitching?
    At first my idea was to use addressables to load scenes in and out of memory, but whenever assets are loaded it causes a massive spike; even loading a single item.

    I've tried the different ways mentioned at https://docs.unity3d.com/Packages/com.unity.entities@0.50/manual/loading_scenes.html - but they all hitch the system. When simply using the Scenesystem, it also doesn't seem to unload from memory.

    Reading this and other threats, I'm to understand that assets are to be kept in a list and then spawned from there.

    I saw a tut at https://coffeebraingames.wordpress.com/2020/07/19/entity-prefab-management/ which describes creating a scriptable object with references to the assets/entities. AFAIK all asset references, even in SOs, are loaded into memory at startup.

    My hope was to simply have scenes that I can load in and out of memory depending on the location of the player, but without the game hitching.

    Is it even feasible? Is there a way to load assets at runtime without spiking/lagging? I have tons of them, so they can't be preloaded in memory.

    @iclemens - I've tried opening your project, but get a compile error.

    PrefabMapBuilderSystem.cs(52,9): error Assets\Scripts\PrefabMapBuilderSystem.cs(52,9): error ConstructBlobWithRefTypeViolation: You may not build a type PrefabMapBlobAsset with Construct as PrefabMapBlobAsset.map.data.values[] is a reference or pointer. Only non-reference types are allowed in Blobs.
     
  5. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    I have not been using the scene system so can't help on that.
    For the blob error it exist since 0.17 more about it here
    https://forum.unity.com/threads/blobarray-with-valuetype-generic-parameters-fails.1045639/
     
    lclemens and Ng0ns like this.
  6. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    Yeah sorry, I forgot to mention that Unity has a blob asset template bug that has been plaguing us for over a year. The only way I know of to get around it is by editing the source code via something like the instructions here: https://forum.unity.com/threads/entities-0-17-changelog.1020202/page-4#post-8267412 (it's the same issue WAYN_Games linked to).

    I haven't noticed any major slowdowns in scene loading, but my levels are really small and they're not loaded in while the player is running around (only when the player clicks on a new level in the main menu).

    It is my understanding that there are two main ways of loading subscenes - the normal way, and the streaming way. I think the streaming way is intended for large open-world games but it is more difficult to implement. In the documentation, there is some info on seamless subscene streaming that I think might be relevant to your situation (if you haven't already seen it): https://docs.unity3d.com/Packages/com.unity.entities@0.51/manual/loading_scenes.html .

    There is also a prefab streaming mechanism that might be be useful?
    https://github.com/Unity-Technologi...aster/ECSSamples/Assets/Advanced/EntityPrefab

    My main topic in this post is loading prefabs for the purpose of quickly spawning them at runtime (bullets, enemies, etc), whereas I think you're more interested in loading entire scenes or subscenes.
     
    Last edited: Aug 7, 2022
  7. Blitzkreig95

    Blitzkreig95

    Joined:
    Jul 21, 2021
    Posts:
    20
    Has this changed with DOTS 1.0 ? Like the "Content Management" workflow
     
    lclemens likes this.
  8. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    Absolutely. All of this gets thrown out the window with the new Content Management workflow.
     
  9. Blitzkreig95

    Blitzkreig95

    Joined:
    Jul 21, 2021
    Posts:
    20
    So Addressables work with Subscene, both in Editor and at Runtime ? I am new to DOTS, and want to leverage Addressable loading in it.
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    They don't. For SubScenes you should use Content Management only.
     
    lclemens and Blitzkreig95 like this.
  11. yokobe0012

    yokobe0012

    Joined:
    Nov 2, 2021
    Posts:
    9
    Do you have any tutorials on content management?
     
  12. One1Guy

    One1Guy

    Joined:
    Aug 26, 2015
    Posts:
    2
    yokobe0012 and lclemens like this.
  13. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    I tried it when I first noticed it in the doc but there were still some internal stuff related to building the bundle that I could not make work. When I figure it out I'll cover it in a video ;)
     
  14. zhangdong304

    zhangdong304

    Joined:
    Mar 21, 2018
    Posts:
    23
    Come on
     
    yokobe0012 likes this.
  15. yokobe0012

    yokobe0012

    Joined:
    Nov 2, 2021
    Posts:
    9
  16. wechat_os_Qy08PgrnDpFuMFG8ZUJPznzGU

    wechat_os_Qy08PgrnDpFuMFG8ZUJPznzGU

    Joined:
    Aug 13, 2023
    Posts:
    1
    Is there a discussion group to study the use of the Content Management system after building the project
     
    yokobe0012 likes this.