I’m actually working on a root motion charactrer controller. I was asking myself the same question and decided to move as much logic away from the anim bp as possible. my basic concept is that you would have different “motions”, for example idle, walk/run, jump, fall, climb, scale wall, slide, etc.
Basically each motion has a base class that comes with the following pattern: InitializeMotion(), TestActivateMotion(), ActivateMotion(), TestUpdateMotion(), UpdateMotion(), DeactivateMotion(). The Motion base class also gets some basic information that could be relevant to all motions such as input, current grounding status of character, slope angle, sorrounding awareness (like edge detection etc.). It also contains a reference to things like character capsule, character mesh, etc.
I have a motion controller class, that on start of the game initializes all available motions. Each frame I run TestActivateto check if another motion should run, if so i deactivate the current motion and activate the new one. If no other motion should run I test if the current motion should continue. If not, I deactivate it, if it should continue, I update it.
Taking the concept further you can break down each motion into motion phases, for example a jump typically consists of start, rise, apex, fall and land. So in my motion update I would check for the current phase of the motion.
This allows me to have a lot of logic in self-contained units aka motions. I pass the current motion, the previous motion and the motion phase of the current motion as enums to my anim BP and work with states and blendtrees from there.
It’s like a super basic overview, if you wanna know more, feel free to text me.