Monday, January 23, 2012

Reducing build size in Unity games

Creating games with Unity, having a large number of custom levels, while trying to get under that App Store and Android Market limit of 20mb?
This is a problem we've faced a few times, and finally i've gotten around to look into creating a method to minimize the size of the final build by serializing the scenes and just instantiating prefabs at level load. We are currently working on a game which will more than likely have 100+ levels, and this method will help us cut down drastically on the final build size. The game has a one-button type gameplay and currently has the very ingenious working title “Rollers”.

The current version limits itself to instantiating prefabs that does not differ from the blueprint, although it should be a rather simple fix to do that, I just don't need it myself :)

In this example I have a number of worlds, each with a number of levels.

Each of these levels contains a number of walls (All instances of a wall prefab with the tag “Wall”)

Additionally the level has a gameobject called info with the following monobehaviour attached:
Basically the only this here is we have the ability to mark each level with a specific world, not at all necessary for everybody, but I need it :)

The following script must be placed in a Assets/Editor folder, and adds a menuitem under Tools/CustomHelpers.
It runs through the currently open scene, locates all prefabs with tag “Wall” and serializes the scene to a textasset which is placed in a corresponding folder.

Ok, so now we're able to serialize a scene, saving the type and location of prefabs, and tag it with the corresponding world.
Now we need a scene which is able to deserialize the textassets and instantiate the prefabs.
Create a new scene called LevelLoader, create an empty gameobject, name it “Loader” and give it the following LevelLoader script.

The above code creates an empty gameobject called walls to use as a parent for all the instantiated prefab, feel free to make this more dynamic. I'll do it myself at a later stage but for the time being it suits my needs.
This should allow you to instantiate any number of levels by serializing them and then just include a single scene in your final build that can deserialize it and spawn the relevant gameobjects.
Screenshot of the Leveloader scene with the instantiated prefabs:

Hope you found this helpful, although it's mainly a proof of concept. I'll make it more dynamic when I get around to it.

Just tried to load the unitypackage from the example and everything works.I think you might have either not placed the prefab you want to spawn in a folder named "Prefabs". Or there is a mismatch between your prefab name and the enum. They must be the same.

Example:

public enum PrefabEnum { PrefabWalls }

Try to open the unitypackage from the tutorial, if you cant make it work

Hi Kristian, thanks a lot for the example. It works great with my game. However, it´s not working when trying to build to Android or iOS because AssetDatabase.Refresh() only works when I´m in the Editor Player. Is there any way to refresh assets in Resources folder without using UnityEditor?