Question

public abstract class State<T>
{
    public virtual Enter(T item)
    {
            // an empty method
    }
}

public class ChaseState : State<FieldPlayer>
{
    public override Enter(Player pl)
    {
        // ...
        pl.Fsm.CurrentState = ChaseState.Instance;
        //...
    }
}

public class TendGoal : State<Goalkeeper>
{
   public override Enter(Goalkeeper gk)
   {
       // ...implementation
       gk.Fsm.CurrentState = TendGoal.Instance;
       // ...implementation
   }
}

public class DefendState : State<Team>
{
    public override Enter(Team team)
    {
        // ....    
        team.Fsm.CurrentState = DefendState.Instance;
        //.....
    }
}

"Goalkeeper" and "FieldPlayer" inherit from an abstract class "Player", while "Team" inherits from another class.

public class FSM
{
    public /*some type*/ owner;         // PROBLEM 1
                                        // OWNER CAN BE TEAM, GOALKEEPEEPER
                                        // OR FIELD PLAYER
    public /*some type*/ globalState;
    public /*some type*/ currentState;
    public /*some type*/ previousState;
    public void Update()
    {
        if (globalState != null)
        {
            globalState.Execute(owner);  // PROBLEM 2
                                         // IF GLOBAL STATE'S TYPE
                                         // IS AN OBJECT, CANT CALL EXECUTE
                                         // OBJECTS TYPE WILL BE KNOWN ONLY
                                         // DURING RUNTIME
        }
     }
}

Each object of type "Goalkeeper", "FieldPlayer" and "Team" will have a State Machine instance. The problem is.. generics cant be properties.

What should I do ?

Was it helpful?

Solution

If you make State an ordinary interface, not generic, and have its Enter method take another interface that your teams, goalkeeprs, players, etc all implement (it can even just be empty), it ought to work.

public interface IOwner {}

public interface IState
{
    void Enter(IOwner item);
}
public class ChaseState : IState
{
    public void Enter(IOwner pl)
    {
        // ...
        //...
    }
}
public class Player :IOwner { }
public class Something {
    IOwner owner = new Team();
    IState globalState = new ChaseState();
    IState currentState = new DefendState();

    public void Update()
    {
        if (globalState != null)
        {
            globalState.Enter(owner); 
        }
        else if (currentState != null)
        {
            currentState.Enter(owner);
        }
     }
}

OTHER TIPS

After reading your code some more, an Abstract Class is unnecessary here. You should convert State to an interface, ex: IState and remove the generic signature from it. Then your properties in your FSM object can all be public IState globalState, etc..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top