Support for custom Unity packages

Hi,

I would like to share some suggestions regarding possible improvements to the Unity Integration for people/teams like us, who have built their own extensions on top of it in the form of Unity Packages.

We have created our own layer on top of the core components of FMOD so that we can simplify certain workflows and gain other benefits. This extension is created as a Unity Package so that we can easily reuse it in future projects. This resulted in us running into a couple of issues which we think might be worth looking into so that other teams who might be in a similar position in the future have easier time making their own custom packages.

The simpler issue affects the ability to re-use the build-in editor features FMOD comes with. The prime example being the event browser, allowing you to easily reference the audio events you want to play. When making custom components, features like these are priceless and having to re-implement them would be a lot of unnecessary work. Currently the EventBrowser class is not marked as public, making it not possible to use it without having to modify the plugin’s source code. This obviously is not a major issue but having to do this with any future updates would certainly be annoying. Another class in a similar position is EditorUtils. It would be great if these and possibly other editor components were made public by default, making it easier for us to reuse them.

A more complicated problem would be making FMOD not dependant on being placed under the Plugins folder. Ideally, the FMOD integration should be contained inside the our package to preserve the modular nature of packages. Sadly, as of now, a lot of the plugin is coded in a way where it is dependant on being under this specific folder. This caused some early issues with the “images” folder that we had to work around by copying it from the package, which by all means and purposes is not ideal.

This approach worked fine until we started making builds of our project, where we ran into constant errors of platform implementations not being found as they were expected to be under the Plugins folder. The approach of copying them also didn’t help this time around because this resulted in there being duplicate implementations which confused the build process. Not to mention the already stated issue that this should not be the way to handle this because it completely breaks the idea of package structure. There is also the option of just moving the package content from the package folder into the plugins folder but then you run the risk of someone accidentally removing some of it and not being able to fix the issue without completely reimporting the entire package. In the end we were forced to directly change the behaviour of the Platform.GetBinaryFilePaths() method to override where the binaries are looked up.

Dealing with this issue lead us through a lot of hoops that made us aware of a lot of inconsistencies in regards to how file paths are handled throughout the plugin. You would assume that with the plugin folder structure being the same, you would in the worst case only need to change the base path such as the RuntimeUtils.PluginBasePath property. This is sadly not the case, as a lot of places either prepend this path with the “Assets/” string, resulting in invalid path errors or for example straight up directly reference the Application.dataPath field, as is the case in the already mentioned Platform.GetBinaryFilePaths() method. This way of handling paths leads me to believe that either the plugin was build with the clear intention of being placed in this specific folder and/or was later on bent over in a lot of places to at least work there with no thought being put into making it more flexible.

It would be lovely if this could be reworked and make it possible for us to choose the base plugin folder. The plugin folder can still be used as default but being able to set this up in the FMOD settings would be great.

Thanks for considering any of these and sorry for the long post.

Thanks for sharing your feedback.

With the release of 2.02.06, the EventBrowser and EditorUtils are both marked as public. If there are other classes you want to extend that are private in this release, let us know and we’ll consider them. While we don’t officially support developers extending our scripts we also don’t want to get in their way either. With 2.02.06 we did a pass on the entire codebase ensuring explicit public / private is specified. This means many of the default “internal” classes are now public and available for extending.

Regarding your second concern about allowing the FMOD plugin to be placed where you like, we added support for this in 2.02.02. The entire FMOD directory can be moved from the current Plugins directory (a legacy from the old days where Unity required this) and it can now be placed wherever you like. Ensure you also move the FMOD.meta file with the folder, this will ensure when you update the FMOD package it gets installed to the location where you moved it (rather than the default). Our code will use the internal ID of that folder (specified in FMOD.meta) as a method to locate any resources we require inside our package, by doing it this way no configuration is required, simply place it where you like.

If any of this isn’t working for you, please let us know.

Thanks for the quick reply mathew.

It is nice to see that the concern of editor related components being available to us had already been addressed. As a side note, is there a specific time schedule for when the versions higher than 2.02.04 will become Unity verified and available through the package manager?

As for the plugin placement issue, I have tried doing what you said in a new project with a fresh import of the plugin at first. I believe what you said is true as long as the folder with the plugin is somewhere under the Assets folder. Having it inside a package brings up the issue I have already mentioned where a lot of the code assumes that the plugin will be under the Assets folder by prepending the plugin base path by either “Assets/” or Application.dataPath. If the plugin is in a package, the RuntimeUtils.PluginBasePath property updates correctly but because of this prepend a lot of code actually ends up looking for …/Assets/Packages/… which is not valid as the Packages folder is not under the Assets folder.

In order to get it to work in this simplified test case I ended up having to make the following changes:

  • Platform.GetBinaryPaths() - ignore the prefix parameter and return info.LatestLocation()
  • EditorUtils.LoadImage() - remove the “Assets/” prepend from the path string passed into the EditorGUIUtility.Load() call

When applying this approach to our actual package, I ended up making additional changes to some other parts of the code where it seemed like the same issue might rise up. There is definitely more that I either missed, skipped or forgot to take a note of, with the exception being the pieces of code that seemed to deal with obsolete parts of the plugin or older versions:

  • EditorSettings.FmodFolderFull property
  • EditorUtils.StagingSystem - PlatformsFolder & StagingFolder properties
  • EventManager.CacheAssetFullName property
  • PlatformPlayInEditor.GetPluginPath() method
  • FileReorganizer.GenerateTasksForCodeFolders() & GenerateTasksForLooseAssets() methods
  • The FileReorganizer.TaskGenerator also seems like an issue but would require more in-depth refactorization

With this I ended up successfully putting the entirety of the plugin into our package. This created the problem of not being able to modify the FMOD settings in the actual production project because of it being in the package folder that you are not allowed to modify the contents of. I fixed this by making it so that the settings and cache files are created under a settings folder that’s located in the Assets folder. I achieved this by changing the path strings returned by the EventManager.CacheAssetFullName, EditorSettings.FmodFolderFull and EditorSettings.CacheFolderRelative properties and changing the implementation of the EditorSettings.CreateSettingsAsset() method a bit.

Currently, this solution is “ideal” as the plugin is contained within the package and it creates and uses the settings file in the project. Obvisously, being able to do this without having to touch the plugin code would be great, but I understand if that is not a primary goal for you. Although, maybe looking into all those path prepends that break the idea of one component deciding where the plugin is located might be worth the time. At least that way we would avoid having to make all those changes and only deal with changing where the settings and cache files are located.

Thanks once again for the info you have provided. It took some more work but at least we are way happier with the state of our package.

Unity have strict requirements for uploading to the store and sometimes they do not accept our update (leaving the store listing on the old version). We are very close to releasing 2.02.07, this will be the next candidate we submit to Unity for verification, the process usually takes around two weeks, if accepted it will go live on the asset store. You can however always get the latest version from our website.

Regarding moving the FMOD folder you are quite right, my comments were regarding moving it anywhere under the assets directory, i.e. Assets/FMOD or Assets/3rd_party/FMOD. We do not currently support moving it to the packages directory, this is largely because we use the old asset package method, not the new package method. Honestly we’d be keen to switch to the new method, but then we would not be allowed to submit to the asset store and we’re not keen on maintaining two different install methods.

I’ll create an internal task to consider the changes you suggest though, this is all work that would be required if Unity ever permit the new style packages into the store. Any work that is done ahead of that goal should make your integration process less involved.