C# Extension Methods

Time is one of the biggest obstacles to creating games. We spend a lot of time writing code and debugging that code. And it’s not uncommon to find ourselves writing the same code over and over which is tedious and worse it’s error-prone. The less code you have to write and the cleaner that code is the faster you can finish your game!

Extension methods can help you do just that - write less code and cleaner code with fewer bugs. Which again means you can finish your game faster.

Extension methods allow us to directly operate on an instance rather than needing to pass that instance into a method and maybe best of all we can do this with types that we don’t have access to, such as the many of the built-in types in Unity or maybe a type from an asset from the Asset Store. As the name suggests, extension methods allow us to extend and add functionality to any class or struct.

Automatic Conversion isn’t built in

Automatic Conversion isn’t built in

As a side note, in my opinion, learning game development is all about adding tools to your toolbox and extension methods should be one of those tools. So let’s take a look at how they work and why they are better than some other solutions.

Concrete Example

Local function to do the conversion

Local function to do the conversion

In a past project, I needed to arrange gameObjects on a grid. The grid lattice was 1 by 1 and set on integer values. The problem, or in reality, the pain point comes from positions in Unity being a Vector3 which is made of 3 floats, not 3 integers.

There is a type Vector3Int and I used that struct to store the position of the objects.

But!

A static helper class with a static function is better, but not the best

A static helper class with a static function is better, but not the best

Casting from Vector3 to Vector3Int isn’t built into Unity (the other direction is!). And sure, you could create a conversion operator, but that’s the topic of another post.

Helper Class Call

Helper Class Call

So, when faced with this inconvenience, my first thought, of course, was to write a function that takes in a Vector3, rounds each component and returns a Vector3Int. This works perfectly fine, but that method is inside a particular class which means if I need to do the conversion somewhere else I need to copy the function into that second class. This means I’m duplicating code which generally isn’t a good practice.

Extension method!!!

Extension method!!!

Ok, fine. The next step is to move the function into a static helper class. I do this type of thing all the time. It’s really helpful. But the result is more code than we need. It’s not A LOT more, but still, it’s more than we need.

If this was my own custom class or struc, I’d just add a public function that could handle the conversion, but I don’t have access to the Vector3 struct. Yet, I have some needed functionality that will be used repeatedly AND I want to type as little as possible while maintaining the readability of the code.

And this situation? This is exactly where extension functions shine!

Extension Method Call

Extension Method Call

To turn our static function into an extension method, all we need to do is add the keyword “this” to the first input parameter of the static function. And then we can call the extension method as if it was part of the struct. Pretty easy and pretty handy.

Important Notes

It’s important to note that with extension functions the type that you are extending needs to be the first input parameter in the function. Also, our static extension method needs to be inside a static class. Miss one of these steps and it won’t work correctly.

More Examples

So let’s look at some more examples of what you could do with extension methods. These of course are highly dependent on your game and what you need to do, but maybe these will spark some ideas and creativity.

Need to swap the Y and Z values of a Vector3. No problem!

Swap Y Z.png
Swap Y Z Call.png

Maybe you need to set the alpha of a sprite in a sprite renderer. Yep. We can do that.

Reset a transform? Locally? Globally? Piece of cake.

Transform Reset.png
Transform Reset Call.png

Extension methods also work with inheritance. For example, most Unity UGUI components inherit from UnityEngine.UI.Graphic which contains the color information. So once again it would be easy to create an extension method to change the alpha for nearly every UGUI element.

Graphic Set Alpha Call.png

Now taking another step down the tunnel of abstraction extension methods also work with generics. If you are scared of generics or have no idea what I’m talking about check out my earlier video on the topic.

Either way, let’s imagine you have a list and you want every other element in that list (or some other sorting). One way, and of course not the only way, to do that filtering would be with a generic extension method like so.

Generic Extension Method.png
Generic Extension Method Call.png

That’s it! They’re pretty simple and easy to use, but I’d argue they provide another tool to write simple, cleaner, and more readable code.