返回调用者状态?

3
我正在使用C#的无状态状态机,但是我以前在其他状态机实现中遇到过这个问题。虽然我可以添加一些虚拟代码,但问题大多是理论性的。
我有一个情况,我不太确定如何解决。假设您有2种状态(行走和奔跑),它们都可以转换为第3种状态(跳跃)。一旦完成第3种状态,我希望回到调用者状态。在某种程度上,我必须能够影响被调用者触发器,但这仅传递给OnEntry等函数,而不是状态本身。
使用EntryFrom似乎行不通,因为没有办法影响“跳跃”状态本身,只有OnEntry函数。 使用PermitDynamic似乎也不起作用,因为一旦进入“跳跃”状态,我就无法知道自己来自哪里。
我可以使用两个跳跃状态(jumpfromrun、jumpfromwalk),并带有单个OnEntry函数,以最小化一些重复代码。这是我目前使用的方法。
我可以将先前的状态保存在外部变量中,并将其传递给我的状态更新。我不想这样做(绝对不想)。
是否有已知的技术或方法来处理这种问题?共享状态,应该返回到调用者? 谢谢!

1
要在“跳跃”状态下,同时记住你是如何到达那里的,唯一的方法就是将这些信息编码到状态中(例如有一个行走跳跃和一个奔跑跳跃),或者使用不同类型的存储方式(例如一个推入自动机的堆栈、额外的枚举变量等)。 - undefined
正如问题中所述,这是我目前使用的方法。但这并不是一个很好的解决方案,因为你会得到大量的复制粘贴代码,而唯一不同的是触发调用的那一行:/ 两个状态完全相同。 - undefined
1
为什么有这么多复制粘贴的代码?你必须重复编写on entry、OnEntry、OnExit和Permits,但是'jump'代码本身可以提取到一个函数中,在两种跳转类型中都调用该函数。 - undefined
改变我的专业?那是什么意思。无论如何,我有一个模糊的记忆,在某个地方工作过,他们对这个问题有一个更优雅的解决方案。但我无法确切地回忆起来。 - undefined
1个回答

3

从阅读文档来看,似乎这是使用子状态的一个非常好的用例。

你可以有一个跳转状态:

stateMachine.Configure(State.Jumping)
    .OnEntry(() => StartJump())
    .OnExit(() => EndJump());

有两种跳转状态。一种是走路,一种是跑步:

stateMachine.Configure(State.WalkJumping)
    .SubstateOf(State.Jumping)
    .Permit(Trigger.DoneJumping, State.Walking);

stateMachine.Configure(State.RunJumping)
    .SubstateOf(State.Jumping)
    .Permit(Trigger.DoneJumping, State.Running);

然后,您可以分别创建步行跳跃(WalkJumping)和奔跑跳跃(RunJumping)的路线。
stateMachine.Configure(State.Walking)
    .OnEntry(() => StartWalking())
    .OnExit(() => EndWalking());
    .Permit(Trigger.Jump, State.WalkJumping);


stateMachine.Configure(State.Running)
    .OnEntry(() => StartRunning())
    .OnExit(() => EndRunning());
    .Permit(Trigger.Jump, State.RunJumping);

使用这样的基板,而不是普通状态,有一个额外的好处,即State.Jumping可以定义相同的OnEntryOnExit,这将被WalkJumpingEndJumping继承。

此外,它为您提供了一种更容易检查是否正在跳跃的方法。不再需要:

var state = stateMachine.state;
var isJumping = state == State.WalkJumping || state == RunJumping;

您可以简单地执行以下操作:
var isJumping = stateMachine.IsInState(State.Jumping);

这将正确考虑当前的所有子状态,包括WalkJumpingRunJumping。但是,如果您在未来添加新的跳跃子状态,例如DoubleJumping,那么isJumping谓词也将自动覆盖该情况,而无需记住修复它。


这正是我在寻找的东西,谢谢!现在,使用子状态,父级“更新”也将被调用。所以我想你可以共享OnEntryTheUpdate。你可能只需修改出口点,使用PermitDynamicPermitDynamicIfOnEntryFrom,这样基本上最终只有两个不同的出口。我今天稍后会尝试一下这个想法,但这肯定是一种优雅和模型化的解决方案。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接