While helping one of my students create and iterate on a game in C using raylib, I realized there was quite a lot of time spent on experimenting with level design and colors, how the player moves, gravity, etc. and a lot of time was wasted making a change, exiting the game, recompiling, running the game, deciding his change wasn't right, and going through the whole cycle over and over. I could tell it was demotivating, and this process was creating a barrier that prevented him from experimenting to his heart's content.<p>I started this project to solve this problem by giving a simple gui to a few core features of lldb through the lldb api. Experimenting with changing colors, where blocks in the level go, how tall the player is, gravity is all now just a simple toggle or text field edit. The variables are modifiable while the program is running.<p>The project is still in its early stages, and so far only targets macOS.
Hey, looks like we had the same idea! I've run into the same issue and wanted to stop building debug UI's that do the same thing.<p>In my case, I went to implement this for Windows, but bit more advanced with inline scripting support. Basically, you insert a snippet anywhere in the code that can call various functions and one of them is `view()` which will show all locals (or a chosen object out of scope) in a Visual Studio window (it's a VS extension [0], website [1]). Calling it again will update the view with the new state. The scripting language underneath is Angelscript and it understands symbols inside your entire project (e.g you could do `view(Namespace::g_variable)` or even call functions from the program etc.
The snippet hook is then JIT'ed into the target function by relocating it using info from the PDB. This took me ~1y to implement, and it's still a research phase project.<p>[0] <a href="https://marketplace.visualstudio.com/items?itemName=donadigo.d0&ssr=false#overview" rel="nofollow">https://marketplace.visualstudio.com/items?itemName=donadigo...</a><p>[1] <a href="https://d-0.dev/" rel="nofollow">https://d-0.dev/</a>
I did a similar thing once in Haxe by using macros to annotate members and rendering control widgets in an auto generated debug UI. This is basically what Unity/Unreal/Godot/etc do with their fancy editors.<p>The best experience I've had with this kind of thing has been Godot. Not only do you get to tweak values at runtime, you can also change the code at runtime and see changes reflected live. It's so awesome being able to hit a breakpoint in a running game, step through some code, change the code, and then continue stepping to see the changes.
I think it might be more useful for your students to learn about making simple GUIs with Dear Imgui or something similar, that make this type of stuff intentional and much more stable/foolproof. A large part of game dev is making tools appropriate for making the game and all of this falls into that.
I'm trying to wrap my head around why build a hook into lldb instead of writing a library that would allow your students to simply spawn an imgui window with the variables exposed in exactly the same way?<p>This is generally a tool you would likely need to build into a game regardless for exactly the reason you mentioned, rebuilding to change gameplay variables isn't exactly a great experience.<p>I personally just use a simple terminal that I can open and close to adjust variables but eith hoe easy imgui is I don't see any reason to not do a gui window for that.
Interesting! My baseline expectation would be that this wouldn't work at all, debugging C++ usually tells me variables have been removed by the optimiser. Perhaps this requires `-O0 -g` or similar to work effectively, which games devs are usually not open to.<p>Optimising IR without dropping debug info is difficult. I don't believe it to be intractable, some of the Sony developers are active in improving this for LLVM. Debug info is roughly a bunch of side tables of data from which one can recompute values which were in the original program and are not in the executing one. I would speculate that a compilation mode which treated any degradation of that as a miscompile could be done with minor to no runtime cost, at serious engineering cost.<p>Perhaps easier would be to restructure the program so that specific variables are always available to the debugger. Deliberately hoist them to escaped global variables, roughly.<p>The other interesting line of attack here is a JIT. The students probably don't change all the parameters simultaneously. Call graph walk + incremental compilation of parts affected by a given variable is probably tractable. A sibling mentioned hot code replacement, that's a similar sort of hack (you block function inlining, pad functions with some nops, then overwrite in place if the new definition fits in the space).<p>Thanks for the link, interesting stuff.
One of the neatest hacks I've seen and think about occasionally but have never used is a library that defines a TWEAK macro to do this at the source level:<p><<a href="https://blog.voxagon.se/2018/03/13/hot-reloading-hardcoded-parameters.html" rel="nofollow">https://blog.voxagon.se/2018/03/13/hot-reloading-hardcoded-p...</a>><p>In other words, rather than having a graphical interface for tweaking values at runtime, you interface with it the same way you normally would—by changing the constants in the original source file, but the difference between the ordinary stop-and-recompile way of doing it is that the changes get picked up live, so there is no stop-and-recompile. (This isn't exactly novel; webdevs have had hot code reloading to various degrees for a while, but the conventional static languages folks have generally needed to rely on support in sophisticated IDEs to get the same thing, and many end up going without.)<p>For those who want the graphical control panel, I suppose you could do the complement: when a value is tweaked in-game, it could overwrite the existing value in the source file so you don't have to tweak in-game and then manually copy them out to source once you've landed on the values you like.
Or you could just set a breakpoint somewhere and edit the values in your debugger.<p>This looks cool but I'm not sure how it is especially superior to functionality that is easily available through your favorite debugger (note: I'm speaking from a standpoint of Qt Creator + gdb; YMMV depending on your IDE/debugger setup), especially given that Hook seems to be mainly targeting macOS.