Get master bank and all events

Hi, I’d like to get a reference to the master bank at runtime and retrieve a list of all events (for a sound test menu feature).
I’m not clear on exactly how you are suppose to retrieve a reference to the master bank in Unity in order to then use bank.getEventList().
https://www.fmod.com/resources/documentation-api?version=2.02&page=studio-api-bank.html#studio_bank_geteventlist
Can someone point me in the right direction? Thank you!

You can try something like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class loadBanksScript : MonoBehaviour
{
    [FMODUnity.BankRef]
    public string bankPath;

    FMOD.Studio.Bank bank;
    FMOD.Studio.EventDescription[] eventDescriptions;

    // Start is called before the first frame update
    void Start()
    {
        FMODUnity.RuntimeManager.StudioSystem.loadBankFile(bankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank);
        bank.getEventList(out eventDescriptions);
        foreach (FMOD.Studio.EventDescription eventDesc in eventDescriptions)
        {
            eventDesc.getPath(out string eventPath);
            Debug.Log(eventPath);
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Please keep in mind that the Master bank does not contain all the events in the FMOD Studio project, only the events that have been assigned to it. You can only get the list of events assigned to a particular bank. Instead, ensuring the Master bank and the Master.strings bank have been loaded, you will need to getEventList on every bank loaded into Unity to get a list of all events.

Thank you for the sample code. I attempted to run this using both Master and Master.strings when selecting the bankPath in the Unity Editor. When I run the game I get the following error:

[FMOD] FMOD_OS_File_Open : fopen failed to open 'Master', errno = 2

UnityEngine.Debug:LogError (object)
FMODUnity.RuntimeUtils:DebugLogError (string) (at Assets/Plugins/FMOD/src/RuntimeUtils.cs:549)
FMODUnity.RuntimeManager:DEBUG_CALLBACK (FMOD.DEBUG_FLAGS,intptr,int,intptr,intptr) (at Assets/Plugins/FMOD/src/RuntimeManager.cs:82)

and the error

[FMOD] RuntimeBankModel::openFile : Failed to open file 'Master'
UnityEngine.Debug:LogError (object)
FMODUnity.RuntimeUtils:DebugLogError (string) (at Assets/Plugins/FMOD/src/RuntimeUtils.cs:549)
FMODUnity.RuntimeManager:DEBUG_CALLBACK (FMOD.DEBUG_FLAGS,intptr,int,intptr,intptr) (at Assets/Plugins/FMOD/src/RuntimeManager.cs:82)

For reference I currently have the FMOD settings configured to:
Source Type: Multiple Platform Build
Import Type: Streaming Assets
Load Banks: All

Thanks again for your help!

My mistake - it seems that FMODUnity.RuntimeManager.StudioSystem.loadBankFile() requires the full bank path which [FMODUnity.BankRef] does not provide. RuntimeManager.LoadBank() does work with [FMODUnity.BankRef] but does not provide the loaded bank back as a variable.

There is also an issue we’ve discovered which is banks don’t get copied over to StreamingAssets until build time, which makes it incompatible with trying to pass the bank’s full path when using the Unity PIE mode. This has been raised and will be looked at for a future release.

In the meantime, please use this instead - it checks if the game is playing in the editor or in a built game:

using System.Collections;
using System.IO;
using System.Collections.Generic;
using UnityEngine;

public class loadBankScript : MonoBehaviour
{
    [FMODUnity.BankRef]
    public string bankPath;

    public FMODUnity.EventReference eventPath;

    FMOD.Studio.Bank bank;
    FMOD.Studio.EventDescription[] eventDescriptions;

    // Start is called before the first frame update
    void Start()
    {
#if UNITY_EDITOR
        FMODUnity.RuntimeManager.StudioSystem.loadBankFile("hard coded path to project's /Build/Desktop/" + bankPath + ".bank", FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank);
#endif

#if !UNITY_EDITOR
        FMODUnity.RuntimeManager.StudioSystem.loadBankFile(Path.Combine(Application.streamingAssetsPath, "Desktop/" + bankPath + ".bank"), FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank);
        if (Directory.Exists(Application.streamingAssetsPath))
        {
            string worldsFolder = Application.streamingAssetsPath;

            DirectoryInfo d = new DirectoryInfo(worldsFolder);
            foreach (var file in d.GetFiles())
            {
                Debug.Log(file);
            }
        }
        else
        {
            Debug.Log("No streaming assets folder");
        }
#endif

        //FMODUnity.RuntimeManager.LoadBank(Application.streamingAssetsPath + "/" + bankPath + ".bank");

        bank.getEventList(out eventDescriptions);
        foreach (FMOD.Studio.EventDescription eventDesc in eventDescriptions)
        {
            eventDesc.getPath(out string eventPath);
            Debug.Log(eventPath);
        }

        
    }

    // Update is called once per frame
    void Update()
    {

    }
}

Be sure to change the hard coded path to where your FMOD Studio project’s build folder is.

Ok, we are making progress.

When I run this code (making appropriate adjustments), I am able to get the bank.
However, when I attempt to call bank.getEventList(out eventDescriptions) the output array is always null, and I get the error code Invalid Handle. To check, I tried calling bank.hasHandle() which appears to always be returning false.
Is there perhaps another step I am missing?

Thanks again for your help in figuring this out. For reference here is the adjusted code I am calling:


        [FMODUnity.BankRef][SerializeField] private string bankPath;

        private void Start() {
            string fullPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Desktop/" + bankPath + ".bank");
#if UNITY_EDITOR
            fullPath = Application.dataPath + "/FMODBuild/Desktop/" + bankPath + ".bank";
#endif
            FMODUnity.RuntimeManager.StudioSystem.loadBankFile(fullPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out FMOD.Studio.Bank bank);

            Debug.Log(bank.hasHandle()); // Returns false

            bank.getEventList(out FMOD.Studio.EventDescription[] eventDescriptions);
            foreach(FMOD.Studio.EventDescription eventDesc in eventDescriptions) {
                eventDesc.getPath(out string path);
                Debug.Log(path);
            }
        }

I’m not able to replicate this issue. Copying your code and copying the built banks to the “FMODBuild” folder in the Unity project directory allows me to get the bank and it’s event list. Could you please verify that the banks are not set to AssetBundle pointing to an FMODBuild folder. This setup places byte files in that folder and not bank files.

The banks are indeed not set to AssetBundles.
I’m using unity 2022.1.0b16, and FMOD Integration 2.02.04.

I tried calling bank.getLoadingState() as well, which returns UNLOADED which seems odd to me.
I am able to hear all sounds running correctly, but for some reason this can’t seem to access the bank.
Any other suggestions? Thanks again.

I’m getting the feeling this bank is being loaded somewhere else and when you try to load it again from your script it is being ignored, therefore always returning UNLOADED.

You can get what banks are already loaded using FMOD.Studio.System.getBanksList().

https://www.fmod.com/resources/documentation-api?version=2.02&page=studio-api-system.html#studio_system_getbanklist

Excellent yes that was the issue. The bank I’m trying to load is the master bank, which is set to load by default. It is a bit counterintuitive that bank.getLoadingState() will return UNLOADED if the bank is already loaded… but I changed the code around to the snippet below and I am able to successfully read all event paths in the bank.
Thanks for your help!

        [FMODUnity.BankRef][SerializeField] private string bankPath;

        private void Start() {
            FMODUnity.RuntimeManager.StudioSystem.getBankList(out FMOD.Studio.Bank[] loadedBanks);
            foreach(FMOD.Studio.Bank bank in loadedBanks) {
                bank.getPath(out string path);
                if(path != bankPath) {
                    return;
                }
                bank.getEventList(out FMOD.Studio.EventDescription[] eventDescriptions);
                foreach(FMOD.Studio.EventDescription eventDesc in eventDescriptions) {
                    eventDesc.getPath(out string eventPath);
                    Debug.Log(eventPath);
                }
            }
        }