CTIN 483

Week 2 Thursday

Drawing

Super Hexagon

(Terry Cavanagh, 2013)

 

Fast, difficult dexterity game with simple graphics and catchy chiptune soundtrack.

Simple Game

Scriptable Objects

sound harder than they are

Scriptable Objects

A Scriptable Object is a special Unity structure that is a template for data objects.

 

You can think of it as the master copy of a form – one that you keep blank so you can make more copies when  you need them.

 

Scriptable Objects are mostly intended to store variables, but you can also write functions in them.

Games involve a lot of information.

  • A text game has a lot of strings and paths
  • An arcade game has enemy attributes
  • A tower-defense game has waves
  • A puzzle game has levels

This information has to live somewhere.

Some things about your game can be represented in the scene file.

 

For example, you might have a scene for each level of a platformer like Thomas Was Alone.

 

But what about a strategy game like Civilization?

Many game teams manage this information outside the game engine, using spreadsheets, text documents, and so on.

image credits: "The VGLC: The Video Game Level Corpus"

image credit: Ruby Cow Games

Pros:

Very flexible.

 

Cons:

The designer has to understand the format of the document, i.e. what information goes in what column.
 

And the engineer has to write code to get and read the file. Unity does not do this automatically.

Scriptable Objects are meant to be a kind of in-between option that lets the designers do their work directly in Unity.

In the homework you will see two examples of the kind of information you might store using Scriptable Objects:

  • Data for Hearthstone cards
  • Scenes (text passages) for your text adventure project

Another way you might use them is like a table in a Word document. For example, to store how many points different things are worth.

image credit: classicgaming.cc

The basic steps for creating ScriptableObjects are:

  1. Create and name a new C# Script.
  2. Delete "MonoBehaviour" and replace it with "ScriptableObject".
  3. Add the variables you need for your object.
  4. Above the "public class" line, write
     
  5. Return to Unity and choose
    Assets->Create->Your Object.
  6. Fill in the values for your object. Repeat steps 5 and 6 for every instance you need.
[CreateAssetMenu]

Ponderable

How would you use Scriptable Objects to represent information in

  • an RPG?
  • a match-three game?
  • an arcade game like Frogger or Pac-Man?

Here's one example, an RPG weapon:

Arrays

An array is like what humans would call a list of objects. (To computers, a List is a different thing.)

 

An array can only contain one kind of value, that is, strings, floats, GameObjects, and so on.

Sometimes there is a set of things you care about as a group:

  • all the currently active enemies
  • all the spawn points in a level
  • the cards a player is currently holding
GameObject card1;
GameObject card2; 
GameObject card3; 

Here is what not to do:

Instead, if you want to store a set of things together, you can create an array variable to hold them. That looks like this:

GameObject[] cards;
string[] studentNames;
InventoryItem[] playerInventory; 
GameObject[] cards; 
  • You can store any number of cards you need without changing your code
     
  • You can easily treat them as a group, for example, tell them all to flip over

For the most part, if you are working with an array you will make it visible in the Inspector, like in the homework:

[SerializeField]
GameObject[] cards;

Then you can just drag in what you need.

 

Later you will learn about List, which is a more flexible version of an array. We will return to Lists soon.

Using the Index

You can only get to an item inside an array via its position, or index.

 

Arrays start counting at zero, which is confusing for humans:

studentNames = new string[3];
studentNames[0] = "Sabrina";
studentNames[1] = "Sandy";
studentNames[2] = "Sriram"; 
{"Sabrina", "Sandy", "Sriram", "Salvador"}

0

1

2

3

Even more confusingly, when you give a length for the array you don't start at zero but at one.

 

So this code says there are three items in the array, but the last item in the array has index 2.

studentNames = new string[3];
studentNames[0] = "Sabrina";
studentNames[1] = "Sandy";
studentNames[2] = "Sriram"; 

The first index (position) in an array is always zero.

studentNames[0] //"Sabrina"

The last position in an array is more complicated.

 

It is the number of items in the array (its length) minus one, because of starting at zero.

studentNames.Length - 1

So the last thing in your array is here:

studentNames[ studentNames.Length - 1 ]
{"Sabrina", "Sandy", "Sriram", "Salvador"}

0

1

2

3

studentNames.Length == 4

A for loop visiting each element in your array will therefore count from 0 to (length-1).

for (int i=0;
     i < studentNames.Length - 1;
     i++)
{
   print(studentNames[i]);
}

You can also use a different kind of loop, a foreach loop:

foreach (string thisStudentName in studentNames)
{
    print(thisStudentName);
}

Arrays: Oops

If you try to get to a position that isn't actually in the array, you will get a particular kind of error:

studentNames = new string[3];
studentNames[0] = "Sabrina";
studentNames[1] = "Sandy";
studentNames[2] = "Sriram";
studentNames[3] = "oops";

Arrays: Oops

If you forget to initialize your array you'll get an error like this.

 

There are lots of other ways to get this error, but if you see that this error comes from a line of code using an array, then you probably forgot to initialize.

Demo: Spheres Array

Asset credits

Synthesized piano notes: GH05TY

 

{Sphere0, Sphere1, Sphere2, Sphere3}

0

1

2

3

{ Key0,    Key1,    Key2,    Key3 }
i =

Think before you Type

When you are trying to get something to work in Unity, take a minute and think through what you're doing before you start typing.

 

Instead of doing the whole thing and then seeing if it works, try to break it down into small steps that you can check.

It's not a beginner thing, though it's especially helpful while you are learning.

 

It is what professionals do, because debugging something can take 4-400 times as long as just doing a little planning and testing.

Walk before you Run

One important principle for writing small, testable chunks is to make a single, concrete piece of something work.

 

For example, in the Spheres demo I made sure I could play the sound on one sphere before setting up the rest.

It is a good idea to print stuff out to the Console as part of this.

 

For example, add a Debug.Log statement just printing out the length of an array or the name of the GameObject.

In the advanced version of the script, I went and found all the spheres from code rather than dragging them into a field in the Inspector.

 

I ran that code and looked at the array in the Inspector to make sure I'd gotten everything into the array at all.

I had done it wrong! But I was able to fix that before moving on to actually working with the array.

 

This is a good principle:

Make sure your references are working before you do anything with them.

Don't Repeat Yourself

As you are writing your code, or sometimes when you are planning it, you will sometimes notice where you are repeating yourself.

 

Or where you are copying and pasting rather than cutting and pasting.

That may be fine while you are just getting it to work. But it may also cause more headaches.

 

So look for ways to abstract your code, that is, make it smart enough to handle more than one situation.

 

We will see many examples of this.

CTIN 483 - W2 Th Sep 2 - 2021 Fall

By Margaret Moser

CTIN 483 - W2 Th Sep 2 - 2021 Fall

Scriptable Objects, arrays.

  • 262