It is possible to pass an entire method as a value to the attribute of another class?

I’m developing a simple game where I have two classes called Player and PowerUp.
The Player class has some public methods for letting the instances of the class PowerUp to activate the power ups like the speed boost and a triple shot. Here are the methods, plus the coroutines, from the Player class.

    /// <summary>
    /// Method for activate the TripleShot
    /// </summary>
    public void ActivateTripleShot()
    {
        StartCoroutine(TripleShot());
    }

    /// <summary>
    /// Method for activate the speed boost.
    /// </summary>
    public void ActivateSpeedBoost()
    {
        StartCoroutine(SpeedBoost());
    }

    /// <summary>
    /// Coroutine for enabling the triple shoot.
    /// </summary>
    /// <returns></returns>
    private IEnumerator TripleShot()
    {
        #if UNITY_EDITOR
        Debug.Log("Player: Triple Shot activated");
        #endif
        //Activate the triple shot.
        _isTripleShotEnabled = true;

        yield return new WaitForSeconds(10.0f);

        #if UNITY_EDITOR
        Debug.Log("Player: Triple Shot deactivated");
        #endif
        //Disable it.
        _isTripleShotEnabled = false;
    }

    /// <summary>
    /// Coroutine for activate the speed boost.
    /// </summary>
    /// <returns></returns>
    private IEnumerator SpeedBoost()
    {
        _speed *= 2; //Multiply the speed by 2.

        yield return new WaitForSeconds(10.0f);

        _speed /= 2; //Divide the speed by 2.
    }

The PowerUp will activate the power up only when the player collides with the instance of the class.
Here is the code of the PowerUp class

using UnityEngine;
[RequireComponent(typeof(SpriteRenderer),typeof(BoxCollider2D))]
public class PowerUp : MonoBehaviour
{
    /// <summary>
    /// Enumerator that tells the name of the power Ups
    /// </summary>
    private enum PowerUpTypes { TripleShot, SpeedBoost, Shield }

    /// <summary>
    /// The power type to assign.
    /// </summary>
    [SerializeField]
    private PowerUpTypes _powerUpType;

    /// <summary>
    /// Speed movement.
    /// </summary>
    [SerializeField]
    private float _speed = 5.5f;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.GetComponent<Player>())
        {
#if UNITY_EDITOR
            Debug.Log("PowerUP: Powering Up Player");
#endif

            Player player = other.GetComponent<Player>();

            //Find the right power up.
            if(_powerUpType == PowerUpTypes.TripleShot)
            {
                player.ActivateTripleShot();
            }
            else if(_powerUpType == PowerUpTypes.SpeedBoost)
            {
                player.ActivateSpeedBoost();
            }
            else if(_powerUpType == PowerUpTypes.Shield)
            {
                //To-DO    
            }

            //I want to call the method assigned to the power up instead.

            //Destroy this gameObject.
            Destroy(this.gameObject);
        }
    }
}

As you can see I had to declare an Enumerator for specify the type of power up to execute. This works fine but if I have 100 power ups I have to write 99 else-if which to me isn’t an efficient way to write the class behavior. So coming back to my question is this. It is possible to pass an entire method as a value for an attribute/variable of the class? Basically I want to declare an attribute/variable that stores the method to call so when the Player collides with the Power up it calls the method stored, similar on how you can do with Buttons by passing the object and then specify the function to call.

It is possible to do this?

I really don’t believe this is the way to go.

Instead, you should simply have a base class for your power ups and specialized classes for each power up. This way, you won’t need to modify the Power up class when you want a new power up, just implement a new class with the behaviour you want. (Following code untested)

using UnityEngine;
[RequireComponent(typeof(SpriteRenderer),typeof(BoxCollider2D))]
public abstract class PowerUp : MonoBehaviour
{
    /// <summary>
    /// Speed movement.
    /// </summary>
    [SerializeField]
    private float _speed = 5.5f;

    private void OnTriggerEnter2D(Collider2D other)
    {
        Player player = other.GetComponent<Player>();
        if (player != null)
        {
#if UNITY_EDITOR
            Debug.Log("PowerUP: Powering Up Player");
#endif

            PowerUpPlayer( player );
            Destroy(this.gameObject);
        }
    }

    protected abstract PowerUpPlayer( Player player );
}

// TripleShotPowerUp.cs
using UnityEngine;
public class TripleShotPowerUp : PowerUp
{
    protected override PowerUpPlayer( Player player )
    {
        player.ActivateTripleShot();
    }
}

// SpeedBoostPowerUp.cs
using UnityEngine;
public class SpeedBoostPowerUp : PowerUp
{
    protected override PowerUpPlayer( Player player )
    {
        player.ActivateSpeedBoost();
    }
}

If you really, really, really want to keep it your way, use a Dictionary. (Following code untested)

using UnityEngine;
using System.Collections.Generic;
 [RequireComponent(typeof(SpriteRenderer),typeof(BoxCollider2D))]
 public class PowerUp : MonoBehaviour
 {
     /// <summary>
     /// Enumerator that tells the name of the power Ups
     /// </summary>
     private enum PowerUpTypes { TripleShot, SpeedBoost, Shield }
 
     /// <summary>
     /// The power type to assign.
     /// </summary>
     [SerializeField]
     private PowerUpTypes _powerUpType;
 
     /// <summary>
     /// Speed movement.
     /// </summary>
     [SerializeField]
     private float _speed = 5.5f;

     private Dictionary<PowerUpTypes, System.Action<Player>> actions = new Dictionary<PowerUpTypes, System.Action<Player>>()
     {
         {TripleShot, p => p.ActivateTripleShot()},
         {SpeedBoost, p => p.ActivateSpeedBoost()},
         // ...
     }
 
     private void OnTriggerEnter2D(Collider2D other)
     {
         Player player = other.GetComponent<Player>();
        if (player != null)
        {
#if UNITY_EDITOR
            Debug.Log("PowerUP: Powering Up Player");
#endif
 
             actions[_powerUpType](player);
             Destroy(this.gameObject);
         }
     }
 }

Hi @Hellium sorry if I didn’t answer to you in the same day but thanks for sharing your ideas.
The use of a base class for power ups is something that I saw from another project made by another developer, which is indeed a good solution, while the use of Dictionary I think is good and I never thought the use of a Dictionary since I’m a beginner in Unity.
In the end I believe both solutions are very good.

Have a nice day.