Currently I am working on a group project to make a tower defense game. I want to add the following damage and armor types to make the game more dynamic (quite similar to Kingdom Rush):
Armors:
Light, Medium, Heavy, Mega Armor (15%,30%,45%,80% physical damage reduction respectively)
Light, Medium, Heavy, Super Resistance(15%,30%,45%,80% magical damage reduction respectively)
I am a newcomer to unity, and I am unsure of how to implement the scriping of of assigning these types to the projectile and enemy prefabs, and interaction between them.
you can make enum for each type of armor and damage (and let it just in the assets folder).
Not sure if this should be class (if so, then just make it as class and use as example: NameOfClass.PhysicArmorType.light).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PhysicArmorType
{
none, light, middle, heavy
}
public enum MagicArmorType
{
none, light, middle, heavy
}
public enum DamageType
{
physical, magical
}
then make prefab for arrow, fireball or what ever
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arrow : MonoBehaviour
{
public float damage;
public DamageType damageType;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag ("Enemy"))
{
collision.GetComponent<HpController>().DoDamage(damage, damageType);
}
}
}
and on the enemy hp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HpController : MonoBehaviour
{
public float hp;
public MagicArmorType magicArmorType;
public PhysicArmorType physicArmorType;
public void DoDamage (float damage, DamageType damageType)
{
switch (damageType)
{
case DamageType.magical:
switch (magicArmorType)
{
case MagicArmorType.light:
hp -= damage * 0.75f;
break;
case MagicArmorType.middle:
hp -= damage * 0.50f;
break;
case MagicArmorType.heavy:
hp -= damage * 0.25f;
break;
default:
hp -= damage;
break;
}
break;
case DamageType.physical:
switch (physicArmorType)
{
case PhysicArmorType.light:
hp -= damage * 0.75f;
break;
case PhysicArmorType.middle:
hp -= damage * 0.50f;
break;
case PhysicArmorType.heavy:
hp -= damage * 0.25f;
break;
default:
hp -= damage;
break;
}
break;
}
}
}
The above example is 100% viable, but since I already wrote this up I’ll leave it here as well. There’s a thousand ways to program a system like this. Just go with whatever makes the most sense to you.
My first instinct would be to use scriptable objects to store armor data. A scriptable object is a class that can hold data and run functions, but is not a monobehavior and does not get attached to a gameobject as a component. You make a definition file for it, then make instances of it and customize the data.
For instance:
using UnityEngine;
// define types of damage, could be in its own DamageType.cs file
public enum DamageType
{
Physical,
Magical
}
[CreateAssetMenu(fileName ="New Armor Type")]
public class Armor : ScriptableObject
{
public DamageType damageType;
public float damageReduction;
}
After defining this, if you right click in your project files and look under the Create menu, there will be a new entry at the top that says “Armor”. If you click it, it creates a new armor asset. You then name it, and configure the damage and reduction for that armor in the inspector.
Then your units or towers could have a field of type “Armor”, and you can drag one of those assets into the field to define their armor.
Here’s an example usage:
using UnityEngine;
public class GameUnit : MonoBehaviour
{
public float health;
public Armor armor;
public void TakeDamage(DamageType damageType, float damageAmount)
{
// if you assigned an armor asset of the damaging type
if (armor != null && armor.damageType == damageType)
{
// reduce the damageAmount by a percentage
damageAmount -= damageAmount * armor.damageReduction;
}
health -= damageAmount;
}
}
exactly And I think scriptable objects will be better for this task (they are not so heavy for pc) , still I didn’t used them much. I should look at them too
So far so good, I created the armors assets, but how do I go about applying the damage types to each kind of tower projectile? How do I add the armor fields to my goblin and orc prefabs? Should I place the armor assets in the scripts folder or the prefab folder?
The easiest way would be to give your projectiles a float field for damage, and a DamageType field, configure those on the prefab. When your projectile hits an enemy, call the enemy’s TakeDamage function and pass the damage and type to it.
I like to use an interface for things that take damage, so that the projectile doesn’t have to look for specific class types, but if you’re not familiar with interfaces then don’t worry about it. If you’re interested I can explain that approach though.
Look at my GameUnit example above for how to add the armor field. You can add a new public variable of type Armor, and assign one of your armor assets to the prefab.
Those armor assets are technically speaking “scriptable object instances”, so I would put them in a Configs folder, and maybe in a subfolder “Armor”. But they can live anywhere, so just organize as you please.