Search Unity

Best approach to coding large scale battles (damage/health)

Discussion in 'Scripting' started by Joevonfo, May 24, 2017.

  1. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    Hi there

    I've been trying to create an overview of needed scripts/functions for a battle system and the best way to do them.
    Combat units will consists of a unit type and a number, displaying how many there are of the given unit - think heroes of might and magic.

    What I can't figure out is how and where to place the damage dealing/damage taken aspect.

    Example 1:


    Unit: Swordsman
    Health: 100
    Damage: 10

    Scenario: team 1 (100 swordsmen) vs team 2 (100 swordsmen).

    Team 1 attack:
    100 x 10 = 1000. Kills 10 swordsmen on team 2.

    Team 2 attack:
    90 x 10 = 900. Kills 9 swordsmen on team 1.

    And so on..
    ------------
    I guess this could be done in multiple ways, but a simple way would seem to be making an attack function in the swordsman script, telling it to deal 10 x count damage to the enemy unit targeted, subtract that amount from enemy total health and have that units script calculate the current number of swordsmen.
    That should work right? (or is there a smarter way to do it?)

    What I can't figure out is how to deal with a more advanced units.

    Example 2:

    Unit: Knight
    Health: 150
    Damage: 20
    Special: Reduce all damage received by 7.

    Scenario: team 1 (20 knights) vs team 2 (100 swordsmen).

    Team 1 attack:
    20 x 20 = 400. Kills 4 swordsmen on team 2.

    Team 2 attack:
    94 x 10 = 940, but with knight reduction it's effectively 94 x 3 = 282. Kills 1 knight, and deal 132 to another.

    and so on..
    ------------
    How would you guys go about implementing abilities like this?
    I can't figure out what part of the code to implement the damage reduction.
    Is the best approach to make an if statement, that check if the opponent have any sort of damage reduction, before dealing damage?
    Or is it smarter to code units with damage reduction so that the unit, every time it has it's health lowered, check how many units attacked it, and reduce the damage?

    When talking about the best approach I guess simplicity has to be considered, but also what is best for future implementation of new abilities. I mean if I later on wanted to add a %-based damage reduction, the first approach would require additional scripting to all units.

    A third option would be to make some sort of combatdamageManager i guess..

    Any of you guys have any good advice or bright ideas on this matter?

    Thank you for reading
     
  2. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,537
    You could make Unit count their total HP, then when you reduce HP the count drops accordingly?
     
  3. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    But that does not solve the damage reduction problem..

    Lets use the knight with 150 health and 7 damage reduction as an example, and we make a line saying "health = damage taken - 7", that would only work vs a single enemy.

    If a single unit deal 150 damage, it would leave the knight at 7 hp.
    if a single unit deal 157 damage it would leave the knight at 0 hp, killing it.
    If 10 units deal 20 damage each, they would deal 193 damage, killing it, rather than the intended 130 damage.
    If 100 units deal 5 damage each, they would deal 493 damage, enough to kill 3 knights, rather than the intended 0 damage.

    A solution would be to divide the damage dealt with enemy count, and then multiply that number by 7, subtracting that number from the initial damage dealt, but I'm unsure how to do this (a way to code a reference to what unit did the attack, in a universal sentence working for all enemy units)
     
  4. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,537
    In that case I think you need to process damage on the "group" separately for each different type of enemy it has.

    So a group of 10 Knights and 10 Pikemen take 400 Damage.
    Knights and Pikemen both have 100 HP, but Knights reduce all damage to them by 5.

    The damage loop would have to process each type of enemy separately, but could still do the types as a whole.

    Knights would take IncomingDamageAmount / (Hp/UnitTypeTotalHp - DamageReduction) or something.
    While Pikemen would simply take IncomingDamageAmount / Hp/UnitTypeTotalHp.

    Maybe those formulas are off, but I think it's an idea that could work. Make it basically just calculating damage per unit type group.
     
  5. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    Unless I misunderstand what you're saying, that's resembling the second approach I mentioned..
    The drawback to that approach is that every time a new ability is introduced (programming wise that is), the code of all unit scripts have to be adjusted to handle this new type..
    I don't think it's a bad approach, but I was just wondering if there wasn't a smarter one?
    I'm almost certain that there is (that has been the case with most of the ideas I've come up with), but as usual I just can't figure it out :D
     
  6. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,537
    Well, you can make a ScriptableObject for Perks, then put those perks on the Unit Group and in the damage loop make it loop through all Perks on that unit group and fire Process() or something - where in Process() it does something to it's owners, or reduces some value, or whatever.

    There is a video in the Learn section by Richard Fine on ScriptableObjects that is really excellent and worth your time to at least scrub through for the good parts. It's literally going to change the way you lay out code architecture.
     
    Joevonfo likes this.
  7. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    Not sure i understand everything you're suggestion, but I'll try to play around with it :)
    Thanks for the suggestions!
     
  8. Donay

    Donay

    Joined:
    Apr 28, 2017
    Posts:
    70
    Is this what your after?

    damagePerUnit=attackingUnitBaseAttack-defendingUnitSpecial
    If (damagePerUnit)<0 then damagePerUnit =0
    totalDamage=damagePerUnit*numberOfAttackingUnits
    numberOfUnitsKilled=Mathf.Round(totalDamage/defendingUnitsHP)
    if numberOfUnitsKilled>numberOfDefendingUnits then numberOfUnitsKilled=numberOfDefendingUnits