Hi there,
I have 3 ScriptableObjects in a directory in the project. They hold a mesh and a material each.
They’re models of 3 types of asteroid rock.
I want to procedurally generate the asteroids, so choose one of the 3 at random on spawn.
However, I want to make it easy to just drop in a fourth, fifth, sixth model etc., and then the code choose from one of 4, 5, 6 models etc. without having to manually edit lists etc.
So, I’m looking for a way for Unity to look for a certain ScriptableObject type (e.g. AsteroidModel), put them in a list, and then be able to access this list at runtime for spawning.
I can’t seem to get the ScriptableObjects into a list using scripting. I can add them manually to a list in a second ScriptableObject, then reference this ScriptableObject and the list inside it from a MonoBehaviour.
I’m aware that ScriptableObject.FindObjectsOfType() is no good because of course not all ScriptableObjects are loaded all the time until called directly. I tried it with no success.
Am I trying to do the impossible? It seems like an obvious thing to want to do, but I can’t figure out how to proceed with this.
Any help with this (what seems to be…!) simple task appreciated! Thanks!
You could put all the scriptable objects in the Resources folder and then use the Resources.LoadAll method.
1 Like
This is spot-on the correct answer, but let me add this:
Use the generic version of Resources.LoadAll (Resources.LoadAll<MyScriptObj>("path");
and make a subfolder JUST for these types of objects.
The reason is that if you do a Resources.LoadAll<MyScriptObj>( "/");
, Unity will actually load EVERY asset located under a Resources path (!!!) into memory, allocating memory for each one, then deciding if it is the type you need or not. This means it may load every texture and music file if that’s where you keep them.
Subdirectories are ALWAYS the big win with Resources.LoadAll<>();
3 Likes
Wonderful! This worked! Thanks @WarmedxMints_1 and @Kurt-Dekker !
To those looking for the same answer remember that the path for Resources.LoadAll
is the path within the Resources folder as @WarmedxMints_1 stated. i.e. can’t just got to ScriptableObjects/Asteroids from the project root.
Also, seems you can’t put these objects into a List. They have to go into an array of objects i.e. Object[ ]
, which is fine for my purposes, but Resources.LoadAll()
returns an array, so you’ll have to live with that.
List actually has three constructors:
- naked empty list
- list of size X (integer)
- list made out of a collection, such as an array
so… trivially, if you ever need a list instead of an array,
FooBar[] myArray = Resources.LoadAll<FooBar>("FoobarDirectory/");
List<FooBar> allFoobars = new List<FooBar>( myArray);
And obviously you can easily go back to an array with the .ToArray() method.
1 Like
Thanks again, that’s really helpful for the future.
1 Like