I'm making an RPG and got to the point where I want a player to be able to use abilities. I decided to use a command pattern to keep keybindings flexible and now I've arrived with the following dilemma:
Command is an abstract class with an abstract method called Execute(). Every ability has a command class (for example FireBallCommand). I have a PlayerInput class. All buttons and the abilities that belong to it are defined there:
public class PlayerInput : MonoBehaviour {
private Command buttonF;
private Command buttonQ;
private PlayableCharacter character;
void Awake () {
character = GetComponent<PlayableCharacter>();
Initialize();
}
void Initialize()
{
//Setup controls here
//TODO: Get user's saved controls from db
//Temporarily hardcoded
buttonF = new BasicAttackCommand();
buttonQ = new FireBallCommand();
}
void Update () {
if (Input.GetKeyDown(KeyCode.F))
{
buttonF.Execute(character);
}
if (Input.GetKeyDown(KeyCode.Q))
{
buttonQ.Execute(character);
}
}
}
The FireBallCommand class looks like this, (atm it creates a GameObject because Command does not derive from MonoBehaviour because I read you should/cant create object using 'new' with MonoBehaviours, in code):
public class FireBallCommand : Command {
public override void Execute(PlayableCharacter character)
{
GameObject go = new GameObject();
go.AddComponent<FireBall>();
go.name = go.GetComponent<FireBall>().Name;
go.GetComponent<FireBall>().Execute(character);
}
}
Next, the abstract class Ability contains an abstract method Execute() as well. It also contains some properties such as name and cooldown. The actually ability derives from Ability and actually executes the ability:
public class FireBall: Ability {
PlayableCharacter character;
public override void Execute(Character character)
{
this.character = character as PlayableCharacter;
StartCoroutine(Fire());
}
IEnumerator Fire()
{
//Here it fires the fireball but there's no need to post that here.
}
}
This is the first time I am making a system like this. The dilemma is that I am not sure whether this is a right way to do it. It feels like casting one ability or spell is passing way to many classes and taking too much code in general. I thought of creating an AbilityManager that is always in the scene, which could be called to cast any spell/ability and takes a player as parameters.
In short: Do you think this would be a fine and fairly clean way to create an ability system? What other way(s) do you suggest? What could I change/remove/add to improve it?
P.S if anyone feels like answering this. I'm not sure where and how to implement cooldowns for the abilities in this system. Got an idea? :)
Thanks a lot in advance guys, if there's anything I should provide please let me know.