Devlog - Landnav

Capsule

Hello, welcome to the dev log for my first unreal engine game and the first game I’ve made on my own (mostly). I do have one other published title to my name but that was made in unity, and I did not do the programming for that.

This project started in unity, but I moved it to unreal some months ago. I want to start a devlog now because the project is getting complex enough that I often need to do some rubber ducky, but I think my wife is getting tired of it :slight_smile: . Perhaps if I do so here, it might be helpful for other developers or perhaps somebody can offer me advices.

LANDNAV is a navigation simulation. Use map and compass to find objectives in the wilderness, under a time limit. Gameplay is designed to create a need for the same decisions that you make in real life doing this stuff to be made in game.

The primary purpose of the project is for me to learn how to make a game on my own and publish it. So learning is the main priority. But I am treating it as a serious commercial endeavor, doing everything I can to make it as marketable as it can be for what it is.

My initial goal for the project was only to make an authentic military land navigation simulation, based on the thousands of hours I spent navigating in the wilderness with map and compass both in the military and on my own. I have succeeded in creating a realistic simulation of that with 1 to 1 parity with real life techniques, however I believe that with a bit more work I can turn this into a fully featured game that includes many of the familiar features we expect from modern games. Thus, LANDNAV could provide fun gameplay and high replay value for a broad audience which includes people who like survival genre games, simulation games, or anybody who likes chill, relaxing gameplay in beautiful natural settings.


(new UI, characters, and general art theme in progress. In addition to the core map/compass navigation gameplay, player will need to manage body temperature, hydration, and energy. Clothing layers take into account insulation and breathability. In mountains environment, getting clothes wet from excessive sweating can create dangerous hypothermia conditions if you have to camp overnight.
Considerations like this create a highly realistic camping/backpacking survivalism experience. But my main goal is to avoid numbers as much as possible and try to communicate these true-life bodily needs as intuitively as possible.)

To that end, I’ve recently began work rebranding the art style from an olive-drab military theme to a more colorful theme in line with popular simulation genre titles. But the major extensions are in gameplay. Currently, the game lets you tackle military style training exercises and has some basic stat tracking. This is suitable for somebody wanting to learn landnav or keep current on their skills, but it is not a real “game” with a sense of progression and the sort of modern hooks you expect to give you goals that keep you engaged.

So now I am working on adding a career mode. This will work much like a racing game, in which you have several brackets of races that get progressively more challenging. In order to meet the challenges later in the brackets, you will need to not only develop your actual skill in navigation techniques, but also get strategic about your money management so that you can get equipped with necessary outdoors survival gear. For instance, late-game events will require overnight camping in the mountains where weather can get extreme, so technical clothing and camping gear is essential. But there is always the trade-off of weight, so figuring out the perfect loadout is always a challenge.

My primary goal is always to ensure that the player has to make similar decisions in the game as they would in real life. A game must be fun, but so far, I think I have succeeded in not creating any scenarios that would instill incorrect or dangerous habits. Many players will be using this game to prepare for military courses or develop/maintain a professional skillset, so I do feel responsibility to not create unrealistic decision-making situations.

In that sense, I believe the LANDNAV might be the most realistic survival simulation created so far - but of course this is quite different from survival genre norms.

dolomites lake - Copy

Well, that is enough set up I think. From here I’ll focus on the nitty-gritty problems I contend with on daily basis. Should you be interested, links below:

My first game: To Battle!: Hell’s Crusade on Steam (steampowered.com)

Current projects webpage: LANDNAV (landnavgame.com)

Current projects Steam: LANDNAV on Steam (steampowered.com)

1 Like

The project is at an interesting point.

I am extending the existing gameplay systems and also adding some new ones. So, I am sort of doing some refactoring I guess you might say, but then I am taking things a little further than they were.

I use an actor that I drop into the level called the “Event Manager” to act as central command and control.

When the player starts a new event (think like a single race in a racing game), the Event Manager gets the message and sets into motion. A clock is started, some data about the win/lose conditions for the event is generated, and gameplay actors are notified. Some actors will need to be teleported, or disabled, or display special information, and so on. So this Event Manager I envision as a guy with a megaphone, making sure everybody knows what is going on, and then it is up to individual actors to make do with the information he is putting out on a case by case basis.
This is my general strategy for the game’s architecture.

For the most part, Event Dispatchers fill the need to broadcast important gameplay happenings. For instance, when the Player begins a new event, the Event Manager will read information about the event from a Data Table,


(note - using the csv file in a data table isn’t just about convenience, it also allows me to use functions in the spreadsheet itself to help determine game balance, pacing, etc. I’ll say more about that when I get to it later.)
. This informs what the Events objectives are, what the time limit will be, etc.

Playing the same Event twice will never be the same. I have some semi-randomization going on.
The basic objective of any event is to navigate to “Control Points”,

(seen here).

The Control points hold some instance editable variables that define their Group and their Grid Location.

A Control Point Group is just a way that I can identify a cluster of CP’s (control points) in an area. Then, for each Event, I just say how many CP’s I want from each Group, and then we can grab random CP’s from those groups. This way I can control the general difficulty, but also it will be different enough each time so as to not get repetitive.

I’ll give a brief overview about how this semi-randomization is accomplished, because it involves some advanced us of Maps (aka dictionaries) and some other things that I think may be helpful to know about in case you have not used them before.

So, before we can look at all of the CP actors in the world (there are hundreds) and pluck a specific number of random ones from designated groups, we need a way associate (or map) the actors with this arbitrary “groups” I define.

The function “Map CP Groups with Assigned CP’s” is where I do that. I tend to have functions and events name just be descriptive sentences, because otherwise, if I try to shorthand things, I find it extremely onerous to reverse engineer later if I forgot what everything did. So I try to make my blueprint code just read like a book as much as I can.

Inside this function, I start by getting an array of all the CP actors in the level. For every one, I am looking into this Map variable and asking, do we have this CP’s Group variable assigned as a key? If not, add it as a key. If we already do, then we add the CP actor into an array that is the Value associated with that key.

The weird thing is that you cannot add elements directly into an array that is inside a map in blueprint. Just a blueprint caveat I guess. So it is necessary to create a temporary array, and then add that array into the map.

With this function completed, a Map variable that holds all of the Groups this event will use as a key, and then every CP actor filed into arrays associated with each key, has been generated.

From this Map then, when an event is started, we can pluck out however many random CP’s we want from each group.

That happens like so:


The basic idea is that the Events data table row tells me “what groups does this event use?” and then I can look into the Map variable for those keys. I get the array CP’s in there and set it as a local array and say, “okay, these are the possible choices.” “Now, how do I pick from this array?”
I get the designated number from the Data Table and use that as the upper limit on a for loop. This just loop through and each iteration I take one CP actor, put it into a “Chosen actors” array, and then also remove it from the “possibilities array” so that no duplicates would occur.

Finally, the output of this function is the CP actors which are chosen for this event.

Now, what if the player saves and quits? Thats where the Random Array Item from Stream comes into play. That integer variable can be saved, and then if I plug in the same number, the random selection will always be the same.

(P.S. special thanks to @Monokkel who helped me design this system. He has some fantastic game templates on the marketplace and has been a big help getting me up to speed with blueprint coding in unreal. I’d be many months behind where I am if it wasn’t for his help!)

My next big task in the Event Manager is to build support for multiple Event Types. This means that the way I measure win and lose conditions may be different.

I am trying to learn more and practice better programming principles. This project is pretty simple so even if I do things like the beginner I am, it still isn’t too much trouble to get things working. But I have began to see some problems that I think you might define as “tight coupling”, so I am reading about SOLID programming principles and trying to do a little better job about keeping my code such that if I need to change say, some widget or a control point actor, it should not break anything in my event manager or player character, as an example.

The Career mode will play out over five weeks in game. Each week there is a number of daily events you can choose to do. There is three types of Events: Score Attack, Follow Route, and Way Finder.

So, what needs to change based on the event type?

A couple bits of information we display to the player and also how the event is measured to be won or failed.

I’ll try to put the The Single Responsibility Principle (SOLID principles) to good use here and also try to ensure that I am not duplicating a lot of functionality since much of the way different events types work will be similar.

The basic idea I have in mind is that, when anything noteworthy happens, the involved actors simply shout out with an Event Dispatcher, “I did a thing!” and then the Event Manager is watching. This manager either records some data, or he might relay what he has heard to others if necessary. With this basic idea as a guiding principle, I hope to make it so that all gameplay actors can just do what they do normally, independent from the Event Type, and only that Event Manager cares what the game rules are. With a simple Eventy Type switch, he can take the information gameplay actors are notifying him about and process it however he needs.

For instance, if player collides with a CP, the CP will send an Event Dispatch out to say, “The player has collided with me!”

The Event Manager will hear that and then ask, “okay, is this CP who is reporting collision one of our objectives?” And then, based on the Event Type, he may have further questions to ask, like, “How many points is that CP worth?”

What questions the Event Manager ask about some happenings going on is just switched on based on the event type.

I think that is the simplest way I can envision all of this working. I am not a good abstract thinker so I like to sketch things out in Scapple:


(note about Scapple: it’s a great mindmapper software because it is dead simple to use. But I think with just a tiny bit of extra functionality, this could all be done with blueprints. I made a feature request thread about this, but just in case anybody who has the chops for it reads this, I think extending blueprint comment notes so that you could format text to create notes like you see here would be a fantastic plugin. This way, you can easily sketch out your logic flow in a very quick way right in blueprint graphs, then you have a nice “paint by the numbers” experience, so to speak without having to do any alt+tabbing or extra reaching with the mouse.)

This helps me a lot with planning.

Well, over next couple days I’ll work on implementing and testing this out.

Good progress on the Event Manager.

I spent some time reading up on SOLID programming principles and got some advice from a few people. It looks like the sort of programming pattern my code was naturally leaning towards is called “Oberserver pattern.” So I have tried to learn more about that so that I can make my code more consistent.

Applying this to the Event Manager seems to have worked out well. Overall my code seems much simpler and feels pretty easy to follow. The Event Manager basically just sends out announcements that also carry data held in a struct, and all gameplay actors in the level take that data and do whatever they need to do with it.

So the Event Manager knows who is who and is very much intertwined with the specifics of this game, but the individual actors, for the most part, are independent. It’s not 100% but sometimes I think it is easier to do a simple thing that works rather than spend an entire day trying to make a system modular if it doesn’t truly have a strong reason to be.

That’s all to say, I am trying to implement these good software development principles so long as they save me work and solve problems I can actually see and understand.

For instance, my Event Manager sends a dispatch to let the Control Point actors know an Event has started. They each check the Events data table to see if one of them is the start or end location. Once the start/end actors are designated, they send out a dispatch to let the world know that it is figured out.

Now the Player Character needs to know who is the start/end actors so that we can teleport to the right location and begin the Event. There is probably some clever way I can get that info without having to reference teh Control Point actors directly to listen for their event dispatch, however I could not come up with a way that was not painfully complicated. So I just make the reference and that seems fine, especially given the fact that this is a small single player project, only one developer, and there is very limited total gameplay actors.

Certainly there is some better way but I think it’s reasonable compromise for now.

Now, going down the checklist of actors which need to do something with the data Event Manager is sending out, next is the map.

Originally I was only giving the player grid coordinates, so marking Control Point positions on the map was up to them. But in interest of makign the game more accessible to newcomers, I want to automatically have CP’s marked for them. This is also how sport orienteering is typically conducted as well.

There is a few ways I can see this working. One way would be to devise some math to convert between world scale and the maps scale, but it is such an enormous difference I think there would be a ton of error, and precision is needed. Plus, I am not a math guy by any means, and what I read about scale conversion looked complicated.

The simplest thing I can do is a common technique used for minimaps. Set up a Scene Capture 2d and have that looking top down on the world. Then I just scale up my 2d topo map to match same size as the landscape, and have it set so the Render Target only views the 2d map.

Now there is no scale to convert, I can simply spawn some sort of markers whereever chosen CP’s or other POI’s are. Pretty easy and I have done something similar to this already. One thing to note though is that because the origin will be shifting, when we read back the location of CP actor in the level, it is necessary to compare the location to another actor in the level which will not move. I call this the “static origin reference.”

Another benefit to this setup is that if allows flexibility and ease of iteration. I can move control points around as much as I like and then during run time their position is just automatically captured and fed as info to the player. So that is good.

I’m working on overhauling the character controller/player pawn.

It was getting hard to manage because of too many conditionals. Before every input was a check for this, a switch for that… every function asking a ton of different questions about if this guy is visible or that guy was called, and in too many cases the order of execution flow was like the worlds hardest puzzle to solve… So, something had to change.

I did a lot of planning and trying to sketch out a better way for communication to flow. Ideally, there should be no puzzles of execution flow or having to hold a bunch of caveats in my head for every little thing. It becomes too exhausting.

So I had an idea like, there should be a state where, while it is active, i can define how input is handled, what UI to show, etc. And then when I change states, everything is just wiped clean and the new state sets its own rules. That way nothing would depend on anything else - no event or function has to ask, “am i allowed to do my thing right now?” They just fire and then the state decides if it cares or not.

This should break my code into bite size chunks that i can just consider one at a time. And that can help me conceptualize the whole of the project because i’ve organized small bits into larger chunks - i dont have to try and hold a big web in my mind when making small decisions.

Well, it’s worked out great. Turns out, there is actually a programming term for what i wanted - the state pattern.

I’ve accomplished this in unreal by extending from the method shown here:
State Management, State Machines, and the State Design Pattern in Unreal Engine 4 Blueprint - YouTube

The idea is that you make an Object class for any state that you want. You can make a parent class and then have children from that. Any common functions you want can go on the parent. So I made an On Construct function and handle inputs functions in the parent.

When I create a state object, I pass in the controller, the HUD, and the pawn into it so the state can have command and control.
On construct I’ll bring up whatever UI is needed, show or hide mouse, and so on.
If Input needs special functionality, I’ll handle that in there as well.

And finally whenever state is changed I call a function I call “Sanitize” which removes UI and a few other specifics - basically anything a state might set gets reset. Then the new state only has to worry about what it wants to show, but no states have to worry about turning anything off. This effectively makes it so that execution flow does not matter at the higher levels. I can then extend and modify things pretty easily.

To me this is a very low brain-drain approach. I dont really have to remember things - I just toss what I want into a state object like its a bucket, and if there is some bug related to input or UI, I have a good idea exactly where its gonna be.

Changing a state:


(i have some concerns about creating new state every time because i am not 100% sure it gets garbage collected. But I can test this later and if there is a problem, just set each unique state to its own variable.)

So, state pattern is a big win in my book for handling input and UI states. This has made maintenance of the project significantly simpler. I am also finding it easier to add new behaviors because I dont have to think, “how does this fit in the web?” I just make a state and try it out.

Of course if i find states getting redundant i can consolidate them, or move some stuff to parent class.

Well, this is great. It’s simplified a major chunk of my projects code. I dont think the state pattern would be well used elsewhere in my project but I’m glad I was able to put it to good use.

Below: The parent state class

I should make a note of this as well, it came in handy big time.

So in LANDNAV you need to move a map and compass around. You do that by clicking on the compass/protractor/map and drag them to make your measurements and whatnot.

Previously I had them in a fixed position near the player characters waist, and you needed to look down at the tools to use them. I wanted to change it so they are always in front of the camera - children to the camera.

Click and drag operations in 3d can have the problem of moving back and forwards in relation to the camera. You can easily set a constant in the Z value as you are updating the position of the dragged object, but if its relationship is relative to the camera then that doesn’t work.

There is probably some intense math you can do to make the conversion from world space to relative space but thats way beyond me. I tried getting some help and got pretty stressed out, but luckily after some effort a friend turned me onto these two nodes:

and man! That made my previous code seem so over-engineered.
This solves the problem of moving back/forwards from teh camera because you are creating a plane at a certain distance from the camera, then just getting the location where you intersect that plane. So the distance is always the same.

I had actually tried to do that manually but then i was going to have to setup multiple trace channels and so on. Really nice that nodes like this exist.