Swastik Bhattacharyya
Swastik Bhattacharyya

Reputation: 105

Find all the Instances of a Scriptable Object and store it in a List

I have one Scriptable Object Character and let us say n instances of that Character.

Character.cs

public class Character : UnityEngine.ScriptableObject
{
...
}
// Let us say that there are 100 instances of this Class

Now I create another Class

CharacterList.cs

public class CharacterList
{
     List<Character> characterList = new List<Character>();
     FindObjectsOfType<Character>();

     // I also tried to write Character[] character = FindObjectsOfType<Character>() but that did not work.
// Now How do I put all the objects found in the List?
}

What I want to do is create a Class that isn't a Monobehaviour. Just a simple Class called CharacterList and in there I want a List of Characters that will contain all the instances of the Character Scriptable Object. Hence, there should be n number of Characters in CharacterList

Upvotes: 3

Views: 18469

Answers (2)

Jack Mariani
Jack Mariani

Reputation: 2408

(SO = Scriptable Object) We've 2 options here. Depending if these SO are serialized or instantiated during play.

Option 1 - SO are serialized

Easier option is to create another monobehaviour or scriptable object and place all the instantiated object there.

public class CharacterList : ScriptableObject
{
     public Character[] characterList;
}

The other way will require you to search for the SO in the assets folder by scripting using AssetDatabase.FindAssets and AssetDatabase.LoadAssetAtPath.

In this case the code will look like this:

public class CharacterList
    {
        List<Character> characterList = new List<Character>();

        void PopulateList()
        {
            string[] assetNames = AssetDatabase.FindAssets("Your_Filter", new[] { "Assets/YourFolder" });
            characterList.Clear();
            foreach (string SOName in assetNames)
            {
                var SOpath    = AssetDatabase.GUIDToAssetPath(SOName);
                var character = AssetDatabase.LoadAssetAtPath<Character>(SOpath);
                characterList.Add(character);
            }
        }
    }

How to find them.

VIA NAME
You can replace "Your_Filter" to retrieve your SO. In this case the SO should share come kind of commonality in their names.

VIA FOLDER
You can replace new[] { "Assets/YourFolder" } with your folder. In this case all the SO should be in the same folder AND this folder should contain ONLY these SO.

Option 2 - SO are instantiated

In this case I would suggest to implement some kind of factory.

Instead of creating the SO with the usual code:

ScriptableObject.CreateInstance<YourSo>();

I would use a factory the Create the Instance and store it. So you will have something like this.

public static class CharacterGenerator
{
     static List<Character> characterList = new List<Character>();

     public static Character CreateCharacter()
     {
          var character = ScriptableObject.CreateInstance<YourSo>();
          characterList.Add(character);
          return character;
     }
}

So whenever you want to create a new character you will call CharacterGenerator.CreateCharacter();

Remember also to Clear the list at the start of the game (or when you think it is required).

Upvotes: 7

Swastik Bhattacharyya
Swastik Bhattacharyya

Reputation: 105

In the CharacterList.cs Class:

object[] characters = FindObjectsOfType(typeof(Character));

Upvotes: -1

Related Questions