unity3d 你能用SOLID原理创建有限状态机吗

lf5gs5x2  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(151)

我目前正在学习游戏开发,在我们的一个项目中,我们必须创建一个有限状态机,它将作为一个简单的人工智能。它一直被鼓励用SOLID原则来编写代码,但在这个项目中,我想不出一种方法来做到这一点。虽然它不是这个项目所必需的,但我仍然想找到一种方法来做到这一点。它是用Unity C#编写的。

public interface IState
{
    public IState CheckForState();
}

public class Walk : IState
{
    float speed = 10;

    public IState CheckForState()
    {
        if (speed > 5)
        {
            return Run;
        }
        return this;
    }
}

要使它成为固体,你必须找到一种方法来删除'运行'从函数的原因,如果'运行'脚本被删除的函数将不再工作,但它应该仍然能够得到它,如果可用。

kq4fsx7k

kq4fsx7k1#

有一对夫妇的解决方案,浮现在脑海中,将允许一个完全坚实的解决方案。

溶液1

满足依赖反转原则的第一个也是最简单的方法是将Run类注入到Walk类中,如下所示:

public class Walk : IState
{
    float speed = 10;
    private readonly IState _runState;
    public Walk(IState runState)
    {
        _runState = runState;
    }

    public IState CheckForState()
    {
        if (speed > 5)
        {
            return _runState;
        }
        return this;
    }
}

这个解决方案使得Walk不再依赖于Run的具体实现,但仍然允许它转换到运行状态。然而,这确实要求Walk知道它可以转换到哪个状态(我认为这是一个合理的期望)。

溶液2

您可以通过将状态转换表示为对象来进一步分离这一点。

public interface IState
{
    public IState CheckForState();
    public float Value {get;}
}

public interface IStateTransition
{
    public IState CheckTransition(IState source);
}

public class GreaterThanTransition : IStateTransition
{
    private readonly IState _targetState;
    private readonly int _checkValue;

    public GreaterThanTransition(IState targetState, int checkValue)
    {
        _targetState = targetState;
        _checkValue = checkValue;
    }
    public IState CheckTransition(IState sourceState) => sourceState.Value > _checkValue ? _targetState : sourceState;
}

public class Walk : IState
{
    private readonly List<IStateTransition> _transitions;

    public Walk(List<IStateTransition> transitions)
    {
        _transitions = transitions;
    }
    public float Value => 10;

    public IState CheckForState() => _transitions.Select(t => t.CheckTransition(this)).FirstOrDefault(s => s != this) ?? this;
}

然后可以创建一个Walk示例,如下所示:

new Walk(new List<IStateTransition>
{
    new GreaterThanTransition(new Run(...), 5)
});

这要求可以在IStateTransition中使用state对象中的值来检查是否需要发生状态转换。我在示例中使用了int作为Value属性的类型,但您可以轻松地将其切换为泛型类型。
这种解决方案完全分离了每个状态,并将状态转换捕获为可重用组件。由于代码现在被分割到更多的类和接口,因此在某些方面更加复杂,但它也完全融入了SOLID原则。

相关问题