HELP!!! How to keep track of all my movement abilities in c++

Hey!

I am creating a first person parkour game with a couple of friends. I use the movement component for walking jumping and crouching and we already have a slide ability. We would like to use c++ for as much as possible.

I am starting to notice that its really hard to keep track of what state the player is in. So I have if statements everywhere to keep track of what the player can and cant do. For example (in the crouch funtion I have if statements with “if player is not sliding, if player is not jumping, if player is not running, then you can crouch”) but this is gonna be really bad if we add more movement abbilities.

In unity I would create a finite state machine, and there are a lot of good tutorials to help me there. but for unreal I can barely find anything.

How do games made in unreal keep track of all there movement abilties and keep the movement script clean? thank you for reading and helping <3

Unreal has state machines in the animation blueprints.

It also got State Trees

Here is an ok tutorial describing state trees and movement

And you have the c++ implementations that you can use as base classes where needed to access them from code & mix with blueprints where its necessary.

You can usually find the c++ equivalent with the prefix

  • u for components & objects
  • a for actors
  • f for structs
  • i for interfaces

etc

1 Like

this will depend on how complex your state machine needs to be:

there is the limitation that getting data out of the Unreal Animation State Machine can be cumbersome without having it share references to active objects as an interconnect.
in that way having the Unreal Animation State Machine control gameplay logic is not ideal, but far from impossible.

if you consider programming/scripting as glorified problem solving then with enough determination you can accomplish anything (getting Doom to run on a printer touch screen “sure”)

on the point of “would like to use C++ as much as possible” there are things that are much better suited in blueprints then C++:

  • getting things from the Content Browser/Drawer assigning them to an exposed Pointer in a Blueprint is much more consistent, and safer then having a Runtime-Resolved-Hard-Reference silently fail because someone renamed, moved, or both to a Blueprint/Asset, or you manually tried to copy the Path/Name of something (the worst type of bug to track down is when you get Nothing as the output)
  • assigning things by specific FName (sockets/channels/Actors) similar to the Content Browser/Drawer especially if the FName is assigned at runtime by the Engine
  • Managing State Machines, especially if “fuzzy logic” is necessary
  • fine tuning member variable values to specifics (this includes manually applying the blueprint wrappers onto your C++ Actors/Pawns/Characters)
  • breaking include hierarchies where technically anything can know about anything.
  • a wide breadth of tutorials and guides (it is C++ that typically needs to be specified when looking things up)

the biggest reason to do things in C++

  • performance (Blueprints get run through effectively a JIT Virtual Machine, unless you make BlueprintPure functions which then that is injected into the Virtual Machine instead). in Unity both the C# and their Visual Scripting things went through technically the same VM built on top of their proprietary C++ backend, so there wasn’t “that much” performance to be gained either way (unless you absolutely didn’t like how something was done)
  • finite control of function flow up to and including pointer magic (please don’t do this on UObject things, and DO NOT: “Assume the Size of Int” or the size of TChar)
  • “easier” creation and maintenance of Heap allocated pointers, and Stack allocated References. (for UObject derived things do not use new this can and will cause memory leaks)
  • ability to use raw C++ classes and structs (the lifetimes of these must be manually managed up to and including “every new should have at least 1 companion delete”)
  • ability to utilize several classes/types exclusive to C++ this list gets big quickly.

why not just use an enum? if you can only be in one movement mode at any time?

otherwise i’d use tags, say slide adds a tag cantcrouch, jump can add the same tag the on crouch all you need to check is does it have the tag cantcrouch

1 Like

■■■■, Thank you for this indepth answer!

I dont understand everything that you are saying, I am pretty new to unreal and c++. So the way I understand is if you need to change materials for example, or play sounds, its way better to do that im blueprints because you need to get the sounds and materials out of the content browser? I also heard that for example, UI is way easier to do in blueprints.

Managing state machines: Way better to do in blueprints because you can physiccaly connect states and stuff? (It is possible to do the state logic in blueprints, and do the code for the movement abbilities in c++, right?)

What do you mean with the “finite control of function flow up to and including pointer magic” part?

I do think I have come up with an idea for my problem tho, I am going to create an enum with all the available movement states. Then I am going to have a current state variable. Then for each movement state I will create an enum with the movement states where it can continue on.

for example, for sliding I will create an enum with just sprinting. Because you can only slide if you are sprinting.

and for crouch for example, I will create an enum with, idle, walking, because you can only crouch if you are in those states.

so then if you want to jump, you press the jump key and call the jump function, then it checks in his own enum if current states is in the enum. if it is, it will change the current state to jumping and jump, if its not, it will return and not do the jump.

this way I will be able to keep track of what the current state is, and if a state can happen after the current state.

sorry if its not clear to you :slight_smile:

I really appreciate your information and help tho, learned a few things again <3

yeah, Im gonna try an enum, my idea is in another reply

thanks for the help

It is possible to do the state logic in blueprints, and do the code for the movement abbilities in c++, right?

possible “yes”, and sometimes ideal
if there are “magic numbers” (speeds, weights, time-delays, cooldowns) it would probably be better for those to be at least exposed to blueprints for more rapid iteration, especially if these would be header file changes (these should be avoided with Hot Reload because the Header Tool and Build Tool will not make full passes and might require manually editing .generated files which should be avoided)

which ties into the other

What do you mean with the “finite control of function flow up to and including pointer magic” part?

sometimes we want very specific flow states of a function/event, like switch-case into if branch into switch-case might look like a spaghetti nightmare in blueprints (you can hover over a connected pin in blueprints and it will highlight its path) while in C++ will be cleaner by just falling indent flow.
C++ can do direct type conversions (similar but not the same as type coercion like in Java) of integral, or near integral types, like converting and enum : uint8 into the uint8 format is simple and clean in C++ while in blueprints we almost need to write a blueprint Function Library helper functions for consistency (I wish I was joking blueprints only sometimes allow the conversion)

"pointer magic" might be the part you are most questioning:
a pointer is just a memory address somewhere on the heap where that object actually lives, so if we take the value the pointer-points-to we can then do operations on it to say gain access to private members, or traverse an array by taking the pointer address and doing arithmetic on it to get to the next index. this is why I said “DO NOT Assume the Size of Int, or TChar” because these are both platform dependent, and the TChar can be language/character set dependent as well.
these is also things like void* which is a type-less pointer that can then be cast to other types almost like creating them without calling the constructor (Don’t do this with UObjects)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.