Tower Defence stat storing system

Tower Defence stat storing system

I'm trying to find a smart way to store and retrieve stats for a tower defence game, but am currently unsure as to which approach would be best.
Description: 
The stats system should quite basic, there are 4 different towers, with up to 5 different levels each.
One important requirement is that the stats should be stored in an XML file so that the game designer easily can access and balance the stats. (He knows nothing about programming)
I can see two ways of doing this:

By creating a TowerStats class which hold values for one type of tower for one level. Something like:
public class TowerStats2
{
    public TowerType type;
    public int lvl;
    public int damageLow;
    public int damageHigh;
    public float range;
    public float attackFrequency;
}


Then i would load the stats from the XMl file using Linq and XDocument and load it directly into a TowerStat List. I would do this for each tower so in the end there would be 4 different List's which would hold the different level stats for the specified tower. 

gunTowerStats[0] would hold level 1 stats of the gun tower 
rocketTowerStats[2] would be level 3 stats of the rocket tower

When a new tower is bought by the player or when a tower is upgraded, the stats would then be taken from the List so something like:
UpgradeTower()
{
    lvl++;
    towerStats = gunTowerStats[towerLevel - 1]
}


Alternativly I could hardcode all the values, and have one big class which would go something like this:
gunTowerDamageLvl1 = 4;
gunTowerDamageLvl2 = 8;
gunTowerDamageLvl3 = 15;
rocketTowerDamageLvl1 = 10;


you get the point.
I know that hardcoding is never never really the way to go. But does that also count for this kind of example where all possible tower attributes are known and will not change? the only thing that will change are the values of these attributes.
Question
I'm personally in favour of the first way, but I must admit that I find both ways a bit clumsy, would it be alright to do it one of these ways or is there a much smarter  and more obvious way to deal with this that I'm completely unable to see?
I hope my question is understandable.

Solutions/Answers:

Answer 1:

Firstly, I see no issue (in principle) with the first approach, the XML file. Easily editable, easily extendable.

Secondly, I would still recommend not using XML, and using JSON instead, since it’s going to make the saving/loading of the stats significantly easier:

[System.Serializable] 
public class TowerStats2 
{
    public TowerType type;
    public int lvl;
    public int damageLow;
    public int damageHigh;
    public float range;
    public float attackFrequency; 
}

And then instead of having to write annoying boilerplate to convert to/from XML, you can just do

var stats = JsonUtility.FromJSON<TowerStats2>(jsonString);
string jsonStats = JsonUtility.ToJson(stats);

And if you ever add new attributes, it’ll still work.

Thirdly, if the XML files are inside the unity Assets folder, meaning to modify them, you need to actually open the project in unity, meaning your designer needs to have unity editor and work within it anyway…
…you might want to look into ScriptableObject, which is basically… A C# class that the unity uses as a prescription for a data storage file, which you can then create in your project as an asset.

How that works in principle is that you can create assets (data files) equivalent to the XML/JSON ones you’d use, except all of the deserialization is automatically handled by unity, you can edit the data in them via inspector, and you can also readily plug them into C# code, assign them into fields in Inspector, all the good standard Unity Editor stuff, so now the workflow for your designer is literally the same as doing anything else within unity editor. So if there’s no need for the files to be external to the project (meaning they would be besides the compiled data, still accessible and editable even within the built game), this would be probably the easiest and “most native to Unity” way to do it.

Answer 2:

Although I think @sh code ‘s answer is the correct way to go, I wanted to add that Unity’s new prefab variant workflow is really useful for making related objects have slightly different properties. It also works great when the visuals need to match the variations in internal state, since each variant can have a different meshes or effects.

You could also take a hybrid approach. Use prefab variants that access different scriptable-object settings for internal state, while still being able to vary the visuals.

References