Dev Deep Dive 01: Designing and Programming Moves (Patreon)
Content
*future feature as of writing of this post
The first task was to write a technical specification document. Personally, I like to keep these very rough.
Note that there’s not a lot of detail here. As prototyping went on, more and more features were added and changed as discoveries were made during early prototyping. Personally, I feel it’s a mistake to overdesign without diving into code as it limits the possibilities you can discover during rapid prototyping. One of the things not mentioned in the document is buffering inputs, a feature added very early in development but not at the time of writing the specifications.
I also knew some features were going to be important for a good attack system:
- An animation-driven system for Moves. Very little coding should actually happen for individual attacks; the animations should reference a bunch of prebuilt functions in code and pass along parameters as necessary.
- Iteration for frame data (cancel windows, attack active frames, etc) need to be fast. Modifying a huge list of milliseconds is far less intuitive compared to something like a timeline with bookmarks.
- Some kind of lunge to give the attacks some weight
- A hard and soft lock on. the soft one needs to be smart enough to detect what enemy the player wants to hit most of the time, with or without input.
- Input buffering for combos
- Various kinds of cancel windows
Soon after, the early prototype was created:
In this prototype, the input buffering, move linking (more on that later), lock-on, basic lunging (capsule-driven), dealing damage, and spawning weapons are implemented. At this point, a very rough idea of how long various parts of the animation should be are also figured out.
Advanced info for the Unreal-savvy: frame data (active windows, cancel windows, damage, weapon spawning, etc…) is passed along from Anim Notifies to the relevant Actors. AnimMontages contain all the AnimNotifies with frame data. Most of the visual / audio feedback notifies such as footsteps, sounds, etc. are stored in the animations instead. A custom AnimNotify class containing all the necessary frame data functionality was written to handle frame data.
There’s a time gap between this stage and the next stage while the character art is being created. At some point during the character modeling process, I drew a bunch of sketches to help visualize the various combos. Most of them get scrapped or modified throughout the development process for various reasons, though. It’s never a direct line from design to implementation:
Some basic, but important things to consider for the design of attacks are speed, range, and damage. The player has access to light and heavy attacks, so when the player makes a choice on what attack to make, it is a choice on what effect is most important to the player at the time, and how health the player is willing to risk to execute it. A very fast attack should have low range and damage. A very slow attack should have a lot of damage and/or a wide range. In choosing a slow attack with a lot of windup, the player is sacrificing speed and introducing a longer period of vulnerability in exchange for greater damage, range, or some other beneficial effect. In addition, there are other parts to consider, like whether an attack launches an enemy or stuns them.
Now, let’s jump ahead and look at the Animation Montage Editor in unreal and see how the data is stored for Amelia’s basic magical girl kick:
The important bit here is labeled Notifies, where the frame data is stored:
The bottom numbered section is the timeline showing the current playback point of the animation in the editor. The white bars with vertical lines are notify tracks. The little red ticks with the words to their left or right are the Notifies, which tell the game what to do at this frame in the animation. It doesn’t matter which track the Notifies are on, having multiple tracks just makes it easier to work on overlapping Notifies. Animation for Mahou Arms is authored and exported at 30fps.
If we draw on this screenshot, we can see the frame data more clearly:
Note the long Cancellable by Moving window. This part of the animation is called the follow-through, which plays if the player decides to let the character stand around after executing the attack. Most of the time it will not be seen as players like to keep moving, but having this helps add life and weight to the character’s actions. This section was completely omitted in earlier versions of the animations to save time, but it was later added in an animation polish pass.
Update: After a refactor, NotifyStates were implemented and a large portion of the Notify system now uses States. Here's what the updated Notifies bar looks like:
For most moves, it’s important for attacks to have a short startup time, about 2-12 frames at 30fps for most attacks. It’s less important for the follow-through to be fast. Having a short startup time makes the game feel more responsive, which is really important since MA is a fast-paced game. This short windup time means that sometimes it’s very hard to give the animation the sense of weight it needs, so animation is always a balancing act between responsiveness and weightliness.
Every animation needs to be edited and tested many times before it’s good enough to be used as a move. Where the attack ends up landing is heavily animation-driven too, so that is another reason animations need to be constantly tested. For this reason, rough animation block-ins are implemented in game, tested, and tweaked before they’re polished.
It’s not named well, but EndCancelable blocks jabs from cancelling the move. End, if placed before the end of the animation, makes the move to end early, which is usually used for testing purposes. In the refactor, it is called BlockJabCancel.
Links are the point in a combo where the game reads the buffered inputs and sees if the next input in the buffer has any valid moves in the combo. If it does, it will play the linked move. In this move, pressing Light will link to am_punch01, and pressing Heavy will link to am_swipe09. duplicate links are included for if players decide to delay the combo a little bit by pressing the button a little later.
In previous versions, Do Autodash was a notify used to do a cheap form of capsule-driven lunging, but it had a lot of unintended consequences. One of them was the difficulty in controlling the distance for the lunge, since it’s often physics or velocity-based. In the current version, lunging is handled through root motion in the attack animation data.
I realize this was very technical, but I hope it gives some insight into what goes into the design and programming of Mahou Arms’s combat. I kept it mostly technical since you guys asked for Game Design / Programming, so there’s not much talk about animation here. If you are a developer, I hope this article helps you make your next erogame. Let me know in the comments below if you have any questions.
Thanks for reading!
-Paperbag