Supporting files for VG1 quests are part of a single archive that you can download here.
*Your Unity version may differ from what is pictured. You MUST use the Unity version required by the instructor for your particular semester.
From Unity Hub Projects tab, click the New Project button.
You will use only one project for all of your solo quest tutorials throughout the entire semester. You will create a second separate project for your semester project.
In the New Project configuration screen, your Unity organization will be whatever is the default for your account. use your own last name and first name as part of the project name. When configuring your project name, make sure you have chosen local project rather than the default cloud project. Notice how the icons are different despite the project name appearing the same.
Make sure your project location is within the GitHub folder you created during our setup instructions. Because we are following our own instructions setting up GitHub, leave source control provider unconfigured.
Unity provides different templates for starting your project. All of the projects we do this first semester will use the Universal 2D template.
After clicking Create Project, give Unity some time to prepare the new project. The full Unity Editor interface will automatically open once the project is ready.
The Unity Editor interface can be overwhelming at first, but nothing is broken by default. It is ok to leave settings untouched until you understand more about them later. We will learn Unity by working through functionality one tab at a time. Every tab in Unity operates as a separate tool/feature, and you are able to rearrange the interface to your liking. We'll start with the Project tab which is usually positioned at the bottom of the screen.
The Project tab portrays your file system and the assets that are within your project. You should always keep your projects organized with an appropriate folder structure. Clicking the + lets you create new assets including folders.
Because we will build all of our quest tutorials within this same project, we will use folders to help organize content from different exercises. Create the folder structure portrayed in this image with a new Textures folder and a Q1 subfolder within Textures.
You can drag-and-drop files into the Project tab to include them in your game. Add the q1_char.png spaceship graphic from the Course Files to your project by dragging that file into the /Assets/Textures/Q1/ folder within Unity's Project tab.
A texture is a visual graphic that can be applied to some aspect of your game to be shown on screen.
Notice how the contents of the Unity Project tab represent what is actually on the file system as shown in our operating system's file browser. Most files are also paired with a meta file that tracks and configures how Unity uses that file.
The Inspector tab is a contextual tool for examining and configuring elements of your game. Clicking different assets will reveal different configuration options for that particular content.
Click your q1_char in the Project tab and match the pictured settings for your newly imported video game graphic using the Inspector tab. (Notice how we are using two tabs in coordination for this task. This is a typical usage pattern in Unity, and we will eventually have tasks where 5 tabs will all be relevant at the same time.)
We are keeping most of the default settings but will specifically change the Pixels Per Unit property. A Pixels Per Unit (PPU) of 512 means we will fit 512 pixels of artwork from this particular file into a grid unit of our game's coordinate system. You will learn more about the grid coordinate system later, but this setting ensures graphics are properly sized when they are brought into the game.
Save your configuration changes by clicking apply in the bottom right of the inspector window.
In line with my prior advice, it is ok to leave everything else on its default setting until you understand more. We will typically introduce only a few new settings to learn at a time as they become relevant to our project. If you are ever curious what a setting does, the question mark icon in the upper-right of the Inspector will link to online documentation. You can also hover your mouse over the name of the setting, and a tooltip is usually available to explain the property.
To keep our project organized for the semester, we will rename our current scene to Q1 to represent this assignment. We'll create more scenes later for future assignments.
Find your Scene file in the Project tab > Assets > Scenes folder and rename SampleScene to Q1.
On some versions of Unity, you may be asked to reload the currently active scene because of the filename change.
Peek at the Hierarchy tab and confirm that it also says we are working in scene Q1. If it does not say Q1, double-click the Q1 scene file in the Project tab before moving on to the next step.
While the Project tab shows you what assets are in your project, the Hierarchy tab shows you what GameObjects are in your Scene. A Scene contains what is currently portrayed by your game. Like a movie, a game will progress through multiple Scenes, and you can use Scenes to organize your experience into distinct levels, screens, or experiences.
In Unity, something appearing on screen (such as a character, vehicle, furniture, or grass) is often a GameObject. GameObjects are the fundamental building blocks of games in the Unity Engine. Some game engines use the term Actor instead of GameObject to further the Scene analogy.
Right now, our Q1 Scene only has a default Main Camera and basic lighting that allow the engine to "see" the game. We will leave these gameobjects at their default settings many of our assignments.
You can use the + to create an empty "blank" GameObject to configure.
Notice how it gives you the opportunity to rename the GameObject. Use Character as the name for the new GameObject. We will eventually make this character move around in response to keyboard input.
When you select Character in the Hierarchy tab, notice that the Inspector tab changes to describe that GameObject.
When you inspect a GameObject, you will see the GameObject's list of Components. While GameObjects are the fundamental entities of the Unity Engine, Components configure functionality and behavior of a GameObject. The Character in this assignment will not move during gameplay if it is only a GameObject named Character. It will move like a Character because of the Components we will program and attach to it. Similarly, you could also have two GameObjects named camera, but the only GameObjects that actually function as cameras will be the ones with a Camera Component.
All GameObjects start with a Transform component because this is the minimum functionality for that object to exist. The Transform component cannot be removed from a GameObject. The Transform component controls the basics of position and rotation.
Next we will look at the Scene tab. The Scene view is like looking at the stage where the actors perform. It visualizes the entities that are present in the virtual world of the video game.
For clearer visualization, it can help to set the Scene view to the Move Tool (portrayed by an icon of arrows in a cross) and set the Tool Handle to Pivot. The Scene view works in tandem with the Hierarchy and Inspector tabs. Make sure Character is still selected in the Hiearchy. When the Scene view's Move Tool is active and set to Pivot, a Handle of intersecting coordinate axes appear in the Scene view exactly where the Character is positioned in the virtual world. In this case, we can see that Character exists at the center.
Notice that without any other components besides the Transform component, our Character simply exists at position 0, 0, 0 somewhere in the game scene. Even the functionality for having graphics is missing until we add more components. You can alter the position data of the Character in the Inspector and see those changes reflected in the Scene view. You can also move the Character in the Scene view by dragging the movement handles, and see its position data updated automatically in the Inspector.
Our Character needs visuals. Rendering graphics is a functionality from having a specific kind of Component attached to our GameObject.
The SpriteRenderer Component allows a GameObject to render 2D graphics. Attach one using the Add Component button at the bottom of the Inspector tab while Character is selected in the Hierarchy.
The Inspector will let us configure the Character's SpriteRenderer component.
For the Sprite property in the Inspector tab, drag-and-drop the spaceship graphic from the Project tab into the Sprite blank. The other default settings are fine.
Our Character now has a graphic! (It is ok if you have some other debug icons in the way when using the Scene view.)
By now, you are starting to see how a single GameObject may depend upon multiple Components for its overall functionality. Character is using both Transform and SpriteRenderer. We will be adding one more component to Character next.
Unity uses C# as its main programming language. (It is possible to import libraries from a variety of other languages, but that is beyond the scope of this course.) Although C# is not a scripting language, we refer to some C# files as Behavior Scripts in Unity because of the analogy of telling actors (GameObjects) how they will perform in a scene.
Whenever we use C# to write a Behavior Script, we are actually writing our own custom Components that we can attach to GameObjects.
We will keep all of our C# code organized in separate folders for each exercise. Create the folder structure portrayed below.
Because C# files are project assets, they can be created from the Project tab. Create a C# file through the + menu by selecting MonoBehaviour Script.
Whenever you create a C# file through Unity, it will automatically generate a code template based on the filename. By convention, class names are capitalized in Unity, so your filenames for behavior scipts should be also. In Unity, it is typical to have the filename exactly match the C# Class inside the file. (This also means you should NOT use spaces or other invalid syntax in these filenames.) Older versions of Unity will not be able to use a component if there is a naming mismatch. These older versions of Unity remain common in professional use, so it is still a good habit to follow the stricter naming conventions.
C# code is generated as soon as you complete naming a file the first time (shown below). A common mistake occurs when someone renames a file later, but does not rename the class definition inside the C# code.
You may briefly see a progress window pop up in the middle of the screen or a progress bar in the bottom-right of the Unity Editor while the new C# file compiles. After compilation has finished, double-click the UFOController C# file to open it in your code editor. Notice how the filename exactly matches the C# class definition within the code.
If your C# file doesn’t open as expected, access the menu for Unity > Preferences (Edit > Preferences on Windows) and make sure your code editor of choice is selected as the External Script Editor under External Tools. Your External Script Editor options may differ based on what you have installed on your computer. You may also need to click the Regenerate Project Files button.
Make the changes highlighted in the code diagram below. Notice that we've enclosed the template code in a namespace. Because we will be creating multiple exercises within the same project, we will use namespaces to isolate the code between assignments.
UFOController.cs
using UnityEngine;
namespace Q1 {
public class UFOController : MonoBehaviour {
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() {
}
// Update is called once per frame
void Update() {
}
}
}
In the Inspector with your Character GameObject selected, click the Add Component button to search for and add UFOController. (You can also drag-and-drop the UFOController file from the Project tab onto the Add Component button or any other open space within the Inspector tab.)
In older versions of Unity, this is when you might see an error. If your code's class declaration does not match the filename, you may receive an error similar to what is shown below. As the error suggests, fix this by making the names match.
Your UFOController Behavior Script will now appear as a Component on the GameObject. Any Component you program has just as much potential functionality as any of the Components that come built-in with Unity. Often, game engines are chosen based on their balance of built-in features and ease of adding custom functionality.
As a kind of "Hello World" exercise, our goal in this assignment is to have a character appear on the screen and move in a direction relevant to the player's input. We will use the Arrow Keys to do this.
Modify UFOController with the changes diagrammed below.
UFOController.cs
using UnityEngine;
using UnityEngine.InputSystem;
namespace Q1 {
public class UFOController : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() {
}
// Update is called once per frame
void Update() {
// Move Up
if(Keyboard.current.upArrowKey.isPressed) {
transform.position += new Vector3(0, 0.02f, 0);
}
// Move Down
if(Keyboard.current.downArrowKey.isPressed) {
transform.position += new Vector3(0, -0.02f, 0);
}
// Move Left
if(Keyboard.current.leftArrowKey.isPressed) {
transform.position += new Vector3(-0.02f, 0, 0);
}
// Move Right
if(Keyboard.current.rightArrowKey.isPressed) {
transform.position += new Vector3(0.02f, 0, 0);
}
}
}
}
Much of this code may be unfamiliar at first, but we will perform a more in-depth line-by-line discussion and demonstration throughout class.
Line 2 helps us access player input devices such as the Keyboard object used in Lines 15, 20, 25, and 30.
UFOController.cs
using UnityEngine.InputSystem;
Each Component on an active GameObject experiences a life cycle pictured below. (There is no need to memorize these functions beyond knowing where to look them up. You'll learn the most important ones out of habit through repeated use.)
You can tie into these life cycle events with your C# code. As described in the comments on Line 7 and Line 12, the Start and Update events happen at specific moments and are the most commonly used. We won't need to use Start for this assignment, so it remains in the code only for the sake of class discussion. Line 13 is our Update event. Because Update executes every frame, it provides an ongoing chance for us to react to changes in keyboard input. (If we programmed controller movement inside the Start event, that logic would never react to the player's ongoing actions.)
UFOController.cs
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() {
}
// Update is called once per frame
void Update() {
Our movement functionality is divided into four directions: Up (Lines 14-17), Down (Lines 19-22), Left (Lines 24-27), and Right(Lines 29-32). The actual movement code is roughly the same for any given direction, so we will break down just one direction in more depth.
UFOController.cs
// Move Up
if(Keyboard.current.upArrowKey.isPressed) {
transform.position += new Vector3(0, 0.02f, 0);
}
Line 14 shows the comment syntax for C#. It is similar to many other languages. While well-written code is reasonably self-documenting, commenting is a good habit. You should use as many comments as are necessary to facilitate your learning and collaboration this semester.
Line 15 starts a Conditional statement (which closes with the curly bracket on Line 17). Always use indentation when code encloses other code. Badly indented code is one of the most common sources of confusion in class. In this line, we access the current Keyboard device and request the boolean state (true or false) whether the up arrow key is pressed during this given Update event. The code inside (Line 16) only executes if the surrounding conditional statement resolves to true. If the up arrow is not pressed, then the conditional resolves to false and the code to move the character is not executed.
A great wealth of functionality in Unity comes from having components work together. UFOController interprets keyboard input, while Transform controls object position. Because every GameObject is guaranteed to have a Transform component, there is a shortcut to access Transform from any other component: simply type (lowercase) transform. C# is case-sensitive. We will learn about (CAPITAL) Transform in C# later.
UFOController.cs
transform.position += new Vector3(0, 0.02f, 0);
In Line 16, we access UFOController's sibling Transform component through the transform property. This technique lets our two components talk to each other. A sibling component is one that lives on the same GameObject as another component. One of the properties we saw in the Inspector within Transform was Position, which we can also access in code using the same name. (By convention, class names are capitalized in Unity C# code, while properties and variable names are lowercase. In our code, lowercase position is a property of the Transform class. Lowercase transform is a property of UFOController giving us a shortcut to access its sibling Transform component.)
Position data is stored as a bundle of three numbers known as a Vector3. (Unity has Vector2 and Vector4 objects too.) Vectors are great for tracking coordinates (x = 2, y = -4, z = 0) and directions (northwest: x = -1, y = 1). More specifically, a Vector3 is a bundle of three float numbers. Float numbers are the main Unity data type for tracking numbers with decimal places. Whole numbers would be integers. You will be exposed to a variety of the most common C# data types used in game development thoughout class. These include int, float, string, bool, Vector2, and Vector3 just to name a few.
We move our character in a desired direction by adding a little to its current position using the += syntax with values only in the axes we want to move. Vector3 organizes axes into x, y, and z. Adding 0 to the x axis means we won't move left or right, but adding 0.02f to the y axis means we will move up a small amount. Different types of number data require different amounts of memory, so C# requires that float numbers be denoted with an "f" at the end of the number. Leaving out the "f" actually describes a double-precision number which takes up twice as much memory as a float. (0.02f is different data than 0.02.)
UFOController.cs
transform.position += new Vector3(0, 0.02f, 0);
This is all a lot of verbose explanation for what is essentially only three Unity coding concepts you need to take away from this assignment: the Update event, conditional player input, and assigning a Transform position. We'll practice and expand on the details in future assignments.
If connecting the dots between abstract functionality and code implementation is not yet comfortable for you, a good way to practice learning game development logic is to focus on code only one line at a time. Ask for feedback while breaking down the bigger functionality of a game mechanic into smaller and smaller chunks until there's no further simplification possible. Our approach toward learning new material will be iterative. We'll continue to review previous code and introduce new concepts and complexity in layers.
Testing is just as important a part of the game creation process as any other activity. It should always be a part of YOUR process in this class.
ALWAYS remember to SAVE AND TEST your work before submission. Playtest frequently as you progress through your exercises to check for both expected and unexpected behavior in your projects. If you only check for things that work, you may miss what is broken. What you submit is what is what we grade. We cannot grade unsubmitted work sitting on your hard drive. You will not receive credit for missing, non-functional, inaccessible, or unplayable work.
Click the Play button to test your game. Your character should move in the matching direction of each of the four arrow keys when pressed. You may notice that on faster computers, the character moves too fast to be controllable. We will learn how to fix this bug in the next assignment.
Pay attention to the bottom-left corner of the Unity Editor window for any Red Errors. You can view more details by opening up Window > General > Console. If your work generates Red Errors, your assignment must be fixed before submission. Testing your work is your responsibility. It is not the job of the instructor or teaching assistants to find red errors for you. Red Errors are critical errors and represent a compilation failure or a video game crash. It is unacceptable to ever ship your software in such a broken state. Unwareness is not an excuse, but rather a failure to engage in the required quality assurance process.
On occasion, Unity itself or third party plugins may generate a red error due to incompatibilities, network errors, tool misconfiguration, or other debugging circumstances. These errors are often harmless occurring during editor debug time and would not affect the execution of a game for an end user. You will NOT be penalized for editor errors that do not originate from your own effots. It can be difficult for newcomers to distinguish between editor errors and your own programming errors, so if you’re ever unsure how to fix a red error, just ask. Otherwise, always assume full responsibility for fixing your projects and do not adopt a habit of blaming the tools, which is a very common crutch of inexperienced game developers. This screenshot shows an example critical red error at compile time which prevents the game from running in the first place:
This screenshot shows an example of a critical red error at execution time which would cause the game to crash if it were exported for consumers:
SAVE all open files and scenes.
Submit your assignment for grading following the instructions supplied for your particular classroom.