- Home /
Can I create instances of types outside of code? (like ScriptableObjects)
Hi. So I basically want to create a type outside of code like I would a ScriptableObject, but since types are far more flexible and have more features than ScriptableObjects, I'm using types instead. I tried making a list of Items in my game public, but I had no luck creating any new Item elements in the inspector. I could also always just make a new line in the code for every new object I want to add to the game, but obviously, there must be a better way. Thanks.
I'm totally confused by the use of the term "type" but maybe I can still give some insight.
If I'm reading this correctly, you want to randomly generate a bunch of items at runtime. The easiest way to do that is something like
public struct Ingot
{
public string IngotName;
public Color IngotColor;
// ...
}
At runtime, you create a List<Ingot>
in some game manager and populate the list. Whenever you want to use one, youspawn a new GameObject and attach a script that has
public class IngotGameObject : $$anonymous$$onoBehaviour
{
public Ingot IngotData;
// ...
}
then write whatever Ingot
from the aforementioned list into IngotData
. Read from IngotData
to get all the values. If that makes sense.
I rephrased the question so what I'm trying to figure out should be more clear now. It's not that I had any trouble creating new random instances of a type at runtime, but quite the opposite. I'm trying to figure out how to create a set of non-procedural generated Items before runtime. So this would be like if I'm creating a bunch of new integers in an array in the inspector, but ins$$anonymous$$d of integers, I'm trying to create Items.
I still have no idea what you're asking.
Are you looking for ingotList.Add(new Ingot());
?
Type and class are interchangeable in the context of the post, though types could refer to simple built in types like floats and ints, the OP is talking about instantiating classes. A class declaration creates a type.
I use type as something that will not be attached to a gameObject, and class as something that will, I didn't realize that they meant the same thing.
Answer by JVene · Aug 16, 2018 at 10:24 PM
I have to make a few somewhat reasonable assumptions about your meaning here. The generation of data from the inspector is actually the result of serialization hidden within the Unity framework. As such, the potential concept you're really thinking of is serialization of data.
Ultimately, no instantiation of a class, or any time including floats and ints, is the result of some line of code declaring that instantiation. The storage for the instance is central to that step. For built in types, like floats and ints, instantiation can be as part of the membership of a class, or of local variables in a method, formed on the stack (temporary local variables). For class instantiations in C# (a common theme to similar languages, but quite different from C++), there must be a 'new' allocation, as you see when using Vector3. If there isn't a 'new' keyword involved, it must be either that the variable declaring the class is null (there's no storage, the instance is not formed and the reference of that type is null), or the instance is actually copied from some other reference holding that instance.
That means that while you don't see it in code yourself, there are 'new' keywords used to instantiate class types when generated by the framework and initialized in the inspector. Indeed, the inspector is merely storing the values to be used to initialize the instantiation in code, though it is hidden below the visibility of user code.
So, one either will have to instantiate 'new' objects at runtime in code, or perform serialization (which, of course, requires one to write out the initialization data somehow). That creates, if you think about it, a bit of a dichotomy. How does one create a file that can be read in during serialization unless there's code that generates that file? The answer, while filled with lots of options, can be to write a C# program outside of Unity that creates the file, create one within Unity that creates the file or use a format you can create in text, like XML.
If, for example, you viewed an XML file of parameters as if they were fields in the inspector, you could create a file suitable for streaming in to instantiate a large population of C# classes.
I'm an old hand at a wide range of programming languages and topics, but I'm fairly new to Unity. There are ways of serializing classes in Unity, but the default inspector automates that process only for MonoBehaviour scripts initialized by the editor. Researching the documentation of serialization may yield some Unity specific means of getting the inspector to work on other classes, but I haven't researched that. I would personally not favor a Unity editor specific approach in my own work, even if it were reasonably well supported, as I would favor XML or some JSON format I can edit with a text editor, but then I'm old school and that's familiar. Put another way, I'd caution against focusing on the Unity editor's features for serialization of general C# classes, favoring methods for doing that which are universal to C# (which could even include some form of SQL database).
As an amateur somewhat beginner coder, who only makes programs with Unity, you have just gone fifty feet above my head. The question I asked was simply how I create an array of a type created by me and not unity in the inspector like I would an integer or vector. Although I will accept this answer as it is very comphrensive even though most of it goes above my head (for which I have only my self to blame). I think I'll just use the makeshift way I thought of to quickly make new Items using the inspector.
Ah, but the word array doesn't seem to be in your original question.
You may be interested in C# array initializations, a way of somewhat compacting the code for initializing an array of C# class instantiations.
The point in my answer is that what Unity does with the inspector is merely a way of initializing objects from storage, probably a text file. The general notion of saving and loading data for a game is similar, where you end up with a number of instantiations of classes at runtime that must be saved to a file, so that they can be loaded when the program runs again in the future. That general notion, serialization of classes, is applicable to your inquiry, and if the style of the text file is X$$anonymous$$L or JSON (Google provides), you can create them in a text editor where appropriate.
Answer by Trevdevs · Aug 16, 2018 at 10:19 PM
If like JVene said by types you just mean classes otherwise I don't know what you mean by types.
If what you want is a class you can create multiple varieties of in the inspector then ScriptableObjects is what you want. Just use subclasses instead to get "types".
Or constructors which are instances of classes.
Example of what I think you mean by types
public class Gender : ScriptableObject
{
//This is a parent class and will not appear in the editor
}
[CreateAssetMenu(menuName = "Gender/Male")]
public class Male : Gender
{
//This is a subclass that will appear in the editor
}
[CreateAssetMenu(menuName = "Gender/Female")]
public class Female : Gender
{
//This is also a subclass that will appear in the editor
}
Are you saying that in order to create default Items before runtime I need to use ScriptableObjects? I've thought about this but I there would be some way to create Items in the inspector. I could even just make a bunch of arrays that will come together to create Items, and I could do that in the inspector, but something about that feels wrong...
public Game game;
public string itemName[];
public float itemWeight[];
public float itemValue[];
for(int i = itemName.Length; i > 0; i--){
game.Items.Add(new Item(itemName[i], itemWeight[i], Itemvalue[i]));
}
//This is pseudo code that I wrote in the insert code box, it won't actually work or do anything.
If you really want to do it in code you could create a class called ItemDatabase and do everything in there via constructors but that would get messy real quick. So yes scriptableobjects are your best bet. It's time consu$$anonymous$$g sure but games aren't made in 2 days
Judging by your code above that would work. However lets say you wanted to change itemName 534 to something different. Then you gotta dig through your weight and value array for index 534 to change that value with scriptableobjects every object would categorized that way ins$$anonymous$$d of having 3 arrays you could just have 1
public Item[] items;
void PlayerEquip(int index) { player.weapon = items[index]; }