- Home /
Runtime instantiation based on XML
Before I start, I'm pretty sure this is not an XML serialization issue. If it is, definitely let me know!
Let's say I have an XML structure similar to the following:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<animals>
<section name="Weird Animal Group 1">
<animal qty="3">Three-Legged Cow</card>
<animal qty="3">Tim the Horse</card>
<animal qty="2">Dog</card>
<animal qty="3">Puppy</card>
<animal qty="3">Cat</card>
<animal qty="3">Kitty</card>
<animal qty="2">Monkey 2.0</card>
<animal qty="2">Robot Dinosaur</card>
...
<animal qty="1">Pen_guin</card>
<animal qty="2">h-y-p-h-e-n-a-t-e-d r-a-b-b-i-t</card>
</section>
</animals>
Let's also say (as I've tried to illustrate with the elipsis) that there's some huge amount of these animal nodes (hundreds).
In my scene, I have an individual prefab for every type of animal that could come in through this XML file. What I need to be able to do is, at runtime, instantiate as many GOs of a particular type as specified by the "qty" attribute in the XML.
I've given every animal in my example strange and varied names using all sorts of weird string structures to illustrate that in my real game there is a comparable amount of unpredictable variety to the way things are named. The only thing I can count on is that they are consistent -- i.e. "Monkey 2.0" will always be called "Monkey 2.0".
Is there some way in C# to have some sort of object pool or database of objects that are mapped to strings like these? I've looked into dictionaries and hashtables -- I think a dictionary might be the way to go -- but I'm worried about efficiency. As I've said, there will be hundreds of these animal types.
I think setting up a structure like this (my full animal database, before reading XML) might be ok:
Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
dictionary.Add("Three-Legged Cow", ThreeLeggedCow);
dictionary.Add("Tim the Horse", TimTheHorse);
dictionary.Add("Dog", Dog);
dictionary.Add("Puppy", Puppy);
...
dictionary.Add("Pen_guin", Penguin);
dictionary.Add("h-y-p-h-e-n-a-t-e-d r-a-b-b-i-t", HyRabbit);
and then, as I loop through and parse each node:
for (int i=0; i<qty; i++) {
GameObject currentAnimal = animals[animalNameAsStringFromXml];
GameObject.Instantiate(currentAnimal);
}
I'm just worried that using a dictionary in this manner might not be very efficient, especially considering there will be hundreds of these. Any ideas?
Thanks so much in advance for any suggestions. Any help is greatly appreciated :)
Answer by $$anonymous$$ · Jan 23, 2013 at 06:20 PM
Have you tried this method, is it has any performance issues? Generate a bunch of data and test it out, to make sure. I think this method makes your code bloated, but performance-wise it doesn't look bad.
You could run the parsing/instantiation in a new thread, so you don't block your main thread while parsing in all those stuff, then it should be seamless.
Also take a look at this: Loading Resources. If you can set up a naming convention for the XML and parsing it with a suitable regex pattern, you could get the actual name of your prefabs from those strings in XML. I mean you would remove whitespaces and special characters, and make the words' first characters capitalized. So with using a regex parser, "Three Legged Cow", "Three-Legged Cow", or "threeLegged Cow" would all mean "ThreeLeggedCow", which is the name of your resource. Then you do:
Instantiate(Resources.Load(resourceName));
This would mean much smaller code since you don't have to set up everything by hand, but I expect it to be slower. Whatever method you use, do it on a different thread, because that much instantiation would slow down your main thread in the beginning for sure.
Thanks so much for the response! Some quick comments regarding your answer:
Can you point me in the right direction for running the parsing/instantiation in a new thread? I'm sure you mean another thread on the CPU, but I'm not very sure how that works in Unity or C#.
I've definitely thought about using a regex function of some sort to standardize the names co$$anonymous$$g in through the X$$anonymous$$L file. Only problem is that there's no standardization that I can see in the names themselves -- Ultimately I think I can force something like in your example, but the regex itself would probably need to be pretty complex. What I'll have to do if I go this route I guess is to run the regex parser ahead of time on all the possible "animals" that I currently have a list of, and then use the output to name my resources (or GOs).
Either way, looks like I'm going to be hand-typing a whole lot! I'll likely do whatever I can in a super-powered text editor like Text$$anonymous$$ate before bringing it all into code in $$anonymous$$onoDevelop.
Read this: http://unitygems.com/threads/ It's a pretty good site with multiple advanced, non-trivial tutorials. I haven't tried this out myself yet, but it seems they have a script (Loom) with which you can easily do stuff on a new thread using anonymus functions (which looks very cool).
I'm not a regex guru myself, but I think if you dig into it you should be able to come up with some complex regex for those names. I don't know much about your situation, but if you're able to hand-code a bunch of string-prefab pairings, you can write a regex (or multiple regexes) for them too. But if you can't predict their format... well that's not so good :)
Yeah definitely use a decent text editor.. you can check out Sublime Text 2, it's pretty neat, and you can even use textmate bundles in it. As for me, I use it for the whole process, I touch $$anonymous$$D only if I need the debugger (which is rare, fortunately).
Whoa. Great resource.
I would love to use a more compact editor like Text$$anonymous$$ate or Sublime Text for all my coding -- but I'm pretty new to Unity and even newer to C#, so all the helpers and code completion in $$anonymous$$D are super helpful for me right now.
Thanks for everything!