Don't Let Sneaky Text Assets and JSONs Crash Your Game

Published March 03, 2020 by Ruben Torres Bonet (The Gamedev Guru)
Do you see issues with this article? Let us know.
Advertisement

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

Get the Project Now

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

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:

  1. Put your text file somewhere in your Assets directory
  2. Mark the text file as addressable asset
  3. (Optional: set the addressable group to LZMA compression for best results)
  4. Make an indirect reference to it
  5. 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

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.

Cancel Save
0 Likes 8 Comments

Comments

phamkim

đồ gỗ phạm kim

April 05, 2020 04:10 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

Featured Tutorial

How would it feel to hold a 1000-page calculus book for two hours? That's how your computer is probably feeling with your big text assets. Let's make it comfy for your game with Addressables.

Advertisement
Advertisement