(This article was originally published at third-helix.com.)
Have you ever found yourself wishing a built-in Unity class had some functionality that isnâ€™t there? C# extension methods are the answer!
In this article, Iâ€™ll teach you how to use extension methods to add functionality to existing classes, no matter if theyâ€™re built-in Unity types, types defined in a third-party plugin, or even types defined in an Asset Store package which you could edit but youâ€™re (rightly) worried about later package updates stomping your â€śpatchâ€ť.
Seemingly obvious API omissions can be frustrating, but extension methods let you â€śfixâ€ť just about any API to your liking.
Imagine you need a way to set the layer of a GameObject and all its children, but thereâ€™s no GameObject.SetLayerRecursively() available. You could embed a loop in your code:
This will work fine, although itâ€™s not the cleanest thing in the world, and youâ€™ll need to copy these lines of code around to every place where you want to do this operation. It would be better to encapsulate that code in a function, and make that function available to everyone via a â€śhelperâ€ť class:
This works fine too, but it can be easy to forget to use the helper class to invoke a function that feels like it belongs in GameObject itself. Wouldnâ€™t it be nicer if you could just do this?
As it turns out, C# lets you make this happen!
Extension methods are declared just like regular functions, except that a) they must be static, b) they must be declared inside a non-generic, non-nested, static class, and c) they include a special syntax for their first argument, which is a reference to the calling object:
Though declared as static, this is invoked as if it were an instance method:
Note that when we call the method we actually omit the first argument and skip straight to the second. Take another look at the method declaration above. See how the first argument is declared using the â€śthisâ€ť keyword? Thatâ€™s what tells the compiler to infer that argument as the calling object; in this case, myGameObject.
Thatâ€™s actually all there is to it. Extension methods are easy!
For what itâ€™s worth, I like to organize my extension methods into classes named ClassNameExtensions. So I have GameObjectExtensions, TransformExtensions, ColorExtensions, and so on. Thereâ€™s nothing that says you have to do this; I just like the organization. You could pack them all together into a single Extensions class if you prefer, or any other kind of organization you want. Just remember that extensions methods must be declared inside a non-generic, non-nested, static class; the compiler will complain otherwise.
Extension methods can add to an existing class, but they cannot override existing methods. For example, if you declared this:
â€¦the compiler would basically ignore you. The rule for multiple method declarations using the same signature is: instance methods always take precedence over extension methods.
To extend a type, youâ€™ll need make sure itâ€™s in scope with the â€śusingâ€ť directive. If youâ€™re extending any built-in Unity type, youâ€™re covered by virtue of the â€śusing UnityEngineâ€ť thatâ€™s a standard entry in most Unity scripts. If youâ€™re extending an editor type, youâ€™ll need to add â€śusing UnityEditorâ€ť, just like you would if you were calling that type. If youâ€™re extending a type from a third-party plugin, you may need to import a namespace; check the pluginâ€™s documentation (or source code, if you have it) for details.
Iâ€™ve already mentioned that extension methods must be declared inside a non-generic, non-nested, static class, which means you canâ€™t just drop them in willy-nilly wherever you want. In practice, this â€ślimitationâ€ť turns out to be a useful organizing device. You can certainly argue that this is virtually identical to the â€śhelper classâ€ť example at the top of this article, and in terms of implementation effort thatâ€™s probably true; the difference is that with extension methods you get a cleaner, more normalized calling syntax. This really comes down to personal preference.
For the rest of this article, Iâ€™ll share some useful extension methods Iâ€™ve written over the past few months. Feel free to incorporate these into your own codebase and modify them at-will. (But donâ€™t just copy-paste them into a text file and try to sell it on the Asset Store; that would make you a horrible person.)
I use the excellent 2D Toolkit for UI, and I use a two-camera setup: one camera for the scene, one camera for the UI. In order to make the UI camera render only UI objects, all the UI objects need to be on a UI layer. When I create UI objects from script I need to set that layer, and often Iâ€™m creating objects with children (like a button with a child sprite and a child text label).
Itâ€™d be nice to have a way to set the layer for this entire hierarchy with a single function call (youâ€™ll recognize this as the example at the top of this article). Hereâ€™s what the call looks like:
And hereâ€™s that extension method:
While weâ€™re doing things recursively, wouldnâ€™t it be nice if we could enable/disable just the renderers, or just the colliders, for an entire hierarchy? This can be useful for UI, but it can also be useful in the scene. Imagine a complex hierarchy that defines a really fancy animated force field, and a game mechanic whereby you can switch your avatarâ€™s polarity, allowing passage through force fields of a particular color. When you switch polarity, youâ€™d loop through the matching force fields and disable their colliders, like this:
Hereâ€™s that extension method:
And the same principle applies for renderers:
Itâ€™s easy to search for child components using GameObject.GetComponentsInChildren(), but what if you have a have hierarchy in which you have lots of instances of a type, and you only want those instances which have a particular tag? In my case, I had a compound object with numerous renderers, and I needed to drive a material color on a subset of those renderers tagged as â€śShieldâ€ť.
This proved convenient:
Hereâ€™s that extension method:
I noted earlier that extension methods must be declared inside non-generic classes. That doesnâ€™t mean the extension method itself canâ€™t be generic, however! When we call this method we replace T with the type weâ€™re interested in â€” in the preceding call example, it was Renderer â€” and that type is used for each occurrence of T in the method implementation. The â€śwhereâ€ť keyword specifies that T must be of type Component or a type derived from Component (the compiler will throw an error otherwise).
See this MSDN article for more information about generics.
Itâ€™s all well and good to get components in children, but sometimes you need to search up. A common case I run into is when figuring out what to do with a collision result. I have a Player type, and its hierarchy is made up of several GameObjects which represent visuals, colliders, equipped items, and so on. Typically when I get a collision result on a player, the collider is bound to a child GameObject, so I canâ€™t just do GetComponent
So now I do this:
Hereâ€™s that extension method:
Just like Unity has both GameObject.GetComponentInChildren (singular) and GameObject.GetComponentsInChildren (plural), I also created a version that gets all components in parents:
Note: it would be trivial to create a GetComponentsInParentsWithTag, but I havenâ€™t run into a need for it yet. If youâ€™d like to exercise your newfound knowledge of extension methods, this might be a good exercise.
Hereâ€™s one whose omission is particularly perplexing. You can get the layer a GameObject is on, which is useful for both rendering and collision purposes, but thereâ€™s no easy way to figure out the set of layers that GameObject can collide against.
I ran into this when implementing weapons. Projectile-based weapons are simple: they get a Rigidbody and a Collider of some sort, and the collision system handles everything for me. But a rail gun-like weapon is a different story: thereâ€™s no Rigidbody, just a script-invoked raytest. You can pass a collision mask â€” a bitfield â€” into a raytest, but what if you want the collision mask to be based on the weaponâ€™s layer? Itâ€™d be nice to set some weapons to â€śTeam1â€ť and others to â€śTeam2â€ť, perhaps, and also to ensure your code doesnâ€™t break if you change the collision matrix in the projectâ€™s Physics Settings.
Really, I wanted to just do this:
That raycast will only hit objects which the calling weapon is allowed to collide with, based on its layer and the projectâ€™s collision matrix.
Hereâ€™s that extension method:
Note the optional â€ślayerâ€ť argument. If omitted, it uses the layer of the calling GameObject, which is the most common/intuitive case (for me, at least). But you can specify a layer and itâ€™ll hand you the collision mask for that layer instead.
I often find myself wanting to modulate the alpha value of a color without changing the color itself, for blinking/pulsing effects. Because Color is a struct, and structs in C# are immutable, you canâ€™t simply assign color.a; youâ€™ll get a compiler error. Fortunately, extension methods can extend structs as well as classes:
This method makes modulating a colorâ€™s alpha clean and simple:
There really arenâ€™t any. Extension methods are a compile-time device; once you reach runtime, they look and act just like any other method call. So it doesnâ€™t matter whether you write an extension method or an explicit helper class; as long as the guts of the method are identical, both implementations should perform identically. You could theoretically squeeze a vanishingly tiny bit of performance out of simply inlining all the code, avoiding the overhead of any function call at all, but in this day and age thatâ€™s completely pointless to worry about unless youâ€™re calling the function millions of times.
Extension methods are mainly useful as a way of cleaning up and normalizing your code. They have little or no effect on the behavior of that code.
I hope this article has been clear and useful. Extension methods are one of my favorite features of C#, because Iâ€™m a bit obsessive about having clean, easy-to-read code and they can really help make that happen. Of course, thereâ€™s more than one way to skin a cat, and Iâ€™m by no means suggesting that extension methods are the right or only way to do things. You can certainly argue that making an explicit helper class containing regular static functions â€” like GameObjectHelper.SetActiveRecursively() in the example at the top of this article â€” is just as good as an extension method-based implementation of the same; theyâ€™re six of one, half-dozen of another. I prefer the extension method approach because it feels like a natural and intuitive API extension, rather than a â€śbolt-onâ€ť, but thatâ€™s strictly a matter of personal preference.
Like every coding practice, extension methods are just one tool in the toolbox. But I encourage you to give them a shot!
(Josh Sutphin is an indie game developer, former lead designer ofÂ StarhawkÂ (PS3), and creator of the Ludum Dare-winning RTS/tower-defense hybridÂ Fail-Deadly. He blogs atÂ third-helix.comÂ and tweets nonsense atÂ @invicticide.)