Advertisement

Suggestions for handling progression data

Started by December 05, 2016 06:25 AM
4 comments, last by MrJonas 7 years, 11 months ago
Hello everyone, I'm new here and for the past couple days I've been looking into a way to handle in-game progression.
What I mean by that is how the player's actions affect the state of game objects and the outcome of certain events. So we store this data according to the player's inputs, and read it whenever necessary, like for example setting the objects correctly when loading an area or retrieving the correct piece of dialogue to display when talking to an NPC. Since I'm a bit new to games and programming (I completed about a dozen different tutorials, like making pong, arkanoid, bowling, etc.), I'd like to know what would be some nice and elegant ways to handle this kind of thing without getting yourself into a sticky mess. By the way, I'm using Unity with C# scripting.
I'm working on a first person RPG style game so I looked into Skyrim for inspiration. Looking at the commands available at the developer console in-game, it appears that they store a single variable for each quest and that variable is set to an int representing the current stage of completion. Look at this page for an example (table at the bottom of the page): Link . There seems to be a variable named after the quest (CW02A in this case), and it can be set to a number of stages - 0 before starting the quest, 10 when started, 30 after completing a certain objective, and so on and so forth until you reach 200 which is completion.
I would like to know, what are some ways you guys would suggest for handling and storing this kind of data?
Which ways do you consider more 'robust' or 'elegant'?
Which variables are better suited for this; when is it better to use ints, booleans, arrays or enums and are there other options?
Would you centralize the handling of this data?
What I imagine is to create a central static public class that contains all these progression-related variables, and access it from other classes when this data needs to be read or changed. This would also make it easier to implement a save and load system. Is it preferable to centralize it or are there any pitfalls?
I'm looking forward to see how you guys usually tackle this kind of problem. I'm open to any suggestions even if I might not use them now or if they're too hard to implement for me at the moment, because they might be useful when tackling another problem in the future. Any resources that look further into this are also much appreciated. Thanks!

Depends a lot on how your game needs to be set up. If you can load it all into memory at the start it certainly makes it easier to work with and gives less loading time, on the other hand it might just be sitting around in memory a lot. That said if we use a 5 character utf16 quest ID paired with an int(worst case scenario) you're talking over a thousand quests in memory for 15 KB of space. Not the kind of data I'd be worried about.

I don't know the details of skyrim but based on their quest id's they probably use a map using a string as a key for the quest "name" paired with an int or a byte or something for the stage the quest is on.

I won't go into centralization cause that's usually demonized around here, you'll probably receive the suggestion to instead have some kind of class that is responsible for managing the state of quests, paired with something to serialize and un-serialize the data, and then giving whatever code needs to access it some indirect method(get it through the game class or have it passed as a list of services, etc.

Advertisement

In the absence of any other information, I'd start simple. Something like:


Dictionary<string, int> questStatuses;

The string would be the name of the quest, the int would be the arbitrary question completion level, as in your Skyrim example. It's just one object for all your quests. Read and write it in your save-game system. Add the name starting value when you start a quest. Have a standard value as the 'completed' score, or allow the quest logic to report whether it's in-progress/failed/completed based on the relevant value. (How you handle the logic itself is relevant, but not really covered here.)

The problem with trying to make it more 'elegant' is that each quest is different and they'll all have their own ways of representing progress and change. No generic enum will capture what you might want to do with every possible quest. Nor is there a fixed number of booleans you could use for the same purpose.

To some degree I'd want it centralised (like the above) because sometimes you'll want one quest to be able to respond to the progress of another. But since it's only really one object (containing a bunch of values) it's not really a concern.

Thank you very much for the responses.
I'm going to look further into implementing dictionaries and how they work.
I'm a bit curious about the concerns with centralization, even if it's alright in this case as Kylotan pointed, could someone give a quick pointer as to why it's generally considered bad?

Sharing any object throughout the code base tends to make the code all heavily dependent on it. That means that a change to that object can have effects all over the program, which in turn makes the program harder to maintain and debug. Generally speaking, each object's visibility should be limited to where it is necessary, not made globally accessible to be convenient.

That makes sense! Thanks

This topic is closed to new replies.

Advertisement