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.

Question Preload and Instantiate by Asset Name

Discussion in 'Addressables' started by FlyVC, Jul 13, 2020.

  1. FlyVC

    FlyVC

    Joined:
    Jan 5, 2020
    Posts:
    22
    I preload my assets and add them into an dictionary by their name:

    var handle = Addressables.LoadAssetsAsync<GameObject>("WeaponMenuPrefabs", op =>
    string name = op.ToString();
    _PreviewAssetsDict.Add(name, op);

    Then I instantiate them inside a placeholder object that holds a AssetReference
    string assetName = parent.assetReference.editorAsset.name;
    GameObject newPreview = Instantiate(_PreviewAssetsDict[assetName], preview.transform, false);

    This runs fine in the editor, however "editorAsset" is not available at runtime in the real app.

    It seems that there is no way to get the name from the AssetReference(which is a bit ridiculous tbh)
    https://forum.unity.com/threads/how-to-get-name-from-assetreference.658618/

    Is there any other way to achieve this LoadAssetsAsync-Callback to AssetReference connection?
     
  2. FlyVC

    FlyVC

    Joined:
    Jan 5, 2020
    Posts:
    22
    just a minor correction from the code above:
    string name = op.ToString();
    should be:
    string name = op.name;

    I could not edit the post above because of a false spam detection :/
     
  3. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    545
    You'll have to build another lookup table (guid -> name) when you build your assets, or inherit from AssetReference and store the name there, and use that everywhere instead of AssetReference. Yeah, it's not ideal...
     
  4. FlyVC

    FlyVC

    Joined:
    Jan 5, 2020
    Posts:
    22
    Thanks for the input, I already tried to solve it in a similar way by executing a script in the editor to save the name in a separate variable, that failed because this would require a static array, what I do not want.

    The ideal case would be that the editor fills out the name variable as soon as I choose the Assetreference in my Array of stats.

    Do you have further advice or how to execute code when I build assets?

    Thanks!
     
  5. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    545
    I do this for a version lookup based on labels, but you can adapt it for name lookups. I created an addressables build script so when I runs, it generates the table and serializes it to a .txt asset and turns it into an addressable before the addressables build actually runs. Then when I initialize addressables, I load that .txt asset and deserialize it back into the lookup table so that I can look up the versions synchronously.

    Yours doesn't have to be this complicated. I did this because I have to work with multiple catalogs (my old version just wrote the lookup table to StreamingAssets, but it's the same idea).

    Code (CSharp):
    1. #if UNITY_EDITOR
    2.         public static AssetVersionDictionary Create()
    3.         {
    4.             AssetVersionDictionary versionDictionary = new AssetVersionDictionary();
    5.  
    6.             var settings = UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings;
    7.  
    8.             if (settings == null) return versionDictionary;
    9.  
    10.             foreach (var group in settings.groups)
    11.             {
    12.                 foreach (var entry in group.entries)
    13.                 {
    14.                     foreach (var label in entry.labels)
    15.                     {
    16.                         versionDictionary.TryAdd(entry.address, label);
    17.                     }
    18.                 }
    19.             }
    20.             return versionDictionary;
    21.         }
    22. #endif

    Code (CSharp):
    1. [InitializeOnLoad]
    2. public static class AssetVersionGenerator
    3. {
    4.     [MenuItem("Build/Build Addressables")]
    5.     public static void BuildAddressables()
    6.     {
    7.         // Generate lookup table for build.
    8.         GenerateVersionLookup();
    9.         UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.BuildPlayerContent();
    10.     }
    11.  
    12.     static AssetVersionGenerator()
    13.     {
    14.         EditorApplication.playModeStateChanged += EditorApplication_playModeStateChanged;
    15.     }
    16.  
    17.     private static void EditorApplication_playModeStateChanged(PlayModeStateChange obj)
    18.     {
    19.         if (obj == PlayModeStateChange.ExitingEditMode)
    20.         {
    21.             // Make sure lookup table is generated for play mode in editor.
    22.             GenerateVersionLookup();
    23.         }
    24.     }
    25.  
    26.     public static void GenerateVersionLookup()
    27.     {
    28.         var settings = UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings;
    29.  
    30.         // Generate TextAsset
    31.         string json = AssetVersionDictionary.Create().Serialize().ToString();
    32.  
    33.         string versionDir = Application.dataPath + "/GeneratedAssets/Text/";
    34.         Directory.CreateDirectory(versionDir);
    35.         File.WriteAllText(versionDir + "addressable-versions.txt", json);
    36.         AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    37.  
    38.         string versionGUID = AssetDatabase.AssetPathToGUID("Assets/GeneratedAssets/Text/addressable-versions.txt");
    39.  
    40.         var group = settings.FindGroup("Generated");
    41.         if (group == null)
    42.         {
    43.             // Create a read-only group if it doesn't already exist.
    44.             group = settings.CreateGroup("Generated", false, true, true, settings.DefaultGroup.Schemas);
    45.         }
    46.         // Make text asset addressable in the "Generated" group.
    47.         settings.CreateOrMoveEntry(versionGUID, group, true).address = "addressable-versions";
    48.         AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    49.     }
    50. }
     
    FlyVC likes this.
  6. FlyVC

    FlyVC

    Joined:
    Jan 5, 2020
    Posts:
    22
    Thanks, that means a bunch :)

    edit, my solution for building the lookup table in a jsonfile
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AddressableAssets;
    5. using System.IO;
    6. using UnityEditor;
    7.  
    8. [InitializeOnLoad]
    9. public static class BuildAddressableLookupTable
    10. {
    11.  
    12.     [System.Serializable]
    13.     public class addressableGUIDName
    14.     {
    15.         public string guid;
    16.         public string name;
    17.     }
    18.     [System.Serializable]
    19.     public class addressableGuidNameList
    20.     {
    21.         public List<addressableGUIDName> GuidNameData;
    22.     }
    23.     static BuildAddressableLookupTable()
    24.     {
    25. #if UNITY_EDITOR
    26.  
    27.         addressableGuidNameList addressableListObject = new addressableGuidNameList();
    28.         addressableListObject.GuidNameData = new List<addressableGUIDName>();
    29.         var settings = UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings;
    30.  
    31.         foreach (var group in settings.groups)
    32.         {
    33.             foreach (var entry in group.entries)
    34.             {
    35.                     addressableGUIDName newitem = new addressableGUIDName();
    36.                     newitem.name = entry.address.ToString();
    37.                     newitem.guid = entry.guid.ToString();
    38.                     addressableListObject.GuidNameData.Add(newitem);
    39.             }
    40.         }
    41.         string json = JsonUtility.ToJson(addressableListObject, true);
    42.         Debug.Log(json);
    43.  
    44.         File.WriteAllText(Application.persistentDataPath + "/assetLookupTable.json", json);
    45. #endif
    46.     }
    47. }
     
    Last edited: Jul 14, 2020
    Mykola_Khimich likes this.