I have a problem with a scriptable object that i want to foreach through in another script.
I’ve made some custom serializable classes in the scriptable object.
This is my scriptable object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Class which holds all the different part types
[System.Serializable]
public class Types
{
public string name;
}
// Class containing all the body types
[System.Serializable]
public class Bodies
{
public string id;
public GameObject prefab;
}
// Class containing all the battery types
[System.Serializable]
public class Batteries
{
public string id;
public GameObject prefab;
}
// Class containing all the motor types
[System.Serializable]
public class Motors
{
public string id;
public GameObject prefab;
}
// Class containing all the pcb types
[System.Serializable]
public class Pcbs
{
public string id;
public GameObject prefab;
}
// Class containing all the wheel types
[System.Serializable]
public class Wheels
{
public string id;
public GameObject prefab;
}
[CreateAssetMenu(fileName = "PartCatalog", menuName = "Catalogs/PartCatalog", order = 0)]
public class PartCatalog : ScriptableObject
{
public List<Types> types;
public List<Bodies> bodies;
public List<Batteries> batteries;
public List<Motors> motors;
public List<Pcbs> pcbs;
public List<Wheels> wheels;
}
I’ve been filling the scriptable object lists with values, that i want to search through in another script.
The scriptable object looks like this at the moment.
I’m new to the subject of reflection, and i think it can help solve my problem, but i’m stuck as to how to do it. I’ve been searching the forums, but haven’t come across an answer yet. Maybe it’s not possible at all, but maybe someone can help me point me in the right direction.
I want to do what’s explained in this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System;
public class SerializeRobot : MonoBehaviour
{
// Set the parts catalog
public PartCatalog PartCatalog;
// Start is called before the first frame update
void Start()
{
foreach(Types type in PartCatalog.types)
{
Debug.Log(type.name);
// Now loop through the scriptable objects class corresponding with the type.name class
// It works for the class Batteries
foreach (Batteries battery in PartCatalog.batteries)
{
Debug.Log(battery.prefab.name);
}
// But instead of Batteries, i want to go through the custom class that we get from type.name
// I'm stuck here...
foreach (/* type.name class */ partType in PartCatalog./* type.name class */)
{
Debug.Log(partType.prefab.name);
}
}
}
}
You definitely could do this with reflection, that doesn’t necessarily mean you should though*.* What’s your end goal here, besides printing out the names of the objects?
Reflection here would involve calling typeof(PartCatalog).GetFields(...) to get all the object fields, and then analyzing the generic type of the list so you can call thatType.GetField("prefab") to get the value of that field… and so on…
It’s really a mess. What is it you are ultimately trying to do? This looks largely like a job for an abstract class or interface at first glance.
What are you actually attempting to do? Like what is the goal of this ScriptableObject and what it represents?
Cause as is, sure, you could use Reflection to get what you want. And I, or many others, could show you how to accomplish it.
BUT… it’s a terrible way to do whatever it is you’re attempting to do.
…
So instead… what is it you’re attempting to do here?
What does the ‘types’ list represent? What would it mean if ‘types’ only contains “batteries” and “pcbs” and none of the others? What would it mean if it contained “FlarghaBlargha” which doesn’t have a corresponding list?
Why is it that you have a special type for each list despite them being shaped exactly the same?
{
string id;
GameObject prefab;
}
Why not use the same type for all lists?
…
Why not do something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class TypeInfo
{
public string name;
public List<PrefabInfo> prefabs;
}
[System.Serializable]
public class PrefabInfo
{
public string id;
public GameObject prefab;
}
[CreateAssetMenu(fileName = "PartCatalog", menuName = "Catalogs/PartCatalog", order = 0)]
public class PartCatalog : ScriptableObject
{
public List<TypeInfo> types;
}
And then you could just loop through them:
foreach(var type in PartCatalog.types)
{
Debug.Log(type.name);
foreach(var info in type.prefabs)
{
Debug.Log(info.id);
Debug.Log(info.prefab.name);
}
}
(note - this design isn’t necessarily the best. But I don’t know what you’re actually attempting to do. But it’s leagues better than using your design and stirring in some reflection.)
Ok, i was afraid it would be a mess, haha… thanks for the first input!
The idea is, i’m fiddling around with some first ideas of making a catalog of parts that can be instantiated. Definately not a final product, and definately a mess, but i’ll sketch the goal;
I have a GameObject with a name, we’ll call him bob, and inside that gameobject there are children, which have scripts with types “Motor”, “Wheel”, “Pcb”, which represent different parts of bob. There are multiple prefabs, which are all motor/wheel/pcb, but with different “specifications” and “models”.
I’ve made a serialization in XML of the different “parts” that are attached to bob, and i want to have a big list of all the parts that CAN be on bob, but not neccessarily HAVE to be on bob. Depending on the data in the XML file, i want to select the corresponding GameObjects from the Scriptable Object that contains all the possible motors/pcb’s/wheels/etc.
Does that make sense?
I’m kind of prototyping with different kind of ways to accomplish this, and i thought this would be a way to go, but now i’m stuck in “selecting” the right gameobject from the partscatalog. Right now each motor/pcb/wheel has the same variables in it’s class, but this will be expanded later.
A list with “identifier” name (battery, pcb, wheel, etc), containing a list of each id and prefab, wow that’s something that hasn’t crossed my mind, that’s waaaaaaay easier and gets rid of the need for reflection… Only this won’t work if all the PrefabInfo’s aren’t the same, right? Hmm…
Now i think of it i could of course just compare the value ID of each part in my XML file to all the parts in the PartsCatalog, that would be fairly easy to get the right data.
It’s making less and less sense now i’m thinking of it again… let’s call this a case of tunnle vision and blindly following the wrong path. I have inspiration for less complicated ways of getting the data now with your help :)!