C# for Unity — Lesson #3: Functions and Methods

March 10 2021

C#programmingUnityvirtual reality

While making a cake, you need to create the batter, the filling, and the icing. You can explain how to make them all in a single text, but that will definitely become messy. Instead, it’s common to separate each part in its own section and later explain how to merge them all together.

Now let’s say you have a different cake built the same way, only changing the icing. By having those sections separated, you can easily reuse the batter and filling sections and only add the new icing piece.

Similarly, in programming, those are precisely the main usages for methods: Code reuse and Organization.

Methods are a named set of instructions that can be invoked throughout your application, thus making it reusable and organized, as you won’t have to go through all instructions in the method to understand what it does; its name will tell you.

Conceptually, Functions and Methods are slightly different things, but they are frequently used interchangeably. For the sake of simplicity, let's assume they are the same thing for now.

Calling a Method

Calling a method is pretty straightforward, and you have actually seen it done before. Recall the example we used on the Advanced Math topic in Chapter 1:

float myFloatA = Mathf.Sqrt(9.0f); // Assigns 3.0f to myFloatB;

float myFloatB = Mathf.Abs(-3); // Assigns 3.0f to myFloatA;

Sqrt and Abs are methods being called. The anatomy of a method is usually like this:

OwnerOfTheMethod.NameOfTheMethod(ParametersOfTheMethod);

The method's owner is usually a class or an instance of a class (More on that in later chapters), and a method can have as many parameters (sometimes called arguments) as it needs, including no arguments at all.

Some more examples of methods:

// This will print a message on your Unity console.
Debug.Log("Use this to help debugging your project");

// This will move your unity gameObject in space
// Uses 3 parameters that should be separated by a comma ","
float zVelocity = 1.0f;
transform.Translate(0, 0.3f, zVelocity);

// This will unparent all children of the gameObject
// Notice how no parameters are passed
transform.DetachChildren();

Method Output

If you look at the Sqrt and Abs calls again, you will notice that we assign the call result to the variables myFloatA and myFloatB. Like a math function, methods can take values as input and return an output.

Not all methods return a value, much like not all methods need parameters (input). Usually, a method without an output has internal side effects, like when we call Debug.Log, we don’t want any value back. We want the effect of having something written on the console.

Some more examples of methods with output:

// Gets a reference to the Transform component in a child of that object
// More on what are these references later 🙂
Transform child = transform.GetChild(1);

// Gets a reference to the a child Transform component that is called “Gun”
Transform gunTransform = transform.Find(“Gun”);

Declaring a Method

So far, we’ve been calling only prebuilt methods from the Unity Engine, but to create a game, you will need a lot of custom methods. Methods mostly follow this structure:

AccessModifier DataType MethodName(Parameters)
{
// method instructions
}

The access Modifier will be covered in depth later. For now, let’s just use “public”, meaning everyone can use it.

Data Types were covered in Lesson 1, but you will need to learn one extra: void. It means no data, and we will use it when the method has no output.

The MethodName follows the same rules as variable names, but in programming, in general, it is common to follow a Code Style Guide. For C#, methods are written in PascalCase, meaning the name starts with an uppercase letter, and each word following begins with an uppercase as well.

The body of your method goes inside the curly braces “{ }”. Every time the method is called, the instructions on the body will be executed, following the control flow inside of it.

Declaration Example:

// Method declaration
public void NewMethodName()
{
          Debug.Log("The new method was just called!");
}

// Calls your method
OwnerOfTheMethod.NewMethodName();

Parameters

Remember how methods can take input? It does so through parameters or arguments as we’ve already seen before:

float zVelocity = 1.0f;
transform.Translate(0, 0.3f, zVelocity);

The method Translate is being called using 3 parameters: 0, 0.3, and 1.0 (As zVelocity currently holds that value).

When defining a method, we don’t know what values will be provided when it is called somewhere else on the code. However, we do now what we intend to do with them and what kind of data we will deal with (Data Types).

Defining a parameter is like defining a variable, you give it a Data Type and a name, and you are done, that new variable can be used in your new method.

public void DamagePlayer(int damageDone)
{
          // Method logic here
          Debug.Log($"Player took {damageDone} damage");
}

This example declares a method with one argument, an “int damageDone” variable, which is later used within the method in the Debug.Log method call.

public void DamagePlayer(int damageDone, string reason)
{
          // Method logic here
          Debug.Log($"Player took {damageDone} damage, due to {reason}");
}

In this example, we see a method with multiple parameters. A comma must separate each parameter; much like when you call a method with various parameters, a comma should separate each value.

DamagePlayer(2, "Knife hits the Head");

Calling that method like this, would set damageDone to 2 and reason to “Knife hits the Head”.

The parameters declared in a method can only be used inside the body of that same method. The same goes for variables declared inside the method, which is delimited by the curly braces “{ }”.

public void DamagePlayer(int damageDone)
{
         // Method logic here
         Debug.Log($"Player took {damageDone} damage");
}

Debug.Log($"Player took {damageDone} damage");

Doing something like this would raise this error in the Unity console: “error CS0103: The name 'damageDone' does not exist in the current context“.

This error is related to the scope of variables, a concept we will discuss later as we need to develop some other concepts beforehand. For now, know that you can only use a method argument inside its function.

Output

Now that we have covered input, the only thing remaining is the output. How can we return the results of whatever logic and calculations performed by the method?

Like with the input, we don’t know beforehand the results that the method will produce, but we know what kind of output we are expecting, that is, the Data Type of the result.

Apart from defining the Data Type of the output, a method must also define what is the output during its execution. That is done using a special statement “return”:

// Linear interpolation (lerp)
public float Lerp(float firstFloat, float secondFloat, float progress)
{
         float lerpResult = firstFloat * (1 - progress) + secondFloat * progress;
        return lerpResult;
}

In the example above we start by defining the return type with: “public float Lerp …”. Previously all our methods had no output because they were all using a void return type.

Next, we have the return statement: “return lerpResult;”, which will get the value currently on the lerpResult variable and output this wherever the method was called. You don’t need to always return a variable, the following is also possible:

public float Lerp(float firstFloat, float secondFloat, float progress)
{
          return firstFloat * (1 - progress) + secondFloat * progress;
}

The return keyword will immediately stop the execution of the method, and return the provided value back to where it was called.

public bool IsNumberEven(int number)
{
     If (number % 2 == 0)
     {
     return true;
     }

     return false;
}

public void Log(string message, int severity)
{
      if (severity < 2)
      {
          return;
     }

     Debug.Log(message);
}

On the first method InNumberEven, if the provided parameter is even, the program execution will reach the statement “return true;”, and then immediately stop the execution of this method and return the value “true” to whoever called it. In this scenario, the statement “return false;” wouldn’t be executed.

Since the method has a void return type, the return statement is used without any return value, but it is still useful when you want to halt a method's execution.

Let’s summarize: A method declaration needs an access modifier, return type, method name, parameters, a method body, and possibly a return statement inside the method body.

Method Overloading

You might have come across this already, but some methods can be called in multiple ways.

// Creates a message on the Unity Console
Debug.Log("Hey Listen!");

// Creates a message on the Unity Console, that when clicked highlights the object that sent it in the hierarchy window
Debug.Log("Things are on fire yo!", gameObject);

This is called method overloading. Each different “version” or overload share the same name, but differ in the number of parameters or their Data Types. Overloading is really useful if you want a different behaviour depending on the input, or just to simplify its usage.

Coming up next!
Next week we’ll take a look at Arrays and Loops. Now that we know how to organize and reuse our code, it’s time to understand how to process a large number of elements.

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.