How do you mean synchronize between them? You mean for multiple state machines? What I do is when the player takes damage, first I set a bool that will switch the output from one state machine to the other… Then, I unset any state specific booleans (i.e. I call functions which cancel states like dashing or hovering or any other state that the player consciously enters)… From there, I just let the machine work. The player will be guaranteed to be in a grounded-idle or falling state when the blend-poses-by-bool that switches between state machines flips back.
As for Montages… Well, the thing is, elegance exists where you let it. Montages are great for combos because they can be configured easily to perform frame-synchronous matchups of animations. Typically, for combos, you don’t want to allow the player to cancel a punch partway through with the second punch, you queue the input on the hit before (so what you press WHILE Punch1 plays determines what plays immediately after it). Montages are WAY more elegant at that than State Machines because of Section operations—if you define an “End” section for each hit, you can configure a montage to default to Punch1, Punch1_End, and if Punch is pressed during Punch1 you can tell the Montage “Set Next Section Punch1, Punch2” with a node and it will automatically make Punch1 lead into Punch2 at the same frame it would normally switch to Punch1_End. These changes reset to default every time the Montage stops so the logic basically just works for combo tree navigation.
And since Montage Sections have easily gettable Name values, it’s trivial to “Get Montage Current Section” and hit a Switch-on-Name node so that whichever attack key was just pressed, that execution path can be forked based on the currently-playing animation to the desired next move (i.e.
Punch > GetMontageCurrentSection > SwitchOnName
> On Punch1, SetMontageNextSection Punch1, Punch2
> On Punch2, SetMontageNextSection Punch2, Punch3
> On Kick1, SetMontageNextSection Kick1, PunchFromKick
> On PunchFromKick, SetMontageNextSection PunchFromKick, Punch2
Etc. This makes the actual Event Graph nice and tidy, with basically no necessary variable values to set AT ALL (with a state machine, you’d need to store an Enum or Name for the current attack, set another Enum or Name for the next desired attack, and use Anim Notifies at key frames in the anim to Set the former’s value to be that of the latter to trigger the actual State Transition Rule each time) and easy to read.
The counterpoint is the Montage ITSELF is going to be an enormous mess because rather than a nice tree, each anim must be laid out more or less linearly. And you have to take care when setting up the montage (my advice is to keep as many notifies and curve values stored in the anims themselves, rather than the montage asset, as you can… And ALWAYS set your Sections to be Relative rather than Absolute) or redesigning move anims can break all subsequent anims in the Montage by misaligning stuff (I recently had to go back and manually transfer like ALL of my Montage notifies and curves for various attack stuff to child anims because I tried to extend one move’s play time by 20 frames to add a new branch and since it was the 5th move in the Montage layout, moves 6 thru 19 were broken when the curve data that corresponded to them got misaligned).
But I suppose that’s a tradeoff you have to decide on. Personally, I’d rather confine my spaghetti to an asset wherever possible and leave my Event Graph and State Machine legible if I can, since they’re already enormous messes and they don’t need any more help from me looking atrocious.