📚

Database & Asset Repository

Sometimes you need a ScriptableObject which contains a collection of other objects or we usually say Database. A simple example is the ScriptableObject which contains all the items in the game that you created. Then you want to find a certain item based on the name of the item, you can perform a search function of all items in the database that match the criteria you are looking for.
Below is an example of an ScriptableObjectWithId Database that contains all the ScriptableObjectWithId contained in a project
Example Database Inspector
Validation in ScriptableObjectWithId
With this I can run a validation when unique id is changed if it has same id with these others ScriptableObject. If yes, it will show errors when editing.
To create a database like this, there are two scripts that must be created, the Repository as the container for the class you want to load and the Database itself. Below are examples of AudioDatabase and AudioRepository scripts, you can follow these examples to create your own database.
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
​
namespace Gamepangin
{
[Serializable]
public class AudioRepository : TRepository<AudioRepository>
{
public override string RepositoryId => "Audio.assets";
​
[SerializeField] private AudioClipSettings[] clips;
​
public AudioClipSettings[] Clips
{
get => clips;
set => clips = value;
}
​
#if UNITY_EDITOR
[InitializeOnEnterPlayMode]
public static void InitializeOnEnterPlayMode() => Instance = null;
#endif
}
}
#if UNITY_EDITOR
using UnityEditor;
#endif
​
namespace Gamepangin
{
public class AudioDatabase : AssetRepository<AudioRepository>
{
#if UNITY_EDITOR
private void OnEnable()
{
EditorApplication.playModeStateChanged -= OnChangePlayMode;
EditorApplication.playModeStateChanged += OnChangePlayMode;
RefreshItemList();
}
​
private void OnChangePlayMode(PlayModeStateChange playModeStateChange)
{
RefreshItemList();
}
​
private void RefreshItemList()
{
string[] itemsGuids = AssetDatabase.FindAssets($"t:{nameof(AudioClipSettings)}", GamepanginGeneralSettings.Instance.databaseFolders);
AudioClipSettings[] clips = new AudioClipSettings[itemsGuids.Length];
​
for (int i = 0; i < itemsGuids.Length; i++)
{
string itemsGuid = itemsGuids[i];
string itemPath = AssetDatabase.GUIDToAssetPath(itemsGuid);
clips[i] = AssetDatabase.LoadAssetAtPath<AudioClipSettings>(itemPath);
}
​
Get().Clips = clips;
}
#endif
}
}
As you can see in the code, the RefreshItemList() method will be executed when the editor enters play/stop mode. Then a script will be run to find assets with a certain class type and update the repository.
Items in the database example above will only refresh when editor play mode changed.

Database.Get

To access a repository you can call the static class Database.Get<T>
// Return all Audio Clip Settings in Audio Repository
var allClips = Database.Get<AudioRepository>().Clips;