How to properly create an array of all ScriptableObjects in a folder?

Hello, I am currently working on a card game in its extreme infancy. I have created a data folder where each of my cards (stored as scriptableobjects) are located. I need to be able to load in every card in this folder as an array, but I’ve realized as the number of cards I have climbs to the dozens, this is going to be an absurd amount of assignment in the inspector. Do I really have to manually drag each card into a slot in the inspector?

I’ve tried using Resources.LoadAll() to create an array at the start of the game for me, but I can’t figure out how to cast the object[ ] as a Card[ ]. Is there a way to get this to work? If I really am better off just assigning the cards manually, I guess I’ll just have to bite the bullet.

Thank you!

this seams to work for me:

using UnityEngine;

public class Card : ScriptableObject
{
    public string test = "Hello world";
}

public class MyScript : MonoBehaviour
{
    private void Start()
    {
        Card[] cardObjects = Resources.LoadAll("Cards") as Card[];

        Debug.Log(cardObjects[cardObjects.Length - 1].test);
    }
}

I doesn’t seem to be working, the array seems to throw out NullReferenceException errors and nulls when I try to print anything out. Here is the relevant data, and yes I am sure this is the correct directory.

    private Card[] allCards;

    void Start()
    {
        health = maxHealth;

        // compile a catalogue of all cards available in the game
        allCards = Resources.LoadAll("Data/Cards") as Card[];
        Debug.Log(allCards.Length.ToString());
    }

I’m sorry, I tested the next bit of code, and it seems to work for me :

using UnityEngine;
public class Card : ScriptableObject
{
    public string test = "Hello world";
}

public class MyScript : MonoBehaviour
{
    private void Start()
    {
        Object[] cardObjects = Resources.LoadAll("Cards");

        Card[] cards = new Card[cardObjects.Length];

        cardObjects.CopyTo(cards, 0);

        Debug.Log(cards[0].test);
    }
}

Looks like it can also be done this way, but you can’t reference a specific folder with this one :

using UnityEngine;
public class Card : ScriptableObject
{
    public string test = "Hello world";
}

public class MyScript : MonoBehaviour
{
    private void Start()
    {
        Card[] allCards = (Card[])Resources.FindObjectsOfTypeAll(typeof(Card));

        Debug.Log(allCards[0].test);
    }
}

Just wanted to point out you can also convert this to a list very easily.
Like so…

using System.linq;

List<Card> cards = Resources.LoadAll<Card>("").ToList();

I always disliked arrays. And TBH the efficiency gains is minor.

Nothing suggested is working, not even switching the type of object loaded doesn’t help, it always returns an array/list that contains nothing. Removing folder directories doesn’t help either, it’s like it refuses to access the resource folders at all.

Thats weird, my second example (copying the object array) works for sure, i tested it myself, and was able to access the “test” variable. Are you sure everything is named as it should be? (capital letters and such). @Cyber-Dog i prefer Lists also but if the op is asking for an array solution then i’m not going to push converting to a List.

@CannedSmeef

Are you sure your files are in folder that is written exactly “Resources” not “resources” or “resource” or something else? You can have many Resources folders and those can be somewhere in your Assets folder.

When I said resource folders I was referring to the asset folders as a whole–simply searching all assets folders for any kind of object, like my scriptable object or sprites, will create a list/array that contains absolutely nothing. Capitalization or spelling isn’t the issue here, I am sure of it.

@CannedSmeef

You explicitly stated you are using Resources.* to load your files:

“I’ve tried using Resources.LoadAll()”

If you are not placing asset files in Resources folder, you can’t load them with Resources.Load commands - AFAIK. Resources.* is meant to also be used runtime in builds.

“When I said resource folders I was referring to the asset folders as a whole”

This piece of information should have been included in the original post.

If you want to access files in any folder of Assets, you will have to use AssetDatabase.* commands that work only in editor.

You can use AssetDatabase.FindAssets to do this. But like @eses said, it is an editor only method, so you’ll need to do the fetching in edit mode in the editor and then serialize the array so that it persists into the build.

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class Deck : MonoBehaviour
{
    [SerializeField]
    private Card[] cards = new Card[0];

    #if UNITY_EDITOR
    private void OnValidate()
    {
        cards = LoadAllCards()
    }

    private static Card[] LoadAllCards()
    {
        string[] guids = AssetDatabase.FindAssets("t:Card", new[] { "Assets/Cards" });
        int count = guids.Length;
        cards = new Card[count];
        for(int n = 0; n < count; n++)
        {
            var path = AssetDatabase.GUIDToAssetPath(guids[n]);
            cards[n] = AssetDatabase.LoadAssetAtPath<Card>(path);
        }
    }
    #endif
}
1 Like

I have an announcement to make: I am very, very dumb.

I was completely unaware that the “resources” and the “assets” folders were two separate entities. I thought they were interchangable terms for one another. So I created a resources folder in my assets folder, moved my card data there, and viola! It works perfectly now. The Scripting API for Resources.Load() methods should probably make the distinction a bit more explicit, but hey you live you learn.

Thank you for helping me everyone! Sorry to waste your time!

3 Likes

The good part is that you can have more than one Resources folder, and they don’t have to be at the root, unlike the Plugins/Gizmos folders.

  • Assets

  • Items

  • Resources

  • Weapons

  • Weapon1ScriptableObject

  • Weapon2ScriptableObject

1 Like

Be wary when using the Resources folder though. Everything you place inside Resources folders is always included in your builds, even if you have zero references to them in any of your scenes.

Excessive use of the Resources folder can easily lead to you having a large number of assets in your builds that haven’t actually been used anywhere for a long time.

Unity Manual: Best Practice Guide

You are right,thanks.

Thanks Cyber Dog - this is exactly what I needed!