Introduction
When developing games in Unity, managing data efficiently is essential for a smooth gameplay experience. Two popular methods for handling game data are JSON files and ScriptableObject
. In this blog post, we’ll look at the differences between these two methods, focusing on performance and ease of use. For our tests, we will load data from the Resources
folder, simulating data loading at runtime.
Problem: Data Loading in Unity
Loading data from JSON and ScriptableObject
has different effects on performance. Loading data from JSON files can lead to performance spikes, especially if done frequently. In contrast, ScriptableObject
is more integrated with Unity, which can improve performance and reduce overhead.
Loading Data from JSON
Implementation
Here’s an example of how to load data from a JSON file in Unity:
using System.Collections.Generic;
using UnityEngine;
public class JsonDataLoader : MonoBehaviour
{
private const string JSON_PATH = "Jsons/";
private List<Data> dataList = new List<Data>();
private TextAsset jsonFile;
private Data loadedData;
public void LoadJsonData()
{
for (int i = 1; i <= 50; i++)
{
string path = JSON_PATH + $"json {i}";
jsonFile = Resources.Load<TextAsset>(path);
if (jsonFile != null)
{
loadedData = JsonUtility.FromJson<Data>(jsonFile.text);
dataList.Add(loadedData);
}
else
{
Debug.LogWarning($"JSON file not found: {path}");
}
}
}
}
Profiling JSON Loading
While loading data from JSON, you may notice spikes in the profiler due to frequent memory allocations and parsing overhead. This can lead to frame drops if the loading process is not managed efficiently.
Loading Data from ScriptableObject
Implementation
In contrast, loading data using ScriptableObject
can be done more efficiently:
using System.Collections.Generic;
using UnityEngine;
public class ScriptableObjectLoader : MonoBehaviour
{
private const string SCRIPTABLE_OBJECT_DATA_PATH = "ScriptableObjectData/";
private List<ScriptableObjectData> scriptableObjectDataList = new List<ScriptableObjectData>();
public void LoadScriptableObjects()
{
for (int i = 1; i <= 50; i++)
{
string path = SCRIPTABLE_OBJECT_DATA_PATH + $"NewData {i}";
ScriptableObjectData loadedData = Resources.Load<ScriptableObjectData>(path);
if (loadedData != null)
{
scriptableObjectDataList.Add(loadedData);
}
else
{
Debug.LogWarning($"ScriptableObject not found: {path}");
}
}
}
}
Profiling ScriptableObject Loading
Loading data from ScriptableObject is faster and results in fewer garbage collection (GC) allocations, leading to smoother performance
Conclusion
Both JSON and ScriptableObject
have their pros and cons when managing data in Unity. JSON offers flexibility but can create performance issues if not used carefully. In contrast, ScriptableObject
integrates better with Unity and often leads to smoother performance.
For advanced data management, consider using Protocol Buffers (protobuf). This method provides a compact binary format for data, which can speed up loading times, especially for large datasets.
Additionally, you can package ScriptableObject
into AssetBundles or addressables for efficient asset management in larger projects.
The inspiration for this blog post came from a real-world scenario where a game map created in Tiled was stored in JSON format. During testing, the map took a long time to load in WebGL builds and on mobile devices. Switching to ScriptableObject
greatly improved loading times, demonstrating the benefits of this approach.
By understanding the differences between these methods, developers can choose the best option for their projects, enhancing gameplay and user experience.