Lesson 6 - Basic Code Review

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


Transcript

In that last video, we hammered out a bunch of code without really going into what all of it is doing. If you are new to coding, hopefully it didn't make you lose your lunch as it were. It may have looked like a lot of code. I deliberately wrote it in a way that is the most basic way possible. We can at least talk about it and understand it in some simple way. Before we move on and write more code, I want to take a minute and review some of what we just did and give you a bit of context on how all of that is able to create a dynamic game world before your very eyes. It is not important right now that you get every piece of code. It is important to remember that. I am not expecting you to completely understand it, but just that you have a concept of how things connect within Unity. We will certainly be revisiting these concepts over and over again throughout this course, but right now I would like to give you a primer on how this is all working.

Before we go into that, I want to do a little bit of house cleaning on this code that we wrote here. Just clean it up a bit, even though we are making a quick and dirty prototype, I don't want it to be too hard on your eyes. If it is going to be ugly, maybe we can try to make it as ugly pretty as we can. Bear with me here as we do a little bit of modest re-factoring. First, we will start off with taking this value 0.09F. It is often a good indicator that you should try to encapsulate it into a single variable whenever it is being repeated over and over again. Just a bit easier to read as well. It is also that way we did it with the sphere controller script. See here with our conditionals, we didn't have any spaces after the conditional. Just to make the code a little more compact, we will remove those spaces as well here. Just a few modest changes in order to keep things consistent. It is good to be as consistent as possible as you move forward. It is just a good rule of thumb to keep in mind.

In the end, how you arrange your code, really often comes down to stylistic choice, but just like you can't slap together anything and have it look pleasing, so too is the case with code. We will try to write our code with some sense of style, as it were, although coders in general and style don't always mix. Take it from me. Another quick thing before we move forward, and that is to add line numbers to the left hand side here. It often makes it easier to reference what line you are talking about when you can actually see the number. Go to Tools > Options > Text Editor > All Languages > General, and line numbers should be right there. Select that and like magic we now have line numbers. Just a little bit more useful when we are trying to describe what we're looking at here.

Now that we have that out of the way and all sorted out, let's make an effort to better understand what is going on in the code that we wrote. A good place to start is this conditional block here, where it hecks to see if a key is pressed, and changes the transform position of our cube. We will start first by looking at this variable - Vector3 Move. Now Vector3 sounds like a really fancy name for a variable. That is basically the variable's type, which basically holds 3 other value types: floats for X, Y, and Z. That is why we chose Vector3 because when you click on cube here, its transform has an X, Y, and Z values. In the script, we created a Vector3 called Move, and at the start, when the game started, we assigned Move to the current transform position of the cube as you can see here, our current transform position is -3X, -2.14 for Y, and 0 for Z. That is where that cube is when the script starts when you press play and the game starts. That is what is happening there.

In the Update() method, what we have is the series of conditionals that checks in this case, if the left arrow is pressed, and if that's the case, then we take the X value in Move and we subtract whatever Speed it is, which is 0.09F from that value, and then it assigns it back. How do we get all that from Move.X -= Speed? You will come to get used to this type of odd notation. It is just a very useful way of basically saying this, which is easier to understand. Move.X=Move.X, take away Speed or 0.09F if that is easier for you to visualize right now. That is basically saying the same thing. These 2 lines are saying the same thing. The second one is easier to understand, so maybe I was a little bit to ahead of myself when I said this is the easiest way possible of representing this kind of code. It is a little bit easier to understand it that way, than by using ‘-=’, but nonetheless we are going to be using that frequently because it is a useful way of representing incremental changes.

The same thing if we move along, if we press the right arrow key, we take the X value and we add to it rather than subtract, because when you go back to the editor and you see the transform, if we subtract from X, it moves to left. If we add to X, then it moves to the right. That is why we use += and -=, respectively. Basically the rest is just the same for the Y-axis. Being a Vector3 it has X and Y. We don't worry about Z because it will retain its position from when we assign move with the transform position when we start the game. The Z value is always going to stay 0. We don't really have to worry about it. After all those checks, after we go through all those checks, those conditionals, we take whatever move has, if it has changed from where we started. Or if it hasn't changed we just assign it back to the transform position, which again represents the actual position in this world space. That is basically all that is going on there. Pretty easy to understand, not really all that difficult to wrap your head around. Even if the code looks strange if you have never seen something like this before.

Now let's look at the code that constrains our movement to the camera’s boundaries. It is all contained here in this method called lateUpdate(). You won't really understand what lateUpdate() is all about, not for a little while. The reason I put this code here was mainly a force of habit. I didn't have to put it here. I usually put my camera-dependent code in lateUpdate(), usually because the camera needs to know the position of your object before it can adjust or move to its position. Of course our camera is not moving so it was not necessary in this context, but nonetheless it is keeping our code separate and somewhat cleaner. We will leave it as is and you will get used to using lateUpdate() later on.

Let's look at our first conditional here. The first one is asking if the transform.position.x, which again relates to this current X position of our game object. If that transform.position.x is less than CamWidthX * -1 and CamWidthX defined up here, 6.2F so you can just substitute 6.2F. If the position of .X of our cube is less than 6.2F times -1, which means -62F, what would -62F be? It would be about right there. Looks like the edge of our screen. If it is less than that, which means it is off the edge of our screen, off the left edge, then we take our Vector3 Move X and we make it equal to 6.2F times -1. Basically what that does is it almost magnetizes the game object to the left here. If it somehow calculates that it is less, to the left hand side, less than 6.2F, it immediately puts it right up to the edge of -6.2F. That is basically what the rest of this conditional block does as well. You may have noticed that my use of 1 and -1 is redundant here. Not so much in the -1, but with the cam. with X times 1, it is just going to be 6.2.

Why don't I just put cam with X, that is a fair assessment. It was because messing around with this and often it is fun when prototyping game and having ideas, but what happens if I want to do this or that and you can try it out with code. I had this idea, kind of like with Pac Man, when Pac Man runs off the far left or right edge of the screen, he ends up on the other edge of the screen. That keeps the play field moving and infinite in a sense. What I did was I realized that with a very simple change, we can just flip these values and we get that effect.

I will demonstrate that to you really quickly. Remove the negative from that, flip that to 1, flip that to -1, flip that to 1, and flip that to -1. Now when our cube reaches the farthest left edge of the screen, -6.2F, it is going to instead clamp to the right side of the screen, 6.2F. If it reaches 6.2F, the far right-hand of the screen, then it will clamp to -6.2F and so and so forth for the Y coordinate as well. Let's save and run that so you can see that in action. There we go. It ends up on the other side of the screen.

Now this may or may not be a fun game mechanic, I don't know, probably not. I don't think I will keep it in there, but it is just another example of when prototyping a game how you can try out these fun little things that small changes often in a game and code can result in a much different and interesting gameplay mechanic. That is just half the fun of prototyping and coming up with ideas on the fly. Unity makes that so much easier than ever before. This is bugging me now to be honest with you, I could have made this code block a little easier to understand. It may not have made total sense the way I described everything. Why don't I just re-factor this as well, very quickly so when we move forward it is a little bit easier to work with.

Let's go up here and create some easy to understand variables. (typing in new variables) Now you can see it is a little bit easier to even understand when you look at it immediately. Especially if you come back later and look at your code. You don't always remember exactly what you were writing and if you go through a lot of lines of code, it can eventually cause your brain to hurt a little bit more than it needs to. That is just a little bit of re-factoring there, and a little tip on how to clean up your code. Just to make sure we didn't make any mistakes, and I don't think I did, play that and see if it is as it should be. Clamps as it should to the edge.

What I didn't go over yet in this video is exactly how these changes are happening incrementally. For example, adding or subtracting the speed value, which is 0.09F. If you go back to the editor here, and if you manually subtract or add 0.09F. Adding 0.09F, we get 43. I will add another 0.09. Not a big change. I didn't really go over how these tiny little changes accumulate. Either adding or subtracting 0.09F and so on. How do they accumulate and add up over time in order to create the perception of a moving and changing game world. It is a pretty central concept in to understanding how Unity works and game development in general. I will take great pains to give you a good primer on that in the next video and hopefully by understanding that, it will give you a good foundation for understanding how the code we write in the coming videos influences and creates our moving and dynamic game world. It will be illustration-heavy and concept-heavy, but fun at the same time and informative. I will see you there in the next video. Thanks.


Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Comments

Please login or register to add a comment