Need Help speeding up a Finite State Machine

daggerspell 101 Nov 23, 2011 at 19:44

Okay I have a miner in my game that has about 10 different states.

I have a problem with slow transitions in some cases. One of these cases is if it is mining and a player comes and attacks him. I have seen it take more then 7 seconds for him to go from mining to combat. In that time a higher level player can almost kill it. Causing the miner to look almost retarded in this case. Below is the state checking code is there a better way to do this so that the miner does not look retarded. I know that part of the problem is in the loop I have the dowork. but I have yet to see a better way to do this and still have a somewhat weighted states.

foreach (State state in States.Where(state => state.actionRequired))
     if (LastState != state)
        if (StateChange != null)
              StateChange(new object(), new NotifyStateChanged(state.Name()));
               Logging.Write("State changed: " + state.Name());
     LastState = state;

Is there a better way to manage states then a foreach loop?

When I first wrote this code it was not a finite state engine it was all just hard coded into the character. That worked well but code was to big and maintaining it became a hassle, because i had to change each character file when I added a new state to them. So I switched to this and it is working good except it is a lot slower in some cases.

5 Replies

Please log in or register to post a reply.

Stainless 151 Nov 23, 2011 at 20:06

Remove the logging for a start, not sure what your dev environment is, but in visual studio a single write to the debug output can sometimes take 500ms

Which is a real pain when you are debugging real time code.

Also check how many states you have in the stack, you may have ended up with states that should have been killed

daggerspell 101 Nov 23, 2011 at 20:56

Thanks for the quick reply. The logging is only there after I notice the behavior and was for debug proposes. With it removed there is not much difference in the timing.

I am debugging now to see if there are any states that should not have been there I will update more when I have checked that.

Also noticed that the do work in the mining state needs some work. the code looks like I just hacked it together to make it work so I will try optimizing that as well because there are some conditions in it that might be causing this issue. Again I will update more once I have debugged that part of the code as well.

edit: It appears that the mining state’s dowork function is causing the problem. In this case the mining state dowork does not exit if combat is detected. So I am putting that in now to see if that fixes the problem. I have a feeling that is main cause. Next time I will review my code better before posting a thread.

_NOISEcore 101 Nov 24, 2011 at 19:28

If I understand your code correctly, states can stack up? And he will finish one state, then go to the other?

If this is how it works, then it finishes all your states before getting to the attack state. Maybe implement some sort of sorter, which re-sorts your state array, to the most important ones first.

This way, when your miner gets attacked, the defend state goes to the top of the stack and the miner will drop what he was doing, defend and then go back to his previous states.

H1veM1nd 101 Dec 15, 2011 at 18:17

I hear the dev tools for Xaitment are pretty decent. That might be of some help to check with them. Specifically about their Finite State Machines. I have been following them for some time and It looks like they recently did an overhaul to their system.

Xcrypt 101 Dec 16, 2011 at 17:15

You should check out the “State Design Pattern”. There’s no need to iterate through all the states with this pattern. You also might want to read the book “Programming Game AI by Example - Mat Buckland” In which he thoroughly explains the state design pattern and many more. I’m loving this book, it taught me so much.

This answer could also be irrelevant though, because I’m not 100% sure what your code does.