Skill based leveling system -- need help.

I’m fairly new to programming and Unity in general, but I’ve been going through a lot of tutorials, etc. lately, and have gotten to the point where I’m bad at modifying things to fit my purpose, instead of just horrific.

Any way – I have an idea I’d like to implement, and I’m fine with figuring out how to put the pieces together myself, but I’m not really sure what pieces to look for.

Here’s what I’d like to create –

RPG-type game, killing things gets EXP, player is able to spend EXP. Unity/C#.

Player can spend EXP on a wide range of skills, for now (since I’m still learning and I’d like to get the concept down and then expand it), I’d like to have skills like this:

combat>offense>swords
combat>offense>daggers
combat>defense>armor
combat>defense>dodging
magic>elemental>fire

So, the player has access to all of these skills at the same time.

To give further example, let’s say wanted to spend EXP on combat, leveling it from 1 → 2, their levels would look like something:

combat 2> offense 2> swords 2
combat 2> offense 2> daggers 2
combat 2> defense 2> armor 2
combat 2> defense 2> dodging 2
magic 1> elemental 1> fire 1

Okay, so now they get some more EXP and this time they decide to spend it on raising swords, 2 → 5, their new levels would look like:

combat 2> offense 3> swords 5
combat 2> offense 3> daggers 2
combat 2> defense 2> armor 2
combat 2> defense 2> dodging 2
magic 1> elemental 1> fire 1

(combat>offense is now 3, because swords 5 and daggers 2 averaged out is 3.5, rounded down. Combat is still 2, because offense 3 and defense 2 averaged and rounded down is still 2.

The ‘top level’ (combat, magic) would then be averaged out to determine the players actual level, rounded down to the nearest whole number.

This is a fairly complicated system, I think – that’s why I’m not entirely sure the best way to implement it. Any ideas are appreciated!

If you don’t know what Inheritance is, I highly suggest you take a look at it:

As it will prove very useful for a system like the one you are trying to create.

With this, you can create a “base skill” that includes all the basic information that all of your skills share, such as accumulated EXP, EXP to level, and current level, as well as any methods that all skills ought to have, such as AddEXP.

From there, you can create other, more specialized Skill types that inherit from this base skill, but add their own functionality.

Whenever you’re dealing with a lot of data, think data-driven design. Don’t try to manage your specific bits of data directly in code. Instead, write code that can work with data in a general sense. Here are a couple presentations: Cornell, UMich. Those presentations focus on the whole development pipeline, particularly how data-driven design lets non-programmers tweak data. But from a programming perspective data-driven design is important for a few reasons:

  • It simplifies the code. Instead of having a tangled mess of several one-off scripts with complicated inheritance trees to separately manage the data of swords, daggers, dodging, etc., you’ll have a single script to manage all skill level data.

  • It separates data management (keeping track of skill level numbers) from data use (using those skill level numbers to determine to-hits and damage).

  • You can add new data points (new skills) without having to modify your existing code.

If you write down what you want to do and it starts to look like a data table (as in your original post), this is a good clue to consider data-driven design.

Here’s a simple example of a data table:

Skill   Level  Influences
Swords     5   Offense
Daggers    2   Offense
Armor      2   Defense
Dodging    2   Defense
Offense   (3)  Combat
Defense   (2)  Combat
Combat    (2)  (none)

Swords is level is 5 and Daggers is level 2. They both influence Offense, so Offense is computed to be (3). You could write a single class (let’s call it SkillTable) that maintains this table and computes values such as Offense that are based on other values. The SkillTable class wouldn’t need to know specifically about “Swords” or “Dodging”. To the class, they’re just data points in a table.

You can add new rows to this table such as:

Fire       1   Magic
Earth      5   Magic
Magic     (3)  (none)

without having to modify the class.

The SkillTable class would provide methods such as GetSkillLevel(skillName) and SetSkillLevel(skillName).

The other side of the house is using the data. Since each skill actually does something different in the game world, you may need to write code specific to each skill. You could use inheritance for this part, or you could devise a way to handle it more generically. In either case, your code can use the SkillTable to get the character’s current skill level. For example:

public bool CanBlock(int attackValue) {
    var defenseValue = skillTable.GetSkillLevel("Defense");
    return (defenseValue > attackValue);
}

I know I glossed over a lot of implementation details, but I just wanted to put in an argument for why you’d want to use data-driven design rather than code-driven design for something like this.