Iron Village Dev Diary #6 – Navigation Struggles

It finally happened – I ran into a Godot feature that was just not intuitive. At least, I didn’t find it especially intuitive. So here’s my experience dealing with that.

I went in having done my research – reading the docs, I understood that this was first and foremost designed with static levels in mind – levels where the player isn’t significantly altering the environment. The documentation doesn’t really cover cases where the player is actively altering the environment, which is basically the main feature of most city builders. I searched for other tutorials, but they didn’t seem to cover this situation. Still, it looked technically feasible, so off I went.

So I set up a box for my NavigationRegion2D, and I notice something about source geometry – nice, that should be exactly what I need! There’s something about static colliders, so I figure if I add some StaticBody2Ds to my buildings, the NavigationRegion2D should pick up on them, right? Nope. Just fills in the whole box. I had also added a CharacterBody2D to each of the pops, and they were successfully blocked by those static bodies, but the navigation just totally ignored them. The pops just helplessly ran against the wall, trying to get to their destination, and failing. (I have since made them AnimatableBody2Ds, since they kept colliding with each other as well. I’m not entirely sure that they’re necessary though.)

I tried messing around with the source geometry, but no combination seemed to be able to get the buildings picked up. (While revisiting the NavigationRegion2D for writing this diary, I finally realized the actual solution was adjacent to this all along – I’ll get to that eventually.) So fine, I guess I can manually mess with the geometry in code – not super pretty, but the API suggests it’s doable, right?

Long story short, it is. But there’s a few caveats:

  1. Baking the navigation polygon (that is, generating the navigable space based on input geometry) is asynchronous. I think you can force it to act on the same thread, but that seems like bad practice? Idk, doing that just gives off bad vibes. (Yes, I have about a decade and a half of programming experience, I’m obviously super professional.) So, you’ll want to be sure you gather all of the geometry in one place before baking it.
  2. The direction of the outlines matters. This is not documented in the official docs, but is mentioned in some videos.

This second part was really the WTF moment for me – manually entering in rectangles counter-clockwise would add to the navigable area, so I never saw any changes. Pops would try to walk straight through buildings still, and the debugger was showing it really was adding those rectangles. Flipping the order around to clockwise though, and now these rectangles were treated as holes in the navigation polygon. I’m guessing there’s some sort of mathematical reason for this, but that was kind of a ridiculous way to discover that “feature”.

Anyway, I got that all finished at the very end of last week, and now that I’m looking back at the NavigationRegion2D source geometry area, I finally figure it out – if I set it to source geometry groups with children, and add all of the StaticBody2Ds to a group that I specify (groups being a feature I haven’t used in Godot until now), then it will finally pick up on those obstacles and include them when baking the navigation polygon in the editor. It still won’t work if I specify root node children, but the grouping does work at least.

So anyway, that was quite an adventure. I’m honestly really tempted to create a video tutorial about it, just to cover things that I missed.

(Screenshots of the navigation setup, finally working and adapting to new buildings.)


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *