Skip to content

Instantly share code, notes, and snippets.

@ababilinski
Last active March 17, 2021 16:16
Show Gist options
  • Save ababilinski/afd46e9f7752bb352380177737b12e96 to your computer and use it in GitHub Desktop.
Save ababilinski/afd46e9f7752bb352380177737b12e96 to your computer and use it in GitHub Desktop.
Abstract class for making reload-proof singletons out of Uniy3D ScriptableObjects
using System.Linq;
using UnityEngine;
/// <summary>
/// Abstract class for making reload-proof singletons out of ScriptableObjects
/// Returns the asset created on editor, null if there is none
/// Based on https://www.youtube.com/watch?v=VBA1QCoEAX4
/// </summary>
/// <typeparam name="T">Type of the singleton</typeparam>
public abstract class SingletonScriptableObject<T> : ScriptableObject where T : ScriptableObject
{
static T _instance = null;
public static T Instance
{
get
{
if (!_instance)
_instance = FindAsset(_instance);
return _instance;
}
}
/// <summary>
/// We have to find the asset through AssetDatabase in case the asset is not loaded.
/// </summary>
/// <typeparam name="TO"></typeparam>
/// <param name="typeObject"></param>
/// <returns></returns>
public static TO FindAsset<TO>(TO typeObject) where TO : Object
{
#if UNITY_EDITOR
if (UnityEditor.EditorPrefs.HasKey(typeof(TO).ToString()))
#else
if (false)
#endif
{
#if UNITY_EDITOR
string objectPath = UnityEditor.EditorPrefs.GetString(typeof(TO).ToString());
var asset = UnityEditor.AssetDatabase.LoadAssetAtPath(objectPath, typeof(TO)) as TO;
if (asset == null)
{
var assets = UnityEditor.AssetDatabase.FindAssets("t:" + typeof(TO));
if (assets.Length > 0)
{
var assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assets[0]);
var foundAsset = (TO)UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(TO));
UnityEditor.EditorPrefs.SetString(typeof(TO).ToString(), assetPath);
return foundAsset;
}
}
else
{
return asset;
}
#endif
}
else
{
#if UNITY_EDITOR
var assets = UnityEditor.AssetDatabase.FindAssets("t:" + typeof(TO));
if (assets.Length > 0)
{
var assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assets[0]);
var foundAsset = (TO)UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(TO));
UnityEditor.EditorPrefs.SetString(typeof(TO).ToString(), assetPath);
return foundAsset;
}
#endif
var asset = Resources.FindObjectsOfTypeAll<TO>().FirstOrDefault();
if (asset != null)
{
#if UNITY_EDITOR
string relPath = UnityEditor.AssetDatabase.GetAssetPath(asset);
UnityEditor.EditorPrefs.SetString(typeof(TO).ToString(), relPath);
#endif
return asset;
}
}
return default;
}
}
@ababilinski
Copy link
Author

Abstract class for making reload-proof singletons out of ScriptableObjects

Returns the asset created on editor, null if there is none
Based on Unite 2017 Video

@ababilinski
Copy link
Author

UPDATE

updated the way the asset is found. I had issues with the asset not loading in the editor and having to select the asset in order for the return value not to be null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment