• Andrew Jonhardt

Troubleshooting: Even prototypes need it

Picture it: Thursday, the last week of May. I'd just finished the first version of my Mask of Undying prototype and had started playing with it. Adjusting enemy speeds, timings, and ranges, that kind of thing.

Perfect. Too perfect.

Everything was going good, so I decided to take the logical next step: make a new level based on what I had so far, and setup transitioning from my first level to my second. I set up the new level, setup a transition, and played the game.


Crash. No error, no explanation, nothing. Every time I navigated to the level transition and attempted to use it, the editor game window would close out completely. This raised a series of questions:

  1. Could it be the code I'm using to transition between levels? No, the one-liner get_tree().change_scene(next_scene) is generally considered safe.

  2. Has anyone else reported a similar issue online? Brief Google search says not really.

  3. Could it be the SmartTilemap2D add-in?

Lucky for me, I've got an earlier version of Mask that doesn't have the SmartTilemap2D add-in integrated. I loaded this earlier version and tested level transitions. get_tree().change_scene(next_scene)

worked perfectly.

After a minute or so of swearing, I sat back and considered my options. I don't know enough about C++ to debug the plugin itself. Maybe there was something I could do from within GDscript? It was clear the issue was occurring during a transition between scenes, so the problem could be related to how Godot was trying to unload the SmartTilemap2D node in my level.


I loaded a test project, and eventually succeeded on triggering a level transition if I ran the following code beforehand:

	var stile = get_child(0)
	stile.clear()
	if stile.get_used_cells() == []:
		get_tree().change_scene("res://AStar/Scenes/Seeker.tscn")

This code, when run from the root-node of a scene (if you think of a scene as a tree, the first node is always the central root from which all other nodes in the scene extend) gets the SmartTilemap2D (the first child, or child0), clears all tiles present in scene that are attached to the SmartTilemap2D node, tests if no tiles are left, and then runs a scene transition.


Unfortunately, the above code didn't work when run from my main project. So, I started testing from within my main project.


I would usually recommend making a copy and working in the copy instead, but I was impatient.

Eventually, I successfully resolved the issue in my main project with 1 line of code before transitioning scenes:

self.remove_child(smart_tile)


I reported the above issue to the creator of SmartTilemap2D on Itch.io, and he updated the plugin a few days later. So cool, problem solved, no one else should have the same issue. New problem time!


I started messing around in my second prototype level, which was significantly larger than the original prototype level, and noticed a very odd kind of tile flickering.


By this time, I had given up on SmartTilemap2D for Mask. I had enough of a prototype to test using collisions instead of A* for enemy movement, and I found something I didn't expect: Enemies with small enough awareness zones can be fun to fight in levels filled with traps.


My initial reasoning for A* made a kind of sense: If a level is filled with traps, and enemies are only using basic pathfinding, it would be too easy for players to steer enemies into traps and avoid them all together. However, this reasoning makes the assumption that there would be enough space in a level for a player to easily maneuver, and it assumes that enemies would possess a large enough awareness to be easily steered safely.


The above gif was taken from a test before I stripped SmartTilemap2D. There's only 1 enemy present, and it moves fairly slowly (on purpose). However, I was surprised to find that steering enemies towards traps (not shown) could be tricky within the confines of a tight level. It was the small awareness field (the large blue collision circle) that seemed to make this possible, and the result was kinda fun!


I had my roommate play the test level, and he concurred that he was having fun.


So, I stripped out SmartTilemap2D from Mask and re-loaded the second test level. And, the tile-flickering re-occurred. Wtf?


Turns out, the flickering issue I was seeing is a known issue that is potentially related to Nvidia's videocard drivers:

https://github.com/godotengine/godot/issues/9913


I built a test project and went through the recommended solutions. I started by going to Project Settings > Rendering > Quality > and enabling "Use Pixel Snap" and "Use Nvidia Rect Flicker Workaround". No change.


Next, I tried switching my project from Godot's Gles3 renderer to the Gles2 renderer. I couldn't tell you what separates Gles3 from Gles2 technically. I did find a YouTube video that explains what difference Gles2 and Gles3 make on game-making:


Switching to Gles2 brought up a whole new issue where scenes in my project failed to load correctly:


Finally, I downloaded the beta3 version of Godot 3.2.2 from this site:

https://downloads.tuxfamily.org/godotengine/3.2.2/


The Godot beta version worked!


I spent Saturday and this morning re-building my prototype in Godot 3.2.2beta3 under the Gles2 renderer. I can now say the prototype is good enough for actual game design testing.


This feels like the first real progress I've made in a year. I don't regret the learning that happened along the way. I still plan to use SmartTilemap2D for a project someday, for example. I'm annoyed it took this long to get to a prototype.


My next post will be on the 21st. Until then!

© 2023 by Andrew Jonhardt. Proudly created with Wix.com