This document should cover all AssetBundle-related topics in modding Subnautica. The following are knowledge prerequisites:
- You know how to create a prefab in Unity.
- You know how to write a mod for Subnautica.
- You know your way around the basic elements of the Unity Editor interface.
- Ensure you have an appropriate version of Unity.
- Prepare your GameObject.
- Convert your GameObject to a prefab.
- Add that prefab to an AssetBundle in the Inspector Window.
- Build all AssetBundles.
- Move the AssetBundle file into your mod folder.
- Load the AssetBundle and extract your GameObject.
You should prepare your AssetBundle in a Unity Editor which matches the version used to build Subnautica. You can find which version was used to build Subnautica in the qmodmanager_log-Subnautica.txt file in the Subnautica root directory. In the top few lines, you should find a line that looks like this:
Initialize engine version: 2019.2.17f1 (441)
or this
[Info : BepInEx] Running under Unity v2019.4.36.870
In this case, we should download Unity version 2019.4.36f1, or at least the closest version we can find. For example, 2019.4.36 might suffice if we cannot find 2019.4.36f1.
The following is a file you should put in a directory called exactly "Editor" in the Assets folder of your Unity project. So you should have the folder structure "Assets/Editor/thisFile". This adds a button to the bottom of the Assets menu in the Unity editor. The button is called "Build AssetBundles," and it does exactly what it says. This might take several minutes to execute, but when you're done you should have a file given the same name you gave the AssetBundle in the Inspector earlier. This file will be stored in the Assets/AssetBundles folder, and it will be easily recognizable both by its lack of an extension (no file type) and by its considerable size. Any non-AssetBundles in the folder will by tiny in comparison- on the order of 1 or 2 KB.
using UnityEditor;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
}
}
The following is an example of how to load an AssetBundle and extract a GameObject and a Sprite from it. In this example, the AssetBundle is placed in a folder called "assets" which is placed inside the mod folder in the QMods folder. In other words, we have the folder structure
Subnautica/QMods/MY_MOD_NAME/assets/MY_ASSET_BUNDLE
Notice we must create the AssetBundle with our sprite in a SpriteAtlas, but we later cast it into an Atlas.Sprite. To build the AssetBundle requires the sprite to be in a SpriteAtlas, but Atlas.Sprite is the type oft-required by Subnautica.
// We will extract our assets to these two variables.
GameObject myAsset;
Atlas.Sprite mySprite;
// We can establish the filepath to our AssetBundle in this way.
string modPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(modPath, "assets/MY_ASSETBUNDLE_NAME"));
if (myLoadedAssetBundle == null)
{
Logger.Log("Failed to load AssetBundle!");
return;
}
// We must iterate over all the assets in our AssetBundle,
// wherein we match them to our target variables by their prefab names.
System.Object[] arr = myLoadedAssetBundle.LoadAllAssets();
foreach (System.Object obj in arr)
{
if (obj.ToString().Contains("MY_SPRITE_ATLAS_NAME"))
{
SpriteAtlas thisAtlas = (SpriteAtlas)obj;
Sprite myRawSprite = thisAtlas.GetSprite("MY_SPRITE_NAME");
mySprite = new Atlas.Sprite(mySprite);
}
else if (obj.ToString().Contains("MY_GAMEOBJECT_NAME"))
{
myAsset = (GameObject)obj;
}
}