C#: Getting class instance/object from string? (or other suggestions)

Hello there,

I’ve spent pretty much the last two hours on this, excluding the amount of time I spent brainstorming and testing before leading up to this solution.

Basically, I’m still working on a saving and loading system, but I realized I have to split my data into two parts: permanent data and temporary stored data. I can easily get the temporary stored data (or so I think…), but my problem is getting the permanent data.

What I did was create a base class, create an instance of that class (or is it called an object?) that has all the data filled in for that level or such, and then I am attempting to get that filled in class by name. However, this is done by typing in the name of the class’s instance (like “W1L1” - a relatively simple system) so I can get the matching instance’s data.

However, I may end up with a ton of these instances (my levels alone would be the majority, but still, they’d be a ton). And so, rather than a million if or switch statements to compare that string to pre-defined names (again- each instance has its own name value for quick output purposes). I’ve come upon System.Reflections (Type.GetType(name)), but that doesn’t seem to work.

Any suggestions? Please feel free to ask for clarifications, because I have no idea how well I described this. Also, here are primary snippets of my code:

(Also, please note that I basically learned and am learning C# by myself as I go. Took quite a bit to figure out all at once classes, “instances” (or objects?), static objects/instances/variables (rather than static classes), enums, and such. My terminology may thus be quite a bit off. And it’s public static on purpose so I can very easily access the data- which may not make sense now that I think about it, since those are just reference instances that won’t be used. Rather, the copy instances/variables will be used globally… I may have wrote this last sentence wrong)

public class Control : MonoBehaviour {
    public LevelType thisType;    // for choosing enum, for a quick switch statement. Very general script
        // ignore the above line if you wish, but it basically defines if the current scene is a level select, world select, or inside a level
    public string levelIDInput;
        // Input from Inspector, the above is how the instance is matched and then assigned... theoretically
        
        public enum LevelType{
        Other,
        WorldSelect,
        LevelSelect,
        Game
    }
    
    // Next two sets are the base classes
    public class levelData{
        public string worldID{ get; set;}
        public string levelID{ get; set;}
        public string levelName{ get; set;}
        public int totalPickups{ get; set;}
        public bool secretCheck{ get; set;}
    }

    public class worldData{
        public string worldID{ get; set;}
        public int levelsTotal{ get; set;}
        public int secretsTotal{ get; set;}
    }
    
    // Next two sets are examples of instances, one of each
    public static worldData W1 = new worldData{
        worldID = "W1",
        levelsTotal = 4,
        secretsTotal = 0
    };
    
    public static levelData W1L1 = new levelData{
        worldID = "W1",
        levelID = "W1L1",
        levelName = "The Beginning",
        totalPickups = 6,
        secretCheck = false
    };
    
        void Start () {        // Uses enum to define what type of scene this is, then acts accordinly    
        if (thisType == LevelType.Other) {
            print ("Undefined LevelType?");
        }

        if (thisType == LevelType.WorldSelect) {
            print ("This is a world menu!");
            // Some random testing removed
        }

        if (thisType == LevelType.LevelSelect){
            print ("This is a level menu!");
        }

        if(thisType == LevelType.Game){
            Type thisLevel = Type.GetType(levelIDInput);
            // The above is what I tried, then I would get all the values
            //         of the class instance into more scene-wise permanent variables
            //        for a variety of uses, including in other programs
            
            //Quite a bit of not-so-random testing removed
        }
    }
    
}

Edit: Added a bit to the code that was more or less necessary

This doesn’t make much sense. You try to read/write properties of an object that is not an object.
If you have an object and need to know its type before doing something you simple do

object.GetType() == typeof(T);

Ignore my example (on line 59). It was me working in circles, trying to find a solution.

Actually, if I can just get a way to use the Inspector to easily select one of those objects, that would solve this. However, listing every single class would be unreasonable, which is why I’m trying to just use a typed–into string.

So… Ignoring my example, how would I READ or otherwise get an object (and therefore its values) by having the name in a string?

Why not just serialize to XML, Bson or Json?

Hmm… I’ve heard of Json, but know nothing about it or Bson. However, XML I sort of have some experience with (messed with some files during web development, and it’s pretty easy and simple to edit at least), but zero with programming. I guess I’ll start to look into XML. :slight_smile: I remember various threads going over XML, but I wasn’t sure if it was really necessary.

However, what would be an example of this? Would I move all the data to XML? How would I call it, in pseudo-code, with a string?

Sorry if somehow my words came out as a garbled message of misconceptions. I’m sort of brain dead with a headache at the moment.

Why not just serialize using Unity’s built-in serialization? From your example it looks like at runtime you will only have to read the data, so using ScriptableObject and custom assets would fit perfectly.

This is you’re doing simple stuff. Or you can use PlayerPrefs to store some data if you’re not going overboard. Or if you want to do something dynamic you could do it with my JSON .NET asset. For example, let’s say you have a class called LeadPipe:

public class LeadPipe
{
      public int Damage { get; set; }
      public int Health { get; set; }
      public string DisplayName = "Lead Pipe";
}

Now to serialize it you just do:

var pipe = new LeadPipe() { Damage = 520, Health = 100 };

var pipeAsString = JsonConvert.SerializeObject(pipe);

Now that pipe object is converted to a string and you can save it to disk or whatever. Now to turn it back into a LeadPiple, load the string and do this:

var pipe = JsonConvert.DeserializeObject<LeadPipe>(pipeAsString);

And there you have it… from a string back to a pipe again.

https://www.assetstore.unity3d.com/#/content/11347

Sorry, forgot to mention a few things:

  1. Not trying to buy any assets. My overall game is pretty simple
  2. This is for mobile development. Would this work?
  3. Would the XML work without another (large) overhaul?

Edit: I see that it works for C# - although I’m not sure if I’ll use it as the $20 doesn’t seem worth it for something so “simple”.

Not a problem. I would still suggest Json. Have a look at JSON Object. It’s a little more work to use (a little more manual) but it’s free. I’m not sure if it actually instantiates classes for you though or if you have to do that manually.

https://www.assetstore.unity3d.com/#/content/710

There’s also SimpleJSON, LitJSON and JsonFX but each has its own shortcomings. Some do not handle collections properly, and some do not work at all on Mobile. I couldn’t really tell you on mobile support, you’d just have to read up on them but they are all alternatives.

XML as long as you’re inheriting from ScriptableObject should work but I think there are some things that the built in Unity serializer doesn’t work with, just don’t remember off the top of my head. Also can’t speak to mobile support on that. The different mobile platforms have varying degrees of implementation for the XML classes.

I would agree with using AssetDatabase for your serialization. It comes with Unity and it works great, no matter the complexity of your data. You basically save a .asset in Resources folder and then you can load it up any time you want, mobile, webplayer, any platform.

I got some pretty wicked class structures in a “temple run” style game. I had the whole game auto-generated from data serialized into a single file, including all the references towards prefabs, texture, and so on.

JSon is great if you need to pass your data over the web, using WWW. Or if you need to serialized data outside the editor’s scope. If you don’t have to do that, there’s no point is not using AssetDatabase.

As for Type.GetType(string) not working, it’s because you were using the class name, not the class assembly-qualified name. Really not the same thing. An assembly-qualified name looks like “TopNamespace.Sub+Namespace.ContainingClass+NestedClass, MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089”… Kind of a mess, but you’re not suppose to type that by hand.

Sorry for throwing more questions at potential solutions, but I can’t find much info on creating a “. asset” file or using one for serialization. I’ve primarily just found methods to import, copy, etc assets as a whole. Am I supposed to make an XML file and use that somehow?

Once again, sorry for the constant questions, but not sure where to really go next with this.

Edit: After finally getting a tad bit off my headache, I decided to connect all the related info in this thread.

Basically… I have to pay attention to ScriptableObjects, Serializing (had to honestly look up that definition), and AssetDatabase.

Well, I guess it’s time for me to delve into these things:

  1. How to serialize my current classes and make them into ScriptableObjects
  2. How to store those objects into .assets
  3. How to retrieve the data from those .assets serialized ScriptableObjects

I haven’t done too much research - I’ve found the first trails for the first two questions already in my preliminary searching and have yet to find #3 (and would appreciate a bit of leading again for this :smile:) - but thank you everybody for the information here. Although tonight’s at an end for me, it seems like tomorrow will be full of progress.
(End corny ending that was added for no reason, I blame the remaining bits of the headache :wink: )

Edit2:
Ah, a beautiful intro to all three parts (or such) that I listed above…
http://ivanozanchetta.com/gamedev/unity3d/unity-serialization-behind-scriptableobject/
Once again, thank you.

You write .asset files using System.IO just like writing any other files on .Net;
I’m building a GDD toolset for my future projects and what I do there is I save the class object itself because I built those classes as ISerializable, you save the class instance to a file and C# can recreate the instance from that binary file stream. This is great for editor tools, performance is great, but for in-game you’re proly better off with xml and scriptableObjects.
Google out for C# serialization and System.IO.

No. You write .asset using AssetDatabase. If it’s in binary, Unity won’t be able to read it natively and you’ll be left alone to rebuild your object by yourself. A lot of pain for no real gain.

Thanks Bruno for finding this thread and posting, but I posted another followup thread to focus the topic on serialization itself, and all the little itty problems I had due to my cluelessness.

And for anyone who needs to find it:
http://forum.unity3d.com/threads/223152-Help-with-creating-ScriptableObject-instances-(and-using-them)-(Errors)