Estoy haciendo un juego de administración de ciudades, donde los trabajadores están completamente controlados por máquinas estatales. Tengo un "problema" en el que me encuentro reescribiendo muchos estados que son 99% similares. Por lo general, la única diferencia en algunos de los estados es a qué estado debe ir cuando se completa.
Por ejemplo, el siguiente estado se usa para entregar recursos, esto es algo que hacen todas las profesiones, pero tengo que escribir uno específico para cada profesión, ya que todos conducen a diferentes estados al completarse.
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() { } }¿Hay alguna forma de pasar a qué estado cambiar en un constructor? O de alguna otra manera puedo ajustar mi diseño que no requerirá que vuelva a escribir tanto código.
¿Qué tal pasar una función anónima al constructor que creará el nuevo estado?
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)); } } }Luego, cuando crea un estado para cada tipo de unidad, puede pasar una función que creará el estado "completado" apropiado (supongo que la arquitectura de su clase de Unidad).
// 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); } } Por supuesto, si el estado secundario ( BakerIdleState ) también requiriera personalización, entonces tendría que hacer lo mismo para establecer el siguiente estado de ese estado y esto se volvería más complicado.