Forum rules - please read before posting.

Make music as addressable.

Hi my build of Android is including music files in the build which is causing my build size to increase. But I want ot load my music files from addressables so that my build size can be reduced. How can I do this?

It shows that music files are used by SettingsManager.asset which is used by References.asset so they were included in build.

Comments

  • edited July 2023

    You can define Music tracks (with labels) in the Editor, but leave the actual "Clip" asset field blank - and populate it at runtime via a custom script.

    As with any Manager/Editor field, you can get an API reference to it by right-clicking the field's label, i.e.:

    AC.KickStarter.settingsManager.musicStorages[2].audioClip = myAudioClip;
    

    A typical script, with public functions to preload and assign clips, would look something like this:

    using UnityEngine.ResourceManagement.AsyncOperations;
    using UnityEngine.AddressableAssets;
    using System.Collections;
    using UnityEngine;
    using AC;
    
    public class MusicAddressables : MonoBehaviour
    {
    
        [SerializeField] private MusicAddressable[] musicAddressables = new MusicAddressable[0];
    
        public void Assign (int trackID)
        {
            foreach (MusicAddressable musicAddressable in musicAddressables)
            {
                if (musicAddressable.trackID == trackID) StartCoroutine (AssignCo (musicAddressable));
            }
        }
    
        public void AssignAll ()
        {
            foreach (MusicAddressable musicAddressable in musicAddressables)
            {
                StartCoroutine (AssignCo (musicAddressable));
            }
        }
    
        public void Preload (int trackID)
        {
            foreach (MusicAddressable musicAddressable in musicAddressables)
            {
                if (musicAddressable.trackID == trackID) StartCoroutine (PreloadCo (musicAddressable));
            }
        }
    
        public void PreloadAll ()
        {
            foreach (MusicAddressable musicAddressable in musicAddressables)
            {
                StartCoroutine (PreloadCo (musicAddressable));
            }
        }
    
        private IEnumerator PreloadCo (MusicAddressable musicAddressable)
        {
            if (!musicAddressable.handle.IsValid ())
            {
                AsyncOperationHandle<AudioClip> handle = Addressables.LoadAssetAsync<AudioClip> (musicAddressable.reference);
                yield return handle;
                musicAddressable.handle = handle;
            }
        }
    
        private void OnDisable ()
        {
            foreach (MusicAddressable musicAddressable in musicAddressables)
            {
                musicAddressable.Reset ();
            }
        }
    
        private IEnumerator AssignCo (MusicAddressable musicAddressable)
        {
            if (!musicAddressable.handle.IsValid ())
            {
                AsyncOperationHandle<AudioClip> handle = Addressables.LoadAssetAsync<AudioClip> (musicAddressable.reference);
                yield return handle;
                musicAddressable.handle = handle;
            }
    
            musicAddressable.Assign ();
        }
    
        [System.Serializable]
        private class MusicAddressable
        {
    
            public int trackID;
            public AssetReference reference;
            public AsyncOperationHandle<AudioClip> handle;
    
            public void Assign ()
            {
                if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
                {
                    KickStarter.settingsManager.musicStorages[trackID].audioClip = handle.Result;
                }
            }
    
            public void Reset ()
            {
                if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
                {
                    Addressables.Release (handle);
                }
                KickStarter.settingsManager.musicStorages[trackID].audioClip = null;
            }
    
        }
    
    }
    
  • edited July 2023

    I get these warning and errors. I created a script named "MusicAddressables" and assigned it to a game object. Then I assigned the addressable audio files in the fields. Left the Music Storage fields empty.

    Screenshot of my setup. https://imgur.com/a/pfaYYgo

    Cannot play _Music - no AudioClip assigned to track 11!

    Exception: Attempting to use an invalid operation handle
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.get_InternalOp () (at Library/PackageCache/com.unity.addressables@1.19.19/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:454)
    UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Release () (at Library/PackageCache/com.unity.addressables@1.19.19/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:525)
    UnityEngine.ResourceManagement.ResourceManager.Release (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle handle) (at Library/PackageCache/com.unity.addressables@1.19.19/Runtime/ResourceManager/ResourceManager.cs:603)
    UnityEngine.AddressableAssets.AddressablesImpl.Release[TObject] (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] handle) (at Library/PackageCache/com.unity.addressables@1.19.19/Runtime/AddressablesImpl.cs:833)
    UnityEngine.AddressableAssets.Addressables.Release[TObject] (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] handle) (at Library/PackageCache/com.unity.addressables@1.19.19/Runtime/Addressables.cs:1258)
    MusicAddressables+MusicAddressable.Reset () (at Assets/MM/MusicAddressables.cs:92)
    MusicAddressables.OnDisable () (at Assets/MM/MusicAddressables.cs:58)
    
  • I've updated the above - it should remove the error now.

    You will still need to load your music addressable at the intended time, however. If you make the GameObject the script is attached to a prefab, you can use the Object: Call event Action to reference that prefab and call its Assign / AssignAll functions as needed.

  • Should I add the action Object: Call event for every scene or just the first one?

  • Thank you Chris, it works perfectly in the editor. Checking on Android and will let you know about how it is.

  • Should I add the action Object: Call event for every scene or just the first one?

    Once a track has been assigned, it won't need to be again for the duration of that build.

    With some slight tweaking, I've gone and made this a page on the AC wiki:
    https://adventure-creator.fandom.com/wiki/Music_track_addressables

  • Thanks Chris, you are awesome.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.