Я бы решил это с помощью списка модификаторов. Предположим, у вас есть интерфейсы:
public interface IHealth
{
float Health {get};
void TakeDamage(float damage);
}
public interface IDamageModifier
{
float Apply(float damage);
}
Теперь давайте сделаем несколько реализаций модификатора:
public class ShieldModifier : ScriptableObject, IDamageModifier
{
private float shieldAmount = 10;
public float Apply(float damage)
{
var actualDamage = Mathf.Max(0, damage - this.shieldAmount)
return actualDamage;
}
}
public class InvulnerabilityModifier: ScriptableObject, IDamageModifier
{
public float Apply(float damage)
{
return 0;
}
}
Наконец, у вашего врага будет список модификаторов:
public class Enemy : MonoBehaviour, IHealth
{
public float Health {get; private set;}
public List<IDamageModifier> modifiers; // Pretend this has both modifiers above.
public void TakeDamage(float damage)
{
var actualDamage = damage;
foreach(var mod in this.modifiers)
{
actualDamage = mod.Apply(actualDamage);
}
this.Health -= actualDamage; // 0 because of Invulnerability
}
}
Так что если у вашего врага есть модификатор щита со значением щита 10, то атака в 50 урона нанесет только 40 урона.
Ваши модификаторы могут быть объектами со сценариями, если вы хотите, чтобы их можно было настраивать с помощью инспектора.
Этот подход довольно элементарный. Для эффекта, подобного ReflectDamageModifier
, вашему интерфейсу-модификатору может потребоваться IHealth attacker
, например:
public class ReflectDamageModifier: IDamageModifier
{
private float reflectionFactor = 0.5; // Reflect 50% of damage
public float Apply(float damage, IHealth attacker)
{
attacker.TakeDamage(damage * this.reflectionFactor);
return damage;
}
}
Однако этот подход уязвим к порядку модификаторов. Например, если вы сначала поместите модификатор отражения, он будет отражать больше урона, чем последний. Вам может потребоваться расширить систему, например, системой приоритетов / заказов.
Этот модификатор отражения также уязвим для исключения переполнения стека, если и у атакующего, и у цели есть модификатор отражения, так что просто следите за этим.
Надеюсь, это поможет.