An Artist's Guide to C# in Unity3D: Collections

This article is part of an ongoing series for code-leaning artists who want to learn Unity 3D. In this article I introduce you to three useful collections types.

This article is part of an ongoing series for code-leaning artists who want to learn Unity 3D. In this article I introduce you to three useful collection types.

Read Previous: Operators


Collections.

No, these aren’t shady callers with anonymous phone numbers shaking you down for that $17.29 water bill you somehow forgot to pay in 2010. 

Ahem.

Collections in C# are much friendlier.  In every program you write you’ll need a way to store a basket (or group) of items that you can reference later.  Things like a list of city names, a list of numbers like geographic coordinates or maybe even something like a list of available weapons in your player’s inventory. 

Basics of a collection

Collections are variable types that let you store several items of data together. As you learned in previous lessons, variables allow you to store a single piece of data (of a particular data type).

string fullName = "Bruno Mars";

What if you wanted to store a list of 10 musicians?  Or 1000?  Would you create 1000 different string variables?  You could, but good heavens, who wants to do that?  This is where collections come into play.

One way to understand collections is to think of them as special variables with the following capabilities:

  1. Have an identifier or label just like regular variables

  2. Work with one type of data (string, float, int, etc) or can work with a mix of data types

  3. May declare a specific number of items they are able to store (this is fixed in most cases) or declare that they can store any number of items

  4. Provide a way to assign/put items into the collection

  5. Provide a way to uniquely access each item in the collection

  6. Provide a way to uniquely change/update each item in the collection

  7. May provide a way to delete one or all items in the collection

In this lesson we will learn about three types of collections:

  • Arrays

  • Lists

  • Dictionaries

Arrays

Arrays are the simplest type of data collection (really a bargain basement collection compared to the other types).  They allow you to store a fixed number of items of a particular data type.  When you create an array, you must specify which data type this array will hold and how many slots to provide.  

To create an array, we use the following format:

data_type_to_store[] name_of_the_array = new data_type_to_store[number_of_items_you_intend_to_store];
string[] musicians = new string[3];

We now have an array called musicians that can store three string data items.  But, our array is empty. 

Lets try adding just one string to the array.  Since the array has three empty slots we need to specify which slot to add our new string into (No, it won’t just know to place it in the first slot--I told you arrays are the economy class of collections).

musicians[0] = "Bruno Mars";

Now we have one string item in the first slot of the array.  But what’s with that 0, you ask?  Well, array positions don’t start counting from 1, they start from 0.  That means our array position indices will be 0, 1 and 2Not 1, 2 and 3!  

Let's add two more items to our array.

musicians[1] = "Miley Cyrus";
musicians[2] = "Alicia Keys";

If we try to add a fourth item, the compiler would yell at us because the array was declared with a fixed size of 3.

musicians[3] = "Philo Debangs";  //Error! Who is Philo Debangs???

What about accessing the array’s items?  If you wanted to print the second item, you would use a similar indexing syntax to retrieve the item:

Debug.Log(musicians[1]); // Prints Miley Cyrus to the console

To change the second item in the array, assign the new value to the item position like this:

musicians[1] = "Beyoncé Knowles";

Now the second item has been updated.

Debug.Log(musicians[1]); // Prints Beyoncé Knowles to the console


We can also check the size of the array using the Length property of the array like this:

Debug.Log("We have " + musicians.Length + " items in our array!");  

// Prints "We have 3 items in our array

*  We'll talk about object properties when we learn about classes.  For now, think of .Length as an attribute of all array objects that returns the size of the array.  

An easier way to print the above line is to use a feature called string interpolation.  If we stick a $ right before the string in the above line we can skip using those ugly plus signs and just wrap our variable in curly braces ({ }) like this:

Debug.Log($ "We have {musicians.Length} items in our array!"); 

// Prints "We have 3 items in our array

So far, we’ve added string items to our list one at a time.  We also could have initialized our array at declaration time like this:

string [] musicians = string[] {"Bruno Mars", "Miley Cyrus",     "Alicia Keys"}

This would produce our three-item array immediately.  Obviously, you may not be able to do this in every situation. It's an alternative way to initialize an array if you know your items at declaration time and your list is short enough.

What if you want to delete an item from an array? 

Well, here’s where I disappoint you.  You can’t. 

Arrays are immutable in size.  Once you declare an array size, it can’t be altered.  If you want an array with a different size, you’ll have to create a new one. You can, however, update the individual array elements as much as you like.  

The next collection type we will look at does not have this size restriction.

Lists

C-sharp provides us with another type of collection called a generic list type.  As mentioned previously, this collection type is a lot more flexible than a basic array.

The basic syntax for creating lists is:

List<data_type_to_store> name_of_list = new List<data_type_to_store>();

To recreate our collection of musicians with a list we could do this:

List<string> musicians = new List<string>();

Now we have an empty list called musicians.  Unlike arrays, lists are able to grow and shrink as we add and remove items so you don’t need to specify a size at declaration time.

Adding items to lists is pretty easy:

musicians.Add(“Bruno Mars”);
musicians.Add(“Miley Cyrus”);
musicians.Add(“Alicia Keys”);

To see how many items we now have in our array, use the list’s .Count property (which is similar to the array’s .Length property).

Debug.Log($"We have {musicians.Count} items in our array");

Accessing a particular item in the list is accomplished just like you would for an array.

Debug.Log(musicians[2]);  //prints Alicia Keys

As with arrays, providing an index that is larger than the list will throw an error.

Debug.log(musicians[3]); //Error!

//The list only has three items so the indices only go up to 2

Similar to arrays, changing or updating an existing item is just a matter of reassigning a new value to that particular index.

musicians[1] = "Beyoncé Knowles";
Debug.Log(musicians[1]); // Prints Beyoncé Knowles as expected

And if we wanted to initialize our list at declaration time we would do this:

List<string> musicians = List<string> {"Bruno Mars", "Miley Cyrus", "Alicia Keys"}

Lastly, our list collection gives us another ability we don’t have with arrays—deletion.  The complement of the .Add feature we used for adding items to the collection is the .Remove feature for—you guessed it—removing items.

List<string> musicians = List<string> {"Bruno Mars", "Miley Cyrus", "Alicia Keys"};

musicians.Remove("Miley Cyrus");

Debug.Log(musicians.Count); // prints 2
Debug.Log(musicians[0]);  // prints Bruno Mars
Debug.Log(musicians[1]);  // prints Alicia Keys
Debug.Log(musicians[2]);  //Error!  Only 2 items left


Dictionaries

So far, with both arrays and lists, we’ve been referencing our collection items with index numbers (from 0 to whatever).  These are called ordered collections (because the items contained are accessed by number in the same order in which they were added) and work well for many purposes.  However, sometimes it's more appropriate to access our list items with something other than a numeric index.

A simple example is keeping track of player scores.  Assume you have the following three players and their scores:

  • Yakko - 61

  • Wakko - 47

  • Dot - 93

Using an array or list would not be the best way to store this data.  When order doesn’t really matter, C-sharp provides another type of collection called a Dictionary for storing key-and-value pairs.  In our case the player’s name would be the lookup key while the player’s score would be the value we want to retrieve.    

The syntax for creating a dictionary is:

Dictionary<data_type_of_the_key, data_type_of_the_value> name_of_dictionary
new Dictionary<data_type_of_the_key, data_type_of_the_value>();

Lets go ahead and create our dictionary.

Dictionary<string,int> playerScores = new Dictionary<string,int>();

Now, just like we did for lists, we can add new items to our dictionary by passing in both the key and value we wish to store.

playerScores.Add("Yakko",  61);

This stores the integer value 61 against the string key Yakko.  Let's add the other two scores.  

playerScores.Add("Wakko", 47);
playerScores.Add("Dot", 93);

With our playerScores dictionary populated, we can lookup a score by using the player’s name (the key) to retrieve the score (the value).

Debug.Log(playerScores["Wakko"]);  // prints 47
Debug.Log(playerScores["Dot"]);  // prints 93
Debug.Log(playerScores["Yakko"]);  // prints 61

If we wanted to update Yakko’s score to 65, we would do this:

playerScores["Yakko"] = 65;
Debug.Log(playerScores["Yakko"]);  // prints 65

Lastly, if we want to remove Yakko from the dictionary we can do this:

playerScores.Remove("Yakko");

Debug.Log(playerScores["Yakko"]);  // Error!  

//Yakko no longer exists in the dictionary


As we can see, dictionaries behave very much like lists except we’re using strings for accessing item values instead of position integers.  It's important to note that dictionaries allow you to use any data type as the lookup key—integers, floats and even other objects are valid keys. We’ll learn more about this in upcoming lessons.

Try it out

Now that you’re comfortable with collections, try answering the following questions to improve your understanding.

  1. Assume, you’re running an experiment where you flip a coin ten times and record the result—whether the coin comes out heads or tails.  What collection could be used to represent this information since you know how many items you need to store?  Create the collection with the appropriate data types and initialize it.

  2. You’re a dispatcher for a traveling sales guy.  He calls you every morning and asks what the temperature is in five different cities.  Today the cities and their temperatures are:
    Atlanta - 74
    Charlotte - 71
    Louisville - 68
    Nashville - 70
    Indianapolis - 62

    What kind of collection would you use to represent this?  Create the collection and add the data.  Remove the Nashville entry and add Richmond with a temperature of 63 degrees.

  3. You’re conducting an online survey.  Everyday, your survey website sends you a list of email addresses submitted to you that day.  What collection would you use to store these email addresses?  Create the collection and add these emails to it:
    larry@stoogehq.com
    moe@stoogehq.com
    curly@stoogehq.com

    Print the email addresses to the console.
    Whoops, two more just came in. Add these extra emails to the collection and print again.
    shemp@stoogehq.com
    joe@stoogehq.com

    Next we’ll learn about flow control in your programs.


    An Artist's Guide to C# in Unity3D

    1. Setting up your environment

    2. Creating your first script

    3. Common data types and variables

    4. Operators

    5. Collections

    6. Flow Control

    7. Functions and Methods


    Subscribe now