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

Generating AssetBundles in a separate project for multiple platforms.

Discussion in 'Addressables' started by Murcho, Oct 10, 2018.

Thread Status:
Not open for further replies.
  1. Murcho

    Murcho

    Joined:
    Mar 2, 2009
    Posts:
    309
    I'm trying to get my head around the Addressable system, but trying to apply it to my specific use case. We will have users uploading images to a server, which I want to then import into Unity, and export AssetBundles for both iOS and Android.

    My understanding is that I should be able to set up an empty project (referencing the Addressables package), import the image, mark it as an addressable asset, then perform a build stage to generate the AssetBundles. In this build stage a json file with information on the addressables is created, and if I were to provide this to my other application, it should be able to load it using Addressables.LoadCatalogsFromRuntimeData() and then be aware of these assets that weren't around at it's build time?

    This information was gathered from this post : https://forum.unity.com/threads/can...te-from-an-other-project.547369/#post-3637720

    I'm missing a couple of stages, so some direction on how to mark the assets programatically for Bundle Exports would be greatly appreciated.
     
    EirikWahl likes this.
  2. Murcho

    Murcho

    Joined:
    Mar 2, 2009
    Posts:
    309
    Version : 0.3.5-preview

    OK, so I worked out how to build Addressable assets in one project and load them in another successfully. I have a few manual steps right now that I need to clear out, and I also think I came across a bug. For anyone interested in the process here's a step by step of what was needed. and where the bug was. I'll ask some further questions below as well so if any devs happen to see this I'd really like some guidance on how to extend the system.


    Project 1 (the project to generate the assets)
    • Add the assets to group(s) in the Addressables window.
    • In the AddressableAssetSettings ScriptableObject, set the remote path to the server you'll be hosting them on. In my case I tested with a public S3 bucket, so my remote path looked like:
    • For each of the groups, set:
      • LoadPath to RemoteLoadPath
      • BundleMode to Pack Separately (this might not be important, but I need separate bundles for individual assets)
    • In an editor script I call BuildScript.PrepareRuntimeData().
      • NOTE : This script is marked obsolete and will be replaced in the next version apparently, however it is what I had to work with here.
      • DEVS: There is a problem with calling this directly in regards to switching platforms.
        • e.g. If I'm on Android, and I call BuildScript.PrepareRuntimeData() passing in iOS as the Build Target, The editor switches to iOS, however the BuildTarget used for the output file paths is left as Android. I haven't tested whether the output bundles are iOS or Android formatted.
        • In order to work around this I would manually change platform in script, then using EditorPrefs and UnityEditor.Callbacks.DidReloadScripts work out if I had to call BuildScript.PrepareRuntimeData(). Very messy, but it worked.
      • DEVS: Second issue, is that I can't configure the settings.json output file location or name. I want to build each asset set out for iOS and Android, and so when doing this, the settings.json and catalog.json files are overwritten.
    • After each platform build, I would upload the output files to S3, maintaining folder structure, and renaming the settings.json to settings_platform.json so we could fetch them separately.
      • The files would be output to Assets/StreamingAssets/com.unity.addressables
    Project 2 (the project to fetch the assets)
    • Here is the example script I used to pull the settings.json and then load an addressable by string key. This is obviously missing proper checks.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.AddressableAssets;
    3. using UnityEngine.UI;
    4.  
    5. public class RemoteAssetLoadTest : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     private RawImage m_Image;
    9.     [SerializeField]
    10.     private string m_ImageRef = "";
    11.  
    12.     void Start ()
    13.     {
    14.         Addressables.Initialize().Completed += (initOp) =>
    15.         {
    16.             Addressables.LoadCatalogsFromRuntimeData("https://s3-us-west-2.amazonaws.com/my-s3-bucket-name/Addressables/settings.json").Completed += (op) =>
    17.             {
    18.                 Addressables.LoadAsset<Texture2D>(m_ImageRef).Completed += (loadOp) =>
    19.                 {
    20.                     m_Image.texture = loadOp.Result;
    21.                 };
    22.             };
    23.         };
    24.     }
    25.  
    26. }
    27.  
    So this works however there is a lot of manual intervention involved so I'd love some feedback from the devs on whether this was the right way to approach it? Being able to output completely separate files that don't overwrite each other would be ideal. I understand that the BuildScript class is marked deprecated to be replaced soon, just wondering if there is an intended way to do this in the current version.

    My next part is to understand how to create custom ResourceProviders. I found the AssetBundleProviderRemoteWebRequest example in the source, however there isn't an example of how to actually implement it in code. Any hints on how to do this?

    Thanks in advance.
     
  3. AustynPember

    AustynPember

    Joined:
    Mar 14, 2018
    Posts:
    17
    I appreciate you posting what you've done so far with this. I am trying to do mostly the same thing (with Azure instead.) What kind of progress have you made since?
     
  4. Murcho

    Murcho

    Joined:
    Mar 2, 2009
    Posts:
    309
    I've put this on the back burner until the Addressables system matures a bit more. We are heading into production and I couldn't rely on an incomplete system.
     
  5. AustynPember

    AustynPember

    Joined:
    Mar 14, 2018
    Posts:
    17
    Thanks - I am still going to try to build out something similar to what you did. We only have to build out to UWP so it should cut down on some of the complexity or issues you had.
    I was wondering for the above part - what exactly goes into the cloud?
    Do you just push the App folder (the build) onto the repository? I dont think so because you're referencing Assets/StreamingAssets which isn't in the build, it's in the project?
    *Edit*
    Also - where is m_ImageRef being set? It's just an empty string?
     
    Last edited: Dec 7, 2018
  6. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    @Murcho : Any progress on loading Project B addressable assets in Project A? If Yes, could you please let us know the process.
    @unity_bill : Any update on Addressable Asset documentation? Our requirement is to have Project independent of main project where addressable assets would be built and uploaded to our CDN servers.
     
  7. Murcho

    Murcho

    Joined:
    Mar 2, 2009
    Posts:
    309
    @deepakguptaPR Unfortunately I haven't been able to return to this system to try again.
     
  8. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    @Murcho : We have successfully implemented the Addressable Assets to be independent of Main project. As of now we don't have blockers. If you need any help regarding that Please drop me a DM. Thanks
     
  9. Shii

    Shii

    Joined:
    Nov 23, 2014
    Posts:
    31
    @deepakguptaPR can you share details? I considering switching from classic assetbundles to addressable system and not sure how to properly generate bundles in one project and load in another. In my project I also planning to have 2 projects - one for asset packing (SDK) and another for asset loading (Main game). Idea is to store game resouces in the asset packs and later distribute them as addons/DLC so people can make their own packs and load into the game by just placing needed files into compiled game StreamingAssets folder.
     
  10. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12

    In Asset packing project, Have AddressableAssetSettings's Remote Catalog Build path to RemoteBuildPath and Remote Catalog Load path to RemoteLoadPath. RemoteBuildPath will have default value as ServerData/[Build Target].

    For the AssetGroups, BuildPath has to be RemoteBuildPath and Load Path has to be RemoteLoadPath.

    Build Player Content in the Addressables Window. After Building, you will get files in [Project folder]/ServerData/[Build Target] folder. Upload all the files in the CDN server(We are using MicroSoft Azure blobs Storage].

    Code in main project to load catalog, assets. Code is not refactored as it was only for testing.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.AddressableAssets;
    4. using UnityEngine.AddressableAssets.ResourceLocators;
    5. using UnityEngine.ResourceManagement.AsyncOperations;
    6. using UnityEngine.ResourceManagement.ResourceLocations;
    7.  
    8. public class AssetLoader : MonoBehaviour
    9. {
    10.     public string catalogPath;
    11.     public List<IResourceLocation> locations;
    12.  
    13.     void Start()
    14.     {
    15.         initAddressables();
    16.     }
    17.  
    18.  
    19.     void initAddressables()
    20.     {
    21.         Debug.Log("initAddressables");
    22.         AsyncOperationHandle<IResourceLocator> handle = Addressables.InitializeAsync();
    23.         handle.Completed += initDone;
    24.     }
    25.     private void initDone(AsyncOperationHandle<IResourceLocator> obj)
    26.     {
    27.         Debug.Log("Initialization Complete ==> " + obj.Status);
    28.         if (obj.Status == AsyncOperationStatus.Succeeded)
    29.         {
    30.             loadCatalog();
    31.         }
    32.     }
    33.  
    34.     void loadCatalog()
    35.     {
    36.         Debug.Log("loadCatalog");
    37.         AsyncOperationHandle<IResourceLocator>  handle = Addressables.LoadContentCatalogAsync(catalogPath);
    38.         handle.Completed += loadCatalogsCompleted;
    39.     }
    40.     void loadCatalogsCompleted(AsyncOperationHandle<IResourceLocator> obj)
    41.     {
    42.         Debug.Log("loadCatalogsCompleted ==> " + obj.Status);
    43.         if (obj.Status == AsyncOperationStatus.Succeeded)
    44.         {
    45.             loadResourceLocation();
    46.         }
    47.         else
    48.         {
    49.             Debug.LogError("LoadCatalogsCompleted is failed");
    50.         }
    51.     }
    52.  
    53.     void loadResourceLocation()
    54.     {
    55.         Debug.Log("loadResourceLocation");
    56.         AsyncOperationHandle<IList<IResourceLocation>> handle = Addressables.LoadResourceLocationsAsync([groupname]);
    57.         handle.Completed += locationsLoaded;
    58.     }
    59.     void locationsLoaded(AsyncOperationHandle<IList<IResourceLocation>> obj)
    60.     {
    61.         Debug.Log("locationsLoaded ==> " + obj.Status);
    62.         if (obj.Status == AsyncOperationStatus.Succeeded)
    63.         {
    64.             locations = new List<IResourceLocation>(obj.Result);
    65.             loadDependency();
    66.         }
    67.         else
    68.         {
    69.             Debug.LogError("locationsLoaded is failed");
    70.         }
    71.     }
    72.  
    73.     void loadDependency()
    74.     {
    75.         Debug.Log("loadDependency");
    76.         AsyncOperationHandle handle = Addressables.DownloadDependenciesAsync("decor");
    77.         handle.Completed += dependencyLoaded;
    78.     }
    79.     void dependencyLoaded(AsyncOperationHandle obj)
    80.     {
    81.         Debug.Log("dependencyLoaded ==> " + obj.Status);
    82.         if (obj.Status == AsyncOperationStatus.Succeeded)
    83.         {
    84.             loadAssets();
    85.         }
    86.         else
    87.         {
    88.             Debug.LogError("dependencyLoaded is Failed");
    89.         }
    90.     }
    91.  
    92.     private void loadAssets()
    93.     {
    94.         AsyncOperationHandle<IList<GameObject>> handle = Addressables.LoadAssetsAsync<GameObject>(locations, onAssetsCategoryLoaded);
    95.         handle.Completed += onAssetsLoaded;
    96.     }
    97.     private void onAssetsCategoryLoaded(GameObject obj)
    98.     {
    99.         SpawnItem(obj.name);
    100.     }
    101.     private void onAssetsLoaded(AsyncOperationHandle<IList<GameObject>> obj)
    102.     {
    103.     }
    104.  
    105.     void SpawnItem(string addressableKey)
    106.     {
    107.         Debug.Log("SpawnItem ==> " + addressableKey);
    108.         AsyncOperationHandle<GameObject> asyncLoad = Addressables.InstantiateAsync(addressableKey, Vector3.zero, Quaternion.identity);
    109.         StartCoroutine(progressAsync(asyncLoad));
    110.         asyncLoad.Completed += assetSpawned;
    111.     }
    112.     void SpawnItem(GameObject addressableObj)
    113.     {
    114.         Debug.Log("SpawnItem ==> " + addressableObj);
    115.         AsyncOperationHandle<GameObject> asyncLoad = Addressables.InstantiateAsync(addressableObj);
    116.         StartCoroutine(progressAsync(asyncLoad));
    117.         asyncLoad.Completed += assetSpawned;
    118.     }
    119.     private System.Collections.IEnumerator progressAsync(AsyncOperationHandle<GameObject> asyncOperation)
    120.     {
    121.         float percentLoaded = asyncOperation.PercentComplete;
    122.         while (!asyncOperation.IsDone)
    123.         {
    124.             Debug.Log("Progress = " + percentLoaded + "%");
    125.             yield return 0;
    126.         }
    127.         Debug.Log("Progress Done= " + percentLoaded + "%");
    128.     }
    129.     void assetSpawned(AsyncOperationHandle<GameObject> obj)
    130.     {
    131.         Debug.Log("Instantiate completed ==> " + obj.Status);
    132.     }
    133. }
    Let me know if you need more clarification
     
    J1wan, milox777, wayne2k and 3 others like this.
  11. Shii

    Shii

    Joined:
    Nov 23, 2014
    Posts:
    31
    Thank you! Very useful information. Instructions are clear. =) Sorry for late response, did not get notification about new thread message.
     
    deepakguptaPR likes this.
  12. jeremedia

    jeremedia

    Joined:
    Apr 21, 2015
    Posts:
    62
    @deepakguptaPR I'm having trouble implementing the code you've shared.

    Is the "catalogPath" string pointing at a local catalog file produced by the asset building project?

    What is the "[groupname]" referenced on line 56?

    Thanks for sharing your solution.
     
  13. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    @jeremedia : Sorry for the late response, Did not get notification :(

    catalogPath is the url of the catalog file. For example, if you are using amazon S3 bucket as CDN, you will upload the catalog file generated from Asset building project to the S3 bucket. CatalogPath is the url of the CDN(S3 bucket url).

    GroupName is the label name which you used while building asset bundle. Though it is not mandatory to provide label.

    Hope this helps :)
     
  14. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi guys, I have one question.
    What happens when you have multiple packing projects?
    The reason I have multiple packing projects is that 1. my project is huge so for efficient, I like to divide them. 2. multiple people working on different projects, for example, I have people working only on characters and others working only on maps. It makes sense to have separate projects for each group.
    I really hope there is way to handle it.
    Thanks.
     
  15. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    @chrisk : You can load multiple catalog files.
     
  16. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Yup, I know you can load multiple catalogs but the problem is conflict management.
    If you build addressable from multiple projects and they use some shared assets such as shaders and textures, you will have a conflict.
    It's very common to have such conflicts but it's not very clear how to manage them.
    I think we need a global addressable system that manages the addressable and it handles the conflict because each individual project cannot know the conflict ahead of time.
     
    pahe4retro likes this.
  17. Pdpalma

    Pdpalma

    Joined:
    Aug 14, 2014
    Posts:
    13
    What's refers the catalogPath variable? The cloud url?
     
  18. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    Yes, catalogPath refers to cloud URL(catalog json file)
     
  19. deepakguptaPR

    deepakguptaPR

    Joined:
    Aug 20, 2019
    Posts:
    12
    We have not tried packing from multiple projects. Not sure how to handle!
     
  20. Julien-Lynge

    Julien-Lynge

    Joined:
    Nov 5, 2010
    Posts:
    142
    I've been working on slimming down your example. The question I'm trying to answer is: what is the absolute minimum you need to load the assetbundle that was created with the other project?

    For my use-case, I don't want to have to generate catalogs for each asset, and I don't want to have to make 2 web requests to download the asset. However, your solution was incredibly valuable: just being able to step through all the steps based on your example has allowed me to figure out what you need to do.

    At the end of the day, you don't actually need to build a full catalog for your asset bundle. You can just build a ContentCatalogData.CompactLocation object. (Note: this class is private, so you can't access it directly. You can either open ContentCatalogData.cs and copy it to a new class, or you can use reflection to create an instance of it.)

    Here's an example showing how you can figure this out. To run this example, follow @deepakguptaPR 's instructions above to generate your catalog. Then, attach the catalog as TextAsset json to your test script, and run:

    Code (CSharp):
    1.        ContentCatalogData contentCatalogData = JsonUtility.FromJson<ContentCatalogData>(json.text);
    2.         var resourceLocationMap = contentCatalogData.CreateLocator();
    3.         resourceLocationMap.Locate("armchair", typeof(GameObject), out IList<IResourceLocation> locations);
    4.         Debug.Log("Resource location is a: " + locations[0].GetType());
    5.         Addressables.LoadAssetAsync<GameObject>(locations[0]);
    So all you really need here is locations[0] - you could skip all the rest. The next question is: what data in that object do you actually need? E.g. what is the smallest amount of data you need to give the Addressables system for it to load an asset bundle from a URL, and still get all the benefits of caching, version control, etc. - if you want those things?

    I'm working on that now, and my guess is: not much. A lot of what you find in CompactLocation is standard data - you could just pre-create a reusable CompactLocation object, then fill in a couple fields each time you want to use it to load an assetbundle.
     
  21. FilipeJorgeTekuchi

    FilipeJorgeTekuchi

    Joined:
    Nov 20, 2013
    Posts:
    4
    Hey!

    Followed @deepakguptaPR example and I'm getting the next error after logging "loadDependency"

    Code (CSharp):
    1. Exception encountered in operation Resource<IAssetBundleResource>(project_assets_all_2439f6fe41f5b377e47afe3b5d70ee91.bundle): Attempting to use an invalid operation handle
    2. UnityEngine.AddressableAssets.Addressables:DownloadDependenciesAsync(Object, Boolean)
    3. LoadDevelopment:loadDependency() (at Assets/LoadDevelopment.cs:77)
    4. LoadDevelopment:locationsLoaded(AsyncOperationHandle`1) (at Assets/LoadDevelopment.cs:66)
    5. DelegateList`1:Invoke(AsyncOperationHandle`1) (at Library/PackageCache/com.unity.addressables@1.8.4/Runtime/ResourceManager/Util/DelegateList.cs:69)
    6. UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    7. MonoBehaviourCallbackHooks:Update() (at Library/PackageCache/com.unity.addressables@1.8.4/Runtime/ResourceManager/Util/MonoBehaviourCallbackHooks.cs:19)
    Also tried other simpler codes like the @Julien-Lynge but always getting that "Attempting to use an invalid operation handle" message.

    Really can't find an explanation about that. Maybe some setting I'm missing when exporting the bundle or in the project that I'm importing them.

    Running in Unity 2019.4.2f1 and Addressables version 1.8.4

    Thanks!
     
    Last edited: Jul 13, 2020
  22. FilipeJorgeTekuchi

    FilipeJorgeTekuchi

    Joined:
    Nov 20, 2013
    Posts:
    4
    Found the issue! It wasn't founding the group name I was providing. At this moment, I can load prefabs and scenes also from another project without problems. Thanks for the code examples in this thread, helped a lot.
     
  23. ProgrammingWhileSleeping

    ProgrammingWhileSleeping

    Joined:
    Nov 10, 2017
    Posts:
    17
    Hi @FilipeJorgeTekuchi I've been trying for a while now still couldn't make it work with his sample. Can you please share the code that you have? I think it's because I have multiple groups which is why I can't make his code work on my end. I'm loading the dependencies of all my groups but it still doesn't seem to work. Maybe you can see something that I did wrong. Here's my code.

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AddressableAssets;
    5. using UnityEngine.AddressableAssets.ResourceLocators;
    6. using UnityEngine.ResourceManagement.AsyncOperations;
    7. using UnityEngine.ResourceManagement.ResourceLocations;
    8.  
    9. public class AssetLoader : MonoBehaviour
    10. {
    11.     public string catalogPath;
    12.     public string jsonFilename;
    13.  
    14.     public List<string> addressableGroups = new List<string>();
    15.     int loadedGroups = 0;
    16.  
    17.     public Console console;
    18.     public List<IResourceLocation> locations = new List<IResourceLocation>();
    19.     public List<GameObject> createdObjs = new List<GameObject>();
    20.  
    21.     void Start()
    22.     {
    23.         initAddressables();
    24.     }
    25.  
    26.  
    27.     void initAddressables()
    28.     {
    29.             catalogPath += jsonFilename;
    30.         Debug.Log("initAddressables");
    31.         AsyncOperationHandle<IResourceLocator> handle = Addressables.InitializeAsync();
    32.         handle.Completed += initDone;
    33.     }
    34.     private void initDone(AsyncOperationHandle<IResourceLocator> obj)
    35.     {
    36.         Debug.Log("Initialization Complete ==> " + obj.Status);
    37.         if (obj.Status == AsyncOperationStatus.Succeeded)
    38.         {
    39.             loadCatalog();
    40.         }
    41.     }
    42.  
    43.     void loadCatalog()
    44.     {
    45.         Debug.Log("loadCatalog");
    46.         AsyncOperationHandle<IResourceLocator>  handle = Addressables.LoadContentCatalogAsync(catalogPath);
    47.         handle.Completed += loadCatalogsCompleted;
    48.     }
    49.     void loadCatalogsCompleted(AsyncOperationHandle<IResourceLocator> obj)
    50.     {
    51.         Debug.Log("loadCatalogsCompleted ==> " + obj.Status);
    52.         if (obj.Status == AsyncOperationStatus.Succeeded)
    53.         {
    54.             loadResourceLocation();
    55.         }
    56.         else
    57.         {
    58.             Debug.LogError("LoadCatalogsCompleted is failed");
    59.         }
    60.     }
    61.  
    62.     void loadResourceLocation()
    63.     {
    64.         Debug.Log("loadResourceLocation");
    65.        
    66.         foreach(string group in addressableGroups){
    67.             AsyncOperationHandle<IList<IResourceLocation>> handle = Addressables.LoadResourceLocationsAsync(group);
    68.             handle.Completed += locationsLoaded;
    69.         }
    70.     }
    71.     void locationsLoaded(AsyncOperationHandle<IList<IResourceLocation>> obj)
    72.     {
    73.         Debug.Log("locationsLoaded ==> " + obj.Status);
    74.         if (obj.Status == AsyncOperationStatus.Succeeded)
    75.         {
    76.             locations.AddRange(obj.Result);
    77.             loadedGroups++;
    78.  
    79.             if(loadedGroups >= addressableGroups.Count){  
    80.                 loadDependency();
    81.             }
    82.         }
    83.         else
    84.         {
    85.             Debug.LogError("locationsLoaded is failed");
    86.         }
    87.     }
    88.  
    89.     void loadDependency()
    90.     {
    91.         loadedGroups = 0;
    92.         Debug.Log("loadDependency");
    93.         foreach(string group in addressableGroups){
    94.             console.log("Loading " + group + " dependencies");
    95.             AsyncOperationHandle handle = Addressables.DownloadDependenciesAsync(group);
    96.             handle.Completed += dependencyLoaded;
    97.         }
    98.     }
    99.     void dependencyLoaded(AsyncOperationHandle obj)
    100.     {
    101.         Debug.Log("dependencyLoaded ==> " + obj.Status);
    102.         if (obj.Status == AsyncOperationStatus.Succeeded)
    103.         {
    104.             loadedGroups++;
    105.  
    106.             if(loadedGroups >= addressableGroups.Count){
    107.                 loadAssets();
    108.             }
    109.         }
    110.         else
    111.         {
    112.             Debug.LogError("dependencyLoaded is Failed");
    113.         }
    114.     }
    115.  
    116.     private void loadAssets()
    117.     {
    118.         var handle = Addressables.LoadAssetsAsync<GameObject>(locations, onAssetsCategoryLoaded);
    119.         handle.Completed += onAssetsLoaded;
    120.     }
    121.     private void onAssetsCategoryLoaded(GameObject obj)
    122.     {
    123.         Debug.Log(obj);
    124.         //SpawnItem(obj.name);
    125.     }
    126.     private void onAssetsLoaded(AsyncOperationHandle<IList<GameObject>> obj)
    127.     {
    128.     }
    129.  
    130.     void SpawnItem(string addressableKey)
    131.     {
    132.         Debug.Log("SpawnItem ==> " + addressableKey);
    133.         AsyncOperationHandle<GameObject> asyncLoad = Addressables.InstantiateAsync(addressableKey, Vector3.zero, Quaternion.identity);
    134.         StartCoroutine(progressAsync(asyncLoad));
    135.         asyncLoad.Completed += assetSpawned;
    136.     }
    137.     void SpawnItem(GameObject addressableObj)
    138.     {
    139.         Debug.Log("SpawnItem ==> " + addressableObj);
    140.         AsyncOperationHandle<GameObject> asyncLoad = Addressables.InstantiateAsync(addressableObj);
    141.         StartCoroutine(progressAsync(asyncLoad));
    142.         asyncLoad.Completed += assetSpawned;
    143.     }
    144.     private System.Collections.IEnumerator progressAsync(AsyncOperationHandle<GameObject> asyncOperation)
    145.     {
    146.         float percentLoaded = asyncOperation.PercentComplete;
    147.         while (!asyncOperation.IsDone)
    148.         {
    149.             Debug.Log("Progress = " + percentLoaded + "%");
    150.             yield return 0;
    151.         }
    152.         Debug.Log("Progress Done= " + percentLoaded + "%");
    153.     }
    154.     void assetSpawned(AsyncOperationHandle<GameObject> obj)
    155.     {
    156.         Debug.Log("Instantiate completed ==> " + obj.Status);
    157.     }
    158. }
    159.  

    Thanks!
     
    Last edited: Sep 19, 2020
  24. ProgrammingWhileSleeping

    ProgrammingWhileSleeping

    Joined:
    Nov 10, 2017
    Posts:
    17
    Btw here's the error that I'm getting as well.

    Code (csharp):
    1.  
    2. Exception encountered in operation Resource<IAssetBundleResource>(materials_assets_blue_fda73c6a11f9b281c7b63807da8d425e.bundle): Attempting to use an invalid operation handle
    3. UnityEngine.AddressableAssets.Addressables:DownloadDependenciesAsync(Object, Boolean)
    4. AssetLoader:loadDependency() (at Assets/Scripts/AssetLoader.cs:84)
    5. AssetLoader:locationsLoaded(AsyncOperationHandle`1) (at Assets/Scripts/AssetLoader.cs:72)
    6. DelegateList`1:Invoke(AsyncOperationHandle`1) (at Library/PackageCache/com.unity.addressables@1.8.4/Runtime/ResourceManager/Util/DelegateList.cs:69)
    7. UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    8. MonoBehaviourCallbackHooks:Update() (at Library/PackageCache/com.unity.addressables@1.8.4/Runtime/ResourceManager/Util/MonoBehaviourCallbackHooks.cs:19)
    9.  
    10.  
     
  25. ProgrammingWhileSleeping

    ProgrammingWhileSleeping

    Joined:
    Nov 10, 2017
    Posts:
    17
    Hi, can you please explain what the "decor" should be here? I'm also getting Attempting to use an invalid operation handle when using your code.

    Also, what Asset Provider should I use for the asset creation project? Thanks A lot!
     
  26. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    659
    Is it possible to set the catalogPath to a local path? e.g. C:\mycatalog\catalogname?
     
  27. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    659
    Nevermind, I was missing .json at the end, like this:
    D:\Unity Testing\Test-Addressable Master\TestHost\catalog_2020.10.23.21.18.55.json
     
Thread Status:
Not open for further replies.