Я бы определил базовый ScriptableObject для способности:
public abstract class Ability : ScriptableObject
{
public abstract void Activate(PlayerController playerController);
public abstract void Deactivate(PlayerController playerController);
}
И затем создавал бы конкретные типы способностей:
[CreateAssetMenu(fileName = "Double Jump", menuName = "Abilities/Double Jump")]
public class DoubleJump : Ability
{
public override void Activate(PlayerController playerController)
{
playerController.MaxJumpCount = 2;
}
public override void Deactivate(PlayerController playerController)
{
playerController.MaxJumpCount = 1;
}
}
Тогда AbilityPickup выглядел бы примерно так:
[RequireComponent(typeof(PlayerController))]
public class AbilityPickup : MonoBehaviour
{
private PlayerController playerController;
private List<Ability> activeAbilities = new List<Ability>();
private void Awake()
{
playerController = GetComponent<PlayerController>();
}
private void OnTriggerEnter(Collider collider)
{
if (collider.TryGetComponent(out AbilityContainer abilityContainer))
AddAbility(abilityContainer.Ability);
}
public void AddAbility(Ability ability)
{
ability.Activate(playerController);
activeAbilities.Add(ability);
}
}
Где то в мире будет лежать объект с компонентом:
public class AbilityContainer : MonoBehaviour
{
[SerializeField] private Ability ability;
public Ability Ability => ability;
}