Skip to content

Commit f44a920

Browse files
author
SolidAlloy
committed
fix: Fixed the bug where methods were added to the MenuItems class on editor start and caused compilation errors
AssetDatabase.LoadAssetAtPath<T>() returns null when it is called on editor start (but not on further scripts reload). Handling this edge case resolved the issue.
1 parent bb632f2 commit f44a920

3 files changed

Lines changed: 55 additions & 24 deletions

File tree

Editor/MenuItemsGeneration/MenuItemsGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public static void GenerateClass(MenuItemMethod[] newMethods)
3030
{
3131
string classContent = GetClassContent();
3232

33+
var oldMethods = GenericSOPersistentStorage.MenuItemMethods;
34+
35+
// Stop if the PersistentStorage asset was not found. It frequently happens on Unity Editor launch, leading
36+
// to the false assumption the MenuItemMethods collection is empty.
37+
if (oldMethods == null)
38+
return;
39+
3340
var oldMethodsSet = new HashSet<MenuItemMethod>(GenericSOPersistentStorage.MenuItemMethods, MenuItemMethod.Comparer);
3441
var newMethodsSet = new HashSet<MenuItemMethod>(newMethods, MenuItemMethod.Comparer);
3542

Editor/Util/GenericSOPersistentStorage.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class GenericSOPersistentStorage : SingletonScriptableObject<GenericSOPer
3232
[HideInInspector]
3333
[SerializeField] private bool _usageExampleTypesAreAdded;
3434

35-
public static bool IsEmpty => Instance._genericType.Type == null;
35+
public static bool IsEmpty => OnlyCreatedInstance == null || OnlyCreatedInstance._genericType.Type == null;
3636

3737
public static TypeReference GenericType => Instance._genericType;
3838
public static string NamespaceName => Instance._namespaceName;
@@ -41,10 +41,10 @@ public class GenericSOPersistentStorage : SingletonScriptableObject<GenericSOPer
4141

4242
public static MenuItemMethod[] MenuItemMethods
4343
{
44-
get => Instance._menuItemMethods;
44+
get => OnlyCreatedInstance == null ? null : OnlyCreatedInstance._menuItemMethods;
4545
set
4646
{
47-
Instance._menuItemMethods = value;
47+
OnlyCreatedInstance._menuItemMethods = value;
4848
EditorUtility.SetDirty(Instance);
4949
}
5050
}

Runtime/Util/SingletonScriptableObject.cs

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace GenericScriptableObjects.Util
22
{
3+
using JetBrains.Annotations;
34
using UnityEngine;
45
using UnityEngine.Assertions;
56
#if UNITY_EDITOR
@@ -17,6 +18,11 @@
1718
public abstract class SingletonScriptableObject<T> : ScriptableObject
1819
where T : ScriptableObject
1920
{
21+
private const string AssetsFolder = "Assets";
22+
private const string ResourcesFolder = "Resources";
23+
24+
private static readonly string AssetPath = AssetsFolder + '/' + ResourcesFolder + '/' + typeof(T).Name + ".asset";
25+
2026
private static T _instance = null;
2127

2228
public static T Instance
@@ -26,25 +32,7 @@ public static T Instance
2632
if (_instance != null)
2733
return _instance;
2834

29-
T instance;
30-
const string assetsFolder = "Assets";
31-
const string resourcesFolder = "Resources";
32-
string assetPath = assetsFolder + '/' + resourcesFolder + '/' + typeof(T).Name + ".asset";
33-
34-
try
35-
{
36-
#if UNITY_EDITOR
37-
instance = AssetDatabase.LoadAssetAtPath<T>(assetPath);
38-
#else
39-
instance = Resources.FindObjectsOfTypeAll<T>().FirstOrDefault();
40-
#endif
41-
}
42-
catch (UnityException)
43-
{
44-
Debug.LogError("GenericScriptableObject.CreateInstance() cannot be called in the field " +
45-
"initializer. Please initialize Generic ScriptableObjects in Awake or Start.");
46-
throw;
47-
}
35+
T instance = GetInstanceFromAsset();
4836

4937
if (instance != null)
5038
{
@@ -64,16 +52,52 @@ public static T Instance
6452
Assert.IsNotNull(_instance);
6553

6654
#if UNITY_EDITOR
67-
AssetDatabaseHelper.MakeSureFolderExists(resourcesFolder);
55+
AssetDatabaseHelper.MakeSureFolderExists(ResourcesFolder);
6856

69-
AssetDatabase.CreateAsset(_instance, assetPath);
57+
AssetDatabase.CreateAsset(_instance, AssetPath);
7058
EditorUtility.SetDirty(_instance);
7159
#else
7260
Debug.Log($"The asset of type {typeof(T)} was not created. Please go to editor and create it.");
7361
#endif
7462

63+
Debug.Log("asset was created");
64+
return _instance;
65+
}
66+
}
67+
68+
public static T OnlyCreatedInstance
69+
{
70+
get
71+
{
72+
if (_instance != null)
73+
return _instance;
74+
75+
_instance = GetInstanceFromAsset();
7576
return _instance;
7677
}
7778
}
79+
80+
[CanBeNull]
81+
private static T GetInstanceFromAsset()
82+
{
83+
T instance;
84+
85+
try
86+
{
87+
#if UNITY_EDITOR
88+
instance = AssetDatabase.LoadAssetAtPath<T>(AssetPath);
89+
#else
90+
instance = Resources.FindObjectsOfTypeAll<T>().FirstOrDefault();
91+
#endif
92+
}
93+
catch (UnityException)
94+
{
95+
Debug.LogError("GenericScriptableObject.CreateInstance() cannot be called in the field " +
96+
"initializer. Please initialize Generic ScriptableObjects in Awake or Start.");
97+
throw;
98+
}
99+
100+
return instance;
101+
}
78102
}
79103
}

0 commit comments

Comments
 (0)