C# Extension Methods in Unity

we will be creating some extension methods of some classes and we will also be looking at some useful uses of extension methods in Unity.

Extension methods in C# are the methods that let you extend the functionality of any class either you own it or not. This means even if you don't own a class you can add a public method to the class that can be used by others. So, in this blog, we will be creating some extension methods of some classes and we will also be looking at some useful uses of extension methods in Unity.

So first of all how do we create an extension method? For that we will first have to create a static class with any name, let's say we create a class named Extension for now which should look like this:

using UnityEngine;
using UnityEngine.UI;

namespace ExtensionMethods
{
    public static class Extension 
    {
     //Do something cool   
    }
}
An empty extension class

Now let's say you wanna apply a fade to a UI image object whenever the object is highlighted and get back to its original state once the highlight is over. In order to do that we can do this:

namespace ExtensionMethods
{
    public class Extension : MonoBehaviour , IPointerEnterHandler , IPointerExitHandler
    {
        void Fade(Image img , float value)
        {
            Color col = img.color;
            col.a = value;
            img.color = col;
        }
        
        public void OnPointerEnter(PointerEventData eventData)
        {
            Fade(eventData.pointerEnter.gameObject.GetComponent<Image>(),0.3f);
        }
        

        public void OnPointerExit(PointerEventData eventData)
        {
            Fade(eventData.pointerEnter.gameObject.GetComponent<Image>(),1f);
        }
    }
}
Fade of an image example

In this script, you can see that all we are doing is we are implementing the IPointerEnterHandler and IPointerExitHandler to get the actions when a user highlights over an object and when the highlight is exited. You can also see a function Fade() where we take Image img and float value as parameters, then we create a new Color object col where the img's colour is assigned and we change the alpha value of the colour to our value parameter. And lastly, we assign the final colour value to our image's current colour value that provides us with some kind of float.

As you can see it works perfectly fine, but wouldn't it be cooler and cleaner to use the fade method you created up there as if it's a built-in function of the image class? You could just directly do myImage.Fade(somevalue) instead of passing the image as a parameter. In order to do that we will create a separate class for the image and call it GameImage.cs.

 public class GameImage: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
   public void OnPointerEnter(PointerEventData eventData) {
     eventData.pointerEnter.gameObject.GetComponent <Image> ();
   }

   public void OnPointerExit(PointerEventData eventData) {
     eventData.pointerEnter.gameObject.GetComponent <Image>();
   }
 }
GameImage.cs after splitting

Here, as you can see I have separated the Highlight handling part of the system from our previous script and created a new GameImage.cs script that is assigned to every object you want to highlight on mouse hover. For now, the fade part won't work as we haven't implemented it up there. So now in the Extension.cs class we will be making the class static and creating a static method which should look like this:

namespace ExtensionMethods
{
    public static class Extension
    {
        public static void Fade(this Image img , float value)
        {
            Color col = img.color;
            col.a = value;
            img.color = col;
        }
        
    }
}
Extension.cs after splitting

In this class, we have made the class static and created a static void Fade which takes the current instance of our Image class and a float value that is the fade amount we want. Basically, anything we put after this keyword here is the class you want to extend. For example, you can change the Image to some other class like Gameobject or even Transform . So after doing this we can implement it in our GameButton.cs which looks like this:

 public class GameImage: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
   public void OnPointerEnter(PointerEventData eventData) {
     eventData.pointerEnter.gameObject.GetComponent < Image > ().Fade(0.1 f);
   }

   public void OnPointerExit(PointerEventData eventData) {
     eventData.pointerEnter.gameObject.GetComponent < Image > ().Fade(1 f);
   }
 }

Now as you can see we can directly call .Fade() to our image as if it is a part of the Image class. This thing can come in handy while you are working with large scaled projects where redundant code is dangerous. For example, you might have 14 different classes that use this Fade function, it would be very redundant and too much repetitive work if you had to write or even copy the Fade function in every class.

Some of the very useful and helpful extensions that helped me a lot are below:

An extension that helps randomize a list :

public static T GetRandomItem<T>(this IList<T> myList)
{
    return myList[Random.Range(0, myList.Count)];
}
An extension to get a random item out of a list
public static T GetJsonFromPrefs < T > (this PlayerPrefs prefs, string key) {
  return JsonUtility.FromJson < T > (PlayerPrefs.GetString(key));
}
Extension to directly get a deserialized object out of a prefs
public static void ResetTransformation(this Transform transform)
{
    transform.position = Vector3.zero;
    transform.localRotation = Quaternion.identity;
    transform.localScale = Vector3.one;
}
Extension of a transform to reset a transform's position to default