Component Based Ability Part 2 : Reusable Components

From what I’ve shown up until now, I could just make do with a single Execute function and put all logic in there. This however, would not be ideal. Lets think about all the commonalities that different abilities might have.

An ability might have some sort of cooldown phase. We wouldn’t want the player to spam a powerful ability like fireball indefinitely. This cooldown component might have different variables that a designer might want control over like cooldown time, cooldown duration etc. There would also be a Boolean that the ability could check to see if it can be cast.

A cooldown component might look something like this. (NOTE: This is done in unity so I make use of MonoBehavior for functionality like Start and Update)

public class Cooldown : MonoBehaviour {

    public float CoolDown { get { return coolDownTime; } set { coolDownTime = value; } }
    public bool IsOnCoolDown { get { return isOnCoolDown; } set { isOnCoolDown = value; } }

    [SerializeField]
    private float coolDownTime = 0.0f;
    private bool isOnCoolDown = false;

    private float currentTime;

    private void Update()
    {
        if (!IsOnCoolDown)
        {
            currentTime = 0.0f;
        }
        else
        {
            if (currentTime < CoolDown)
            {
                currentTime += Time.deltaTime;
            }
            else
            {
                Debug.Log("cooldown complete");
                IsOnCoolDown = false;
            }
        }
    }
}

Another common component different abilities might have is an effect that fires when the ability is cast. E.g. When casting an ability like GravityWell which, as the name suggests, spawns a gravity well that pulls nearby players towards its center, you might want a visual representation of the Well in the level that the players can see. Or for an ability like Fireball there would probably need to be an explosion effect when it connects with a player.

The component might look something like this (Again, this code is written in Unity)

public class SkillEffect : MonoBehaviour
{
    [SerializeField]
    GameObject effectPrefab;

    [SerializeField]
    Ability owningAbility;

	public void PlayEffect()
    {
        if(effectPrefab != null)
        {
            effect = Instantiate(effectPrefab, transform);
            effect.transform.position = owningAbility.Owner.transform.position;

            effect.GetComponent<ParticleSystem>().Play();

            StopAllCoroutines();
            StartCoroutine(PlayAndStop(3.0f));
        }
    }

    IEnumerator PlayAndStop(float i_time)
    {
        yield return new WaitForSeconds(i_time);

        StopEffect();

        yield break;
    }

    public void StopEffect()
    {
        if (effect != null)
        {
            effect.GetComponent<ParticleSystem>().Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
            Destroy(effect);
            effect = null;
        }
    }

    private GameObject effect;
}

Here the effectPrefab represents the particle effect that needs to be instantiated and effect represents an instance of that particle effect. I also make use of Unity’s built in feature of Coroutines to automatically stop the effect after a set amount of time (usually when the ability has finished firing)

Along these lines there are quite a few components you could come up with for your ability system (I’ve only demonstrated 2 out of the 8 I use for my system). You just need to keep in mind for what parts of an ability will it make logical sense to create a component that can then be shared among different abilities.

In the next blog update I will demonstrate how I use my components for two of the abilities in my game namely Detonate and Teleport.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s