A skill concept, advice on how to implement?

Is this the right place for this thread?

I want to create a skill system with a central "database that stores the skills (and respective base information) and allows me to update, add and remove skills without actually affecting the code of my concept. This gets coupled with Attributes and Stats in a Base character class to be instanced by each character, player and non-player alike.

Basically, its a skill-based leveling system with a huge variety of skills. Skills get discovered along the player’s journey, and improve with use. Each skill has its own experience meter and levels up when enough experience has been gained. Character experience is only affected by skill experience, and characters level up when the minimum experience requirement is met. Skills are also affected by character stats, etc. Skills need to be equipped before you can use them, and the hopes is that they will eventually expand to hundreds of skills. Some skills will also have prerequisite skills before they can be discovered and used.

As you can imagine, hard coding the individual skills for such an idea will inevitably get tedious, especially when the skills increase in number. And being that I’m generally lazy and doing this solo for the most part, I want to build a system from the ground up that lets me add the skills to a central database which the concept will call from, and have it integrated as a foundation for my game. This is so that I don’t have to change masses of code just to get a single skill working. I can just add it to the database, and the scripts do the rest, sort of thing.

And although I’m only prototyping at the moment, the eventual goal is to make some sort of MMO out of it.

However, I’m still inexperienced in programming, and the methods I’ve tried so far have failed to produce the results I’m looking for. So, in my desperation, I’m turning to the online community for advice and some sort of direction to get this going.

At the moment I’ve got the following questions:

What would I need to do to implement this idea? Or rather, what steps would i need to take in regards to coding, to achieve this?

What advice do you have that will point me in the right direction?

What would the better option be to use for this database, XML or ScriptableObject? Or do you have a better suggestions than either?

What things can I try to not only improve my programming knowledge, but to let me see first hand the effects of your suggestions?

If you post this in the Scripting forum, you’ll get more implementation-minded eyes on it. The Game Design forum is better for higher level questions such as what types of skills you’ll have in your game, how progression will work, stuff like that.

That said, I consider the discussion of data-driven design (versus hard-coding) to be a “design” topic. For implementation, I recommend ScriptableObjects. Jacob Pennock wrote a good tutorial. Make each skill a separate ScriptableObject asset file. You can create subclasses for different types of skills. ScriptableObjects are nice because Unity handles serialization for you, and you can edit them in the Inspector view just like any other Unity asset. Then you can have a MonoBehaviour or another ScriptableObject that has an array or list of skill assets.

Try to generalize things as much as possible. Instead of a “fire projectile” class (subclassing ScriptableObject), design a generic “spawn prefab” class for which you can specify an optional velocity. Then you can use this class to create lots of different types of skills such as:

  • Fireball: spawn a fireball prefab with a strong forward velocity
  • Web: spawn a web prefab with a low forward velocity that traps enemies
  • Bardsong: spawn a prefab with no velocity that plays an AudioSource and affects entities within its trigger area
  • and so on
2 Likes

I went ahead and put in a Report to get this moved to Scripting.

I’ve got some code that does this sort of thing in my “dead” project Sara the Shieldmage. Here’s the 10,000 foot view for you.

As you say - hardcoding values for a game is a bad idea (you have to re-compile to iterate an idea.) “Softcoding” values via the editor is similarly bad (the same restriction applies, it’s just a better interface for hardcoding.) The only other option is to put them in an external file of some sort.

Luckily, JSON is well-suited to this sort of thing. All you need is some library for managing JSON (I prefer SimpleJSON), and then you can get started coding.

“But wait!” you ask, “What do I code?” I’ll help you with that too.

Generally what you want are layers. The way I like to architect this sort of setup, is to start with a Repository (a static object, possibly even a static class) that has the sole and explicit responsibility of reading or saving data. The way I choose to do it, is create a MonoBehavior that goes on an object that is never unloaded between scenes, that has a reference in-project to the config file I want to use - this is better, because this way, only the config file-to-code relationship is hardcoded. I prefer to go the extra mile for my players, and put it under a Resources folder so that the player can mod their game if they so choose.

The next thing you need, though, is something to hold the data. I call these sorts of objects Models. These are not monobehaviors; instead, chances are good you’ll want these to be serializable objects, so you can inspect them during your development. Generally the template looks like this:

using System;
using SimpleJSON;

[Serializable]
public class SomeModel
{
    #region Fields

    // Fields...

    #endregion Fields

    #region Constructors

    public SomeModel(JSONClass state)
    {
        ImportState(state);
    }

    #endregion Constructors

    #region Methods

    public JSONClass ExportState()
    {
        // Export the object contents to a JSONClass, so you can save to a file.
    }

    public void ImportState(JSONClass state)
    {
        // Import named properties from the state, into this instance of the class.
    }

    #endregion Methods
}

The next thing you need is the ability to use a model…this is where things get murky based on your implementation. It could be a behavior on a live game object that’s doing things in your game. It could be something that controls GUIs. The applications start to diverge from my web development experience here, so I’ll talk about it the way I see it; feel free to correct me if there’s a better term or way of phrasing the idea.

The thing I just mentioned - a live object doing things that the player is supposed to respond to in the game world - I instead like to call an actuator. Actuators take the model and make the consequences of the data that you just read in through the stack actually apply to the game world. This can be stat systems, prefab paths (As @TonyLi said above)…anything.

Conversely, if the data is going to be used to feed a GUI, you may consider creating a Controller. The controller tells certain objects called Views how to present information to the player. Views collectively are just groups of buttons, labels, images, all that sort of thing.

Man, Asvarduil, that’s a lot of stuff! Why do I want to do it that way?
Because it’s maintainable. If you’re unsatisfied with your GUI or need to change something, you just change your GUI - you don’t have to change the whole stack, necessarily.

That’s good, what are the upsides, not in nerd-speak?
Here you go…

  • It’s easy to change things when you need to. Specifically, changing one thing should have minimal impact on other stuff, provided you keep the interface between layers.

  • You don’t have to worry about inheritance chains so much - those are hard to understand. Instead, you can create good GUIs and game behaviors by composing objects of various models.

  • You’re adhering to a convention. Data always comes in the Repository and is stored to a Model, which is used by an Actuator or Controller. The controller always uses the model to update a View.

OK. What’s the catch?
Good on you for thinking that - there’s always a catch in computer science. The catches are:

  • More code to keep track of. Above and beyond having to read/understand more, it mean…

  • More possible points of failure. You’ll need to have a way of debugging each layer if something goes wrong.

  • More RAM is required for the end-user. It should be said that this should generally be a small amount, but if you’re needing to squeeze, say, an XBox 360 for every microsecond of performance, you may be in for some refactoring down the line. You’re storing each layer as well as all instances of all models in memory, after all.

  • Because you’re adhering to a convention, it’s up to you to have the discipline to adhere to that, in your own self-interest. At the same time, it’s a pattern; there may a case where you need to break this pattern. For code-understandability reasons, it’s worth noting you do this at your own risk.

I hope this helps you. Just remember - Repository → Model → Actuator OR Controller → View. 3-4 layers for a more data-driven bit of software.

Yes, this applies outside games. In fact this is more or less the enforced architecture of Microsoft’s MVC.NET. You’ve learned something that just made you more employable!

I’m curious - what’s the difference between softcoding in ScriptableObject format versus JSON format (or XML for that matter)?

I will grant you that JSON is more portable if you jump ship to another game engine. But ScriptableObjects have fewer moving parts. (Simpler = less opportunity for bugs.)

I was actually wondering the same thing. I opted to go the scriptable object route with my development since it was already integrated into Unity over getting something to work with Unity.

I’ve never heard of “ScriptableObject” as a data format prior to this. Any references you’d recommend?

As far as the actual differences - if by “ScriptableObject” you’re referring to game objects in Unity - the fact remains that the game still has to be built for value changes to take effect; there’s no external way of affecting those values, unless you do something exotic.

A JSON file, conversely, doesn’t get built with the project - it’s fully external, it’s just data. If you change it and re-run your game, you get the changes instantly. Heck, if you implement your data stack correctly, it may be possible to just change the data, and swap back to your game, and the game itself instantly pick up the changes.

TL;DR - Iteration times. If you have to compile your game, it means you’re spending more time building, less time checking the result.

Check out Tony’s link above. Unity also did a scripting video on it and you can find a number of videos by other devs by searching it on YouTube. Here is the link to the Unity Live Training one -

I think Asvarduil’s point is that ScriptableObjects get packaged by Unity, so end-users can’t edit them. This also means that to patch a skill you have to build the project and send the entire assets file to the user, while if you’re using JSON or XML you can just edit and send the relevant xml/json file.

1 Like

But do you really want users to be able to edit their files? In most cases I would prefer they couldn’t, dependent on what type of data it is. But that is an excellent point. It probably depends a lot of type of game as well. Most of the games I play, I’m used to patching as a standard process and as such have accepted it as something that will be part of my game’s process as well.

Ok, that’s pretty cool - from both sources.

I still see some pretty significant tradeoffs, though, as someone who doesn’t yet use this technique.

Benefits that I see:

  • Can edit directly in the editor, without needing to open VS, or custom middleware, or any of that stuff.
  • Can see details that a text format like JSON doesn’t convey - for instance, thumbnails of images, etc.
  • Can set up a GUI that other team members or even you can use to efficiently do this sort of thing.

Disadvantages that I see:

  • The API exposing this capability is very obtuse, as an outsider - I’m not sure exactly how this setup allows you to “just change some data” and see your changes propagate to your game. The pipeline for saving the data is significantly clearer. For “Joe Grammer”, the new, clueless, but otherwise skilled developer on the team, I will have to take time to explain the pipeline to them.

  • You’re still creating middleware - specifically, the Editor interface with which to modify the ScriptableObject file.

  • There’s a lot of action happening here outside of the game, proper, which further hampers being able to trace problems that arise.

This is some cool stuff that I need to pay more attention to. Still, I think it could be argued either way. It seems like a “MVC-like” architecture provides more control, at the expense of more code and having to know implementation details. This setup provides ease of setup and use, at the cost of less clear code, and having to understand the engine’s implementation of the pipeline in this specific case.

Yes, I do. I want people to be able to mod my games. Modding is not a bad thing.

  • Modding communities are a thing - some players like to customize, others like to reap the benefits. Also, watching them mod my game tells me things about what they may want. It’s sort of like research, only they’re pretty much just telling me.
  • It makes it easy for me to fix “Stupid Asvarduil” mistakes.
2 Likes

ScriptableObjects are just another tool in the toolbox. They’ll be more appropriate than JSON for some uses, less appropriate for others.

I think most people do their iterative development in the Unity editor. ScriptableObject assets are just data; you don’t need to recompile after changes. Internally, they’re in YAML format (versus XML or JSON). Some advantages:

  • You don’t need to worry about the format. Unity natively serializes and deserializes them. (Unity serialization details for anyone who’s curious)
  • You can edit their contents using Unity’s Inspector view, without having to write any extra editor code, which provides a very consistent UI.
  • You can edit them during play, and the game will recognize the changes.

They’re also easy to pack into asset bundles if you want to send patches or DLC.

That said, they’re not good for letting players edit the files.

1 Like

The problem is not with patching itself, but with the size of the patches. Patches for Unity games on Steam can be several gigs, even if only minor changes were made.

I bet @Wolfie5493 wasn’t expecting quite so much discussion. :slight_smile:

1 Like

That’s just a design flaw by the developer. If you design a game to be patchable with asset bundles, patches can be very small.

3 Likes

That is what I was going to say. Designer really has to put some thought into the game’s structure to avoid having to do a full patch when the patch is released. I haven’t figured that part out myself and exactly what will be bundled with what. Truth is, I’m a long ways away from releasing anything. But that is one of the things I have on my table of things to do when that time draws closer… lol

1 Like

Okay, excellent discussion. Learning a lot already.

Maybe a small insight into my goal might be in order:

As I mentioned already, its a skill based leveling system. Skills are implemented differently to require players to “discover” them to use them. Some skills will have a chance to be accidentally used, thus flagging it as discovered. Skills will be separated into various groups, eg: Combat Skills, Defense Skills, Profession Skills, etc. Skills are anything that can generally be learned, where as Stats are what make up the character physically, so to speak.

To use a skill once discovered, the character equips it, and just uses it, which will add experience to that particular skill, which will eventually cause it to level up, thus increase the base stats for the skill. Characters level up if the total COMBINED experience of all skills reaches a certain amount. So character progression is entirely dependent on the level of the various skills. AI will utilize this concept as well, but will be automated where players get choice.

Now, the big thing about this is that the end result will make use of server-side rendering, as opposed to the local client rendering. Just think of a broadband connection between your PC box and you monitor. Thus, patching won’t be necessary. When the idea is eventually rolled out, and the game needs updating, I can just update the files on the server and clients will see the update the next time they log in (at least that’s what i’ve got in mind). No downloading, no patching, and of course, I’m not sure if modding is possible with this idea. But everything is done server side. However, this is beyond the scope of my experience and this topic, but its to give a better idea of what i’m wanting to eventually achieve with this.

At the moment i’m just prototyping the individual concepts, and have begun with creating the Base character, which the Player character and NPCs will inherit to gain the basic “skeleton” of their character. The rest will obviously be done per object (AI will be done in the AI branch, and Player will be done on the Player branch) to give them the code necessary to do what needs done.

Anyway, the idea is to have a central database of skills. One place to update the skill catalog, that the game automatically picks up, etc etc. What I struggle with is the logical progression of the whole concept, and thus the implementation of it. Perhaps its still too advance for me? Regardless, the coding itself is easy, i just need the logic behind it worked out, which is why I’ve come here: To better understand that logic behind a game, and character creation.

Now below is the XML I started to try out the most recent method, and it will give you a better idea of what I’m after in terms of the skills database:

<Skills_Collection>
  <Offensive>
    <Punch>
      <Description>Punch the foe's very hard</Description>
      <Required_Stamina>15</Required_Stamina>
      <Base_Effectiveness>100</Base_Effectiveness>
      <Exp_Modifier>1.75</Exp_Modifier>
    </Punch>

    <Spit>
      <Description>Spit at your foes</Description>
      <Required_Stamina>5</Required_Stamina>
      <Base_Effectiveness>10</Base_Effectiveness>
      <Exp_Modifier>1.5</Exp_Modifier>
    </Spit>

    <Kick>
      <Description>Kick them</Description>
      <Required_Stamina>50</Required_Stamina>
      <Base_Effectiveness>9000</Base_Effectiveness>
      <Exp_Modifier>1.25</Exp_Modifier>   
    </Kick>

    <Insult>
      <Description>Hurt you foe's feelings</Description>
      <Required_Stamina>7</Required_Stamina>
      <Base_Effectiveness>23</Base_Effectiveness>
      <Exp_Modifier>2.3</Exp_Modifier>   
    </Insult>
  </Offensive>

  <Defensive>
    <Block>
      <Description>Block an Attack</Description>
      <Required_Stamina>2</Required_Stamina>
      <Base_Effectiveness>12</Base_Effectiveness>
      <Exp_Modifier>1.33</Exp_Modifier>
    </Block>
 
  </Defensive>
</Skills_Collection>

So a few more questions have sprung to mind, and some are based on what is mentioned in the discussion:

@TonyLi Using scriptable objects, doesn’t that mean lots of files if each skill has its own asset? Or doesn’t that really matter?

And i’ve watched tons of tutorials on Scriptable Objects, but I’m still struggling to grasp it. I understand it can be used to make custom inspectors and editor elements, but how does the logic behind using it as a database work?

@AndrewGrayGames I’m liking the concept of Layers. Could you help me visualize the logic behind that?

What I’m doing to build my Base Character Script is:

AttributesScript + StatsScript + VitalsScript + SkillsScript = Base CharacterScript where everything is put together.

Would that be some sort of layering concept? Please explain more if you can. Until I can visualize the concept, I will struggle with understanding how it works.

Which of the two options given, and possibly XML, would be better suited to this sort of programming? In fact, which of them would you use if you designed such a project?

And most important of all, and maybe slightly off topic: I started with creating the character, but is there any unwritten or written rule about where to actually start when creating a game?

1 Like

Think of the scriptable object as a database. You probably wouldn’t want a scriptable object for every skill. In looking at your XML, I would probably either use a single scriptable object to manage the whole list with one of the elements of each item being SkillType which could either be Offensive or Defensive. Or I might break it down into two scriptable objects and have one for each type. Really, since it looks like all of the data is essentially the same, I’d probably lean more towards a single scriptable object to house all the info. Something like having a scriptable object named SkillsCollection (or whatever you want to name it) based off of an item that contains a skill type, skill name, description, required stamina, base effectiveness, and exp modifier.

1 Like

So far, I’ve used only JSON. I’ve no experience with ScriptableObjects (though, I plan to experiment with it sooner or later), and I haven’t found a good XML library/framework.

If you go with something that’s not ScriptableObject, you’ll find that a layered architecture makes it easy. If you decide XML isn’t a good fit, and would like to use JSON instead, it’s just a matter of swapping out the framework, updating the mechanism(s) that let you save/load data, and going from there. To be fully honest, I’d say SimpleJSON might not be the best setup for JSON parsing - I do find I have to do manual mapping in the model. I could create ‘mapper’ classes that operate off to the side…I forgot about that.

As far as ScriptableObject, @TonyLi is correct - there are fewer moving parts. It’s perfectly viable to have all your abilities in a single scriptable asset, or each one broken out into a separate asset.

Ultimately, this is a tech choice you have to make. All you can be given is information, we should not choose for you.

1 Like

Definitely agree. Both are good solutions. I know I have some videos bookmarked on using JSON as well and still may end up diving into it for some other parts of my project. I do like keeping possibilities of modding available but there are some things that I wouldn’t want players to be able to mod easily. So a combination of the two methods may be what I do in the end. Keep things which could be used to effect gameplay advantages in scriptable objects and cosmetic stuff in XML/JSON/something similar. Or something along those lines.

1 Like