If you’ve never created a script before, don’t worry, it’s not exactly rocket science. Learning to program is like learning a new language, but you are “talking” to the computer. Just like a human language can be broken down into sentences which consist of a noun and a verb, programming languages can be broken down into variables (the noun) and methods (the verb) which are often paired in statements (the sentence). Learning to program simply requires a bit of effort to learn the vocabulary and then to put it all together in a logical way.
The script we will create will contain code we refer to as a “class”. A class is often conceptually related to a blueprint from which you can create objects. In Unity, you will use your class to create “components” which attach to “GameObjects” very much like you can add a physics collider or audio source component. By writing your own scripts you can have completely new and customized functionality of your own design.
In Unity’s Project pane, select the “Create” button, from which you have the option “C# script”. Alternatively you can also use the menu bar, “Assets-> Create-> C# Script” but either way you will still have to turn your attention to the project pane in order to name and open the new file. By default, it will have made a file named “NewBehaviourScript” and the filename will be selected for you to edit. For now just type “Demo” for our script’s name.
The file name you enter for your script is important for a variety of reasons:
- The name of the file will automatically be used as the name of the class in the template code it automatically creates for you.
- There are some rules regarding what names are legal to use for a class:
- It must start with a letter and must consist only of alpha-numeric characters. If you tried entering “1Bunny”, you will get an error (a red exclamation mark will appear in the Console, and at the bottom of the Unity window) with the following message, “Assets/1Bunny.cs(4,14): error CS8025: Parsing error”. Note that you will be unable to play your game while any errors are present.
- It can not support spaces. If you tried entering a name with a space in it, such as “My Class”, Unity tries to fix it for you (but only half way) and creates the template code with a class name of “MyClass” even though it leaves the space in the file name. Then whenever you try to add the script to an object, Unity will complain at you: “Can’t add script. Can’t add component ‘ScriptName’ because it doesn’t exist. Check to see if the file name and class name match.” Remember this just in case you ever rename the class at a later point – you have to rename the file itself to match.
- The names of your classes must be unique – you can’t have two classes named “Boogers” no matter how funny you might think it would be. Again, Unity will try to fix this problem automatically and will enumerate your file and class name (append a number to the end) so that it is unique.
- If you name a class the same name as something Unity has already taken, such as “Light” then you will get a warning, “Script ‘Light’ has the same name as built-in Unity component. AddComponent and GetComponent will not work with this script.” The duplicate name is allowed here because Unity’s Light was defined in a separate “namespace” which is an advanced topic for later. Note that even though you can play your game with warnings present, a good programmer will treat it as if it had been an error, and make every effort to resolve it.
- Programmers can be a nit-picky bunch, and have guidelines for just about everything including the names you use and even the case of the letters with which you type it out. A good class name will be a noun or noun phrase and will use “PascalCasing” where the first letter of each word is capital and all other letters are lower case. Note that these guidelines are not mandatory, but are a good practice. Read more on naming conventions and guideline here, http://msdn.microsoft.com/en-us/library/4xhs4564(v=vs.71).aspx
Now that we have created a script, we can double click to open it. MonoDevelop should open as your default editor (if you have not already installed any other code editor), and is the one I recommend you use to follow along. With MonoDevelop open, it should have automatically loaded your script for you, and you should see something like the following:
using UnityEngine; using System.Collections; public class Demo : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } }
If you have followed along with other beginner C# tutorials, you may be surprised to find that you won’t be writing a typical program structure. You won’t need to write a “Main” method, because you are writing scripts which are attaching to an existing system, not writing the whole system yourself.
The first two lines of our script refer to something called namespaces. Going back to our analogy of a programming language being like a human language, I can say that different words mean different things depending on the language, and sometimes even words within the same language can have different meanings depending on the context. For example, a word spoken which sounds like “see” could be interpreted as “yes” by a Spanish speaking individual, or as something perceived by sight by an English speaking one. When we say that we are using a namespace, we are telling the computer the context with which to interpret the words we will type out. The words that it will automatically understand are referred to as “libraries” of code and are intended to be very reusable. As a beginner, you don’t really need to concern yourself with the concept of namespaces too much, because most of the time the only namespaces you will need have already been added in the template code.
The “UnityEngine” namespace is what allows your script to inherit from MonoBehaviour, and allows you to reference things like GameObjects, Lights and Cameras, etc. in code. The System.Collections namespace allows you to use Coroutines (a system which makes it easy to make things occur over time). Other namespaces which you might see are “UnityEngine.UI”, which allows you to reference things from Unity’s new user interface components like Buttons and Images, “UnityEngine.Events” and “UnityEngine.EventSystems” if you get into some more advanced event driven programming. “System” (without “.Collections”) for C# events and event handlers, and much more, System.IO for reading and writing files to disk, and “System.Collections.Generic” to take advantage of generics, which is another advanced topic we can cover later.
Occasionally you might follow along with an example that shows code without showing that it required a library (I do this in several of my own posts). Then, when you type in the example, you encounter an ugly error. We can simulate one now, by deleting the first line, “using UnityEngine;
” from our script. Save the file and try to build the solution (from MonoDevelop’s menu bar choose “Build-> Build All”). The code editor should show a red line across our class definition “public class Demo : MonoBehaviour {
” with the following error message “The type or namespace name ‘MonoBehaviour’ could not be found. Are you missing a using directive or an assembly reference?” It is actually fairly easy to resolve this problem. You can right click on the word MonoBehaviour (because that is the word mentioned in the error message) and you should see an option to “Resolve” – and the top option will be the same line I had you delete earlier. MonoDevelop re-inserts the line we needed and you should now be able to build the script again without issue.
After the two namespace lines, there is an empty line. Empty lines and other “white space” such as tabs and extra spaces etc mean nothing to the code itself and are there purely for human readability.
The next line is the declaration of our class. It has several key words:
- public: this means that other scripts will be aware of this script and can work with it. Sometimes you might see the words “protected” or “private” instead, but those are more advanced topics and can be skipped for now.
- class: this is how I know my script is a “class”. There are multiple types of things which can be defined, some of which include: struct, enum, and interface, but again, those are more advanced topics and can be skipped for now.
- Demo: this is the name of the class and should also be the same name as the file we created. Just like you can add components to GameObjects such as colliders or lights, you will now be able to add a component called “Demo” which will do something eventually… (but we haven’t implemented anything just yet)
- MonoBehaviour: note that this word is separated by a colon. It means that our script inherits from another class (by that name). Inheritance is another advanced topic, but for now it is enough to know that you have access to a bunch of functionality because of it.
The class declaration line ends with an open bracket “{”. There will be closing bracket “}” on the last line of the script. Everything which is between those two brackets are the contents of our class, and for the most part will consist of the declarations and implementations of variables and methods.
On lines 6 and 11, you will see a double forward slash, “//”. This indicates something called a “comment”. Much like white space, a comment is something which exists to aid readability, not the code itself. Anything following a double slash, all the way until the next new line, is part of the comment. People use comments to explain what code is supposed to do and to give hints about how it is intended to be used. If you need a very long comment you can use “/*” to begin and “*/” to end a comment. Anything between will be considered part of the comment, even if it spans multiple new lines.
You can toggle the lines of a script to be a comment by highlighting them, right clicking and choosing “Toggle Line Comment(s)”. Sometimes I do this when I have a tricky “bug” (an error in my code or logic) and I want to isolate parts of my code from running to help understand what is going on. I can highlight large sections of code and turn it off, by making it a comment. As I am ready, I can turn it back on with the same command.
The template code which was generated for us contains two methods, one called “Start” (line 7) and the other is called “Update” (line 12). Generally speaking you can name a method whatever you want, although there are a few rules and conventions, just like there are for naming the class. However, these two methods are special, and will be “called” by Unity automatically. This functionality is obtained because we “inherited” from “MonoBehaviour” in our class definition. See this link http://docs.unity3d.com/ScriptReference/MonoBehaviour.html to find out more about what a MonoBehaviour can do.
All methods have something called a signature which includes three things:
- A return type
- The method name
- A parameter set
The two methods defined in our script both have a return type of “void” which means it doesn’t return a value, and have an empty parameter set, because there is nothing between the open and close parenthesis following the method name. I’ll go deeper into explaining variations on these signatures in a future lesson. Each method has its own open and close brackets “{}” just like the class did. Any code “statements” between those two brackets will be performed whenever the method is “called”. Currently our methods don’t have any statements inside them. This means that even though our methods will be called, nothing special is happening.
A statement is often the combination of a method and variable, and always ends in a semicolon, much like our written sentences often end with a mark like a period. For our first example, let’s just have the computer talk back to us. In between the brackets of the start method, add the following line:
Debug.Log("Time: " + Time.timeSinceLevelLoad);
You must be very careful to type out the examples (or copy and paste them) exactly as they are presented or you will likely generate errors in your code. Mis-spelling a variable or method, using the wrong case for a letter, or forgetting the semi-colon at the end of the line are common beginner mistakes.
Save the script, then go back into Unity. Create a new scene, and attach the “Demo” script to the camera by dragging and dropping it from the project pane onto the camera object in the hierarchy pane. Alternatively you can select the Main Camera and use the inspector button “Add Component” and then type the name “Demo” and press Enter.
Play the scene and a message will be printed to the Console window. Note that if the Console window is not open you can open it from the menu bar “Window-> Console”. You will also see the last message from the console at the very bottom of the Unity window. The message displayed is “Time: 0”.
So what happened? Unity called the “Start” method of our script when our script was finished loading. We in turn called a method called “Log” on a class called “Debug” and passed a single parameter which was a message telling us what time it was. In this example, the message is actually created dynamically as the addition of the word “Time: ” and the time it actually is when the statement executes, and that information is found inside the “Time” class by a variable called “timeSinceLevelLoad”.
Our script knew about the Debug and Time classes because of the namespace we are using. The contents of the classes (the methods and variables) are then accessible by something called dot notation (the period separating them).
To help illustrate the idea that the message was dynamically generated, and to show the power of a “variable” move the statement from inside the Start method to inside of the Update method. Play the scene again and the console window will rapidly fill with messages, and each one will show a different but current time. This is because the “Update” method is automatically called by Unity once for every frame the game is playing (this might be 30 to 60 times a second or more), and the Time class is continually updating the value stored in the variable which we are referencing.
Summary:
In this lesson we covered how to create a new C# script inside Unity. We introduced some new programming vocabulary and discussed each line of the default code template. We wrote a first line of code and saw how our script could be attached to a Game Object as a component.