- Home /
pass child class to ScriptableObject.CreateInstance<> ?
I'm building a custom editor to assemble a list of custom scripts and put them in a List on a script deriving from MonoBehaviour.
So far, my editor is working well. The point I'm stuck at is passing a variable from a list of types to ScriptableObject.CreateInstance
code snippets:
public class MyEditorClass: Editor
{
private List<Type> behaviorTypes = new List<Type>();
private int selectedType;
void OnEnable()
{
behaviorTypes = ReflectionVoodooThatGetsDesiredTypes(); // this works as expected
}
void OnInspectorGUI()
{
if (GUILayout.Button("Add", GUILayout.ExpandWidth(true)))
{
AddStuff();
}
}
void AddStuff()
{
Type childClass = behaviorTypes[selectedType];
AddBehavior(ScriptableObject.CreateInstance<childClass >()); // this doesn't work. what is the proper way to do what I'm conceptually trying to achieve here?
}
}
I have a base behavior class that inherits from ScritpableObject, and then several child classes that branch off of that to create a behavior tree. I have a List that stores all types that are derived from my base behavior class. I want to be able to select a type from that list and pass it to the ScriptableObject.CreateInstance() function.
I had this previously working using this line of code:
AddBehavior(behaviors[typeSelection].GetConstructors()[0].Invoke(new object[0]) as BaseBehavior);
this worked, but due to serialization child class types were being lost. So, now that I've switched over to ScriptableObject, my serialization problems are solved, but instantiation problems arise.
Thanks in advance
just to clarify, i do not know what type will be passed to ScriptableObject.CreateInstance, and I want that to remain flexible without having to build a large switch case, so that the behavior tree can be extended in the future with no updates to this chunk of code
I don't think you can instantiate a scriptable object. Only $$anonymous$$onobehaviors.
ScriptableObject.CreateInstance() is the preferred method for creating a ScriptableObject. if you try to create one via:
new BehaviorObject(); // where BehaviorObject inherits from ScriptableObject
you'll get a warning.
btw: UnityEngine.Object.Instantiate works for all objects derived from UnityEngine.Object (that includes even $$anonymous$$esh, $$anonymous$$aterial, ... and should also work with ScriptableObject) :)
Hmm, well, it is only a warning, but this warning pops up every time I try to use the class constructor via System.Reflection. I wanted to make sure that I do things properly to avoid any weird serialization problems later.
The warning I'm seeing:
AlternateExplode must be instantiated using the ScriptableObject.CreateInstance method ins$$anonymous$$d of new AlternateExplode. UnityEngine.ScriptableObject:.ctor()
Answer by Bunny83 · Nov 12, 2013 at 12:06 AM
Simply don't use the generic version of CreateInstance but the Type version
http://docs.unity3d.com/Documentation/ScriptReference/ScriptableObject.CreateInstance.html
how do i get this to work with a List list?
it does not work to call the method like this:
List<Type> types; // this is how i am currently storing my BehaviorTypes, and it works for everything else that i need it for
ScriptableObject.CreateInstance(types[0]); // this doesn't work
similarly, I can't just say:
ScriptableObject.CreateInstance("string_name_of_my_type"), because this doesn't actually become my inherited type, but only a scriptable object named "string_name_of_my_type".
er, what am I missing here?
I can't make an explicit reference, as it will defeat the purpose of the entire editor script.
I cannot code:
ScriptableObject.CreateInstance<BehaviorType>();
because in my code, BehaviorType will in reality be any one of several subclasses of my base class BehaviorType
This
ScriptableObject.CreateInstance(types[0]);
Should work just finefine. Are you sure you have a valid ScriptableObject? So the filename matches the classname?
I can't test myself at the moment since I'm not at home and only have my tablet here :-)
arrg! haha yeah, ok, I switched some code in a different area that bypassed my typechecking, so I was no longer checking to make sure that only one BehaviorType was added. So, I was mislead to believe that ScriptableObject wasn't checking it's type, and was therefore not doing what I wanted.
Thanks for the help!
ScriptableObject.CreateInstance(types[0]);
that works as it should. the fault is, of course, $$anonymous$$e :D