My take on “RPG Core Combat Creator” – physical combat
In my last post I justified the addition of dodge mechanics to the game’s core movement system. To briefly summarize that post, physical combat, i.e. combat that uses physics to calculate hits, requires a method for avoiding such physically calculated hits.
Extending the movement system was one thing. But physical combat also required the weapons and fighters to have actual collision. For character collision, I decided to stay with the capsule collider solution proposed in the RPG Core Combat Creator course. Thus, my characters retained the capsule collider approximating the shape of their body.
Improving the weapon system
The weapon system, on the other hand, had to be redone. I needed weapons that could be physically present in the world, both as pickables and as colliders for whacking enemies. To achieve this I extended the functionality of the course’s original scriptable object. In my workflow each weapon would consist of two prefabs (1 pickable object within the world, 1 for a weapon held in a character’s hand). In addition, the scriptable object holds all information necessary for attaching the weapon to characters. I also extended the weapon’s statistics to allow for calculating critical hit chance, bonus and stamina cost of weapon usage.
Let’s now focus for a bit on the weapon prefab. If you look closely at the screenshot presented below you may notice one thing. It has a collider, as expected. But the collider is actually inactive by default.
When a collider that causes damage is always active, it will always cause damage. Enemies will kill themselves just by touching a weapon that is not even moving. To fix this I came up with two ways of filtering hit calculation. One way would be to calculate weapon velocity. Based on that velocity the game would treat the weapon as either damaging or non-damaging. The other method would be to enable and disable the weapon’s collider based on the animation. The second option is less elegant but much easier to implement for a rookie like myself.
Putting it all together with animation events
I worked with a very flexible animation pack called RPG Character Mecanim Animation Pack from Explosive. The pack costs 99$ now. To create my physical attacks I first browsed through my animation library. I picked attacks which seemed like they would drive the weapon in such a way, so as to provide a proper collider contact with the enemy. Once I’ve picked an animation, I would edit it to add animation events on the animations timeline. Each animation event calls a method from an attached class.
The screenshot above shows an animation’s Events dropdown in the Inspector window. For my purposes I needed two methods in the WeaponSystem class: PlaySwingSound() and ToggleWeaponCollider(). The first method is rather simple and the code is presented above. The second method is responsible for enabling and disabling weapon colliders.
The GIF below shows in a simplified manner how I reviewed the animations. I picked 3 locations within an animation and added events to each of them. First I determined the place where the swing sound would start. Then, based on the collider’s position and momentum, I picked a location to turn the collider on. The last location’s purpose was to disable the collider. Of course this was based purely on my subjective feeling. I would then have to test the animation in gameplay mode and adjust the timing of the events. The starting point of the PlaySwingSound() method had to be aligned particularly well because premature or late playback of sound was quite noticeable.
Experimenting with this animation based combat system was very enlightening. I learned many things that come only with real practice. The most important points are summarized below.
Weapon colliders may not be toggled off by an animation
If there is no guarantee that an animation will play in full, than the collider may remain enabled even in idle stance. And in a dynamic system, when one animation may interrupt another, this is highly probable. Consider an example, when a character is hit in the middle of an attack and goes into the hit reaction animation before the ToggleWeaponCollider() animation could disable the collider. Now every time anyone touches the weapon, they will receive a hit. Even if the weapon’s owner is dead on the ground. But this is not the biggest issue. Now the whole cycle of collider enabling/disabling is broken. Every attack animation will first disable the collider and then enable it again. This is a showstopping bug.
The only solution I came up with without rewriting the whole system was also a very easy one to implement. It also provided a safeguard against any other bugs that could lead to a similar situation. I simply created another method called DisableWeaponCollider(). I then added it as an event at the start of animations that may potentially follow an attack animation. This way I am sure that even if the attack animation does not toggle the collider off, potentially problematic animations (like hit reactions) will perform a double check.
Not all general purpose animations fit a dynamic physical combat system
A collider based physical combat system requires much thought with regards to the selection of animations. Specific combinations of animation clips and weapon collider shapes may not work as expected. The animation might, for example, not drive the collider far enough for the collider to make contact with the target. This way even a cool looking animation may be useless for physical combat calculations.
In addition, the way animations transition from one to another plays a crucial role in collider based combat. As an example, imagine you want to create a set of sword attack animations. If your animation library contains only swings from left to right, the resulting sequences may not be fluid.
Another thing to consider is animation duration. If you give your characters a set of 4 random hit reaction animations, and one of them is much longer than the others, than this will create an obvious imbalance. The same applies to attack animations. If some animations are much slower, they will be very undesirable by the players. But we may also use such imbalances creatively to drive character progression. For example, we could assign only suboptimal animations to characters with low melee proficiency. With increasing proficiency better animations could be unlocked and slower animations could be even removed from the rotation.
In the follow up article I will provide some details into other features of my combat system, including damage calculations, armor system and destructibles.