Как я могу добавить в коллекцию каждый экземпляр объекта со сценарием? - PullRequest
0 голосов
/ 30 мая 2020

hello :)

I wi sh, чтобы добавить каждый экземпляр класса объекта с возможностью сценария в HashSet (который находится в классе c stati в отдельном скрипте).

Я сделал это, создав метод, который добавляет указанный класс в хэш-набор, и вызвал этот метод в конструкторе класса, который я создаю. Вот в чем дело ... работает, но не всегда? Вот код, go я расскажу подробнее о проблеме в конце:

//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. В первый раз мне всегда нужно go в любой экземпляр моего «MyClassToInstantiate» и что-то менять (что угодно), и он просто начинает работать (я использую атрибут [createAssetMenu], кстати).

ps. Я уверен, что у меня есть очевидная теоретическая проблема, которую я не вижу! Заранее спасибо всем, кто дает мне некоторое представление о том, что происходит

1 Ответ

1 голос
/ 30 мая 2020

Итак, вот основная проблема. Экземпляр scriptableObject - это актив, который постоянно живет в вашем проекте Unity. Ваш класс stati c с хеш-набором - это данные, которые существуют только во время работы unity. Как только вы выйдете из приложения, оно исчезнет, ​​поэтому вам нужно будет восстановить данные. Теперь я не уверен на 100%, почему unity вызывает конструктор scriptableObject, который, похоже, проверяется (когда вы выбираете его / вносите изменения), но полагаясь на что-то подобное, наверняка вызовет проблемы;).

Вы могли бы получить все экземпляры при доступе к данным.

 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 () затем вернет все экземпляры ваш объект со сценариями.

Но если вам нужно более чистое решение, лучше иметь другой scriptableObject со ссылками на все экземпляры MyClassToIntanctiate. Это позволит вам отредактировать список, чтобы они не все добавлялись по умолчанию .

...