如何将可编写脚本的对象的每个实例添加到集合中?

How can I add each instance of a scriptable object to a collection?

你好:)

我希望将可编写脚本的对象 class 的每个实例添加到 HashSet(它位于单独脚本中的静态 class 中)。

我通过创建一个方法来做到这一点,该方法将 class 添加到哈希集,我在我正在实例化的 class 的构造函数中调用了这个方法。事情是这样的……它有效,但并非总是如此?这是代码,我会在最后进一步探讨问题:

//first script where the hashset is:
public static class Record
{
    private static HashSet<MyClassToInstantiate> MyHashSet = new HashSet<MyClassToInstantiate>();

    public static void AddToMyHashSet(MyClassToInstantiate obj)
    {                
        MyHashSet.Add(obj);                
    }

}       

//the other script:
[CreateAssetMenu(menuName = "X")]
public class MyClassToInstantiate : ScriptableObject
{
    [SerializeField] string someRandomData1;
    [SerializeField] int someRandomData2;

    public MyClassToInstantiate()
    {
        Record.AddToMyHashSet(this);
    }
}

除第一次打开 Unity 外,这一切都很好。第一次我总是必须进入我的 "MyClassToInstantiate" 的任何实例并更改一些东西(任何东西)并且它刚刚开始工作(我正在使用 [createAssetMenu] 属性 btw)。

ps。我确定我有一个我没有看到的明显的理论问题!预先感谢任何让我了解正在发生的事情的人

所以这是主要问题。 ScriptableObject 实例是永久存在于您的统一项目中的资产。带有哈希集的静态 class 是仅在统一为 运行 时才存在的数据。一旦您离开应用程序,它就消失了,因此您需要重新生成数据。现在我不是 100% 确定为什么 unity 在验证时调用 scriptableObject 的构造函数(当您 select it/make 更改时),但依赖类似的东西肯定会导致问题;)。

您可以在访问数据时get all instances

 public static class Record

{

private static HashSet<MyClassToInstantiate> MyHashet;

public static HashSet<MyClassToInstantiate> GetHashSet() 
{
    RefreshHash();

    return MyHashet;
}

public static void RefreshHash() 
{
    MyClassToInstantiate[] allInstances = GetAllInstances<MyClassToInstantiate>();
    MyHashet = new HashSet<MyClassToInstantiate>();
    for (int i = 0; i < allInstances.Length; ++i)
    {
        MyHashet.Add(allInstances[i]);
    }
}

private static T[] GetAllInstances<T>() where T : ScriptableObject
{
    string[] guids = UnityEditor.AssetDatabase.FindAssets("t:" + typeof(T).Name);  //FindAssets uses tags check documentation for more info
    T[] a = new T[guids.Length];
    for (int i = 0; i < guids.Length; i++)         //probably could get optimized 
    {
        string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
        a[i] = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(path);
    }

    return a;
}

}

GetHashSet() 函数将 return 您的脚本化对象的所有实例。

但是,如果您想要一个更简洁的解决方案,那么使用另一个带有指向您想要的所有 MyClassToIntanctiate 实例的链接的 scriptableObject 可能会更好。它可以让您编辑列表,因此默认情况下不会全部添加它们。