teaching machines

Object Instantiation- The Easy and Clean Way

November 29, 2012 by . Filed under fall 2012, honors 304.503, postmortems.

For one of our labs, we had to write a C# script to instantiate objects in Unity to form a two-dimensional platform level. From what I heard while we were working on this, there were a lot of people with several ‘if…then’ statements, which ends up being ugly and not very future-proof. The method that I came up with prevents any need for editing the script to add more objects.

To start with, we have our text file with the level built in it:

As you can see, each letter represents a block or item in the level, and the spaces are the playable area. One thing that is important for this method to work is that your Unity objects need to be named to what the character in the text file is (e.g. our ground block is named ‘B’ in Unity).

Now, onto the script.

The first thing that we need to do is our imports. These go up at the very top of the document, and they tell the script that we will be using some  C# functions not normally included for Unity.

Also in that screenshot, you can see that we are in a void Start() function. This is because, obviously, we need to load the level up to start the game.

Now to get into the function itself. We are going to be using StringReaders, which are C# classes that can read lines from text files.  We need to declare two StringReaders- one for the whole text file, and one for individual lines. We also need to have the xpos variable declared so that it is ready to be used later. This variable will be used to position the blocks.

We start out in line 14 by creating a new TextAsset called ‘level’, which is our text file. The text file needs to be in a folder called ‘Resources’ in Unity.

Line 16 assigns the text from the ‘level’ TextAsset to the first StringReader.

Lines 18-20 simply catch the error that would result if the file was not present.

Now we move inside the ‘else’ portion, which is where all the meat of the function is.

We start off by declaring our ypos variable, which, obviously is for positioning of the blocks.

In line 23 we tell our first StringReader to read the next line of the text file.

Line 25 starts a loop that continues until the StringReader runs out of lines to read (the end of the text file).

Lines 26 and 27 first count the number of characters in the line, and then create an array that holds that many values.

Lines 29-31 use the second StringReader to fill the array. Each value in the array is one character from the line (spaces are characters).

Then we just loop over the array, and for each character in the array. Line 34 skips  to line 39 if the character is a space. Lines 36 and 37 are actually one line of code, and they are responsible for actually instantiating the object. We do this with the normal Unity command for instantiating objects. Inside the ‘Resources.Load’ parentheses we first provide the name of the object, which is our character (we need to run ToString() on it because characters and strings are different datatypes). Then we tell Unity where to place the object, this is done by simply passing the xpos and ypos variables with 0.0f as the z-position. The Quaternion.Euler controls rotation, in this case we didn’t want any rotation. Then the xpos is adjusted for the next character (our blocks were 1 high and 2 wide, which is why it is xpos+2).

After the line is completed, we tell the first StringReader to go on to the next line, we reset the xpos variable, and we subtract 1 from the ypos variable (because the StringReader goes from top to bottom).

That’s all there is to it. Attach the script to an Empty in your scene, and it should run when you press ‘Play’.