So, this isn’t necessarily UE4 related, so not sure if I’m posting in the right forum.
The other day I had to rebuild my work-in-progress for various reasons. One thing that was sorely missing from my game was a way to manage the various states it may be in at any given time, so I thought this is the perfect opportunity to explore some solutions. I had played around with FSMs in other projects, and knew they were a very powerful way of structuring the flow of things, but I didn’t realize just how powerful they are until I implemented them for my game. I used essentially the ShooterGame state stuff as inspiration, since there are a ton of ways of implementing an FSM.
Boy. I’m telling you, state machines are so powerful, it is like night and day now. The ability to:
Do something when the state begins
Do something while in the state
Do something when the state ends
is so incredibly powerful. It made almost everything related to the state of my game a breeze to setup. The flow of my game state is rock solid now, even with multiplayer (by replicating authoritative state changes to the clients, etc.)
Just some random thoughts. Curious if anyone else has had a situation like this where their brain just lit up with possibilites after discovering something cool.
All I do is use two enums vars – current state and pending state and make a bunch of OnBeginWhateverState, OnTickWhateverState, and OnEndWhateverState functions that are called at the appropriate time. Totally hacky and hard coded and all that fun stuff, but it really works like a charm. A tick will check if pending state != current state, then change to the new state if true.
I thought about using interfaces, but my first pass I just strung it all together without a whole lot of concern about being overly generic.
Really – If you take a look at the ShooterGame code, I did it very similar to that, just using blueprints.
Oh man, you should get into BP interfaces. It took a little while for me to figure them out but now that I have I’m totally dependent on them :P. It’s so much nicer to not have every state dependent BP listening for a state change on every tick.
If you’re interested in learning I could post up a little example mockup explaining how it works.
Step 1:
Create your Blueprint Interface file, and add all of the states you need as functions. I’ve abstracted it down to A B and C to keep it generic, but a meaningful name is useful. At this point, you should also have a matching enum file.
Step 2:
Go to your GameMode BP and make a public variable of your enum. (This doesn’t have to be your GameMode BP, you could use GameState or anything else, as long as you can reference it. ) Now you have a way to find the current state from anywhere.
Step 3:
Attach your Blueprint Interface to every Blueprint that needs to listen for state changes. If you can’t find the place, you have to select “Class Settings” and then select from the “Add” dropdown in the Interfaces section.
Step 4:
Go back to your GameMode BP (or whatever you’re using), and set up as following:
This will update the enum whenever a state has been triggered.
Step 5:
This step is more of a convenience, but at this point I like to make a macro for querying the current state, so that I don’t have to do it manually each time I need it.
At this point, you’re pretty much set up to use your Interface system how you want to. In this example, we have the Player controller listening for each state change. We’re also using the macro we made earlier to bind Left Mouse Button to different actions depending on the current state.
Finally, the event on the right is illustrating how you can trigger state changes. Using that method, the signal gets sent to every Blueprint that’s listening for it (all of the blueprints that are attached to the interface).
Note: A BP doesn’t need to be attached to the interface in order to send the state change signal, it only needs to be attached to receive it.
Cool, thanks for sharing! Always interesting to see other peoples solutions to their problems! While this doesn’t really do what I need in my particular case, it is definitely something I will take into consideration on future designs.