Closed tomsseisums closed 5 months ago
Right, I remember another aspect to this, while technically we can use IStateMachine
, AddState
does not support IStateMachine
.
And also IStateMachine
is super limited if used to expose StateMachine
for public use, it could make use Trigger
and OnAction
methods at least. Or give us two types, like IActionableStateMachine that derives from IStateMachine
and exposes Trigger
/OnAction
.
I guess a better example is this:
And here the IStateMachine
issue:
And also
IStateMachine
is super limited if used to exposeStateMachine
for public use, it could make useTrigger
andOnAction
methods at least. Or give us two types, like IActionableStateMachine that derives fromIStateMachine
and exposesTrigger
/OnAction
.
Right, we have ITriggerable
and IActionable
, but no way to have both-in-one excluding other public methods.
Hi @tomsseisums,
Thanks for providing so much information!
The issue you are talking about is one of the minor inconveniences of the way that UnityHFSM is implemented internally regarding its support for generics.
StateMachine
, StateMachine<T>
, HybridStateMachine
and other overloads of these classes do actually share a common base class - it's just not directly apparent.
The "actual" StateMachine
implementation is in the generic version of the class: StateMachine<TOwnId, TStateId, TEvent>
. The other overloads that require less parameters inherit from this base class and help you avoid boilerplate code when working with the defaults (strings).
As HybridStateMachine
extends the behaviour of StateMachine
, it simply inherits from this class. As it also has to support generics, it inherits from the aforementioned generic version of StateMachine
.
If UnityHFSM didn't support generics, the inheritance hierarchy would therefore look like this:
classDiagram
class StateMachine
class HybridStateMachine
StateMachine <|-- HybridStateMachine
With generics, it looks like this:
classDiagram
class StateMachineTTT["StateMachine[T, T, T]"]
class StateMachineTT["StateMachine[T, T]"]
class StateMachineT["StateMachine[T]"]
class StateMachine["StateMachine"]
class HybridStateMachineTTT["HybridStateMachine[T, T, T]"]
class HybridStateMachineTT["HybridStateMachine[T, T]"]
class HybridStateMachineT["HybridStateMachine[T]"]
class HybridStateMachine["HybridStateMachine"]
StateMachineTTT <|-- StateMachineTT
StateMachineTTT <|-- StateMachineT
StateMachineTTT <|-- StateMachine
StateMachineTTT <|-- HybridStateMachineTTT
HybridStateMachineTTT <|-- HybridStateMachineTT
HybridStateMachineTTT <|-- HybridStateMachineT
HybridStateMachineTTT <|-- HybridStateMachine
In other words, using StateMachine<TOwnId, TStateId, TEvent>
as the type in your examples should fix the bugs.
As to the IStateMachine
interface, I've explored different alternatives and reached the conclusion that the current implementation covers all practical conceivable cases at this point in time, without introducing additional complexity. As you have noticed, the IStateMachine
interface was not intended to be used "publicly". Instead it creates a minimal layer of abstraction between the nested state machines, that allows each nested state machine to use its own generic types.
For more information on the use of generics, please check out the WIP README in the release
branch for the 2.0 release or this issue.
I hope I could clarify this.
or