C# 如何编写状态机,使我不';你不必用99%的相似代码复制州吗?

C# 如何编写状态机,使我不';你不必用99%的相似代码复制州吗?,c#,unity3d,logic,state-machine,C#,Unity3d,Logic,State Machine,我正在制作一个城市管理游戏,工人完全由国家机器控制。我有一个“问题”,我发现我自己重写了很多99%相似的州。通常情况下,某些状态的唯一区别是完成时应转到哪个状态 例如,下面的状态用于交付资源,这是所有职业都会做的事情,但我有一个为每个职业编写一个特定的状态,因为它们在完成时都会导致不同的状态 public class BakerDeliverGrainState : BaseWorkerState, IState { public void Enter() { /

我正在制作一个城市管理游戏,工人完全由国家机器控制。我有一个“问题”,我发现我自己重写了很多99%相似的州。通常情况下,某些状态的唯一区别是完成时应转到哪个状态

例如,下面的状态用于交付资源,这是所有职业都会做的事情,但我有一个为每个职业编写一个特定的状态,因为它们在完成时都会导致不同的状态

public class BakerDeliverGrainState : BaseWorkerState, IState
{
    public void Enter()
    {
        //Go to storage
        SetDestination(storage.position);
    }

    public void Execute()
    {
        if (unit.ReachedDestination())
        {
            //Reached destination, state completed
            storage.Store(unit.TakeResource());
            unit.stateMachine.ChangeState(new BakerWorkState(unit)); //This is the line that seperates the states. For example a blacksmith will go to "BlacksmithWorkState", and so on.
        }
    }

    public void Exit()
    {
        
    }
}

是否有某种方法可以在构造函数中传递要更改的状态?或者,我可以通过其他方式调整我的设计,而不需要重新编写这么多代码。

将匿名函数传递到构造函数中以创建新状态如何

public class BaseWorkerState
{
   protected Func<Unit, IState> createCompletedState;
  
   // Use this constructor for states where you don't need to customize the
   // next state
   public BaseWorkerState()
   {
   }

   // Use this constructor for states where you do need to customize the 
   // next state
   public BaseWorkerState(Func<Unit, IState> createCompletedState)
   {
      this.createCompletedState = createCompletedState;
   }
}

public class BakerDeliverGrainState : BaseWorkerState, IState
{
   public BakerDeliverGrainState(Func<Unit, IState> createCompletedState) 
      : base(createCompletedState)
   {
   }

   public void Execute()
   {
      if (unit.ReachedDestination())
      {
         // Reached destination, state completed
         storage.Store(unit.TakeResource());
         unit.stateMachine.ChangeState(this.createCompletedState(unit));
       }
   }
}

当然,如果子状态(
BakerIdleState
)也需要自定义,那么您必须做同样的事情来设置该状态的下一个状态,这将变得更加复杂。

真的很有趣,我明天将对此进行一点试验,可能会奏效!)
// When the baker is done delivering grain, he'll go into this state
public class BakerIdleState: IState
{
   public BakerIdleState(Unit unit) : base(unit)
   {
   }  
}

public class Baker : Unit
{
   public void DeliverGrain()
   {
      var newState = new BakerDeliverGrainState(unit => 
      {
         return new BakerIdleState(unit);
      }); 
      this.stateMachine.ChangeState(newState);
   }
}