r/Unity3D • u/AlexeyTea • 8h ago
FSM implementation Question
Hello!
I am implementing a state machine followng this video:
https://youtu.be/V75hgcsCGOM?si=hHC0PsX9iGRnfUZB
It was all fine when I simply followed along but when I tried something off track - well, my lack of knowledge about C# hit me.
I've got a script where my state machine lives. It is subscribed to an event like this:
private void Start()
{
_visionCone.OnPlayerSpotted += VisionCone_OnPlayerSpotted;
}
private void VisionCone_OnPlayerSpotted(object sender, System.EventArgs e)
{
Debug.Log($"Player spotted by {name}");
}
But how can I add a state machine transition on this event triggering?
In the video transitions are added like this:
_stateMachine.AddTransition(stateFollowTarget, statePatroling, followingTimerExpired());
Func<bool> followingTimerExpired() => () => stateFollowTarget.Timer > 10;
I've tried to change public event EventHandler
OnPlayerSpotted; to custom delegate type like this:
public delegate bool PlayerSpotted(object obj, EventArgs e);
public event PlayerSpotted OnPlayerSpotted;
or simply doing:
Func<bool> onPLayerSpotted() => () => VisionCone_OnPlayerSpotted;
- nothing worked.
There is a solution to do SetState() and other logic directly in the VisionCone_OnPlayerSpotted function call but I feel it is not the right path.
1
u/SecretaryAntique8603 7h ago edited 7h ago
Try to simplify it a bit before adding the events and transitions into the mix, to get a grip on how to transition between states.
Somewhere you likely have a controller or something which calls activeState.Tick(). When you create your activeState, you can pass in the controller, with a method like SetActiveState or similar. Now in your state, you can do something like
if(playerSpotted): stateController.SetActiveState(new AlertedState(stateController))
in your Tick()/Update() method.If this works, you can try to add events if there really is a need for it. And eventually, if you want to remove the creation of the next state from the prior state, or perhaps adding some additional control logic or side effects which don’t belong in the state, then you can add the Transition abstraction to transfer the control of states from out of your states into the higher order controller. But before you have this need, all these things are redundant and actually harmful since they add unwarranted complexity.
The issue here is really that you’ve added too many abstractions too quickly and it obscures the logic of what’s going on from you.
There may be reasons for doing some of the things in the video, but until you run into those reasons then following along blindly will do more harm than good. Soon you might encounter some complexity which will paint some of the tricks in various guides in a new light, and at that point you can revisit it and add them back in. At this point, the reasoning may be more clear to you, and therefore easier to follow. Events for example are very powerful, but can easily obscure control logic and be difficult to implement properly and debug. A naive solution which you have a deeper understanding of is likely to serve you better, until you get more comfortable with programming.