You're working on the most amazing map you've ever made. It has it all, floors, walls, even ceilings. But you've decided it's missing something important, traps!
This isn't the first time you've used Unity, so you open up your code editor and write a quick script for a simple trapdoor. When the trigger is hit, it disables all the floor objects, and hopefully your naive player will fall in.
You add your script to the scene and give it a quick in-editor test to be sure it's working, and then you build your assets and run the game.
Unfortunately, your player finds that they're just fine. Your script doesn't seem to be working, and a new error has appeared in the console:
We see custom scripts exported with our assets all the time. Items have scripts for handles, whoosh points, damagers, and more. These scripts seem to work fine in the game, so what's going on here?
Lets go ahead and dump the contents of our trapdoor component and see what the addressables system is bundling:
This might look like nonsense at first, but it actually makes sense. We can see our thingsToToggle field is included here, with a list of the gameobjects it was referencing. But it doesn't look like our code was included in the bundle at all.
The other fields in this dump are fairly self explanatory, but what is m_Script? It seems to point to another asset in our bundle, so lets take a look:
We can see the name of our class here, and the name of the assembly it is contained inside.
This makes sense! Instead of packing the code in our bundle, addressables instead packs a reference to where the code should be in the built version of the game.
Code is not included in our asset bundles. Instead, a reference for where to find our code is packed inside. The information it uses for this is as follows:
Any serializable fields that our class had were preserved. Looking inside our bundle, we found that the thingsToPreserve variable was packed and the references it had were included.
[SerializeField]
attribute.
You can read more about serialization here:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/
To solve our problem we need to do two things.
We need to actually include our code with our mod. Thankfully this part isn't too bad! You can follow this guide here to learn how to build assemblies that you can include in your mod folder:
https://hackmd.io/@lyneca/bas-script-modding#Writing-Code
We're going to include an exact copy of our Trapdoor class in this assembly, and include this assembly in our mod folder. The name of this assembly file is important!
We need to find a way to change the location our script reference points to. Currently it tells Unity to check Assembly-CSharp.dll for our class. Unfortunately we can't modify this assembly to include our code, so we need to redirect this reference elsewhere.
Thankfully, Unity provides a built-in solution to this problem! Assembly Defintions are a special asset that will cause all scripts it shares a folder with to build to a different assembly.
We can create an assembly definition by right clicking in the project window and selecting it under the Create>
dropdown. The name of this file is important, we want to make sure it matches the name of the assembly we built to our mod folder (excluding the .dll)
The last step is to make sure your scripts are placed in the same folder as your assembly defintion, and then simply rebuild your mod!
Inspecting our bundle again, we can see it now looks for our custom assembly instead!
Since only our fields were included in the bundle, we can actually exclude our methods in the Unity version.
Script in our Unity project:
Script in our mod folder assembly:
We can still make use of UnityEvents without breaking references. Take this simple component for example:
We can create a button and reference this method in the Unity Inspector
And so long as a matching script exists in our mod assembly, this event will still work! You can also minify method code in your Unity version, since you're only looking to reference the method:
And that's it! I hope you can find this helpful. If you have any questions, feel free to contact me on Discord.