I am making a Finite State Machine (FSM) in C# for a game. The goal is to make it as independant of traditional control flow as possible. I am currently trying to create a gun behaviour with it. When the gun enters an "Out of ammo" state it should start listening for when ammo is added and automatically change state to reloading, but i am having some trouble with the C# language.
I basically want to pass an Action to another function. In that function I would like to subscribe to it:
var outOfAmmo = new ListenerState<GunState>(GunState.OUT_OF_AMMO);
outOfAmmo.AddTrigger(currentAmmo.OnAdded, GunState.RELOAD);
The function:
public class ListenerState<TStateID> : State<TStateID>
...
public void AddTrigger(Action trigger, TStateID next)
{
Action setState = () => fsm.SetState(next);
OnEnter += () => trigger += setState; //When we enter "Out of ammo" start listening for when ammo is added.
OnExit += () => trigger -= setState; //When we exit "Out of ammo" we don't want to change state to reloading when ammo is added anymore
}
When OnEnter and later the trigger is invoked, I expect setState to be called but its not.
Pulling out the content of AddTrigger makes everything work as expected:
outOfAmmo.AddTrigger(currentAmmo.OnAdded, GunState.RELOAD);
Action setReload = () => fsm.SetState(GunState.RELOAD);
outOfAmmo.OnEnter += () => currentAmmo.OnAdded += setReload;
outOfAmmo.OnExit += () => currentAmmo.OnAdded -= setReload;
I have made a smaller example of the problem here: https://dotnetfiddle.net/MG1tve
I am not sure what is going on here.
Is the action by default passed by value :O? because passing as ref solves the problem (https://dotnetfiddle.net/XNresg)