Discussion: melee damage calculation strategies for a 2.5D game

Hi all, I have an interesting programming/logic challenge I don’t specifically need to solve but am interested in solving for a 2.5D indie game I’m building.

I have some melee animations and a sword with a rigid body and collider attached. Picking up collisions is no problem, but here’s the thing: there are different ways to distribute damage. Weapons (and spells, and anything that can damage something) have three types of damage applications:

  1. full: entire damage amount is dealt to each target
  2. divide: damage amount is spread evenly between targets
  3. diminish: damage amount drops off at a rate defined by a formula that outputs a linear decline

I mean there is also single target but it’s not relevant here.

For the 2nd and 3rd types, we have an interesting problem. Say we have 3 enemies closely grouped. A 2H sword is swung and passes through all 3 units. The collision events for each unit fire during Fixed Update (as specified on the OnTriggerEnter docs page) - but of course, at separate times.

By waiting until the melee swing “finishes” (triggered by an animation event) I can collect each collision and at the end of the swing, feed the total amount of enemies into the damage handler which is required to calculate divided or diminishing damage types.

This introduces a delay between when the sword passes through the enemy and when damage is dealt. It’s not game breaking, but it is a bit off putting and will be more noticeable for heavy, slow swinging weapons.

The other approach is to attach a semi circle trigger collider to the attacking unit/player, and at the beginning of the swing, check what units are within that semi circle collider.

This would mean I could trigger the “damage” when each collision occurs, but this introduces another problem: if a player rotates while attacking (which the game in its current state allows) that initial semi circle check will be inaccurate. It also means figuring out a range that “mirrors” the sword’s swing trajectory but doesn’t necessarily match it, we are just approximating, so we loose a bit of skill play here.

Another benefit using this approach is that that all 2H swords (even if a few pixels longer/shorter) would have the same trajectory/range check which makes for a more consistent melee play style across different weapons that share the same type.

If any of you have experience with combat and damage systems and have encountered this problem before, I would love to hear some ideas - it’s my first time building these systems from the ground up.

Enjoy your Xmas holidays peeps (if you have any)!

3rd is simple, start with a value of 100% dmg, for each target you collide you reduce the % of damage the next collision will deal

for the 2nd, dividing dmg before enemies are hit doesnt make much sense. If you need to do reduced damage to the 1st collision that means that you are expecting a second collision. If when the sword reaches the 2nd target the enemy has moved and there is no collision then there is no reason to divide damage for the 1st hit.

You can divide damage if you are sure that all enemies in the path of the sword will be hit from the moment when it collides with the 1st enemy, by having a larger collider that maps the full swing of the sword and detects the existence of more than 1 enemy within.

The theory is that you cannot produce a reaction in advance ( dividing damage ) that is dependant of an uncertain causation that happens in the future ( there will be a 2nd enemy hit at the end of the swing )

you would be trying to predict the future in a situation where the future is unpredictable

IMHO most games calculate damage at the instant the attack is made. They often add a delay to the reaction to hopefully match the delay of the attack animation. This can be unrealistic if you swing a faster or slower weapon, or purposely turn or attack from a funny angle, but it’s fine. Because, as you wrote, your sword is passing through their body but somehow not cutting them in half. If you can’t solve that horrible unrealism, it hardly seems worth it to worry about something lesser.

1 Like

Hey, thanks for your replies.

I tested out the collider approach which uses a sphere to get the number of enemies in advance, which allowed me to apply damage at the moment of collision, but the tradeoffs were too high: I now had to call the damage controller multiple times and there were edge cases where the enemy could move out of range of the attack and would have had to handle that somehow.

In the end I stuck with the original workflow. For anyone interested:

Attack Button Pushed > Weapon Animation Clip Plays > Animation Event: Melee Start (signals frame to begin collecting collision events, spawn VFX) > Collision Event: Enemy Hit (play Enemy Damaged Clip, store reference to enemy) > Collision Event: Enemy Hit (N) > Animation Event: Melee End (call damage controller with damage amount, num enemies, and damage application type)

Turns out as long as the enemy plays the “damaged” animation clip as soon as the collision occurs, the delay in applying damage is barely noticeable at all and ended up in a much cleaner work flow and simplified code.

End result: 8fu7yv