The Essential Unity Classes To Know

Comments 0

Share to social media

There are several components that make up the Unity game engine, all of which can become important depending on the project being made in it. Just off the top of one’s head, there’s transforms, animators, navigation, shaders, debugging, and the ever-present GameObject. And that’s before you get into any assets you can download to add onto the engine or the more niche elements of Unity. Even those familiar with the engine can risk becoming overwhelmed as they figure out what they need to know to make their project come to life. The necessary knowledge of the Unity game engine will differ depending on one’s role in the project, and programmers are no exception. In order to assist newcomers to the engine as well as those who need a refresher, we’ll be covering what is considered by Unity Technologies themselves to be the most important classes coders will likely utilize when creating the scripts for their projects. As we progress, code examples and other illustrations will be used to help demonstrate how a class is used to accomplish goals where applicable.

GameObject

For Unity, this class acts as the starting point for the vast majority of objects you code for. It is a base class that represents any object which can appear in a Scene (a Scene being the environment that the user interacts with the app’s systems in). Whether they be a player avatar, a source of light, or an invisible object that manages data, almost everything in a Unity project begins life as a GameObject. This is arguably the one part of Unity that everyone, whether they be programmer, writer, or artist, should have a basic familiarity with. As far as programmers are concerned, the GameObject will ultimately be what holds different components based on the object’s needs, contain variables and references to other objects, and of course, perform operations as defined in custom scripts.

Take, for example, the code shown above. We first create a GameObject, then give it some components. Depending on its purpose, you may also instantiate the object shortly after this. For this example though, we’ll get the Transform component using GetComponent and set its scale to two, effectively doubling its size, followed by destroying the BoxCollider component, once again using GetComponent to specify the component we wish to destroy. This is to demonstrate that Destroy doesn’t have to remove entire objects if you don’t want it to. Moving on from that, we have a check for an object tag. Of course, we won’t get the Debug.Log message since we never assigned a tag to the newly created object in the first place. If it did have the “myTag” tag, we could print the special message and, in real world scenarios, perform tasks specific to objects with that tag.

As we wrap up this section, we use SetActive() to hide the object from the scene as well as stop any scripts and components attached to the object, including this one. It’s a handy tool, but caution is needed when using it. You don’t want to accidentally disable an object without any way to bring it back online later. For the final demonstration, the above code shows off the Find method, which looks for any object with a specified name. In this case, we try searching for an object named “obj2”, and assign it as our secondObj. And as one final demonstration of the Destroy function, we destroy the object we just found.

MonoBehaviour

Closely related to the GameObject is the MonoBehaviour class, which is the default class that Unity scripts derive from. Whenever you create a C# script in Unity, the created class will automatically inherit from the MonoBehaviour script. MonoBehaviours are what allow you to attach scripts to GameObjects as components, and also grants access to methods like Start, FixedUpdate, and OnDestroy, all of which are regularly used with GameObjects. Unless otherwise noted, all the code displayed here is used in scripts that are inheriting from MonoBehaviour.

The code above shows the Start method as well as all the different types of Update methods. Of particular note is the varying Update methods, which all work similarly to each other but have some important key differences. Update is run once per frame, meaning any logic you want to execute all the time would go here. A good example of what to do here would be timer control. If you’re wanting to increment every second, you can do that in Update using deltaTime like in the code above. FixedUpdate, meanwhile, is generally used for physics calculations thanks to its regular call time. It’s not framerate dependent like Update is, hence, the recommendation for use with physics. Finally, LateUpdate is generally used for ordering tasks. It will wait until all the other update functions have executed before performing any tasks specified within LateUpdate. It’s best used for guaranteeing certain tasks are done after all other code has been run.

Two more Monobehaviour methods worth mentioning is OnGUI and OnDestroy. OnDestroy is pretty intuitive, as it simply executes commands once the object is destroyed. It’s handy for any last minute cleanup you wish to do before an object is removed from the application. OnGUI is often used for making quick and easy buttons in an application. Unity does have a UI system that let’s you create very nice menus, buttons, and more, but if all you want is something really simple and basic then OnGUI is a good choice.

Transform

One of the more straightforward classes in Unity, the Transform class is responsible for working with a GameObject‘s position, rotation, and scale. Whenever you need to update any of these object attributes at runtime, Transform is what you’ll need to use. These are so important to GameObject that Unity does not allow you to remove a GameObject‘s Transform component. While managing position, rotation, and scale is the Transform‘s primary job, it is also used in regards to parent and child relationships in GameObjects. Anytime you need to access the parent or child GameObject, the Transform class will be your gateway to that object.

The code shown above shows everything I just described in action. In the Start method we first get this object’s Transform before then finding the object’s child. We could then use that information later if we wanted to do something with the child object. The code in the Update method is a bit simpler, showing an example of moving and rotating an object. Since there’s no physics involved, it is okay to execute this code once per frame.

Object

The base class of GameObject, Object is a class for any object Unity can reference in the editor. It is in the UnityEngine namepsace, and encompasses items like components, materials, text, and more. This is not to be confused with the Object class derived from .NET’s System namespace. Though they share names, they are not at all the same things. That said, you can still use .NET’s Object class as desired in your C# scripts if you have no interest in the script being assigned to a GameObject in the Unity inspector.

Object brings with it a handful of methods helpful for managing other objects. Of particular usefulness is the Destroy and Instantiate methods, which is used for deleting and spawning new objects respectively. There’s also DontDestroyOnLoad, which is best used for any objects you want to persist between scenes like game managers. Finally, there’s the FindObjectOfType method and its sibling, FindObjectsOfType (note the difference between single and plural “Object”). Though slow in performance, these methods are useful for locating specific objects in a scene and doing something with them later. Just be sure you’re not calling either of these every frame, or prepare to see your project take a hit in performance.

Debug

Debugging in Unity is one topic that has been covered here previously. You can read more about that here. To recap what was said before, the Debug class helps you diagnose any issues in your project using console messages, lines, and more. Utilization of Debug is inevitable, as it will often be the sole way you’re able to fully understand a situation you may be presented with. Some helpful tips before moving on – first, you should know that clicking messages in the Unity console window will highlight the object the message came from, and double clicking will take you to the line of code that generated the message. Second, you can make a distinction between a log, warning, and error message in code to further assist your debugging. Error messages in particular will pause the Unity editor so long as Error Pause is enabled in your console. Finally, don’t ignore the DrawLine and DrawRay methods. In 3D applications specifically, this is a great way to figure out where any raycasts or other lines drawn in the app are located and the direction they’ve gone.

Time

You’ll likely need to perform some sort of time-related task in your projects such as counting the number of seconds that have passed between one moment and another. The Time class is here for scenarios such as this. Closely linked with Time is the project’s FPS (frames per second), which can affect the results of your scripts depending on the exact methods used. For this reason, it will be important to know your target FPS and do your best to maintain that FPS. This will vary based on the device the project runs on and how demanding of said device the project is expected to be. As you’ll see in the code example below, deltaTime is generally what you want to use when tracking time since it returns the time since the last completed frame. This way, you’ll be able to get consistent results from your code regardless of the FPS.

Our example code is very simple, but there’s one key difference between the two lines that update position. Moving the position based off Time.time results in an object moving according to the number of real-world seconds that has passed since the start of the application. That’s okay if the project is running flawlessly, but your app running perfectly on every conceivable machine is quite unrealistic. Instead, it’s better to base it off Time.deltaTime, which tracks the time passed based off the last completed frame. In other words, regardless of if your application is running at sixty frames per second or six, the object’s position will be remain consistent. You won’t have to worry about an object suddenly teleporting upwards if the application is running slowly.

Random

Randomized elements are often useful for giving projects an exciting and suspenseful feel. For instance, if you want to shuffle a deck of cards in a game, you’ll need to utilize some randomness to make that happen. Thankfully, incorporating those random elements into a project has been made easy thanks to the Random class. Much like Mathf, the exact uses for Random will vary. Sometimes, you just need a simple random number in a range, at which point the Range function will be utilized. But Range need not be limited to one number. You can create a random position in your scene using multiple numbers that are randomly generated. Or, if we go back to our earlier example where we needed to shuffle a deck of cards, you can setup a loop that gets a random number in each loop and orders your cards accordingly. If you desire, you can change the seed from which Unity’s random generation is based upon, or you can simply leave the seed at what Unity itself generates, which is the time at the start of the application.

Executing randomization doesn’t have to just be about randomizing numbers. You can also get random points in an area, a random rotation, or a random color to name a few. For random points, you have insideUnitCircle, insideUnitSphere, and onUnitSphere functions. The first two simply find a random point in a circle, handy for 2D applications, and finding a random point in a sphere, which is tailored for 3D. onUnitSphere is unique in that it finds a random point on top of a surface of a sphere. If you take a ball and call onUnitSphere and insideUnitSphere on it, insideUnitSphere will find a spot on the inside of the ball, while onUnitSphere will find a random point along the outside of the ball. Depending on your project’s needs, this can be a very important distinction. Random’s last two functions are a lot more straightforward, with rotation being used to generate a completely random rotation, and ColorHSV gets a random color with HSV and alpha values within a certain range. You can even specify the range on ColorHSV on as many or as few parameters as you wish. Below are some examples of Random in action.

Vectors

You might know Vectors as a mathematics concept that describes things like direction. The same basic logic is applied to the Vector class in Unity, used primarily for items like position of a GameObject or the distance between two objects. Vectors can be broken down further into Vector2, Vector3, and Vector4 classes, corresponding to 2D, 3D, and 4D vectors respectively. Each of these vectors use many of the same functions, so the information presented here is relevant to all three types. While working in Unity, a Vector will most commonly be used alongside Transform objects to update an object’s current position and perform vector arithmetic which can then be used when gathering information like checking a minimum distance between two objects or figuring out an object’s current direction.

Vectors have several properties and methods that make working with Vectors easier. For starters, Vectors have handy shorthand for moving a direction by one. As an example, Vector2s have down (which is like writing Vector2(0,-1)), left (Vector2(-1,0)), one (Vector2(1,1)), and more. Vector3s and Vector4s have most of these shorthands as well, though the exact word used for each may be a little different. Additionally, you can use Equals and Set to compare vectors and update existing vectors. There are also methods for finding distance, interpolating between two vectors, calculating angles, and more.

Lerp is perhaps the most frequently used of the Vector methods. It’s used to move an object from some starting position to another ending position gradually over time. The Transform section had code that behaved very similarly, but in that case we were simply moving an object to the right forever. With Lerp, you have more control over where you move. MoveTowards works pretty similarly to Lerp, with both serving the same broad purpose. Lerp uses the lerpTime parameter like a percentage, while MoveTowards operates more like a time limit.

Quaternion

The Quaternion class is another class that works closely with Transform, specifically in regards to an object’s rotation. These are not quite the same as Euler angles, which is what you see displayed in the Inspector window in Unity. Euler angles are a Transform coordinate which represent the object’s angle of rotation displayed like a Vector. Quaternions are the mathematical notation for this rotation, tracking the rotation as well as direction of the object. While the two work hand in hand, generally you’ll be converting Euler angles to Quaternions for the purpose of efficiency and stability. It’s perfectly fine to use Euler angles in your scripts, but it’s important to eventually convert those to Quaternions somewhere in your code.

The above code shows two examples of doing the same task but in different ways. Start sees us instantly rotating this object towards another object somewhere in the scene, while Update makes use of Quaternion‘s Slerp to smoothly rotate the object towards its target over a period of time.

Mathf

Of course, it would hardly be programming without some kind of mathematics involved. Unity’s Mathf class provides a helpful collection of common functions you’re likely to use during development. The functions can be broken down into categories. There are trigonometric functions, like Sin and Cos. Exponential, square root, and powers form another category, while Log and Log10 cover the main logarithmic functions. Interpolation functions are available as well, with MoveTowards and Lerp both seeing regular use in many Unity projects due to their frequent relation to movement related code. Finally, there’s limiting and repeating functions like Clamp, useful for keeping values within a certain range, and Min which gives you the lowest between two numbers.

The exact ways you use these math functions will run the gamut. Sometimes, you may make use of them to make simple decisions based off what numbers get returned. Other times, you can use them to help calculate items like in-game power or pricing, while making sure those values don’t go beyond a certain point. Some use math functions alongside their movement code, while others utilize them to assist with how numbers are displayed on screen. Whatever your goal is, there’s likely a Mathf function that can assist you. With all of them being conveniently called from Mathf, it’s been made easy to incorporate mathematics of all forms into your project. Here’s a few examples of what you can use the Mathf class for:

ScriptableObject

Utilizing ScriptableObjects has been covered before, so it’s recommended you check out this article if you want more in depth knowledge of the class and how to use it. But in brief, ScriptableObjects are data containers meant to hold large amounts of data that’s independent of individual class instances. As an example, if you have a consumable item such as an apple in your project, you can make an apple ScriptableObject which holds the data for the apple (weight, price, etc.), then apply that data to each instance of the apple class. Then, if you decide later you want to adjust the properties of an apple, you can instead update the ScriptableObject, thus updating every apple instance in your project all at once. It’s a handy way to save time in the long run as well as reduce the project’s memory usage.

Gizmos

Allowing the developer to create lines, shapes, and full meshes in the scene view, Gizmos are an excellent way to extend your debugging or create visual aids for development. This can be especially helpful for communicating the locations of otherwise “invisible” objects like light sources or managers. For debugging, you can use it to give additional visual information on anything from collision info to spawn locations. What you do with Gizmos is really up to you as the developer. There aren’t as many methods here as there are in other classes, but what’s here is clear and easy to understand, thus they are also easy to integrate into your workflow. Here’s an example of how one can easily create some kind of visual element for an object that is otherwise invisible, such as a trigger area.

That’s it! The key thing to remember when utilizing gizmos is the OnDrawGizmos method. This is how Unity will know to draw a gizmo for you at all, so don’t forget it. Here’s another example that demonstrates making a gizmo which displays a custom icon for the object.

This code may look even simpler than the previous example, but there’s one important catch. For the above code to work, you’ll need to place your icon in a folder named “Gizmos”. The default filepath Unity searches for icons is Assets/Gizmos, so not having that folder and placing your icon of choice there will lead to some confusion from Unity. Once you have that set up, you’ll be able to display any icon you wish for your object.

Handles

Complimenting Gizmos is the Handles class, which focuses more on interaction and manipulation as opposed to Gizmos' emphasis on information. The 3D controls that you see in Unity’s scene window are one such example of a Handle. With it you can quickly move, rotate, and scale an object to your heart’s desire. This and other built-in tools work well, but sometimes you simply need a tool that is tailored to your project. Using Handles, you can create your own waypoints, tools for defining “safe” areas in a scene, and much, much more. They’re a great tool for streamlining your own development or creating helpers to anyone on the development team that’s not necessarily a programmer. Customizing how the handle looks is also an option, letting you choose which graphic to represent the handle, the color, displaying of text, and the list goes on. There are many options with Handles, too many to thoroughly showcase in this section, but here’s a few examples gathered into a single script. Given how much is here, comments have been added to the code to clarify what’s going on as you go.

By including all this, any object that has this code attached as a component will give helpful controls that change the object’s parameters without having to navigate the Inspector window. You’ll notice that the file has two classes, one for the object itself and one for the handles. HandleDemo inherits from MonoBehaviour, and recall that scripts can only be attached to game objects as components if they inherit from that class. But the Handles methods used throughout DrawHandle asks that we inherit from the Editor class, thus we split them up into separate classes. In order to make the two talk to each other, we first get the object we have selected and inform DrawHandle of who it is. Once that information is established, the Handles can then take user input through the button or arrow handle that acts as the object’s controls. It applies that input to the object itself while also updating its own displays based on current values.

Conclusion

If you’re new to Unity, even the most essential of Unity classes can seem like a daunting list to learn. But as the old saying goes, practice makes perfect. This list attempts to order the classes based off what’s easiest to learn and most important to know for any given project, which should hopefully help any newcomers among us who are interested in using the engine for their projects. Of course, feel free to use this as a quick guide. As for experienced Unity users, one may be surprised at the things they think have figured out, only to discover a whole new way of doing things that’s far more efficient. For those users, the hope is there’s still some new knowledge you’ve obtained here. Whether you’re a hobbyist or a member of a large team working on a Unity project, these essential classes will likely become useful to you during your project’s development.

become useful to you during your project’s development.

 

About the author

Lance Talbert

See Profile

Lance Talbert is a game developer and programming lover that has been learning to code since the age of thirteen. A recent college graduate, Lance has studied programming in various languages and forms ranging from C# to Javascript. He spends most of his spare time creating projects in Visual Studio or building his own games. Lance has released two games, War Ender and Impressions, and is currently working on a third titled The Future Project. Beyond programming and game development, Lance also has interests in writing, acting, and composing music. You can keep up with Lance by following him on twitter as well as through his gaming blog. You can also view his game development updates here: https://www.infinitelevel.net/.

Lance's contributions