Imagine the following case: You’re building your awesome FPS game using UE4 and you’ve built a handgun, an assault rifle and a knife. Now, you want to give the players the ability to equip each weapon by pressing a specific key (let’s say button 1 is the bound input for the handgun equip functionality, button 2 is for the assault rifle and so on). That’s easy, right? I will just implement the following logic and bind it to my inputs:

In order to specify my inputs and hook up the corresponding bindings and logic I will just follow the related post from the official UE4 documentation. When you complete the said tutorial, you may notice that in the binding phase of your game actions you can’t hook up a function with parameters, thus the implemented function for our weapon equipment has gone to waste.

A simple workaround to achieve the functionality we need, is to create three new functions, one for each weapon and use copy-paste to transfer our logic from the Equip function into our newly created functions (but modifying it a bit in order to work for one weapon at a time). After doing the above steps our code will end up like the following example:

When you find yourself copy and pasting your code logic, chances are there is a better way to implement the functionality you need without replicating bugs everywhere.

After declaring three new functions without parameters we can hook up our logic for our action bindings and be done with it. However, imagine that you’ve made a bug in the first version of your code (which was later copy-pasted into the three functions). This means that each time you find a bug you have to modify three version of the same code, isn’t that a same?

In this post, I will show you a better workaround to overcome the above situation using templates. This will be a lengthy tutorial, so grab your coffee and take a deep breath.

This post is divided into the following parts:

  1. Templates Explanation (non UE4 Project)
  2. Binding Inputs with parameters (UE4 Project)

So, let’s get started!

Understanding Templates

In object oriented programming, inheritance, overloading and interfaces provide a way to write flexible code. However, in some cases, this is not enough. Templates allow a function or a class to work with many different data types without the need to re-write the function.

Let’s say that we want to find the max number based on two integer inputs. To do that, we write the following code:

However, later on, we decide that we need to find the max number based on two double inputs. To do so, we overload the above function like so:

Later on, you may need to find the max between two different types which are not covered with the above blocks of code. Notice that in order to find the max between the given inputs, we execute exactly the same logic but with different types. That’s where templates come in!

Function templates provide a way to write a function without knowing the data types we need. You might be thinking, how is this possible? Well, everything will be clear in a bit!

In order to write a function template, we write the following code:

Let’s break down the above code in order to better understand what’s happening here!

In the first line, we declared that this is a template function, and inside the brackets (<>) we declared a typename of T. This means that we declared a variable, named T, of type “typename”. This means that we don’t know what is the type of T. It could be int, double or really anything you want it to be (please take into consideration the note at the end of this example).

Then, we declared a function which has a return type of T (again, we don’t know what is the type just yet) which takes two parameters of type T.

Having written the code above, the following lines are valid and will execute without any problem:

When you call a function template, the compiler will determine the data types based on what you provided. In the above example, the compiler can determine that 5 and 10 are integers, so the max(5,10) will return an int type. The same applies for the max(5.0,10.0), the compiler determines that 5.0 and 10.0 are double and will return a double type as a result.

Important note: So…does this mean that the max function can be executed with really anything? The answer is yes….and no. In order for the templated max function to work, the types we use as arguments must overload the > operator. Otherwise, the compiler will give you an error.

Binding Inputs with Parameters

Let’s recall for a moment the first example of this post. We have 3 weapons and we need to provide a function with parameters for our action inputs. To do so, create the following enum in order to determine what type of weapon our character will equip:

Then, inside your character’s header file, type in the following functions:

Switch to your character’s source file and type in the following implementation of the EquipWeapon:

Then, inside the SetupPlayerInputComponent, add the following logic:

And we’re done! Even though we have 3 different inputs, we handle them with the same function, but we change the input in every case!

Share postShare on Facebook3Tweet about this on TwitterShare on LinkedIn0Share on Reddit0