Skip to content

Instantly share code, notes, and snippets.

@cathei
Last active September 4, 2022 19:16
Show Gist options
  • Save cathei/ed8ea7f088237b681a43db2dfec256ea to your computer and use it in GitHub Desktop.
Save cathei/ed8ea7f088237b681a43db2dfec256ea to your computer and use it in GitHub Desktop.
Example of interface application to Trigger/Effect system
using System.Collections.Generic;
using UnityEngine;
// this is for void events, other events will also implement this
public interface IEventParam { }
// sample event param
public interface IPositionalEventParam : IEventParam
{
Vector3 Position { get; }
}
// sample event param
public interface ICombatEventParam : IEventParam
{
int Damage { get; }
}
// ItemEffect should implement this with their desired effect param
// since it's contravariant, you can do this
// IItemEffect<IEventParam> effect = new ItemEffect();
// IItemEffect<ICombatEventParam> converted = effect;
public interface IItemEffect<in T> where T : IEventParam
{
void ProcessEvent(T param);
}
// now we do concrete types
public class VoidEventParam : IEventParam { }
public class PositionalEventParam : IPositionalEventParam
{
public Vector3 Position { get; }
public PositionalEventParam(Vector3 position)
{
Position = position;
}
}
// sample event param
public class CombatEventParam : ICombatEventParam
{
public int Damage { get; }
public CombatEventParam(int damage)
{
Damage = damage;
}
}
public class NormalItemEffect : IItemEffect<IEventParam>
{
public void ProcessEvent(IEventParam param)
{
Debug.Log("NormalItemEffect");
}
}
public class OnHitItemEffect : IItemEffect<ICombatEventParam>
{
public void ProcessEvent(ICombatEventParam param)
{
Debug.Log("OnHitItemEffect " + param.Damage);
}
}
public class OnMoveItemEffect : IItemEffect<IPositionalEventParam>
{
public void ProcessEvent(IPositionalEventParam param)
{
Debug.Log("OnMoveItemEffect " + param.Position);
}
}
// event trigger will only accept corresponding IItemEffect<T>
public class EventTrigger<T> where T : IEventParam
{
List<IItemEffect<T>> effects = new List<IItemEffect<T>>();
public void AddEffect(IItemEffect<T> effect)
{
effects.Add(effect);
}
public void ProcessTrigger(T param)
{
foreach (var effect in effects)
{
effect.ProcessEvent(param);
}
}
}
// now we do sample code
public static class Sample
{
public static void SampleMain()
{
var onHitEventTrigger = new EventTrigger<ICombatEventParam>();
var onMoveEventTrigger = new EventTrigger<IPositionalEventParam>();
var onSkillUsedTrigger = new EventTrigger<IEventParam>();
var onHitItemEffect = new OnHitItemEffect();
var onMoveItemEffect = new OnMoveItemEffect();
var normalItemEffect = new NormalItemEffect();
// you can add normal item effect to any event trigger
onHitEventTrigger.AddEffect(normalItemEffect);
onMoveEventTrigger.AddEffect(normalItemEffect);
onSkillUsedTrigger.AddEffect(normalItemEffect);
// you can only add on hit item effect to on hit event trigger
onHitEventTrigger.AddEffect(onHitItemEffect);
// onMoveEventTrigger.AddEffect(onHitItemEffect);
// onSkillUsedTrigger.AddEffect(onHitItemEffect);
// you can only add on move item effect to on move event trigger
// onHitEventTrigger.AddEffect(onMoveItemEffect);
onMoveEventTrigger.AddEffect(onMoveItemEffect);
// onSkillUsedTrigger.AddEffect(onMoveItemEffect);
// you can call triggers with corresponding arguments
onHitEventTrigger.ProcessTrigger(new CombatEventParam(100));
onMoveEventTrigger.ProcessTrigger(new PositionalEventParam(Vector3.forward));
onSkillUsedTrigger.ProcessTrigger(new VoidEventParam());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment