I am trying to make a component-based ability system for my new turn based game that I am working on. I not sure with the architecture and the approach I am following.
So here my idea:
Every Ability is a Prefab.
Four Ability Prefabs will be attached to every Character, those are their abilities.
An Ability consists of an AbilityController.cs
. This will have the name and some basic data for the ability. Then I will attach one or more AbilityTargetMode.cs
. Here I can pick a target mode (enemySingle, enemyAll, enemyRandom, AllySelf, ...) and attach one or more AbilityComponent.cs
to every AbilityTargetMode
. AbilityComponents
are things like "Do Damage", "Apply Poison", and so on.
The idea behind this is that I can build complex abilities:
Do damage to a random enemy and poison him, then heal self, then apply buff to all allies.
The structure for an ability would be:
-- Controller
---- TargetMode: EnemySingle
------ Component 1: Damage
------ Component 2: Poison
---- TargetMode: Self
------ Component 1: Heal
---- TargetMode: AlliesAll
------ Component 1 : Buff
And so on..
But I'm not sure about the whole system. Is it something that sounds right? Should I overthink something?
And another problem that I have is that I do not know how to attach my Components and my target mode to my Controller/Prefab. Is it better to use scriptable objects? What are your thoughts on the system?
######EDIT######
So yesterday i got my system working. At least a prototype for it. Here is a picture what i can do with it in the inspector:
Cool thing about it is, that i can make Components like "DoDamage" or "ApplyPoison". Then chain them and compose my custom abilitys. One ability can have more effects. Like a chain of effects. Damage one Enemy > heal one ally > buff all other allys
Its not optimal. I really would like to have something like this with scriptabla objects, but i was not able to pull it off. Is this system okay how i did it?
My game is turn based. The game is based around the combat and around a lot of characters. thats why i want an easy ability composer.
I have 3 codes:
- AbilityController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AbilityController : MonoBehaviour
{
public string abilityName;
public AbilityTargetMode[] targetModes;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
for(int i = 0; i < targetModes.Length; i++)
{
targetModes[i].Execute();
}
}
}
}
- AbilityTargetMode
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum TargetMode { EnemySingle, EnemyAll, EnemyRandom, AllySingle, AllySingleOther, AllyAll, AllyAllOther, AllyRandom, AllyRandomOther, AllySelf}
[System.Serializable]
public class AbilityTargetMode
{
public TargetMode targetMode;
public AbilityComponent[] abilityComponents;
private Character[] targets;
public void Execute()
{
CastAbilityComponentsOnTarget();
}
private void CastAbilityComponentsOnTarget()
{
for (int i = 0; i < abilityComponents.Length; i++)
{
abilityComponents[i].CastAbilityComponent(targets);
}
}
private void SelectTargets()
{
switch (targetMode)
{
case TargetMode.EnemySingle:
break;
case TargetMode.EnemyAll:
break;
case TargetMode.EnemyRandom:
break;
case TargetMode.AllySingle:
break;
case TargetMode.AllySingleOther:
break;
case TargetMode.AllyAll:
break;
case TargetMode.AllyAllOther:
break;
case TargetMode.AllyRandom:
break;
case TargetMode.AllyRandomOther:
break;
case TargetMode.AllySelf:
break;
}
}
}
- AbilityComponent
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class AbilityComponent : MonoBehaviour
{
public virtual void CastAbilityComponent(Character[] _targets)
{
//do stuff
}
}
ScriptableObject
s, rather than prefabs, if you're never instantiating them as scene objects. But other than that, I'd generally advise against using the Q&A here to ask internet strangers to vet your ideas. Instead, try implementing your ideas first. If if works as you planned, great, you're done, and you never had to wait for input from us in the peanut gallery. 😉 If it doesn't work, then you'll have a clear problem that you can ask how to solve. \$\endgroup\$Instantiate
on ScriptableObjects to copy them, but it doesn't copy children scriptable objects as references to those are copies which is good by design. I would use ScriptableObjects in my project if these were objects that I wanted to copy in runtime and use as a base, but being able to edit them in editor. \$\endgroup\$