Picture yourself at the university's library, holding a heavy 1000-page Calculus book on your hands for about two hours. Tell me, how would that feel on your arms? Here's the thing: that's exactly what Unity is doing by default to your operating system with all your text files. Here's the more lightweight solution: Unity Addressables TextAsset loading.
In this blog post, you'll learn how to:
- What's the memory risk that large text files pose to developing your Unity game
- How to efficiently reference and manage large text files in Unity before it's too late
Maybe you've been in this situation.
Or maybe you haven't yet, but you will.
Handling large text files is a bit problematic in Unity. What happens under the hood is just too implicit...
Many developers are unaware of the memory implications of using big text files in Unity.
In any case, there are different ways to handle text files in Unity, and some are plain worse than others.
Let's see them.
Quick Navigation
The Traditional Ways to Load Text Files
Using Unity Addressables with TextAssets
The Traditional Ways to Load Text Files
Games love text files.
From small configuration files to huge XML databases that hold game items that you generated with an external tool.
Some developers even use JSON files to support game localization.
No matter the reason, many game developers prefer to work with text files for certain subsystems of their games. What they do next is to import these text files into Unity and then get them loaded into memory... somehow.
In Unity, there are several ways you can load text files into memory. Sorted from least desirable to most desirable:
- TextAsset API + Resources API. You place your text in the resources directory and you load it with the Resources API. The problem? You shouldn't be using the Resources directory. It's considered bad practice for anything bigger than a small configuration file
- TextAsset API. You can also put your text file somewhere inside your assets directories. Then, you make a direct reference out of it in any of your scripts. This is the most usual way of doing it. The problem? This automatically increases memory consumption and loading times there where it's referenced, as you'll see in the image below
- FileReader API + StreamingAssets. The text files you put in StreamingAssets land in your final build packages as you put them without any processing. This means you'll have to put extra manual work to read them, e.g. by using the C# FileReader API. The main problem is that you'll end up with hardcoded paths... and we know how stable these paths are
TextAsset: Nasty Memory Consumption
While reading text files from StreamingAssets on demand is fine, sometimes it's just nice if we can let Unity help us a bit through references and its TextAsset API. And as you might argue, it's better to avoid hardcoded paths such as StreamingAssets/MyEpicWeapons.xml
What we want is to leverage the memory efficiency of StreamingAssets with the power of Unity references.
Surprise! We can easily do this with Unity Addressables + TextAsset processing.
Using Unity Addressables with TextAssets
Here's the process:
- Put your text file somewhere in your Assets directory
- Mark the text file as addressable asset
- (Optional: set the addressable group to LZMA compression for best results)
- Make an indirect reference to it
- Load/Unload it as usual with a combination of the addressables and TextAsset APIs
Easy.
Since I've done already quite many tutorials on this, I won't go in detail on the steps but on the last one. For more information, read my Unity Addressables Tutorial and/or download this unity project here.
Let's create a script that loads the file, prints its length to the console and then unloads it.
Read the code for PrintAddressablesTextLength.cs below:
public class PrintAddressablesTextLength : MonoBehaviour
{
[SerializeField] private AssetReference _addressableTextAsset = null;
void Start()
{
_addressableTextAsset.LoadAssetAsync<TextAsset>().Completed += handle =>
{
Debug.Log($"Length: {handle.Result.text.Length}");
Addressables.Release(handle);
};
}
}
It can hardly be simpler.
As soon as you add this script to any game object, you'll be able to assign an indirect reference pointing to any TextAsset file in your Assets directory. On Start, you'll see how it automatically prints the length of the text file for you.
The main benefit of this approach is that you pay the memory and loading times on demand, while the traditional route of assigning direct references makes you pay by default.
To go a step further, you can create an addressable group for text files that use LZMA compression. This algorithm is very suitable for text as I show in my Unity Addressables Compression Benchmark.
Addressables TextAsset: LZMA Group Compression
Doesn't it feel better now that you left the calculus book on the bookshelf to hold it only when you really need it?
Get the Project Now
And see in action how to load the addressable json file through LZMA compression.
đồ gỗ phạm kim