- Home /
List myClass where MyClass : ScriptableObject not working
Hey Guys,
I obviously don't know how to solve this
I have 3 Classes A, B and C
C : B
B : ScriptableObject
A : MonoBehaviour
in A theres a List
List<B> bList = new List<B>();
now I want to put C into this List with it's own values
public class A : MonoBehaviour
{
List<B> bList = new List<B>();
public void AddToList(B bElement) //where I want to add C (or even D : B)
// maybe I could call this function this way: A.AddToList(C);
{
//and there is the problem - I have to create an Instance of C
//with
//bList.Add(null);
//bList[0] = (C) ScriptableObject.CreateInstance(typeof(C));
//but if I do this, no values of C are passed and also it could be D instead of C
}
}
Does anyone know how to solve this?
Thanks in advice.
if B and C derive from the same thing then the list will accept either. If they do not, then only a List<object>
will work. Then you can parse out the data like this.
if (myList[i].GetType() == typeof(objectB)
{
(myList[i] as objectB).BProperty1 = 42;
}
@RobAnthem Hi Rob, I am new to Unity answers so I dont know the social norms here. Would it be acceptable for me to add this to my answer to make it more thorough? Or is that inappropriate and it should just remain as only your comment?
Answer by CarterG81 · Feb 11, 2017 at 03:39 PM
If C derives from B
C : B
Then you should be able to automatically put it into any container that holds B.
C myC:
bList.Add (myC);
This is useful when you have methods in B that are overridden in C.
Class B
SetupObject ()
{
//assign variables of B
}
Class C : B
override SetupObject ()
{
//assign variables of B
//assign variables of C
}
@RobAnthem had some great advice:
For objects that DON'T derive from the same base class
if B and C derive from the same thing then the list will accept either. If they do not, then only a List will work. Then you can parse out the data like this. if (myList[i].GetType() == typeof(objectB) { (myList[i] as objectB).BProperty1 = 42; }
ScriptableObject
Unity can't serialize non-Unity based objects. If you want to serialize this use binary or convert it into a ScriptableObject. The main thing about ScriptableObject though is that it requires each instance is created AND stored. Therefore you would need to do something like this.
AssetDatabase.CreateAsset(newRoomObject, "Assets/Resources/Rooms/" + newRoomObject.RoomName + ".asset");
RoomObjects tempRoom;
AssetDatabase.AddObjectToAsset(tempRoom = CreateInstance<RoomObjects>(), "Assets/Resources/Rooms/" + newRoomObject.RoomName + ".asset");
newRoomObject.requiredObjects.Add(tempRoom);
100% Credit to @RobAnthem for the above. Thank you!
I get this warning when I do so:
Test3 must be instantiated using the ScriptableObject.CreateInstance method ins$$anonymous$$d of new Test3.
UnityEngine.ScriptableObject:.ctor()
Test2:.ctor()
Test3:.ctor()
TestEditor1:OnSceneGUI() (at Assets/Editor/TestEditor1.cs:16)
UnityEditor.DockArea:OnGUI()
here are my test classes:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Test1 : $$anonymous$$onoBehaviour {
public List<Test2> t2 = new List<Test2>();
public void addToList (Test2 typeToAdd)
{
t2.Add(typeToAdd);
}
// Use this for initialization
void Start () {
Debug.Log((t2[1] as Test3).asd);
}
// Update is called once per frame
void Update () {
}
}
(for adding Test3: )
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
[CustomEditor(typeof(Test1))]
public class TestEditor1 : Editor
{
void OnSceneGUI()
{
Test1 t = target as Test1;
t.transform.position = new Vector3($$anonymous$$athf.RoundToInt(t.transform.position.x-0.5f) +0.5f, $$anonymous$$athf.RoundToInt(t.transform.position.y), $$anonymous$$athf.RoundToInt(t.transform.position.z- 0.5f)+ 0.5f);
Handles.BeginGUI();
GUILayout.BeginArea(new Rect(Screen.width - 130, Screen.height - 190, 120, 500));
Test3 testClass = new Test3();
if (GUILayout.Button("Add Field"))
t.addToList(testClass);
GUILayout.EndArea();
Handles.EndGUI();
}
}
Test2
using UnityEngine;
using System.Collections;
public class Test2 : ScriptableObject {
int val = 1;
}
Test3
using UnityEngine;
using System.Collections;
public class Test3 : Test2 {
public int asd = 2;
}
Why is Test2 derived from ScriptableObject?
@Hannibal_Leo Updated the answer to include Rob's advice about ScriptableObject. Perhaps this will help?
Still theres the error I just wan't to get rid of it
All classes derive from the Class B - object is not necessary I just want to remove the error message
Test3 must be instantiated using the ScriptableObject.CreateInstance method ins$$anonymous$$d of new Test3.
UnityEngine.ScriptableObject:.ctor()
Test2:.ctor()
Test3:.ctor()
TestEditor1:OnSceneGUI() (at Assets/Editor/TestEditor1.cs:16)
UnityEditor.DockArea:OnGUI()
if you have a list of objects that derive from scriptable object, it is best to make a base class like
public class classA : ScriptableObject
{
}
public class classB: classA
{
}
public class classC: classA
{
}
public class classD : $$anonymous$$onobehaviour
{
public List<classA> aList;
public void CreateAndAdd()
{
aList.Add(CreateInstance<classB>());
}
public void AddToList(classA a)
{
aList.Add(a);
}
}
CreateInstance() will not get the values nor the type of the classes I want to add I want to use the function CreateAndAdd() with a specific class Like classB = Helmet ; Helmet can have Helmet.health = 5; or Helmet.health = 7; so I have to add the parameters as well as the class so the function has to look like: CreateAndAdd( theClassToAddWithItsValues) { aList.Add(theClassToAddWithItsValues); //not just the plain class I get when I use CreateInstance, also I don't know the exact type, just the baseclass }RobAnthem