Even if Patico’s code works as intended, though in my opinion your “spell” effect (or whatever you call it) should be a MonoBehaviour itself to be instantiated on the human target else you will need to create a class for every “spell” even if it’s only the duration and damage to change.
Probably the easiest way I suggest is to have a base timed effect class, so you basically will create the classes for your effects inheriting from it.
For example the base class would be something like this:
using UnityEngine;
using System.Collections;
public class TimedEffect : MonoBehaviour {
public float duration; // when it should expire?
public float startTime; // should delay the (first) effect tick?
public float repeatTime; // how much time between each effect tick?
[HideInInspector]
public Human target;
void Start () {
// Apply the effect repeated over time or direct?
if (repeatTime > 0)
InvokeRepeating("ApplyEffect", startTime, repeatTime);
else
Invoke("ApplyEffect", startTime);
// End the effect accordingly to the duration
Invoke("EndEffect", duration);
}
protected virtual void ApplyEffect () {
}
protected virtual void EndEffect () {
CancelInvoke();
Destroy(gameObject);
}
}
An example of damage over time:
using UnityEngine;
using System.Collections;
public class DamageOverTime : TimedEffect {
public int damage;
protected override void ApplyEffect () {
target.TakeDamage(damage);
}
}
An example of stat (strength, constitution, speed, etc) buff/debuff (for debuff you just set buffValue to a negative value):
using UnityEngine;
using System.Collections;
public class StatBuff : TimedEffect {
public BaseStat stat;
public int buffValue;
protected override void ApplyEffect ()
{
target.BuffStat(stat, buffValue);
}
protected override void EndEffect ()
{
target.BuffStat(stat, -buffValue);
base.EndEffect ();
}
}
To use this you will Instantiate the effect prefab and assign the “target” (since Start should be theoretically called in the next frame it should work, else you could turn the Start function in TimedEffect into another named public function and call it after Instantiate).
PS: notice that I didn’t change directly the health value of the target but it calls TakeDamage (that should be in the target script), because you need at least few things to do upon each damage taken (at least verify that the health doesn’t never be negative, and probably you will want to do something when it reaches 0).