Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a StateChanged changed event for when any transition occurs, even a sub-machine one? #29

Closed
tomsseisums opened this issue Aug 31, 2023 · 3 comments

Comments

@tomsseisums
Copy link

Haven't found a way to listen to any transition happening.

Currently I have found I would like something like that for debugging, as I'm working with hierarchical machines.

But I also feel I could make use for something like that to build UI around State. As to keep the game logic in states and respective transitions, but UI being reactive on top of it, no matter what and how deep is going on.

@tomsseisums
Copy link
Author

I see this PR is kind of implementing that: #23

I'd vouch for StateChanged(fromState, toState) signature.

And for sub-machine states being reported on highest level, maybe an array signature could work: StateChanged([topState, nestedState, fromState], [topState, nestedState, toState])?

@sandsalamand
Copy link

I think you can do this by having all your states inherit from a state that calls an event in OnEnter or OnExit.

@Inspiaaa
Copy link
Owner

Hi @tomsseisums,
Thanks again for providing real-world use cases with your issue. This is much appreciated!

Having such an event for debugging purposes sounds very useful and the idea to use it to separate game logic and UI code is especially intriguing.

I have though about your proposed event signature StateChanged([topState, nestedState, fromState], [topState, nestedState, toState]) and as far as I can tell, there are multiple problems with it, two of which I would like to illustrate in the following.

The first problem is generics. Each nested state machine allows you to use a different type for the TStateId generic type parameter. This means that in the current implementation the states do not share a common base class and can therefore not be stored in an array like StateBase<T>[]. Instead a general purpose object[] array has to be used. The resulting signature for the event is hard to read, does not convey its intent, and also undermines the minimum level of type safety afforded by the current system.

The second issue is performance. One of the main goals of UnityHFSM is to be extremely performant and to avoid GC allocations after initialisation. Having to allocate an array on each transition reduces the transition performance and increases the pressure on the garbage collector, potentially contributing to lag spikes.

Although I can see where you are coming from with this signature, all things considered, I do not think that I am going to implement it in UnityHFSM. But this does not mean that you cannot do so in your own project. As UnityHFSM is open source, you could edit the code to better fit your exact use case. Alternatively, you could also write your own util code that uses the existing features of UnityHFSM to accommodate your use case.

Generally speaking, I think that the StateChanged event is a good feature to have. That's why I have recently merged a PR that implements it, albeit in its most basic form. Future versions may bring enhancements, depending on how it is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants