Lesson 15 - Complex Evaluations and States

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


Very similar to the and operator, or having that in your clause (your evaluation clause) in which both operands have to be true to execute that if code's block. We have the option to have nested if's, which you can represent like so. Let's comment this out and write this in. if (isButtonAPressed) and if (isButtonBPressed) Here, we can see that there is pretty much the same functionality as when we have the && Let's just quickly switch it back to and operator. That evaluates true when both bools in that single statement are true. Alright, put it back there. We only get this output much the same, only when if (isButtonAPressed == true) and if (isButtonBPressed == true) I will finish up coding this out.

We will use the same thing as before for the false. I will un-comment that. We have to make this true if we want it to evaluate the way we are expecting. It will evaluate as true. There you go. When you look at that, you see that it commits the same logical evaluation that we had with the && that we saw earlier. The and operator being used in that single statement being evaluated right here, but and instead of 'or'. Both if’s have to evaluate true in order to execute this code block. It has pretty much the same functionality. It may or may not be more readable. Nested if’s can quickly get out of hand often, so it is a matter of taste or choice when choosing to use nested if statements.

You did get one added bonus using nesting rather than just using the && in a single statement, that is that you can choose to add some other code when the first if evaluates as true. Let's show you what I mean by that. Type in after the first if evaluation is true, Button A evaluates as true. What happens here, Button A and Button B evaluate as true. We will run that and show you the output. Button A evaluates as true because the first if evaluates as true. Button A being pressed is true, so it outputs that, the button log message, and then it outputs, “Button A and Button B evaluates as true.” We have the option for this added functionality that you can't otherwise achieve if you have your evaluation all in one if statement evaluation. You can keep nesting away as much as you want.

Nesting can eventually can get hard to read as I mentioned earlier. Sometimes it does make sense depending on what you are going for, and you will see it often in code. Often, you will have the somewhat complex if/then going on, and it's handy to store the state of your code using bools. I touched upon this a couple videos ago, but let’s illustrate this really quickly. I'll try to do this quickly. Let's make yet another method definition. This one we'll name a little differently. We are not just running a conditional, we are actually going to do some basic state handling. Let's just call it, StateHandler() Put it at the top there .You don't have to, but that is where I want to put it. Let's call that. Let's write in this basic code. Remember when I told you earlier about if you have a game where you pick up a Power Up, then you can create am invincibility state. That is basically what we are doing here with this code. We are simulating it because we are not really doing this in our game world. We are just outputting it to our Debug.Log().

Those are both false to start out with and then I will immediately make grabbed PowerUp = true. Let's evaluate that. if (grabbedPowerUp == true), then we will switch I isInvincible, which by default is false, we will switch it to true.Else, we simply make sure it is switched back to false. If we didn't grab Power Up, that we are simulating that kind of functionality here. Let's put it in our Debug.Log(). Let's actually see our invincibility state in our Debug.Log(). Let's save that and go back into our game. Run that. isInvincible is true because we evaluated grabbedPowerUp as true, then it executed this code block which then changes isInvincible to true and then we get the output in the Debug.Log().

This is a very contrived example, but hopefully it is illustrative none the less. It is all we are doing here. We are just trying to get you to see how this could be useful to handling states in your codes. This is actually what we will be doing later on with our game projects quite frequently. It is a good idea to touch upon it right now. Here, the player's invincibility state is stored in the isInvincible bool, which itself is dependent on whether or not a Power Up grabbed in the game that we are simulating here. It could be triggered with collision detection or whatnot. It doesn't matter. We are just simulating it, again. And it is reflected in the bool grabbedPowerUp. Then you can have another conditional block that handles what happens whether or not we are in that invincibility state as follows.

We will add another conditional block that evaluates whether isInvincible is true now. We can do something like this. Let's add a new variable. We actually should add it before conditional block. At the top, you are going to type in int damageRating. This would be akin to how much damage our character takes. Invincibility means you don't take any damage, so let's just make that our default. Let's just comment that our default. We will assign 0 to that when isInvincible == true. Else, we will not want it to represent a 0 damageRating when... Sorry, I should make that a capital R, We will want to not make 0 our damageRating when our invincibility is not true. Else, damageRating equals, arbitrarily, doesn't matter, 100 let's say. Here, we can... Let's not worry about making this code block anymore complicated, so we will just put in a little note to ourselves, a "To do" to put in a countdown timer conditional. If we get to the point where we want to eventually not be invincible forever, we get to the point where that timer reaches 0, it will then flip the isInvincible to false.

Let's just finish this off by seeing the output. Let's save that. We grabbed the Power Up. We are simulating the idea of grabbing the Power Up and then we become invincible. isInvincible becomes true and then that in turn, sets our damageRating to 0. We are going to pretend that we are no longer grabbing that Power Up. If you are no longer grabbing that Power Up, isInvincible will remain false and we expect this to execute this code block. Let's save that and see that output. There you go. We get a normal damageRating because we are not invincible anymore. See, false for invincible. All of that code can look a bit off putting, but there are a lot of ways that we cango about simplifying it and making it more readable. We can't do that yet without looking into concepts that we have not yet dealt with. For now, this is the simplest way to understand this logical branching behavior we will want to create in our game logic and get a glimpse of how we can handle states in our game.

We simulated a game state here by using bools and conditionals in tandem. One other quick thing I want to mention is, you may have noticed that we used all of these squiggly brackets for our if statements here. We have all these if and squiggly brackets. In our prototype game project for conditionals, if you remember going back to that, we didn't use the squiggly brackets always. Let me just chase that down and show you what I mean. Let me refresh your memory. Here at the cube controller script, right here, we have this movement conditional block. We didn't even use those squiggly brackets, those curly braces for those conditionals. How is that? Brackets are optional if you have just one line of code right after the evaluation such as we have here. Just a single line and then it continues on. Be aware if you do something like this, some other line. Just arbitrarily, let's just write in Move. x += Whatever. If you do this, that second line will not be apart of this if conditional evaluation. In other words, this will evaluate just like this. The second line will then be put on its own line. Its not any longer apart of this conditional block.

Just be aware of that if you do choose to use this for readability sake, which is really the only reason to do it. Just to make things more compact and readable. That's the basics of conditionals. Actually, the basics of if statements, there are other conditionals in C#. You have looping conditionals, which are similar to if statements in that we are evaluating a statement if it's true, and then it executes a code block in the immediate squiggly brackets right after. Same as if statements, but instead it loops back to the top and keeps executing until or unless something becomes false. Until that evaluation becomes false for example. The loops are not going to be that commonly used in Unity for us because we are dealing with Unity's game loop. Primarily through the Update() method, if you remember that illustration from a few videos back. Remember when we showed in that illustration how every frame, you have a loop occurring constantly naturally built-in to Unity.

If you have a loop conditional executing within that game loop, it will execute in full within the single frame, which is probably not the functionality you will picture from loops in a game. You are probably thinking while something is the case, do this over a successive frames. Sometimes it might be what you are going for, sometimes you want to iterate through a collection of variables, arrays and collections that we will look into a b it later for example. You will want to do that all within a single frame. In most cases, you will be thinking in terms of functionality looping over time. There is a way around this hitch with the Update() loop in Unity where loops occur on each frame and it's called, Co-Routines, which sound kind of fancy like a lot of these names, but it's not. It gives you this exact functionality where you can suspend an operation over frames and continue that loop. That's more a bit down the line toward the end of our video series. It is not at all necessary. We will be looking at loops at some point, but right now we will do a lot of stuff with our knowledge of if statements as we have done in the last couple of videos.

We also have another conditional called a Switch. If you are familiar with coding already, you will know is available to us. Is in a lot of ways simplified version of if statements but is a little less flexible. We might look at that down the line when it becomes more useful and illustrative with a certain context with coding up our games, but if statements are going to continue being our work courses for conditional coding in Unity.

All right, that's the basics of if statement conditionals, but there is a hidden issue with the code that we just wrote, that has to do with Variable Scope, so this will be the exact topic in our next set of videos and it will be a very interesting prelude to expanding on our simple understanding of classes and object-oriented programming, which brings us very close to unlocking the understanding required to deal well with the Unity API. Again, good work, good for you for following along and I will see you in the next set of videos. 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


Please login or register to add a comment