In Unity, when using C# to create your game, you will be writing statements and creating new classes in C# following an object-oriented programming syntax. However, compared to the usual Object Oriented programming practices, Unity’s syntax may seem different, at first glance, even to seasoned developers. So this post will help you to compare and see how Object Oriented concepts can be used with Unity.
In Unity all the objects that you will create in your scene whether there are empty or not, will be instances of the class GameObject. The class GameObject is therefore the parent (or base class) for any object added to the scene.
Also note that the class GameObject provides static functions that can be used to deal with objects; for example, the method GameObject.Find can help to look for a particular object in your scene.
Any object in the scene can be accessed through your code, based on its name or tag, for example, if we create a new (built-in) Cube (i.e., GameObject | 3D Object | Cube) called Cube1 in the Scene view, we could access it in our code using the following:
GameObject g = GameObject.Find(“Cube1”);
Each GameObject will then have inherited properties, such as a transform (to store position, rotation and scale attributes), or a tag, and methods such as SetActive (to activate or deactivate the GameObject), AddComponent, or GetComponent to add and manipulate associated components.
So, for a particular GameObject, it is possible to access its attributes and methods using the dot notation.
GameObject g; g.tag will return the tag g.SetActive(false) will deactivate the GameObject.
So, so far the notation used to access and modify objects in the scene is quite similar to what other Object-Oriented Programming notations.
If you create an object in Unity, for example a cube, you will see, in the Inspector that it also includes what is called components. A component usually provides some additional features to your object. They can be used to render an object (i.e., Renderer component), as a class attached to this object (e.g., any new C# class), or to detect collision (i.e., Collider component).
For example, if you create a new Cube in Unity, it will have by default, the components Box Collider, Mesh Renderer, along with the attributes tag, layer, and Transform
To be able to access the components, it is necessary to use member methods; for example, if we wanted to access a new object’s Renderer component, we could write teh following:
Renderer r = g.GetComponent<Renderer>;();
In the previous code, we specify the type of the component that we want to access by entering its name between the signs < and >. For example, if we wanted to access a component of type MeshRenderer, we could have written the following code instead:
MeshRenderer r = g.GetComponent<MeshRenderer>();
Each component is an object that is an instance of a particular class. For example, a Renderer can, as for GameObjects, includes several member methods and variables. For example, we could decide not to render an object by deactivating its Renderer component as follow.
Renderer r = g.GetComponent<Renderer>(); r.enabled = false;
So again, while a scene includes a collection of GameObjects; each GameObject includes member methods and variables often referred as components that can be accessed and customized through code. These GameObjets include all GameObjects that can be seen and listed in the Hierarchy view.
In addition to being able to access the GameObjects in the current scene, Unity also makes it possible to manage scenes through the class SceneManager; this class provides utility methods to be able to select, create, load, add, or merge scenes from your code.
Understanding and remembering the syntax
When writing Unity scripts, I often see students confused with several common issues; I assume that you have (or will) go through these, so this section will deal with the most common sources of confusion when dealing with C# script in Unity.
Using gameObject or GameObject: When you create a C# script in Unity and attach it to an object, you may need to use either of these keywords; but often, you may wonder which one to use;
The keyword gameObject, when used with a lower case g, means the “object linked to this script or the linked to the current object”; for example, let’s look at the following code:
void Start () { float xPos = gameObject.transform.position.x; }
In the previous code:
- We use the the Start method.
- We record the x position for the object linked to the current script.
- To do so, we access the transform attribute of the object, then its position, and then its x coordinate.
The keyword GameObject, when used with an upper-case G, refers to the class GameObject; used this way, it can be employed to declare a new GameObject, or to access a static method from the class GameObject.
Let’s look at the first aspect:
GameObject g = new GameObject ();
In the previous code, we create a new GameObejct called g and call one of the the constructors of the class GameObject.
The second aspect is related to static methods; a static method for a class, is a method that can be accessed without instantiating the class; let’s look at the following example:
GameObject g2 = GameObject.Find ("Cube1");
In the previous code we look for a GameObject in the scene called Cube1, and we then place the result in the variable g2.
If you remember the last section, we looked into how to access a component; for example, to access the Renderer component of an object called Cube1, we could do as follows:
MeshRenderer m = GameObject.Find ("CUbe1").GetComponent<MeshRenderer>();
This is usually called a generic function, and you may produce the same code using what is called non-generic function; however, the former is always more efficient, as it makes your code shorter;
For example, this code is using generic functions:
MeshRenderer m = GameObject.Find ("Cube1").GetComponent<MeshRenderer>();
It would initially be written with non-generic functions this way:
MeshRenderer m2 = (MeshRenderer) GameObject.Find ("Cube").GetComponent(typeof(MeshRenderer));