Skip to main content
GameDev.net gamedev.net

PRO Tired of ads? Read GameDev.net ad-free and help keep the community independent with GameDev Pro — $3/month.

Improving the inventory system framework using the Command Pattern

Improving the inventory system framework using the Command Pattern

aljav
Project Alaska · · 7 min read
3,038 0

This game will be the second that I've created in which I've handled the code (first one I am wrapping up for publication now). I am getting comfortable enough with visual scripting in unreal now that for most problems, I can usually imagine a solution pretty quickly and create the code for it intuitively.

Because of this familiarity where I am not having to thrutch my way through every tiny logic problem, I am now able to focus on the bigger picture. So, I am making some effort to explore programming patterns and try some out whenever it seems like it may be a good fit.

In my last post I talked a little about the inventory/pickup system. I had come to a satisfactory solution, but it was code that left me with a bit of anxiety - like it was just a little more complex than it ought to be.

Just by chance during some downtime I was browsing YouTube and I saw some introduction to the command pattern video. The popular use case for that is an undo/redo history, which is not something I am interested in for this project, but there was another detail that jumped out at me - if I can encapsulate actions like picking up and object or transferring an object from one container to another into Uobjects, that might make for easier long-term management of the code. When I first learned about the state pattern, in which I encapsulate player states into uobjects, that really made my projects code way more manageable. No longer did I need to manage complex conditionals - I just have named states in which I define an in and an out and it's very clean and easy to manage.
There was nothing necessarily wrong with just having the logic for transferring pickups handled by a single event with a few switch statements - it works and with some comments and blueprint organization tools it's mostly pretty straightforward… but every time I return to it, I still have to spend at least a few minutes going through node by node to get a sense what is happening. It may be pure idiosyncrasy, but it just feels a bit messy to me.

Now if I encapsulate each “command” into an Uobject, then I can do a simple project search to find the command I seek, and everything about that command is just handled in that one place. So, I don't need to follow execution flow to find where the part I'm interested in happens, and I don't have any non-pertinent code in my view to distract me when I am reviewing. So, like, if I have a bug with “transfer item from ground to equipped container”, I can just open that uobject and view everything in one place, without any extraneous details involved.

I've found that if I am editing some little bit of code but I can see a bunch of other code at the same, it becomes hard for me to stay focused. It's like I can see and think about other problems at the same time, so I become like a shark that is chasing a school of fish. Which one do I bite?!? Whereas if I have states or commands contained as single objects, I find that I dont have this problem of focus at all, and I stay productive more easily.

That really works for me, and it also nets me a few side benefits as well. I can derive the command objects from a parent so that I can share some global functionality. Right now the only common thing I am doing is to have an instance editable “command log” variable which gets logged to an array. This allows me to keep a history of things the player has done. This may also be sorted by types of commands. For instance if the player wanted to just view item transfers they made, they could filter for that. Or just view commands related to hunting, or fishing, they could filter for that.

I have an idea to write out these command logs in a way so that it might read back like a journal which I think some players might enjoy.
"September 30th. It was freezing rain, I was soaked through and shivering.

I spotted a moose about 100 meters away…
I took aim with my 30-30…

I was shaking. My aim was unsteady…

I waited….my aim steadied a little, but I was still shivering…I squeezed the trigger….I missed!"

That's just an idea that I'll explore later, but it's always nice when you discover a solution that also opens new opportunities.

Another thing I might be able to do is send that command log as data that I could use for analytics. I dunno anything about that sort of thing, but even a simple thing I could do without any sort of networking is have the command log saved to a file and ask play testers send that to me after playing. Just an idea for the moment.

Perhaps the biggest benefit of implementing the command pattern was that it helped solve a problem that I didn't not have a clean solution for: I wanted a universal “latent action” timer, so that I can define how long certain things should take. For instance, if you ever played a survival game like The Long Dark, you know that it is common that doing certain things like cook some food, build a tent, etc take a certain amount of time in game and are accompanied by some sort of GUI to indicate progress of the action.

Using the command pattern, I just put that timer logic right into the parent command class, and then each instance can set their own desired “time to perform” variable. Some commands might be instant in which case they just set the float variable to zero. Others might take five minutes (in game minutes) so I can set that.
And the really nice thing is that I can put all of this static data about commands into a spreadsheet so that I can easily run formulas to help optimize game balance later.

I also realized that I had some redundancy between the “actions” system and this new “command” system. I decided to rename the actions system to “input actions” to avoid confusion. The input actions system works more like a state machine where I am changing what happens when input is pressed based on the characters current state. The commands system is just a standardized way for me to handle virtually everything the player might do in the game otherwise.

Well, I would share some screenshots of the blueprint code but my workstation is in storage at the moment and I am at a cozy BnB in the wilderness. I just wanted to jot down some of these improvements I had made so that I might refer back to it later when I pick this back up.

My next task that I will focus on for this project will be to shift gears from code and try to find a suitable art style. I have something in mind that I think might be fantastic and I'm stoked to try it out. But I got to finish up my current project first. It is not something that will ever be a huge market hit, and the work I have left to do is all boring stuff so it's just a matter of doing what I need to do, not what I want to do.

But it's my first solo-dev game and I've put a lot of effort into it, and there is small community that is using the game to help with their professional training, so I got to make sure it is as good as can be for them. Much of what I have learned from LANDNAV I will be putting to good use in this Project Alaska, but I can have a bit more fun with Project Alaska because it is a game purely designed for fun, rather than a technical training simulation.

Well, that is all for a little while. Hopefully next time i update this devblog i have some nice art prototype scenes I can share.



Discussion

Loading comments...