Designing objectives
Published by James on 30/09/2024Hey Kinoko fans!
We’ve been working on our game for quite some time now, but it never really started to feel like an actual ‘game’ until recently. We’ve dedicated a lot of time to things like Kinoko’s platforming skills, his health system and his gadgets, but we’ve never given him anything to actually do. I guess what I’m saying is that there’s never been any kind of objective for the player in our game, until now.
I spent much of September continuing to work on starsprites – their following dynamics work loads better now than they did before, and the way they’re summoned has been completely overhauled! – but a couple of weeks ago I turned my attention towards obstacles. As Chelsey’s been busy designing levels, she’s started to come up with things like traps and hazards and new enemy types, so I’ve been diligently keeping up with her requests, creating things like breakable walls and floors and bouncy platforms that can be placed anywhere. With these new levels and props in development, our game was already starting to feel more like a real game, but it also got me thinking more about player progression.
For example, say we have an NPC that the player must have must speak to in order to continue in a level. How do we ensure they do this? Sure, we could just set some flag from ‘false’ to ‘true’ somewhere, but that seems messy. I like to keep my logic organised. And what if we want to somehow tell and remind player what they need to do next? Our game was calling for a unified objectives system, so that’s what I decided to focus my attention on next.
Now, I don’t doubt that some amazing members of the Godot community have already created assets/plugins for this sort of thing. That would certainly have been the case for Unity and other game engines. I remember looking into them before, back when we were still on Unity, and I wanted to add NPC dialogue. The thing about these plugins, though, is that they’re designed to be a bit ‘one size fits all’ – and if they’re not, then they’re unlikely to be precisely what you’re looking for anyway. I’m not comfortable with the idea of adding plugins to my project, nor (beyond the Godot engine itself) any code that I didn’t personally write. Whether I’m working on a website or a game, I like to have complete oversight over my code. I like to know what’s in it and where and how it all works, and I’m not willing to sacrifice that for a plugin.
I knew the way forward would be to develop our own objectives system. That way, I’m able to set it up exactly the way I want it, in a way that’s perfectly suited to the game we’re trying to make, without any unnecessary bells and whistles that we’re never going to use. I started thinking about objectives in some of my personal favourite video games, and how they’re handled.
In terms of the game experience, we don’t think we actually want the player to see their objectives – at least not in the form of a list on the UI, or anything like that. We’re driven to the idea of giving the player discovery-driven objectives, so they’ll find out what to do next through exploration and through talking to NPCs. There are plenty of great games out there that do things that way, like Hollow Knight and The Elder Scrolls III: Morrowind, but for me, today, as the guy whose job it is to design and develop it, that’s all kind of hard to visualise. That’s why I started to look at visual objective systems first. If I can create one of those, even if it’s very rough and basic, then I can look to reverse-engineer it and strip it down to its core later.
Being an RPG, my all-time favourite video game – The Elder Scrolls IV: Oblivion – has a good and very comprehensive objectives system. I did like how its predecessor, The Elder Scrolls III: Morrowind, used a single-threaded journal format and entrusted the player to keep themselves organised. I actually have a sheet of A4 paper on my desk beside me right now, covered from top to bottom in notes, reminders and travel directions from my last game of Morrowind, and it’s really quite satisfying having to do that – but all the same, I do prefer Oblivion’s expanded journal, which breaks objectives out of that single thread and presents them as their own individual quests.
Still, Morrowind and Oblivion are both RPGs, and our Kinoko game is not! All the same, I find them both to be a good point of reference when looking at how objectives might work under the hood. I happen to know that quests in both these games are constructed in a similar way. They each use individual quest IDs (e.g. ‘MS48’), and each quest is broken up into a number of stages referred to by unique indexes. For example, stage 50 of Oblivion’s MS48 quest (‘Breaking the Siege of Kvatch’) refers to the part when the player has taken the sigil stone and closed the Oblivion gate, and can now let Savlian Matius know that the way to Kvatch is now open. This approach to quest design mechanics makes a lot of sense to me, and I did consider doing something similar at first.
The fact remains however that Oblivion is an RPG, and whatever mechanics were used to construct quests there are probably too much for a game like ours. So, I thought about some of the other games I’ve enjoyed playing that are less story-focused, like Cult of the Lamb, and both Two Point Hospital and Two Point Campus.
These games take a simpler approach. There are no ‘quests’ in these games – just sets of objectives. In both Two Point Hospital and Two Point Campus, completing objectives is how you gain ‘stars’ to unlock the next hospital or university and progress in the game. A typical objective might be to cure 25 patients of a specific illness, or perhaps to earn $100,000 profit. These objectives are mechanically simple, and, although at first I was drawn to Oblivion’s system because it’s more story-focused, whilst Two Point Hospital and Two Point Campus’ objectives are more number-focused, I came to realise that, actually, a system closer to this one would suit our needs just fine.
Whilst not all objectives in our game are going to be based on multiples (I’d expect a typical objective to be one that requires the player to talk to a single NPC one time, not to ten different NPCs for instance), neither are the objectives in Two Point Campus – the objectives system remains unchanged in any case. The screenshot above shows an objective for the player to build a staff room. That’s a singular requirement, but regardless my progress is displayed on the screen as 0/1.
And why not? The system works. Not every objectives needs to be based on multiples, but the flexibility is there to have multiple-step objectives when the game calls for them. Now I don’t actually know how these objectives in Two Point Campus have been developed under-the-hood, but it isn’t too hard to imagine. Combined with the technical understanding I have of Oblivion’s quest system, and the vision of where we’re trying to get to (that being something more like Hollow Knight, where the objectives exist behind-the-scenes but are technically invisible to the player), I felt like this was enough for me to go off with designing our own system!
The ‘PlayerObjectives’ component currently has just three methods: ‘AddObjective’, ‘ProgressObjective’, and ‘IsObjectiveComplete’. The first two add an objective to the game and update an objective’s progress respectively. Both take in a unique objective ID (I’m using simple IDs at the moment, like ‘TALK’ or ‘SUMMON’) and an integer amount. The integer amount on the AddObjective method defines the number of times that a given action must be completed; the integer on the ProgressObjective method increments that number by the amount specified. ‘IsObjectiveComplete’ takes in an objective ID, then returns a boolean value: ‘true’ if the objective has been completed, and ‘false’ if it hasn’t.
The only other parameter that exists for any of these methods is a ‘description’ field, which is provided as part of the AddObjective method – but that’s really just for testing, and could eventually be removed if we’re not actually showing the player their objectives on the user interface. Because I’m developing and testing at the moment, I have created myself a simple HUD for objectives, displaying the objectives I currently have and my progress towards completing them. I’ve added objectives to a variety of actions, and so far it’s proven really versatile.
I can add the ProgressObjective method to any action I want. For example, if I want the player to have to speak to an NPC, I simply need to create a new objective (via AddObjective), then update that objective when the player has talked to that NPC (via ProgressObjective), then check the objective is complete when the player tries to continue (via IsObjectiveComplete). If I want the player to have to repeat an action multiple times, such as killing five instances of an enemy, it’s the same progress, but I include an integer amount of five when adding the objective. Each time the player kills an instance of that enemy, I call the ProgressObjective method to increment their progress by one, until their progress is equal to the required amount, at which point the objective is marked completed.
This system’s still a work in progress and so I’ve yet to use it in any meaningful way, but I’m pleased with the promise and versatility that it shows. Like I mentioned at the start of this blog post, this is going to go a long way towards making our game feel like an actual game with things to do, and a story and a purpose, especially when combined with the stuff Chelsey’s been working on like levels and coming up with obstacles, hazards and enemies.
Again, we’re not actually planning for the player to see their objectives (though it’s nice to know we can slap a UI on it easily enough if we do change our minds). My main goal here is to create an objectives system which does what it needs to do mechanically, so we can start requiring the player to do certain things before they can do certain other things. With objectives coming together, we can now finally begin doing that.
Anyway, that’s about all I have to say for now. I keep leaving my blog posts until the last minute each month, so by the time I get around to them I struggle to make the time for a more comprehensive update, but I’ll try to do that next month and let you know more about the progress we’re making towards sharing a playable build.
Until next time!