C# for Unity — Lesson #2: Programming Logic and Conditionals

March 02 2021

C#programmingUnityvirtual reality

In a program, we continuously ask questions and make decisions to adapt how the code manages the system's state and reacts to the player's actions. These questions and decisions must be structured so that the answers can be as simple as yes or no, true or false. Computers can only deal with binary information: zeroes and ones. Complex questions such as "What is the meaning of life" cannot be answered (at least not yet) by computers.

Due to this restriction on how computers make decisions, boolean types are fundamental as they are just that: true or false, yes or no.

bool logicRocks = true; // Declares a boolean variable and assigns true to it
bool giveUpCoding = false; // Declares a boolean variable and assigns false to it

Comparison Operators

Comparison operators are the way we ask questions about the state of your program:

  • Is the hand close to the grabable object?
  • Is the enemy holding a gun?

Much like Arithmetic Operators, Comparison Operators transform an expression into a value. However, while arithmetic expressions will output a number, boolean expressions (expressions with comparison operators) will output either true or false.

// Assigns true, as 3 is less than 10.65f.
bool answer = 3 < 10.65f;

// Assigns false, as -12 is not greater than 5.
answer = -12 > 5;

int health = 0;

// Assigns true, as health is less than or equal to 0;
answer = health <= 0;

// Assigns true, as 1 is greater than or equal to health;
answer = 1 >= health;

string weaponType = "Sword";

// Assigns false, as weaponType is not equal to "Mace"
answer = weaponType == "Mace";

// Assigns true, as true is different from false;
answer = (true != false);

Logical Operators

The questions we ask our program are often way too complicated. We need to split them into multiple smaller questions that together answer the initial one.

A common question could be:

Did the player attack hit the enemy?

And a possible split:

Is the enemy inside the attack area? AND is the enemy NOT being blocked?

Logical operators, also known as Boolean operators, are the way we group smaller questions together. What happens under the hood is: comparison operators (our smaller questions) output boolean values, which are used by the logical operators to output a new boolean value.

// AND &&: true only if both expressions evaluate to true. Otherwise, it will return false.
bool answer = true && false; // = false

// OR ||: true if at least one of the expressions evaluates to true. Otherwise, it will return false.
answer = true || false; // = true

// NOT !: Evaluates to the opposite value, true becomes false and false becomes true.
answer = !true; // = false

Truth Table

A truth table is a simple way to visualize the outcome of the logical operators:

learning c# for unity

Usage

Boolean expressions will make use of both logical and comparison operators, and multiple expressions can be chained together:

string attackType = "Blunt";
bool isBlocking = false;

bool attackHit = (0 < 10 && 100 > 10) &&
                               (!isBlocking || attackType == "Piercing");

Tip:
A statement only ends when it reaches a semicolon “;” so the last two lines of the previous snippet are a single statement and are only divided into multiple lines for the sake of readability.

This example is even more complicated than our starting example and will evaluate to true. But let’s go over how the program would solve this.

Like with arithmetic expressions, this is solved from left to right respecting the parentheses, so we start with the first block:

(0 < 10 && 100 > 10)

Evaluating the comparison operators we have:

(true && true)

As BOTH are true the expression evaluates to true, and substituting back in the initial expression we have:

true && (!isBlocking || attackType == "Piercing");

Now to the second block:

(!isBlocking || attackType == "Piercing")

Evaluating the NOT operator, and knowing isBlocking = false, we are left with:

(true || attackType == "Piercing")

Since we are dealing with an OR, we could stop this block evaluation right here (and C# does it), since as we already have a true value in the expression, this will resolve to true. But for the sake of teaching, let’s keep going!

Knowing attackType = "Blunt", we have:

(true || false)

As AT LEAST ONE value is true, this is indeed true, and now back at the initial expression, we are left with only:

(true && true)

Which leads to the final result: true.

It is important to know that in some cases, it is better to create some variables to hold parts of the expression for the sake of readability:

string attackType = "Blunt";
bool isBlocking = false;

bool isInsideAttackArea = 0 < 10 && 100 > 10;
bool canAttackHit = !isBlocking || attackType == "Piercing";

bool attackHit = isInsideAttackArea && canAttackHit;

Conditional Statements

So we are already able to answer some pretty dope questions, but what do we use it for? That's where conditional statements come in! They are used to make decisions on how to run the code, and these decisions are made based on our previous questions.

The order that computer programs execute a set of instructions is known as control flow. Conditional or selection statements can alter our program's flow, allowing us to skip entire blocks of code or just run specific ones.

If statements

The most used conditional statement by far is the if statement. An if statement executes a block of code if the specified condition is true.

float cooldown = 2.5f;
float remainingCooldown = -0.2f;

if (remainingCooldown <= 0)
{

// This code block will only execute if the condition is true
remainingCooldown = cooldown; // Reset cooldown

}

In this snippet, the program checks if the variable ‘remainingCooldown’ is less than or equal to 0. Since it is, the if block is executed, this, in turn, resets the ‘remainingCooldown’ value to the variable ‘cooldown’ value.

Usage

The boolean expression (question) that drives the if statement must be inside the parentheses.

Braces ( { } ) are used in C# to define blocks of code, so after the boolean expression of an if statement, you must add the block of code you want executed in case the boolean expression resolves to true.

Spaces, new lines, or tabs don’t change how the code is executed, but they definitely help the programmer understand what is happening in your code. Always indent the code inside the braces, so it is easily distinguishable from what is outside the block. The indentation size varies from one company to another, but a good rule of thumb is four spaces.

If .. Else

Now, what if we wanted to do something in case the remainingCooldown is greater than 0?

float cooldown = 2.5f;
float remainingCooldown = 0.2f;

if (remainingCooldown <= 0)
{
     // This code block will only execute if the condition is true
     remainingCooldown = cooldown; // Reset cooldown
}
else
{
     // This code block will only execute if the condition is false
     remainingCooldown -= 0.1f;
}

Just like in the previous example, we have an initial block that will execute if ‘remainingCooldown’ is less than or equal to 0. But now we also have an else block; This will be executed if the previous condition wasn’t met, and in this example is exactly what happens, as ‘remainingCooldown’ is greater than 0 this time.

Tip: ‘-=’ is a shorthand for ‘remainingCooldown = remainingCooldown - 0.1f’, every arithmetic operator has one of those: +=, *=, /=.

Usage

Declare an if statement just like before, and add the else statement and code block immediately after it.

Else If

Now, what if we wanted to change the object color when we were about to complete cooldown?

float cooldown = 2.5f;
float remainingCooldown = 0.2f;
string color = "white";

if (remainingCooldown <= 0)
{
// This code block will only execute if the condition (remainingCooldown <= 0) is true
remainingCooldown = cooldown; // Reset cooldown
}
else if (remainingCooldown <= 1)
{
// This code block will only execute if the condition (remainingCooldown <= 1) is true
color = "red";
remainingCooldown -= 0.1f;
}
else // Having an else block is optional
{
// This code block will only execute if all previous conditions are false
remainingCooldown -= 0.1f;
}

With else if statements, the code will go through the conditions for each statement, and execute the first that resolves to true, and if none does, execute the else block (which is optional).

In this example, remainingCooldown is greater than 0, but is less than or equal to 1, meaning the else if block will be executed, setting the color variable to “red”, and decreasing the remainingCooldown by 0.1f .

Usage

Each ‘else if’ statement declares its own condition and corresponding code block, following the same rules: boolean expression inside parentheses and code block defined through braces ( { } ).

You can have as many else if statements chained together as you want, just make sure to always declare the conditions and that they immediately follow one another, always starting with a plain if statement, and an optional closing else statement.

The if conditions are checked in order, so if we had remainingCooldown = -0.2f in the previous example, even though it would satisfy both the ‘if’ and ‘else if’ conditions, only the first if block would execute.

Switch statements

While we can have multiple else if statements, abusing it can get your code really messy and outright unreadable. A switch statement helps solve some problems that usually lead to multiple condition checks.

By evaluating a single expression, a switch statement chooses a code block to execute based on what condition matches the result of that expression.

float damage;
string difficulty = "hard";

switch (difficulty)
{

case "easy":
{

// execute if the value the variable difficulty is "easy"
damage = 1;
break;

}
case "medium":
{

// execute if the value the variable difficulty is "medium"
damage = 5;
break;

}
case "hard":
{

// execute if the value the variable difficulty is "hard"
damage = 10;
break;

}
default:
{
// execute if none of the cases are a match
damage = 5;
break;
}

}

In this example, the expression evaluated by the switch statement is the simple variable ‘difficulty’, it then tries to match the output value of that expression to each case defined, and if one is a match, the corresponding code block is executed.

If no case is matched, the default code block will run.

Usage

Start declaring the switch statement followed by the evaluated expression that will be matched to the cases. The evaluated expression must be inside parentheses.

After the evaluated expression, open a set of braces, inside them we will add every switch case.

We don’t declare a boolean expression for the switch cases, but rather only the target value that the expression should evaluate to execute this case. Make sure to end a case declaration with colons ( : ).

After the switch case declaration comes the code block executed for the corresponding case.

In the example we defined that block with braces, making it really clear what code will be executed for each case, but this is not obligatory, since the case syntax is enough for C# to delineate those blocks.

While braces are optional, the keyword break is not. A break statement will end the execution of that switch statement and return the program flow to the next statement after the switch block.

Every switch statement must include a default case, even if only with a single break statement.

Ternary Operators

A ternary operator is like a short version of an if .. else conditional, but the code executed for each outcome may only contain a single statement.

float distance = 1f;
string color = (distance < 2.35f) ? "yellow" : "white";

The previous snippet is an example of a way to create a hover feedback. The ternary operator starts evaluating the boolean expression (distance < 2.35f). and if it resolves to true, executes the statement before the colon (“yellow”), and executes the second statement (“white”) otherwise. In this case, the variable color would be set to “yellow”.

Usage

Start with a boolean expression (it’s a good practice to keep this inside parentheses, but is not mandatory).

After the boolean expression comes a question mark ( ? ) character followed by the first statement that will be executed if the boolean expression is true.

After the first statement add a colon ( : ) character followed by the second statement, which will be executed if the boolean expression resolves to false.

Finish it with a semicolon ( ; ) character.

Coming up next!

Next week we’ll take a look at Functions and Methods. Now that we know how to control the flow of execution, it’s time to see how to better organize and reuse our code!

Happy coding 🙂

🔙  Back to the Learn C# for Unity menu

WRITTEN BY

Arthur Ribeiro / Dejan Gajsek

Circuit Stream Instructor

Receive our newsletter to stay on top of the latest virtual reality and augmented reality info.