Search Unity

Structure questions

Discussion in 'Addressables' started by Ramobo, Nov 22, 2019.

  1. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    1: The root addressables folder in StreamingAssets is called "aa". I assume it's short for "Addressable Assets". If so, why? At, say, "C:\Program Files (x86)\Steam\steamapps\common\Shooting Game\ShootingGame_Data\StreamingAssets\aa", that's still just 96 characters against the 260 character limit, and it doesn't go much deeper than that unless you select "Pack Separately". Are there platforms with shorter limits?

    2: I'm making a modding system and want things structured specifically. How can you change the build path? When I change it in the group settings, when I try to build player content either it says "BuildPath for group '{X}' is set to the dynamic-lookup version of StreamingAssets, but LoadPath is not" or, if I precede it with "{UnityEngine.AddressableAssets.Addressables.RuntimePath}", just doesn't change anything at all. My target location is still in StreamingAssets, although outside of "aa". See the target structure below.

    3: How can you make each group be part of a separate catalog?

    For reference, this is the mod structure I'm aiming for:
    Code (CSharp):
    1. StreamingAssets\ // For bundled mods.
    2. {persistentDataPath}\ // For user mods.
    3.     Mods\
    4.         Mod\
    5.             {Addressables stuff: catalog.json, folders...}
    6.             Mod.dll // For mods with code.
    7.             Mod.json // For mods without code.
     
    Last edited: Dec 4, 2019
  2. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    I'd really like to know about this.
     
  3. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
  4. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    After seeing recent activity from him in this forum, I'll ask @DavidUnity3d instead.
     
  5. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Hey @Ramobo

    1) aa does stand for Addressable Assets. We shortened it for the long path limitations like you've said. We were in a situation where we were hitting that limitation pretty regularly when a group was set to pack separately. We figured since we hit it as often as we did that we should shorten paths where we can so users wouldn't hit it; or at least do our best to prevent it.

    2) So you cannot change the "Addressables.BuildPath" currently but what you can do is go to the profile window and create build and load paths there that map to your desired location, then set the build and load paths on your group schemas. The dynamic lookup error you're seeing... what version are you on? I remember seeing that a while back but I didn't think that was still an issue by default.

    3) Currently you cannot. That is a topic of conversation though so it may be added in the future but I cannot make any promises one way or the other.
     
  6. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    I observed the opposite. Setting it directly through <custom> or indirectly through the profile both yield the same results for the same inputs.

    I'm on 1.1.10, the latest version that the package manager shows for 2019.3.0f1. I tried 1.4.0 by editing the manifest and saw no difference regarding my issues.

    Well, that's a big press F for me. "in the future" doesn't inspire confidence.
     
  7. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Interesting that you saw no difference. I'll double check that what I think should happen is actually the expected behavior or if there's a bug.

    1.1.10 is actually a very old version. I'm not sure why that one keeps showing up like that. But, you tried 1.4.0 and it didn't change anything so I can't suggest that.

    that's the best I can offer at the moment. I'll say it has come up in conversation to make group build to different catalogs but I'm not sure that it was ever decided one way or the other on if we were going to do it or not.
     
    Ramobo likes this.
  8. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    I'll add that 1.4.0 doesn't appear in 2020.1.0a14 either, a version that also has a last segment whose type I've never seen before in Unity: ".1541". The latest version that appears there is 1.2.4.
     
  9. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    But is there a way to load different catalogs and their binary data dynamically at runtime ?
     
  10. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    @Azengar
    Code (CSharp):
    1. Addressables.LoadContentCatalogAsync
     
  11. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    Thanks a lot for the quick answer I wasn't sure that was the correct way to do it, so if I understand correctly once a catalog has been loaded then any asset referenced in it can loaded using Addressables.LoadAssetAsync?

    And one last question, is there a way to choose where the catalog is exported when building? I managed to move the actual groups using what you described above, but the catalog is still getting copied to StreamingAssets/aa.
     
  12. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Sure thing. And yeah, once you've loaded the new catalogs Addressables can use those asset locations/keys.

    Currently no, I don't believe you can set where the catalogs get built to. Just curious, what's your use case for that? It might be something we can look at adding in the future.
     
  13. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    I can't say about his, but as I mentioned, I want to dogfeed on my modding system as much as possible by building my game as mods. Obviously this requires the built in mods to be structured how a real mod is.

    There comes the need for changing the build location to outside of aa, but still in StreamingAssets[/Mods/...], and with it the need for separating catalogs without creating multiple projects.
    If catalogs weren't a thing and we just loaded bundles individually instead of whole catalogs, a complicated build post processor and iterating over bundles in a mod folder would suffice, although be less than ideal, especially considering what I needed to do the same to assemblies, which is another problem entirely.
     
  14. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    Thanks again I feel like I'm finally getting the hang of it.

    My use case is about the same as Ramobo.

    I'm building a very data-driven game (think Skyrim) and was previously using AssetBundles but since they have many limitations decided to upgrade to the Addressables system which looks really cool.

    The idea is that there is a base API that defines the basic data structures (items, monsters, spells, animations, etc.) for the game as ScriptableObject and then all the actual data comes as packages that are loaded dynamically by the game, mods as well but even the base game data.

    A package before was an AssetBundle + an assembly that I was loading via reflection, it would work similarly with Addressable except that I would need to load the catalog instead of the bundles directly.

    The precise use case that I need would be a way to move all files outputted by the Addressables build to a single directory so that I can zip them and then put the archive in someone's else game build to unzip it and load it dynamically.
     
  15. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    On an unrelated note, about your assembly problem @Ramobo, I have been able to load assemblies into Unity by simply compiling them under a speical name using an AssemblyDefinition file and then loading them via Reflection.

    If I do this and load the assembly before loading any AssetBundle then scripts that are attached to prefabs, etc. will resolve.

    There is however a bug in the Unity Editor (as seen here), or at least I believe it's a bug, that makes it so that the asset id of every asset loaded from an asset bundle is null in the editor, causing scripts not to resolve with assets from asset bundles, but as said in the link everything works fine outside of editor.

    PS : The only problem I have with this system, is that while asset bundles can be unloaded, assemblies cannot until they are in a custom application domain, which I could not get to work with Unity, so I can't unload assemblies.
     
    Last edited: Dec 6, 2019
  16. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    What's that special name?

    Doing so would definitely cause issues, so I'll require a restart to "disable" mods. Instead of unloading unwanted mods, just don't load them. Much better.
     
    Last edited: Dec 6, 2019
  17. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    @Ramobo

    Any name, as long as two assemblies don't have the same name, I use AssemblyDefinition because renaming assemblies manually don't work and by using this Unity will name them for me, basically the name of the assembly is the mod name.

    About disabling mods yes that's the main issue, but currently I don't see a different way of doing it sadly. Now I'm using a mod manager app that the user needs to run before starting the game to manage mods and then when mods are correctly setup the game starts and at this point mods cannot be loaded / unloaded any longer.

    But if you really want to unload mods I don't believe that it is too much of a problem, a single assembly will rarely weight more than a few megabytes (usually much less) so it's basically a memory leak but one that will never be problematic, as long as all assets from the bundles are unloaded. Another problem caused by this is naming problems, which is why every assembly should have a unique name as well as a unique namespace (can totally be the same as the name).
     
  18. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    Then I'm doing something wrong or it just doesn't work. I load all mod assemblies, then I do Addressables.LoadContentCatalogAsync() on the master catalog, which I know works because it did before I turned Core into a mod, and yet I have those missing module and missing script logs, including my PreloadSceneManager, meaning that it doesn't even get to the main menu. I know that the catalog loads because PreloadScene is there, and PreloadScene loading is confirmed by the missing script logs. Now it makes sense to me why a script that was in another mod didn't work either before this Core mod issue.

    The workflow for disabling mods in-game is quite simple, actually: Disable in some UI, restart the game, the mod loader sees that it shoudn't load the mod (that configuration is saved in a file in {persistentDataPath}) and it doesn't. I see just unloading the assembly as an issue because of MonoBehaviours that the mod will most likely have there.
    I follow the unique name and namespace part. Indeed, I'm sane enough to actually use namespaces, unlike many Unity developers, even some advanced ones.
     
    Last edited: Dec 6, 2019
  19. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    Yeah I'm also having issues with Addressables since I just started trying to use them yesterday but I found out a few things already.

    • The same bug with asset id being null in editor is still there, meaning you will get unresolved scripts on your components in the editor only
      Edit : Actually, maybe I spoke too soon, I managed to get it working in editor as well.
    • I copied the entire "Windows" Addressables directory found in StreamingAssetsCopy/aa to the client build StreamingAssets and managed to load an assembly then load a prefab from the Addressables but I had to tweaks the paths from the catalog.json

    From :

    "m_InternalIds":[
    "{UnityEngine.AddressableAssets.Addressables.RuntimePath}/StandaloneWindows/plugina_assets_all_5b89a10ddbfbc4371e2ff50d4706c1de.bundle",
    "Assets/PluginA/Assets/PluginASpawner.prefab"
    ],

    To :

    "m_InternalIds":[
    "PluginClient_Data/StreamingAssets/Mods/PluginA/Windows/StandaloneWindows/plugina_assets_all_5b89a10ddbfbc4371e2ff50d4706c1de.bundle",
    "Assets/PluginA/Assets/PluginASpawner.prefab"
    ],

    Sorry for the crap formatting, for some reason I can't get it to format better.
    If i can I'll try to put up an example on github tomorrow for both projects (the client and the mod) so that maybe I can help you.
     
    Last edited: Dec 6, 2019
    Ultroman and Ramobo like this.
  20. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    Github seemed overkill, so here are my 2 projects and what I've done step by step to make it work, using Unity 2020 for both projects.

    Projects are without the Build and Library folders so that they are smaller, so if you want to follow every steps you'll have to build both the Addressables and the project (I describe the process in details below).

    If you want to try it for yourself, you should be able to immediately make it work by just launching the PluginClient project in the editor, opening the "SampleScene" scene and then clicking play, PluginClient use Addressable data from the PluginA project loaded dynamically to spawn a colored cube (square because project is in 2D).

    If you do this, you'll notice an error in the console but the cube appears nonetheless and everything seems to be working fine (even the result of the async operation is Succeeded).

    Everything I've done in order:
    1. Create a PluginA project, added Addressables package 1.4.0
    2. Add 2 scripts basically just to spawn a colored cube, create a prefab with the spawner, then add an AssemblyDefinition and name it "PluginA", both scripts are also in namespace "PluginA"
    3. Create a custom material for the cube spawner and set it in the prefab because the standard material has problem with AssetBundles
      (You can run the PluginA project in the SampleScene to try it and see the spawner in action, although the scene is not exported with the Addressables)
    4. Go to the build window, make sure to exclude all scenes from the build (else they are automatically included into Addressables)
    5. Create an Addressables group named "plugina", add it the material and the spawner prefab, rename the spawner as plugina_spawner, then set the build mode as "Use Existing Build" and then build the Addressables
    6. Go to the build directory (Project root/Library/com.unity.addressables/StreamingAssetsCopy/aa/Windows) and keep an explorer open there
    7. Create a PluginClient project, added Addressables package 1.4.0
    8. Create a "Mods" directory in the root directory of this project, then add a "PluginA" subdir inside it.
    9. Copy the build directory from step 5 inside this directory (meaning you have "Project root/Mods/PluginA/Windows/...)
    10. Edit the catalog.json file from this folder and replace every occurrence of :
      {UnityEngine.AddressableAssets.Addressables.RuntimePath}
      By :
      Mods/PluginA/Windows
      If you want it to StreamingAssets in the build directory later, you'll need to put:<path_to_build_data_folder>/StreamingAssets/...
      But for now let's just get it to work in the editor.
    11. Back to the PluginA project, and build it using the standard Unity build window
    12. Go to the build directory then "PluginA_Data/Managed" and copy the PluginA dll from there to the mods directory from step 9 and place it inside the "StandaloneWindows" directory (Assembly + Assets)
    13. Now the mod is complete, so back to the PluginClient project and create a Test script, inside it I load the assembly, then the catalog and then the spawner (paths are hardcoded because I was just toying around)
    14. Open the SampleScene, add the Test script to the MainCamera, because I was too lazy to create a new game object.
    15. Now start the ProjectClient in edit mode and hopefully you'll see a cube being spawn and colored in red

    Hope I was as clear as possible!
     

    Attached Files:

  21. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    I don't really follow. My method is loading assemblies with an IMod interface, instantiating all such interfaces with Activator and calling an OnLoaded method in them. That's the mod loader's job in essence. From there, it's the game developer's problem to make registries, maybe APIs to make modding easier.

    Besides, I automated moving assemblies with IMod out of Managed with build post processing, then found resolution issues. If we get separate catalogs and custom build locations with Addressables, that's a big step towards what I want. Then I'd need to hear from the scripting team, who didn't reply yet, despite it being almost two weeks since my post.
     
    Exanite likes this.
  22. Azengar

    Azengar

    Joined:
    Nov 20, 2016
    Posts:
    11
    Yeah I get what you mean, then our system are fundamentally different, since I use mods to mostly add ScriptableObject and scenes to my games, mine is more focused on adding data through the editor than code.

    Also this was just a very quick test, definitely not a good or optimal solution.

    But in the end we want the same thing, separate catalogs and the option to specify a custom build location so let's hope we can get that. :)
     
    Ramobo likes this.