Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to use addressable system in editor script

Discussion in 'Addressables' started by lifetree, Jul 23, 2019.

  1. lifetree

    lifetree

    Joined:
    Mar 28, 2014
    Posts:
    49
    Hi,

    I have been working on adding the addressable system to my project, and one of the things I want to do is press a button in the inspector on my editor script and load a list of objects using their addresses. I have been trying to use several methods that work during play, but not in the editor. Is there something that needs to be done to make it work in the editor?

    Here is what I have so far, and this doesn't work at all (OnBGDLoad() doesn't run once). Forgive me if I have made a stupid mistake, I am still relatively new to C#:

    Code (CSharp):
    1. [CustomEditor(typeof(LoadTexture))]
    2. public class LoadTextureEditor : Editor
    3. {
    4.     Camera cam;
    5.  
    6.     public void OnEnable()
    7.     {
    8.         EditorApplication.update += Update;
    9.     }
    10.  
    11.     public void OnDisable()
    12.     {
    13.         EditorApplication.update -= Update;
    14.     }
    15.  
    16.     public override void OnInspectorGUI()
    17.     {
    18.         var lt = target as LoadTexture;
    19.  
    20.         base.DrawDefaultInspector();
    21.         EditorGUILayout.Space();
    22.  
    23.         if (GUILayout.Button("Save addresses and delete textures"))
    24.         {
    25.             lt.ConvertToAddressables();
    26.         }
    27.  
    28.         if (GUILayout.Button("Reload textures"))
    29.         {
    30.             lt.reload = true;
    31.         }
    32.     }
    33.  
    34.     void Update()
    35.     {
    36.         var lt = target as LoadTexture;
    37.         if (lt.reload)
    38.         {
    39.             Debug.LogError("Reload Executed");
    40.             lt.reload = false;
    41.             lt.allCams = Resources.FindObjectsOfTypeAll<Camera>();
    42.             foreach (Camera c in lt.allCams)
    43.             {
    44.                 if (c.name != "SettingsCam" && c.name != "SceneCamera" && c.name != "Preview Camera")
    45.                 {
    46.                     if (c.transform.parent.Find("Background") != null)
    47.                     {
    48.                         cam = c;
    49.                         Addressables.LoadAssetAsync<Sprite>(c.GetComponent<LoadTexture>().backgroundTextureAddress).Completed += OnBGDLoad;
    50.                      
    51.                     }
    52.                 }
    53.             }
    54.         }
    55.     }
    56.  
    57.     private void OnBGDLoad(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<Sprite> op)
    58.     {
    59.         cam.transform.parent.Find("Background").GetComponent<SpriteRenderer>().sprite = op.Result;
    60.         Debug.LogError(cam.name);
    61.     }
    62. }
    P.S. The reason I am using the Update method is because I was having trouble getting foreach loops to run in editor, so I thought if I use update, I can force it to run as long as I have that inspector open (based on my understanding of how EditorApplication.update works)
     
  2. lifetree

    lifetree

    Joined:
    Mar 28, 2014
    Posts:
    49
    So I realized that update would be running multiple times (obviously, duh) and thus it would cancel the foreach loop in progress. So I created a different solution, but it is still not working. Here is my code:

    Code (CSharp):
    1. public void ReloadAddressables()
    2.     {
    3.         StartCoroutine(ReloadAddressablesIE());
    4.     }
    5.  
    6.     IEnumerator ReloadAddressablesIE()
    7.     {
    8.         Debug.LogError("Reload Executed");
    9.         allCams = Resources.FindObjectsOfTypeAll<Camera>();
    10.         foreach (Camera c in allCams)
    11.         {
    12.             if (c.name != "SettingsCam" && c.name != "SceneCamera" && c.name != "Preview Camera")
    13.             {
    14.                 if (c.transform.parent.Find("Background") != null)
    15.                 {
    16.                     cam = c;
    17.                     var op = Addressables.LoadAssetAsync<Sprite>(c.GetComponent<LoadTexture>().backgroundTextureAddress);
    18.                     op.Completed += OnBGDLoad;
    19.  
    20.                     while (op.Status != AsyncOperationStatus.Succeeded)
    21.                     {
    22.                         Debug.LogError("op running");
    23.                         //Do nothing
    24.                         yield return null;
    25.                     }
    26.  
    27.                     Debug.LogError(c.name + " finished loading");
    28.                     yield return new WaitForSecondsRealtime(0.01f); //== Maybe this will give it enough time to finish OnBGDLoad() before starting another async op
    29.                 }
    30.             }
    31.         }
    32.     }
    33.  
    34.     private void OnBGDLoad(AsyncOperationHandle<Sprite> async)
    35.     {
    36.         cam.transform.parent.Find("Background").GetComponent<SpriteRenderer>().sprite = async.Result;
    37.         Debug.LogError(cam.name + " added to scene");
    38.     }
    39. }
    40.  
    41. #if UNITY_EDITOR
    42. [CustomEditor(typeof(LoadTexture))]
    43. public class LoadTextureEditor : Editor
    44. {
    45.     public override void OnInspectorGUI()
    46.     {
    47.         var lt = target as LoadTexture;
    48.  
    49.         base.DrawDefaultInspector();
    50.         EditorGUILayout.Space();
    51.  
    52.         if (GUILayout.Button("Save addresses and delete textures"))
    53.         {
    54.             lt.ConvertToAddressables();
    55.         }
    56.  
    57.         if (GUILayout.Button("Reload textures"))
    58.         {
    59.             lt.ReloadAddressables();
    60.         }
    61.     }
    62. }
    63. #endif
    When I click "Reload Textures", in the log, it says "Reload Executed" and then says "op running" once or maybe twice. That is it. I can't figure out why this wouldn't be working.
     
    Last edited: Jul 23, 2019
  3. lifetree

    lifetree

    Joined:
    Mar 28, 2014
    Posts:
    49
    Ok, so I was able to fix my issue. The key was to abandon the addressable system entirely when reloading the textures in the editor. Here is my code:
    Code (CSharp):
    1. public void ReloadAddressables()
    2.     {
    3.         allCams = Resources.FindObjectsOfTypeAll<Camera>();
    4.         foreach (Camera c in allCams)
    5.         {
    6.             if (c.name != "SettingsCam" && c.name != "SceneCamera" && c.name != "Preview Camera")
    7.             {
    8.                 if (c.transform.parent.Find("Background") != null)
    9.                 {
    10.                     c.transform.parent.Find("Background").GetComponent<SpriteRenderer>().sprite = AssetDatabase.LoadAssetAtPath<Sprite>(c.gameObject.GetComponent<LoadTexture>().backgroundTextureAddress);
    11.                 }
    12.             }
    13.         }
    14.     }
    15. #if UNITY_EDITOR
    16. [CustomEditor(typeof(LoadTexture))]
    17. public class LoadTextureEditor : Editor
    18. {
    19.     public override void OnInspectorGUI()
    20.     {
    21.         var lt = target as LoadTexture;
    22.  
    23.         base.DrawDefaultInspector();
    24.         EditorGUILayout.Space();
    25.  
    26.         if (GUILayout.Button("Save addresses and delete textures"))
    27.         {
    28.             lt.ConvertToAddressables();
    29.         }
    30.  
    31.         if (GUILayout.Button("Reload textures"))
    32.         {
    33.             lt.ReloadAddressables();
    34.         }
    35.     }
    36. }
    37. #endif
    The reason this works for me is because my address happens to be the same as the asset path. Even if it isn't, you could get something working using AssetDatabase.GetAssetPath().

    So in conclusion, I don't know if this is a bug with the addressable system or not, but I had to use AssetDatabase.LoadAssetAtPath() when trying to load in the editor. Hope this helps someone.
     
    DMorock and jasonatkaruna like this.
  4. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    not a bug. maybe a "missing feature". Addressbles just isn't set up for editor loading (outside of play mode) yet. It could be extended to work, and we've been looking at adding it ourselves, but it's not there today.
     
  5. rbabiuch

    rbabiuch

    Joined:
    Jul 22, 2019
    Posts:
    8
    Any update on extending the package to include this feature of loading in editor scripts?
     
    NMJ_GD likes this.
  6. calc1fer

    calc1fer

    Joined:
    Oct 5, 2019
    Posts:
    62
    Loading addressables in editor is important feature...
     
    Nevermiss, Vedran_M, NMJ_GD and 3 others like this.
  7. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    @unity_bill

    Hi,

    I also have to say why loading addressable into the editor is very important.

    My project size is fairly large(~100GB) and the Editor is dog slow and it's almost impossible to work in the current state. I'm in a huge pain every day and it's really hopeless if I have to keep working like this.
    And it's getting worse every day with increasing size and newer Unity version update makes it even worse. I cannot believe what's going on.

    However, I'll have to finish what I started and I'm doing my best trying to figure out a way to make it somewhat workable.

    The only way I can do this is to split the project into smaller projects. I don't think there isn't a better way other than that.

    Well, it looks like using Addressable is the best way to split the project.

    The largest portion of the project is Maps(2/3 of the total project size are maps) and I first decided to split the Maps into its own project.

    However, Maps contains both Static and Dynamic elements.
    The Dynamic element often contains Scripts, thus it has to stay with the Main project.
    Therefore, the new Map project will only contain Static elements, and they are built using Addressable.

    So far so good.

    Now it's time to bring this Static Addressable Scene into the Main project so that I can layer Dynamic Scene on top of the Static Scene.

    I of course thought loading Addressable into the Editor is a supported feature. It has to. If it can be dynamically loaded, why won't it loaded into the Editor? I just learned that it's not supported. And my hope is shattered.

    Why!!! This is a huge surprise and I'm stuck right now and all my efforts will going to be wasted.

    I'm pretty sure you are well aware that there are many complaints about slow Editor.
    I think it's to a point that it's not acceptable.
    If you agree, can you please support this feature, soonish? So that it can help us do the work, instead of fighting with the slow Editor?

    If you read this far, I think you know why it's important for the editor to be able to load addressables into the editor.
    Even if you don't agree, please give us a logical explanation or let us know better ways to work large projects.

    If you don't have answers, just make the Editor faster so that we don't have to do this monkey work.

    Thanks.
     
    Last edited: Dec 12, 2019
    DMorock and NMJ_GD like this.
  8. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Super important, subscribing to hear when it happens hopefully?
     
    phobos2077 and VagabondOfHell like this.
  9. VOTRUBEC

    VOTRUBEC

    Joined:
    Dec 17, 2014
    Posts:
    106
    Oh, I just ran into this problem. I would have thought this would have been an obvious feature. :) Subscribing to thread.
     
  10. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    @unity_bill
    Hi, Bill, I think there are enough interests among users who will appreciate the feature.
    I'm pretty sure many are not even aware of what this feature can enable us to do. If they do, they will change how they work with their project quite significantly.

    I pushed Fast-Enter-to-Play mode hard and we finally have it in 2019.3. It's a small(seemingly) feature but it's the best feature I ever had past few years to improve the workflow significantly. And I believe many users finally appreciate it after experiencing it. I think loading Addressable into Editor is going to be another incredible feature similar to Fast-Enter-to-Play mode. Trust me, it worths having in a Unite Keynotes because it will change how we will work with large size projects forever. Unable to scale up to large projects has been one of the weakest points in Unity and it will alleviate the problem quite a bit.

    Please understand that I'm trying to separate the large project into smaller parts with Addressable out of necessity not because I just want to. And I really don't want to do this if the Editor could handle a large project. Besides, having multiple projects has more side benefits because you can separate the projects depends on the work responsibilities for more efficient and better security.

    I understand that loading Addressables into the Editor is not on the original spec but I think it's a very reasonable feature. You may say, it goes against the normal workflow but I can reason that there are many extensions already exists in the Editor that were not in the normal workflow, such as Prefabs editor, DOTS sub-scenes. To me, Addressbles is just read-only asset and I don't expect to edit them after loading. If you treat Addressable as read-only assets, it will simplify many problems, am I wrong? And having it pre-loaded into the editor will also reduce the time to load every time you click on "Play" if you have Fast-Enter-to-Play mode enabled.

    Please consider adding the support and it's really crucial for the success of my project.

    Thank you very much for your understanding.
     
    NMJ_GD, phobos2077, Sasho_ and 4 others like this.
  11. SudoCat

    SudoCat

    Joined:
    Feb 19, 2013
    Posts:
    64
    Why isn't this written front and centre on the documentation for the addressables system? At least in the migration guide. Instead I need to find a random forum thread to learn that this new system, which the docs proudly proclaim can be seamlessly migrated to, actually does not work for many common uses (edit mode or synchronous usage)?
     
    DMorock, Tony_Max, bartofzo and 7 others like this.
  12. Michal_Stangel

    Michal_Stangel

    Joined:
    Apr 17, 2017
    Posts:
    151
    Ran in to this today. I suppose it's still not possible to use Addressables outside Play mode?
    I have a lot of scripts automating work on fbx models. Migrated from Resources to Addressables and just realized I don't know how to replace Resources.Load in these cases.
     
  13. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I was able to load an Audio Clip addressable in edit mode with the following code. You can change it to Game Object by changing the method signature and all instances of "AudioClip".

    Code (csharp):
    1.  
    2.     public static AudioClip EditModeLoadAddressable(AssetReference assetRef) {
    3.         if (!IsAddressableValid(assetRef)) { // seems a good way to check if you chose something other than "none".
    4.             return null;
    5.         }
    6.  
    7.         var path = AssetDatabase.GUIDToAssetPath(assetRef.RuntimeKey.ToString());
    8.         var type = AssetDatabase.GetMainAssetTypeAtPath(path);
    9.         if (type != typeof(AudioClip)) {
    10.             Debug.Log("Your addressable is not an Audio Clip. Can't play.");
    11.             return null;
    12.         }
    13.         var clip = AssetDatabase.LoadAssetAtPath<AudioClip>(path);
    14.         return clip;
    15.     }
    16.  
    17.         public static bool IsAddressableValid(AssetReference addressable) {
    18.             if (addressable == null) {
    19.                 return false;
    20.             }
    21.  
    22. #if UNITY_EDITOR
    23.             return addressable.editorAsset != null;
    24. #else
    25.         return addressable.RuntimeKeyIsValid();
    26. #endif
    27.         }
    28.  
    29.  
     
    DMorock, KReguiegReply, hifar and 6 others like this.
  14. oxysofts

    oxysofts

    Joined:
    Dec 17, 2015
    Posts:
    124
    Sharing this other utility function we made for those using string addresses directly instead.

    Code (CSharp):
    1.  
    2.         /// <summary>
    3.         /// Load the asset using the asset database. (or return null if the address does not match any)
    4.         /// </summary>
    5.         /// <param name="address"></param>
    6.         /// <typeparam name="TValue"></typeparam>
    7.         /// <returns></returns>
    8.         public static TValue LoadInEditor<TValue>(string address)
    9.             where TValue : Object
    10.         {
    11.             AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings;
    12.  
    13.             List<AddressableAssetEntry> allEntries = new List<AddressableAssetEntry>(settings.groups.SelectMany(g => g.entries));
    14.             AddressableAssetEntry       foundEntry = allEntries.FirstOrDefault(e => e.address == address);
    15.             return foundEntry != null
    16.                        ? AssetDatabase.LoadAssetAtPath<TValue>(foundEntry.AssetPath)
    17.                        : null;
    18.         }
    19.  
    Note that writing custom code for editor is actually not that big of a deal, because you should not be using a single point of access for your loaded assets in the first place. For example, if you are loading inside of a ScriptableObject and keeping the loaded instance there, you are using Addressables wrong and you will not benefit from its automatic ref-count management.

    Loading should happen where the asset is actually needed, i.e. your editor script or a component/functionality which uses the asset, not inside the asset itself. As such it is simply a matter of using a different function, such as the one I shared above. It would be nice if could use the same APIs, but this is at worse a minor inconvenience.

    (Obviously I am not talking about actual support of the whole addressables system in editor which would increase performance and scalability. I just thought some of the frustration in this thread may actually be from incorrect usage of addressables, especially those migrating from a synchronous solution like Resources who would be inclined to handle loading lazily and synchronously as part of their classes, such as a getter which fetches the asset and caches it on first use.)

    Edit: note that the function above will not scale well the larger your project gets and can degrade performances. Unfortunately this is the only way to achieve this right now.
     
    Last edited: Feb 15, 2021
  15. avenk2

    avenk2

    Joined:
    Jul 10, 2019
    Posts:
    1
    This seems great for the catalog already loaded, however I am facing a problem where I have a remote content catalog file which I want to read and then get the AssetPath from that. This script seems to work for only the loaded content catalog, is there anyway to get the AddressableAssetSettings for another catalog because the LoadContentCatalogAsync function doesnt work in editor either.
     
    NMJ_GD likes this.
  16. madGlory

    madGlory

    Joined:
    Jan 12, 2016
    Posts:
    44
    + 1 we would also like to load addressables in edit mode.
     
  17. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Read my post up 4. It works for me.
     
  18. madGlory

    madGlory

    Joined:
    Jan 12, 2016
    Posts:
    44
    Hey thanks for the ping, got it working with your reference!
     
  19. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Sure no problem. Glad it's working for you.
     
  20. madGlory

    madGlory

    Joined:
    Jan 12, 2016
    Posts:
    44
    +1 for editor support.

    After using this solution, I maintain that I would very much appreciate better support for addressables in edit mode so that I don't need to write and maintain extra code just to repeat the same functionality of the library while in edit mode.
     
  21. alex_dossamer

    alex_dossamer

    Joined:
    Jun 19, 2018
    Posts:
    25
    Hello! @unity_bill is there a place where feature requests can be formally submitted and voted on by the community? This feels like a good candidate for getting out of the forum and into a more formal feature consideration process. Thank you!
     
  22. jperry_oddgames

    jperry_oddgames

    Joined:
    Sep 18, 2017
    Posts:
    62
    +1 for editor support :)
     
  23. Flying_Banana

    Flying_Banana

    Joined:
    Jun 19, 2019
    Posts:
    29
    Also ran into this issue. Would be great to hear from the dev team on this! @unity_bill
     
    Last edited: Apr 27, 2021
  24. eliphat

    eliphat

    Joined:
    Jul 4, 2017
    Posts:
    48
    +1 for editor support
     
  25. eliphat

    eliphat

    Joined:
    Jul 4, 2017
    Posts:
    48
    I have some kind of meta file in my project and I want to validate it. Being unable to load addressables in editors keeps me away from this.
    Actually on my computer when I use editor coroutines, an exception was thrown. When I use .Complete += and abandon them I have to minimize the editor and revive it several times until it finishes its job.
    Code (CSharp):
    1. Exception: Attempting to use an invalid operation handle
    2. UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject].get_InternalOp () (at Library/PackageCache/com.unity.addressables@1.16.19/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:160)
    3. UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject].get_Result () (at Library/PackageCache/com.unity.addressables@1.16.19/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:220)
    4. UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject].System.Collections.IEnumerator.get_Current () (at Library/PackageCache/com.unity.addressables@1.16.19/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:241)
    5. Unity.EditorCoroutines.Editor.EditorCoroutine.ProcessIEnumeratorRecursive (System.Collections.IEnumerator enumerator) (at Library/PackageCache/com.unity.editorcoroutines@1.0.0/Editor/EditorCoroutine.cs:126)
    6. Unity.EditorCoroutines.Editor.EditorCoroutine.MoveNext () (at Library/PackageCache/com.unity.editorcoroutines@1.0.0/Editor/EditorCoroutine.cs:115)
    7. System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <9577ac7a62ef43179789031239ba8798>:0)
    8. Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    9. System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <9577ac7a62ef43179789031239ba8798>:0)
    10. System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <9577ac7a62ef43179789031239ba8798>:0)
    11. System.Delegate.DynamicInvokeImpl (System.Object[] args) (at <9577ac7a62ef43179789031239ba8798>:0)
    12. System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) (at <9577ac7a62ef43179789031239ba8798>:0)
    13. System.Delegate.DynamicInvoke (System.Object[] args) (at <9577ac7a62ef43179789031239ba8798>:0)
    14. UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at <51ff56607d9e437d85595c71a8c6fb65>:0)
    15.  
     
  26. aholla

    aholla

    Joined:
    May 27, 2014
    Posts:
    81
    Hi,

    Can we load Addressables in the editor yet?

    I see to be able to but only when the method is called again...
     
  27. jperry_oddgames

    jperry_oddgames

    Joined:
    Sep 18, 2017
    Posts:
    62
    @unity_bill are you able to reveal if you guys have any plans on bringing editor support for addressables? cheers
     
  28. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    The long silence usually means that the developer is gone. The turnover is very common at Unity and the project often hibernates for a long time. And then it leads to "Ok, we heard you loud and clear. We will redo the project from scratch" and it will take another 2 or 3 years before we hear something new.

    Please remember Unity doesn't profit from users being successful but selling as many Assets to new users. That's the reason why they are so stubborn and lazy. I would like to be wrong on this but there is some truth to it. Has the Editor gotten faster past a couple of years? They are just saying it but I believe it's going the other way.

    I quit Unity finally and moved to Unreal. I shouldn't have started the project on Unity and I can only blame myself for giving Unity another chance. The slow Editor is gone and I'm so much more productive. The only thing I'm missing is C# but Unreal will have a new scripting language soon. We will see how it turns out. I'll probably use Unity for making FlappyBird-like games only.

    I'll not return to Unity to start another large project unless they make the Editor faster. 2 times faster will not do it but it needs to be faster at least 5 times to feel snappy. IMHO, Unity should drop everything and move to .Net first so that it will get rid of the Domain Reload once and for all. It's the biggest evil of all. But what are they doing now? Still struggling with DOTS and no one knows when it will be finished. 90% of the projects out there don't need DOTS and actually, it will be better off without DOTS, yet Unity is betting everything on it. Have they put 10% effort the put into DOTS, we probably have .Net Unity now and everyone benefits. Whoever is setting the priority at Unity should be removed immediately and think about what's more important and urgent. Will the lazy and stubborn Unity do something? Probably when their stock drops below $10 but they are enjoying the overvalue and they need to make something flash to please the shareholders, not the developer.

    My two cents!
     
    CameronND likes this.
  29. alex_dossamer

    alex_dossamer

    Joined:
    Jun 19, 2018
    Posts:
    25
    My money in the indie space over the next few years is honestly on Godot at this point. Unity is a tool I only ever use for enterprise development now (but even that is slowly changing).

    The addressable system honestly did seem overengineered; they had to overcome a lot of fragmentation in the way resources are handled in different parts of the engine, and at the end of the day, they made it work, but the solution is exceedingly complex.
     
  30. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,816
    I'll ping the team for an update.
     
    jperry_oddgames likes this.
  31. PaulBurslem

    PaulBurslem

    Unity Technologies

    Joined:
    Oct 7, 2016
    Posts:
    79
    Loading addressables in edit mode works with packed data and a built catalog, though there are issues with coroutines and async await that are due to limitations in the engine. I suspect there may be issues when using the sync APIs as well. From reading this thread it appears that a more general support is wanted that works in a similar way to fast mode. This seems technically possible but as always we need to make sure this fits in our internal roadmaps and plans. I will create a ticket to investigate this - it may end up being "easy"...
     
  32. rhys_vdw

    rhys_vdw

    Joined:
    Mar 9, 2012
    Posts:
    110
    Thanks mate, life saver. More generally:

    Code (CSharp):
    1.  
    2.     public static T LoadInEditor<T>(
    3.       this AssetReference assetReference
    4.     ) where T : UnityEngine.Object {
    5.       var path = AssetDatabase.GUIDToAssetPath(assetReference.RuntimeKey.ToString());
    6.       return AssetDatabase.LoadAssetAtPath<T>(path);
    7.     }
    8.  
    Edit:See correction below.
     
    Last edited: Feb 13, 2024
  33. NMJ_GD

    NMJ_GD

    Joined:
    Dec 28, 2019
    Posts:
    14
    +1 editor
    This feature is really important. Maybe some can use rhys_vdw script, but it is only applicable if you are working in one project. But the moment you start using remote catalogues and splitting project in several smaller ones, whole thing falls apart.
     
  34. calc1fer

    calc1fer

    Joined:
    Oct 5, 2019
    Posts:
    62
    This is why I stopped using the addressables and giving feedback. Many people value this function, but developers of addressables don't. Because they only make tools all day long, and they don't develop products to provide end users. Only then do they pretend to hear it when many users make an effort to understand what's important and what's not. I've tried this a few times, but most of them took two to three years to get started. It's a waste of time.

    gl.
     
    BillyWM likes this.
  35. eggsamurai

    eggsamurai

    Joined:
    Oct 10, 2015
    Posts:
    110
    +1
    I hope I can make our asset private. Provide built-only assets to programmer as we are home working group, TBs assets for different Country is :(. And send repo to outcoming in a more safer way.
     
    Last edited: Jan 7, 2022
  36. seoyeon222222

    seoyeon222222

    Joined:
    Nov 18, 2020
    Posts:
    176
    When I found about the addressable, I think that it was indispensable and very valuable.
    Over the past few days, I have suffered numerous problems,
    discovered problems that are difficult to understand, contemplated a detour, and shed tears.
    The problem with this thread is also like that.
    Other thread problems have also been discussed over the years,
    and I have seen many things that have not yet been solved.

    I'm worried if this can be used for actual development. : (
    Don't you still use the addressable?
    What other way do you use to replace it?
     
  37. SugoiDev

    SugoiDev

    Joined:
    Mar 27, 2013
    Posts:
    395
    alex_dossamer likes this.
  38. littlemiemie

    littlemiemie

    Joined:
    Jun 3, 2017
    Posts:
    3
    an awesome solution. (I think you will like it)

    Analysis of the source code shows that
    the AddressableAsset system is implemented based on Time.unscaledTime.
    But the time doesn't refresh in edit mode unless the scene changes.
    So just need to advance Time.unscaledTime in edit mode.
    The following code is used to advance Time.unscaledTime and make the AddressableAsset system work in edit mode.


    Code (CSharp):
    1. #if UNITY_EDITOR
    2.  
    3. using UnityEngine;
    4. using UnityEditor;
    5. using System.Threading.Tasks;
    6.  
    7. /// <summary>
    8. /// This script is used to automatically refresh the time in edit mode to support some time-dependent logic
    9. /// </summary>
    10. [InitializeOnLoad]
    11. public static class TimeInEditMode
    12. {
    13.     static int cnt_running = -1;
    14.  
    15.     static TimeInEditMode()
    16.     {
    17.         EditorApplication.update += Update;
    18.         EditorApplication.playModeStateChanged += PlayModeStateChanged;
    19.     }
    20.  
    21.     static void Update()
    22.     {
    23.         if (cnt_running > 0)
    24.         {
    25.             EditorApplication.QueuePlayerLoopUpdate();
    26.         }
    27.     }
    28.  
    29.     static void PlayModeStateChanged(PlayModeStateChange state)
    30.     {
    31.  
    32.         switch (state)
    33.         {
    34.             case PlayModeStateChange.ExitingEditMode: Clear(); break;
    35.         }
    36.     }
    37.  
    38.  
    39.     [MenuItem("Tools/TimeInEditMode/Start", false, 100)]
    40.     /// <summary>
    41.     /// Start it where you need it, or keep it on all the time
    42.     /// <summary>
    43.     public static bool Start()
    44.     {
    45.         if (Application.isPlaying)
    46.         {
    47.             Debug.Log("cannot call TimeInEditMode/Start in play mode");
    48.             return false;
    49.         }
    50.         if (cnt_running < 0) cnt_running = 1;
    51.         else ++cnt_running;
    52.         return true;
    53.     }
    54.  
    55.     [MenuItem("Tools/TimeInEditMode/Stop", false, 101)]
    56.     public static void Stop()
    57.     {
    58.         if (cnt_running < 0) return;
    59.         --cnt_running;
    60.     }
    61.  
    62.     [MenuItem("Tools/TimeInEditMode/Clear", false, 102)]
    63.     public static void Clear()
    64.     {
    65.         cnt_running = -1;
    66.     }
    67.  
    68.     /// <summary>
    69.     /// You can use it with tasks
    70.     /// <summary>
    71.     public async static void StartWithTask(Task task)
    72.     {
    73.         if (Start())
    74.         {
    75.             await task;
    76.             Stop();
    77.         }
    78.     }
    79.  
    80. }
    81.  
    82. #endif
     
    CameronND and Immu like this.
  39. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Hi Paul!

    Any news here?

    Thanks!
     
  40. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Hi @TreyK-47,

    do you have any news regarding this topic?

    Thanks!
     
  41. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hi @ManuelRauber support for loading Addressables in edit mode was added in 1.19.18
     
    Last edited: Sep 27, 2022
  42. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Great, thank you! :)
     
    dsfgddsfgdsgd likes this.
  43. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Just looked around in the docs, since I've not found a special "do this in edit mode" I assume I can simply use the same APIs?
     
  44. fhn-oncomfort

    fhn-oncomfort

    Joined:
    Jan 14, 2022
    Posts:
    4
    That's how I managed to do it on my side by digging the API (1.19.19):
    That's probably not the most optimized way, but it's pretty straightforward

    Code (CSharp):
    1.         private AudioClip[] GetLanguageClips(List<string> labelsFilter)
    2.         {
    3.             this.labelsFilter = labelsFilter;
    4.  
    5.             List<AudioClip> clips = new List<AudioClip>();
    6.             UnityEditor.AddressableAssets.Settings.AddressableAssetGroup[] groups = GetAllAddressablesGroups();
    7.  
    8.             // Grab all audio clips that match the labels array
    9.             for(int i = 0; i < groups.Length; ++i)
    10.             {
    11.                 List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry> result = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry>();
    12.                 groups[i].GatherAllAssets(result, true, true, true, Filter);
    13.  
    14.                 for(int j = 0; j < result.Count; ++j)
    15.                 {
    16.                     AudioClip clip = result[j].TargetAsset as AudioClip;
    17.                     if (clip != null) clips.Add(clip);
    18.                 }
    19.             }
    20.  
    21.             return clips.ToArray();
    22.         }
    23.  
    24.         private List<string> labelsFilter;
    25.         private bool Filter(UnityEditor.AddressableAssets.Settings.AddressableAssetEntry entry)
    26.         {
    27.             // The filter condition will take the assets that match ALL the labels filter
    28.             int count = 0;
    29.             foreach (string label in entry.labels)
    30.             {
    31.                 if (labelsFilter.Contains(label))
    32.                     count++;
    33.             }
    34.  
    35.             return count == labelsFilter.Count;
    36.         }
    37.  
    38.         private UnityEditor.AddressableAssets.Settings.AddressableAssetGroup[] GetAllAddressablesGroups()
    39.         {
    40.             // Get all .asset files path
    41.             string[] paths = AssetDatabase.GetAllAssetPaths();
    42.             List<string> assetsPaths = new List<string>();
    43.             for (int i = 0; i < paths.Length; ++i)
    44.                 if (paths[i].EndsWith(".asset")) // We know that the addressables groups files end with .asset
    45.                     assetsPaths.Add(paths[i]);
    46.  
    47.             // Load all Addressables Groups
    48.             List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroup> groups = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetGroup>();
    49.             for (int i = 0; i < assetsPaths.Count; ++i)
    50.             {
    51.                 UnityEditor.AddressableAssets.Settings.AddressableAssetGroup group = AssetDatabase.LoadAssetAtPath<UnityEditor.AddressableAssets.Settings.AddressableAssetGroup>(assetsPaths[i]);
    52.                 if (group != null)
    53.                     groups.Add(group);
    54.             }
    55.  
    56.             return groups.ToArray();
    57.         }
     
    adrianadrian likes this.
  45. DeathPro

    DeathPro

    Joined:
    Jul 28, 2018
    Posts:
    87
    I tried the same APIs like LoadAssetAsync but seems like it does not change the original Scriptable Object.

    Code (CSharp):
    1. private static async Task SetSoloModeOptions()
    2.         {
    3.             var mmData = Resources.Load<CD_Matchmaking>("Data/Config/CD_Matchmaking");
    4.             mmData.MaxPlayers = 1;
    5.  
    6.             //var combatData = Resources.Load<CombatSettingsAsset>("DB/GameConfigs/Combat Settings");
    7.             var combatData =
    8.                 UnityEngine.AddressableAssets.Addressables.LoadAssetAsync<CombatSettingsAsset>("WOK0_Combat_Settings");
    9.             await combatData.Task;
    10.             combatData.Result.Settings.MinPlayerCountForStartGame = 1;
    11.  
    12.             EditorUtility.SetDirty(mmData);
    13.             EditorUtility.SetDirty(combatData.Result);
    14.             AssetDatabase.SaveAssets();
    15.             AssetDatabase.Refresh();
    16.  
    17.             UnityEngine.AddressableAssets.Addressables.Release(combatData);
    18.         }
     
  46. DeathPro

    DeathPro

    Joined:
    Jul 28, 2018
    Posts:
    87

    I made something like this and it's working. But the first time it takes 1s to execute because it's iterating all addressable asset in the Addressable Groups. After that, I cache the result.


    Code (CSharp):
    1. private static void SetSoloModeOptions()
    2.         {
    3.             var mmData = Resources.Load<CD_Matchmaking>("Data/Config/CD_Matchmaking");
    4.             mmData.MaxPlayers = 1;
    5.             mmData.IsDebugModeOn = true;
    6.  
    7.             if (_combatSettingsAsset == null)
    8.                 FindCombatSettingsAsset();
    9.            
    10.             _combatSettingsAsset.Settings.MinPlayerCountForStartGame = 1;
    11.  
    12.             EditorUtility.SetDirty(mmData);
    13.             EditorUtility.SetDirty(_combatSettingsAsset);
    14.             AssetDatabase.SaveAssets();
    15.             AssetDatabase.Refresh();
    16.         }
    Code (CSharp):
    1. private static void FindCombatSettingsAsset()
    2.         {
    3.             var assetList = new List<AddressableAssetEntry>();
    4.  
    5.             AddressableAssetSettingsDefaultObject.Settings.GetAllAssets(assetList, true);
    6.             foreach (AddressableAssetEntry addressableAssetEntry in assetList)
    7.             {
    8.                 if (addressableAssetEntry.address != "WOK0_Combat_Settings") continue;
    9.  
    10.                 _combatSettingsAsset = AssetDatabase.LoadAssetAtPath<CombatSettingsAsset>(
    11.                     AssetDatabase.GUIDToAssetPath(addressableAssetEntry.guid));
    12.  
    13.                 break;
    14.             }
    15.         }
     
  47. miraycalskn

    miraycalskn

    Joined:
    Jun 28, 2020
    Posts:
    10
    I'm not sure if this ever worked so i'll say in never versions of unity if you're getting null object from this function, try replacing this line :
    "var path = AssetDatabase.GUIDToAssetPath(assetReference.RuntimeKey.ToString());"
    with this line :
    "var path = AssetDatabase.GUIDToAssetPath(assetReference.AssetGUID);"
    Hope it helps!
     
  48. rhys_vdw

    rhys_vdw

    Joined:
    Mar 9, 2012
    Posts:
    110
    It definitely worked at the time, but I wouldn't be surprised if the API changed.
     
    miraycalskn likes this.