Dana Vrajitoru
I355/C490/C590 3D Games Programming

I355/C490/C590 Lab 1 / Homework 1

Date: Wednesday, September 4, 2022. To be turned in by Wednesday, September 11. Here is a snapshot of the game:

We assume that you have successfully installed the Unity Hub and Unity Editor 2022.4.33f1 to your computer based on the installation instructions.

Lab Part

Ex. 1. In this lab we'll get used to the Unity environment and write a small application implementing a 3D game of Racquetball.

Open Unity Hub. Create a new project from the Projects tab, the Core section, 3D Core, and call it Racquetball.

Assets - Scene. In the Project area in the bottom left quadrant, note a folder called Assets and a subfolder called Scenes. The Assets folder is where we normally store all the resources needed for the project. If there is no folder inside called Scenes, just create one using the + button below Project. The current scene should be in this folder under the name SampleScene. Rename it in the folder as Game and then click the button to reload it with this new name in the dialog that the editor opens. Save your game (the scene) from time to time.

Creating a Box. Let's create a box to hold the Racquetball game.

First, let's create a plane for the box to sit on. Click on the + button below Hierarchy and on 3D Object - Plane. Note an object appearing as child of the scene Game. Using the Inspector on the right side of the window, rename this object as Ground.

Also in the Inspector, change the scale of this object to 3 x 3 x 3 to make it large enough to have space to build the box on it. Note that the horizontal plane sits on the X and Z axes and that the vertical is the Y axis. You can take a moment to get used to the navigation in the scene editor:

Now, let's make this object green. At the bottom of the inspector, notice a material component that looks like a white sphere. We'll replace it with another material. In the Assets folder, add another folder called Materials and click on it on the left. Then using the + button below Project, create a new Material and give it the name green. With this material selected, notice the property Albedo in the Inspector. Click on the big white rectangle and change its color to a medium green. Now, all we need to do is to drag this material from the assets and drop it over the plane in the scene editor to apply it to this object. When you click on the Ground object, it should show the Green material in material component in the Inspector.

Box. Let's create a box for the game to take place in. We will create it out of 5 walls in addition to the ground.

Next, from the Hierarchy, add another 3D Object of type Cube. Set the scale of this object to 10 x 10 x 10. Set its position to (0, 5, 0). This is the shape of the box we want to create. However, we will make it out of 5 different boxes because of the following reason:

If you look in the Inspector, the box came with a component called a Box Collider. This allows Unity's physics engine to detect collisions between this object and others that have colliders. However, it will not function well if the ball is already inside it when the game starts. So we'll create a box for each wall that will each have its own collider. Also, looking at the ground, that object also came with a pre-made collider.

Let's make this object thinner and move it away from the center. Set the X scaling to 0.5 and the X coordinate in the Position to 5. Rename this object Wall1.

With the object still selected, right-click on it and select Duplicate. Rename the new object as Wall2 and set its X coordinate to -5. Repeat the procedure to create two more walls where the X scale is back to 10 and the Z scale is 0.5. Set these walls at coordinates (0, 5, 5) and (0, 5, -5). The top view is great to see the layout here. Finally, for the 5th wall, set the Y scale to 0.5 and the Y coordinate to 10.

a. Camera and Layout Setup. To be able to run the game inside the box, we need to set the camera so that we can see the inside.

Switch to a view from the side where you can see the camera well. Click on it to select it, then pull on the vertical arrow to place it around the half of the cube. After that, pull on the blue arrow and pull until it is just inside the cube. You should see that you are inside in the game preview in the bottom right corner.

In the properties of the camera in the Inspector, play with the Field of View until you think you can see a good amount of the box inside without it being too dramatic. You can also play with the directional light to see the effect, but make sure it remains inside the box.

Above the Scene Editor, there is a Play button. Click on it to launch the game, just to get an idea of what it looks like. Click on Play again to stop it.

The Ball. Let's create the ball that will be bouncing against the walls. Select the front wall of the cube, the one close to the camera, and un-check the mark next to its name in the Inspector. The wall should be hidden now.

Click on the + below the Hierarchy and create a new 3D object of type Sphere. Apply some material to it to make it well visible, and move it towards the center of the cube. You can even set the coordinates as (0, 5, 0). Rename the object Ball.

The sphere already has a collider, but we need to add a Rigidbody component to it so that we can give it speed and have it bounce against the walls. With the ball selected, click on Add Component in the Inspector and add a Rigidbody from the Physics menu. Then un-check the Use Gravity property for it. Also, for the Collision Detection attribute, change it from Discrete to Continuous.

For the ball to bounce against the walls, it needs to have a physics material that allows it to do it. In the Materials folder in the Assets, add a new Physics Material and rename it bounce. Set the Bounciness to 1 and both friction parameters to 0.

Then select the ball again, and in the Sphere Collider component, click on the little circle next to Material and select the bounce material. Alternatively, you can also drag and drop the material over the object or into the box next to the Material property.

If you run the program now, nothing happens. This is because the ball doesn't use gravity and its initial speed is 0, so there's no reason for it to move.

To make it move, we need to apply some velocity to it. For that, first we need to add a script component to it. Click Add Component and then select New script all the way at the bottom of the menu, and then call it BallController. In the Assets folder, create a new folder called Scripts and move the new script inside it. Then click on the folder on the left and double-click on the script to open it in Visual Studio.

This script already has two functions, Start and Update. The function Start will be called when the object is created at runtime. The function Update is called in every frame. We only want to set the velocity in the function Start, because after that, the physics engine will take care of moving the object. Add the following line to this function:

GetComponent<Rigidbody>().velocity = new Vector3(Random.Range(-10f, 10f), Random.Range(-10f, 10f), Random.Range(-10f, 10f));

Next, we would like to be able to calibrate the ball's speed without recompiling the code. Let's add an attribute speed in the code at the top of the class:

public float speed;

Then replace 10f everywhere in the velocity by this variable. Save the file and go back to Unity. In the Inspector, under the script component, we should have an extra attribute Speed. Set its value with something like 20, then run the program to see if it works.

Racket. Let's create an object that will play the role of the racket, so that the user can interact with the game. Add a new object to the scene of type Cylinder. Set the scale for this object to 2 x 0.05 x 2, and then the rotation around x to 90 degrees. Set a material for the racket where the Alpha component of the Albedo is somewhere in the middle. That way, we'll be able to see the ball through the racket. Switch to a side view and move the paddle to the inside of the box using the green arrow, a little bit ahead of the camera. Rename the object Racket.

Now, we need to be able to move the racket around to try and catch the ball. For that, we also need to add a script to it. Add a new script component to the racket and call it RacketController. Add a public attribute speed, also of type float. Then add the following attribute to the class:

public KeyCode moveUp, moveDown, moveLeft, moveRight;

Declare an attribute of type Rigidbody called rbody. In the function start, get a reference to the rigid body component of the object and store it in the attribute rbody:

rbody = GetComponent<Rigidbody>();

Then in the function Update, add the following code to move the paddle when the up arrow key is pressed:

if (Input.GetKey(moveUp))
    rbody.velocity = new Vector3(0f, speed, 0f);

Add 3 more similar cases for the other directions of movement, each of them on an else from the previous if. Add an else to the condition where you set the velocity to 0.

Going back to Unity, first add a Rigidbody component to the racket and un-check the Using Gravity setting. You should see 5 attributes added to the script component in the inspector. Set the move attributes with the arrow keys or the WASD keys. Then set the speed to 1. Try the game and adjust the speed if needed. You can now make the front wall visible again so that the ball doesn't get lost passing through it.

In the rigid body component, expand Constraints, and the check the boxes to freeze the rotation in all directions. Otherwise when the ball collides with the racket, it could give it a spin. The same way, freeze its position over Z. Then also change its collision detection from discrete to continuous.

Collision. In the last part of the lab, we will handle the collision between the racket and the ball. We would like to have a score in the game and to have it increase every time there is a collision between the ball and the racket.

We will make the ball in charge of keeping the score and detecting the collision with the racket. But first, we need to add a tag to the racket that will identify it as such, so that the ball can tell it apart from the walls.

Select the racket, then in the Inspector, just below the name of the object, click on the menu next to Tag and click on Add Tag. Click on the + to add a new user tag and call it racket. Then select the racket object again and change its tag to this one.

In the ball controller script, add a public integer score initialized as 0. Then add the following function to the same script. Do not call it explicitly because the engine will call it automatically when a collision happens:

void OnCollisionEnter(Collision colInfo)
{
    if (colInfo.collider.tag == "racket")
    {
        score += 1;
        Debug.Log("Score: " + score);
    }
}

Test the program to see if it works. Click on the Console next to the project browser on the bottom left to see the score displayed. This will be continued in the homework.

Homework Part

Set some materials with the colors you like to the walls of the box and to the ball. You can play with the transparency in the Albedo component of the materials to see if that makes it look better.

Change the formula for the initial speed of the ball so that the Z component of the speed is between 0.5 * speed and speed.

Your game should be ready to go. Test it to make sure it works in both cases. Comment out any debug statements.

Experiment with the angular drag, freezing the ball's rotation, and other factors in the rigid body to find an optimal setting for the ball's movement. You can add some extra velocity to the ball when it hits the racket.

Create another cylindrical object called Target with the goal of giving the player extra points if the ball hits it. Set the target close to the back wall and give it a tag called "target". Add a case in the collision function where if it hits this target, you add 10 points to the score and output it.

Executable

As a last step, after you make sure everything works, from the File menu choose Build and Run. This will create a stand-alone executable for the platform of your choice. First, you need to add the scene to the executable. You can simply do that by clicking the button Add Open Scenes. Create a folder called Build inside the project folder (not inside the Assets folder). Create an executable for your architecture (so you can test it) and one for Windows (so that I can test it). Create a zip file with the entire buid folder. It should contain the following:

You can add the scripts and the scene to the same zip file.

Homework Submission

Create a zip file and copy inside it the Windows executable, the ..._Data folder, the scene Game.unity and the script files BallController.cs and RacketController.cs. Upload it to Canvas to Homework 1, as this is your homework. There is no separate submission for the lab.