Image 1 — My wife and I built our own board gaming table for €579
Image 2 — My wife and I built our own board gaming table for €579
Image 3 — My wife and I built our own board gaming table for €579
Image 4 — My wife and I built our own board gaming table for €579
Image 5 — My wife and I built our own board gaming table for €579
Image 6 — My wife and I built our own board gaming table for €579
Image 7 — My wife and I built our own board gaming table for €579
Image 8 — My wife and I built our own board gaming table for €579
Image 9 — My wife and I built our own board gaming table for €579
▲ 1.3k r/Brettspiele+1 crossposts

My wife and I built our own board gaming table for €579

My wife and I have wanted a dedicated board gaming table for our basement for a long time. We finally built one together, and I wanted to share some pictures of how it came together.

The base is a 220 × 105 cm spruce panel, 27 mm thick, which we had cut to size at a local hardware store. We ordered the metal legs from Amazon and bought the fabric for the playing surface from a local fabric shop.

The frame and accessories are 3D-printed parts from Gameframe. We went with black for the frame and gold for the trays, cup holders and corner dice towers. The printed parts use almost 20 kg of filament altogether. We also added an LED strip around the inside edge.

Here is our material cost breakdown:

- Wooden tabletop: €150

- Table legs: €109

- Fabric: €52

- Gameframe parts: €238

- LED strip: €30

- Total: €579

One of my favourite additions is a separate wooden panel that sits on small supports above the main playing surface. We can leave a board game set up underneath and use the upper level for miniature games. The game below stays visible and accessible.

There is also comfortably enough room for War of the Ring and all its bits, which was a pretty good test for us!

Putting it together bit by bit was a fun project to share. Having our own gaming table down in the basement feels like a little dream come true.

u/Gl4dr3x — 11 days ago

First Steam capsule for my board game tycoon. Does it work at small size?

I have been working on the Steam capsule for Board Game Tycoon and I think I reached the point where I stared at it for too long 😅

Before I explain the game: what kind of game would you expect from the capsule alone?

I also added a sheet with the different Steam sizes, grayscale versions and the small capsule next to some other management games. The 120x45 version is probably the one I am most worried about.

The game itself is a cozy management game where you run a small board game publisher. You design games, test them, print them, sell them and slowly grow the company.

Basically a bit of the Game Dev Tycoon idea, just around board games, to put it simple

The capsule is made from an in-engine render because I want the Steam page to stay pretty close to how the actual game looks.

Main things I am unsure about:

  • Is BOARD GAME TYCOON still readable at 120x45?
  • Does it look like a management/tycoon game?
  • Is the character, title and board readable enough or is there too much going on?

The board game boxes on the right are still WIP, so those will change anyway. I am working on let them be procedural generated with simple icons regarding theme and mechanic, worth another post somewhere else.

Any feedback is welcome. Especially first impressions, because that is something I cannot really judge anymore after looking at this thing for days 😄

u/Gl4dr3x — 1 month ago

Headless rendering in UE5 with Python: what actually worked for me and the traps that cost me hours and hours

Hi huys, first post here, happy reader and lurker for a long time with my old and now new account ;) Did a Unreal project 10 years ago and now I am currently migrating an RTS from Godot to Unreal 5.8 and needed a small automated QC pipeline:
Spawn a skeletal mesh, apply an animation, render a few fixed camera angles and save the results with no manual clicking in the editor.

I expected this to be fairly straightforward, but the reality was different :D

I spent a few days going through different approaches, and several of them looked like they were working because Unreal happily created output files without actually giving me the rendered scene I expected.

I do not want to keep the infos for myself, maybe some are totally obvious, but here are the things that worked and did not work for me.

-run=pythonscript was a dead end

I initially tried running the Python script as a commandlet, including `-AllowCommandletRendering`. The RHI started.

`SceneCapture2D.capture_scene()` ran.

`RenderingLibrary.export_render_target()` wrote a PNG.

With no Python error as a response, but the rendered image was basically empty.

That was the most confusing part of this whole thing, because all the individual API calls appeared to succeed. At one point I had valid PNG files on disk, a clean Python run, and still nothing useful in them?

Whatever exactly is happening internally in this mode, my dynamically spawned meshes simply were not making it into the capture the same way they do in a normally ticking editor. So I stopped trying to force the commandlet route for actual rendered QC.

-game wasn't useful for my editor automation either

My next attempt was running the editor binary with `-game`. Python executed and the map loaded, but the editor APIs I needed were no longer available in the same way. Editor subsystems returned `None`, and one attempt to fall back to `unreal.EditorLevelLibrary` ended in a hard crash. Meh, that route was also not working. Then I finally found out, what helps me:

I ranthe full editor offscreen:

UnrealEditor-Cmd.exe <project> -RenderOffScreen -unattended -nosplash \\
  -ExecCmds="py C:/path/to/script.py" -stdout

With no `-run` or`-game`.

That gives me both the editor world and a normally ticking rendering environment.

For the world:

world = unreal.get\_editor\_subsystem(
    unreal.UnrealEditorSubsystem
).get\_editor\_world()

The important part was not trying to do everything inside one Python call. Instead I register a Slate tick callback:

handle = unreal.register\_slate\_post\_tick\_callback(on\_tick)

and run a very small state machine. Mine is roughly:

  1. Spawn/setup the scene.
  2. Wait a few ticks.
  3. Set the animation position.
  4. Wait a few more ticks.
  5. Capture.
  6. Save the render target.
  7. Move to the next frame/view.
  8. Quit when the queue is done.

Those extra ticks mattered really really strong! For example, immediately capturing after changing the scene gave me inconsistent exposure/lighting results. Giving the editor a few frames to settle made the output much more reliable in the end.

Skeletal mesh animation

I am using a normal `SkeletalMeshActor` and its skeletal mesh component.

The relevant calls are basically:

set\_skeletal\_mesh\_asset(...)
set\_animation(...)
set\_play\_rate(0)
set\_position(seconds)

In the ticking editor this gave me the animation pose I expected without doing anything special. For the capture itself Im using:

* `SceneCapture2D` * `SCS_FINAL_COLOR_LDR` * `RenderingLibrary.create_render_target2d` * `RenderingLibrary.export_render_target`

Nothing fancy as you can see :D

Lighting was another weird one

For this QC setup I hav ended up keeping the lighting deliberately simple with a couple of normal directional lights.

I also tried adding `SkyAtmosphere`. That waS a bad idea for this particular use case :D

My isolated meshes suddenly looked almost completely washed out / fogged away and for a while I thought rendering had broken again. Removing it fixed the scene immediately.

So if you are building one of these tiny isolated render stages, I would start simple before adding the normal world/environment stack.

Other things I learned the hard way and you can avoid!

Do not blindly trust the process exit code.

In my setup Unreal sometimes returns exit code `1` even when the script itself completed and all expected renders were successfully written. There are startup warnings/ensures in the log unrelated to my capture job.

I am therefore validating success using my own log marker plus checking that the expected output files exist.

`refresh_bone_transforms()` did not make commandlet animation work f.e.

Before switching to the full editor approach, I tried forcing skeletal updates manually.

For my setup, calling:

skeletal\_comp.refresh\_bone\_transforms()

still left me effectively looking at the same/rest pose when sampling frames that way. If you dont actually need rendered images and only want to inspect poses, there is another route that worked much better for me:

unreal.AnimationLibrary.get\_bone\_pose\_for\_frame(...)

You can grab the local bone transforms for a frame and then build the hierarchy yourself using the parent bones.

I used:

comp.get\_parent\_bone(name)

and:

MathLibrary.compose\_transforms(local, parent\_cs)

That turned out to be useful for cheap silhouette validation without needing the rendered editor at all.

**Use keyword arguments for** `Rotator`\*\*.\*\*

This cost me an embarrassing amount of time I could have used somewhere else.

I had assumed:

unreal.Rotator(a, b, c)

was pitch/yaw/roll.

It is not! Man, was that a pill to swallow (this is a english saying, right? :D)

The positional order is roll/pitch/yaw.

Since then I only write:

unreal.Rotator(
    pitch=...,
    yaw=...,
    roll=...
)

Much harder to mess up that from now on, before i forget it again.

**If one camera angle is mysteriously empty, move it slightly.**

I also had a case where a mesh vanished when one of my cameras was looking almost perfectly along an axis, while Other camera angles rendered correctly.

Changing it to a slight three-quarter angle fixed it.

I have not investigated that one deeply enough to say what exactly caused it, but it is worth trying before rebuilding your whole capture pipeline because one view is black.

MRQ

I also experimented briefly with Movie Render Queue.

The main problem for my use case was that I was trying to start it from a commandlet-style Python process and then return from the script. MRQ is asynchronous, so the process lifecycle becomes important very quickly.

I eventually decided that for these simple fixed-angle QC shots, `SceneCapture2D` inside the ticking editor was much less machinery. If I needed actual cinematic output, temporal sampling etc., I would probably approach MRQ separately rather than trying to bolt it onto the same script.

All of this is from **UE 5.8** by the way!

The Python API changes often enough between Unreal versions that I would definitely check the names against your own version before copying anything directly, this is what the documentation and videos make it seem to be the case at least.

Hopefully this saves someone else from staring at perfectly valid black PNG files for a day, like I did!

And if I am totally wrong one some thinks, you are welcome to correct me!

reddit.com
u/Gl4dr3x — 2 months ago
▲ 92 r/godot

Pushing my Godot RTS from 7 to 35 FPS in a 340-unit battle

Last devlog I wrote about shrinking the download to a sixth of its size, from 4.5 GB to 763 MB. This time it was the battle itself. A roughly 340-man fight was running at a miserable 7 FPS. By the end of fixes it was at about 35 FPS on the exact same scene. Four changes, none of them changing how anything looks. Unfortunately I do not have a version left on my PC to do a side by side video witht the same units and UI again :/

1. The simulation was sabotaging itself
When the sim fell behind, it tried to catch up by running up to 8 physics steps in a single frame. That made the next frame even slower, which meant even more catch-up, a textbook feedback loop pinned against the cap. Capping the catch-up broke the spiral.

2. Every soldier was scanning the whole map
Each unit was searching the entire battlefield for enemies 60 times a second, including enemies half a kilometre away it could never reach. Now each regiment only looks at its own neighbourhood, and only a few times a second instead of 60. Units still react just as promptly, you can’t feel the difference in play.

3. One soldier was 23 draw calls
A single soldier was a kit of 16 separate parts, and the Spartan hoplite was 23, all sharing one texture. They’re now merged into a single mesh at load time. The model is millimetre-for-millimetre identical, the GPU just doesn’t have to ask for it 23 times anymore.

4. Distant regiments have no skeleton at all
Past about 60 m, a regiment’s movement comes from a pre-baked table the GPU reads by itself, with no per-bone CPU work. It switches over at around 60 m and back again, and you never catch the swap.

Also, the archers were throwing one hidden error per archer, per volley. Invisible, but quietly eating CPU. In a fight with several ranged units, deleting that alone was noticeable.
While doing the distant LOD work, the horses lost their legs. And three automated checks in a row told me everything was fine. The first looked at the wrong skeleton, the second never actually moved the horse, and the third only inspected the finest detail level while the game was drawing the coarser one. What finally caught it was a dumb before/after screenshot diff :D

u/Gl4dr3x — 2 months ago
▲ 16 r/godot

RTS with 340 units: do you run unit logic at 60 Hz or on a slower simulation tick?

I am building a Total War style battle game in Godot 4.7. A full battle currently has 18 regiments and around 340 animated soldiers, with a host authoritative multiplayer setup.

Depending on how much of the battle is visible, I currently get around 7 to 15 FPS. The GPU is mostly waiting and total CPU usage also looks low, so I did some profiling instead of randomly disabling things.

In the worst case shown in the screenshot, I measured around 5 ms of GPU work during a frame that took more than 100 ms. CPU usage was around 13% on a Ryzen 5700X, so this looks like a classic main thread bottleneck.

These are the results from that worst case. The values are summed over all 18 regiments and all physics steps executed during one rendered frame:

movement, pathing and kiting       28.2 ms
idle enemy acquisition             13.0 ms
melee and per-soldier combat       12.8 ms
status effects and progress bars   12.8 ms
visual state reapply                8.6 ms
everything else                     4.9 ms
total                               80.3 ms

I also ran two tests to make sure I was looking at the correct system:

animations disabled:       9.2 FPS -> 8.4 FPS
unit simulation disabled:  9.2 FPS -> 27.2 FPS

The animation result is basically normal variance. Disabling the simulation clearly makes the difference.

The part that surprised me was the number of physics steps. My probe reported exactly 8 physics steps per rendered frame, which is also the default value of max_physics_steps_per_frame.

One simulation tick only costs around 10 ms. But once the game falls behind, Godot tries to catch up by running several ticks during the next frame. Those ticks make the frame even slower, so even more catch-up work is needed. It eventually stays at the limit of eight steps per frame.

Basically, slow makes slower.

Lowering the physics rate broke that loop:

60 Hz   7.5 to 10.6 FPS   80.3 ms simulation per frame
30 Hz   15.4 FPS          19.5 ms
20 Hz   22.3 FPS           9.1 ms

At 20 Hz the game was back below one simulation tick per rendered frame and everything became stable again.

So I am curious how other RTS or large unit projects handle this:

  1. Do you run unit logic directly in _physics_process() at the project physics rate, or use your own accumulator and update the actual simulation at something like 10 to 20 Hz?
  2. When splitting the rates, what still stays at the normal physics rate? Movement, NavigationAgent3D, collision checks, combat, target searching?
  3. How did you handle timers and balance code that quietly assumed a 60 Hz update rate? I already use delta in most places, but I am sure there are still some hidden assumptions.
  4. Do you normally lower max_physics_steps_per_frame? Running the simulation slightly slower under heavy load seems better than entering this catch-up spiral, but I rarely see this setting discussed.

I am also interested in physics interpolation. Does Godots 3D interpolation work well for units moved with NavigationAgent3D when the actual simulation only updates at 20 Hz?

One secondary problem is skeletal animation. I measured around 0.28 ms per skeleton update, so at some point Skeleton3D itself becomes the next limit. At what unit count did you move to baked vertex animations, MultiMesh, or another solution?

The host is authoritative, so clients can interpolate visuals, but I still want the simulation rate to stay stable and predictable. I would rather not make multiplayer synchronization much harder just to gain frames.

In the end, what my current plan would be is do make a conversion to MultiMesh and VAT vor Animation to move the load to GPU instead of CPU. But before I tackle that Mammoth, I wanted to ask you guys first :)

I am building a Total War style battle game in Godot 4.7. A full battle currently has 18 regiments and around 340 animated soldiers, with a host authoritative multiplayer setup.

Depending on how much of the battle is visible, I currently get around 7 to 15 FPS. The GPU is mostly waiting and total CPU usage also looks low, so I did some profiling instead of randomly disabling things.

In the actual worst case, I measured around 5 ms of GPU work during a frame that took more than 100 ms. CPU usage was around 13% on a Ryzen 5700X, so this looks like a classic main thread bottleneck.

The attached screenshot shows a slightly less severe moment at around 15 FPS, not that exact worst-case measurement.

These are the results from the worst case. The values are summed over all 18 regiments and all physics steps executed during one rendered frame:

movement, pathing and kiting       28.2 ms
idle enemy acquisition             13.0 ms
melee and per-soldier combat       12.8 ms
status effects and progress bars   12.8 ms
visual state reapply                8.6 ms
everything else                     4.9 ms
total                               80.3 ms

I also ran two tests to make sure I was looking at the correct system:

animations disabled:       9.2 FPS -> 8.4 FPS
unit simulation disabled:  9.2 FPS -> 27.2 FPS

The animation result is basically normal variance. Disabling the simulation clearly makes the difference.

The part that surprised me was the number of physics steps. My probe reported exactly 8 physics steps per rendered frame, which is also the default value of max_physics_steps_per_frame.

One simulation tick only costs around 10 ms. But once the game falls behind, Godot tries to catch up by running several ticks during the next frame. Those ticks make the frame even slower, so even more catch-up work is needed. It eventually stays at the limit of eight steps per frame.

Basically, slow makes slower.

Lowering the physics rate broke that loop:

60 Hz   7.5 to 10.6 FPS   80.3 ms simulation per frame
30 Hz   15.4 FPS          19.5 ms  (test only, not shipped)
20 Hz   22.3 FPS           9.1 ms  (test only, not shipped)

At 20 Hz the game was back below one simulation tick per rendered frame and everything became stable again. This was only a test though, not a decision on how the final simulation should work.

So I am curious how other RTS or large unit projects handle this:

  1. Do you run unit logic directly in _physics_process() at the project physics rate, or use your own accumulator and update the actual simulation at something like 10 to 20 Hz?
  2. When splitting the rates, what still stays at the normal physics rate? Movement, pathfinding queries, collision checks, combat, target searching?
  3. How did you handle timers and balance code that quietly assumed a 60 Hz update rate? I already use delta in most places, but I am sure there are still some hidden assumptions.
  4. Do you normally lower max_physics_steps_per_frame? Running the simulation slightly slower under heavy load seems better than entering this catch-up spiral, but I rarely see this setting discussed.

I am also interested in physics interpolation. Does Godot's 3D interpolation work well for units that are moved directly in _physics_process (Iquery NavigationServer paths ourselves and move plain Node3Ds, no NavigationAgent3D) when the actual simulation only updates at 20 Hz?

One secondary problem is skeletal animation. I measured around 0.28 ms per skeleton update, so at some point Skeleton3D itself becomes the next limit. At what unit count did you move to baked vertex animations, MultiMesh, or another solution?

The host is authoritative, so clients can interpolate visuals, but I still want the simulation rate to stay stable and predictable. I would rather not make multiplayer synchronization much harder just to gain frames.

My longer term plan is to move rendering and animation to MultiMesh with baked vertex animation, since skeletons will become the next wall once the simulation is fixed. But my own numbers say the current bottleneck is pure game logic, so before I tackle that mammoth I wanted to ask how you structure the simulation side first :)

u/Gl4dr3x — 3 months ago
▲ 421 r/godot

My Godot export was 4.5 GB. 52 textures went from 1 GB to 67 MB

I am using Godot 4.7.1 and my 3D RTS exported at 4.5 GB, which was way over itch.io’s 1 GB limit.

It is now down to 763 MB, with 655 MB of that being the PCK. Nothing in the game looks noticeably different.

There were two main causes, and I was wrong about both of them at first. I blamed the audio, but audio was not causing that. I have around 1.1 GB of raw WAV libraries inside the project folder, so thats where I started looking, would have been to obvious ^^

But that folder already had a .gdignore and had never been included in the PCK at all. Around two hours wasted on the most obvious suspect, hm :/ The search I continued lead to the first Cause of the problem!

Cause 1: source file size does not decide the exported texture size

This was the part I did not understand at first.

Godot compresses textures for export into a VRAM format like BPTC/S3TC, which uses a fixed bitrate. What your PNG or JPEG weighs on disk does not decide what it weighs in the build, but the resolution does.

With my import settings, a 2048x2048 texture ends up at around 5.3 MB. A 4096x4096 texture ends up at around 21.3 MB, mipmaps included. It does not matter whether the source file is a small JPEG or a huge PNG.

The screenshot shows this pretty clearly. Source files with sizes of 52.9 MB, 22 MB and 15.2 MB all end up at exactly 21.3 MB when imported at 4096. So I had been optimizing the wrong thing. Compressing the source images made the project folder smaller, but it did nothing for the exported texture size.

Textures alone were taking up around 4.0 GB of the build when checked, totally crazy.

The fix was process/size_limit inside the texture .import files. This downscales the image before VRAM compression, reducing both build size and VRAM usage. I set most unit and prop textures to 1024. From an RTS camera distance I honestly cannot see a difference at all. That reduced the textures from around 4.0 GB to 433 MB.

The screenshot contains 52 textures where I could still compare both imported versions. At 4096 they take up 1009 MB together. At 1024 they only use 67 MB.

I deliberately left some textures untouched:

  • Terrain detail textures, since they sit close to the camera and tile across large surfaces
  • UI textures, since they are displayed as 2D images
  • Anything inside my addons/ folder

But this was not all, I found another problem which is cause 2:

Cause 2: export_filter="all_resources" was packing unused files

My export preset was using all_resources, so it also included files that nothing in the game referenced anymore. Stuff like placehodlers, older models (like KayKit Assets) etc.

I switched toexport_filter="exclude" after I discovered it. I now generate the exclusion list from the actual dependency graph, so it stays correct when assets move around.

The annoying part, for me at least, is that neither problem is very visible inside the editor. The .import file does not really tell you how much a texture will weigh inside the final build.

I only found it after exporting the game, unpacking the PCK and sorting everything by size. In hindsight, that should have been step one instead of step ten. Maybe this can be of help for someone else as well :)

u/Gl4dr3x — 3 months ago
▲ 3 r/GameDevs+1 crossposts

I am torn on my battle UI. Does this fit a ancient RTS, or is it too modern?

Solo dev here, working on a Total War style PvP battle game set in antiquity in Godot.

The clip shows the battle feedback I have so far: regiment strength and morale bars, archers loosing a volley and reloading, damage numbers popping off units taking hits, and a regiment breaking and routing in the middle.

Both sides are Romans on purpose, so the only thing separating them is the UI itself, the slate ring versus the rust one. That is part of what I am unsure about.

My worry is tone. Everything is readable, but I keep going back and forth on whether an ancient setting wants something more muted and worn, closer to bronze and stone, or whether readability should just win in a fast PvP game.

Does anything here clash with the setting for you? And if you solved this in your own game, how did you decide between style and readability? Thanks in advance :)

u/Gl4dr3x — 3 months ago
▲ 18 r/godot

A Fab asset creator told me he is already waiting to publish directly on the Godot Asset Store

I recently contacted the creator of Horse Animset Pro, an animation pack I found through Fab, because I wanted to make sure I could use and retarget the animations in my Godot project.

Besides confirming that this was fine, he creator told me that offering the pack for Godot is already his goal once the Asset Store supports commercial publishers.

It is only one creator, of course, but I found the response quite encouraging. There seem to be established asset publishers from the Unity and Unreal/Fab ecosystems who would happily offer their work directly for Godot once selling paid assets becomes possible.

Godot’s official roadmap also says that paid assets will initially be rolled out together with a selected group of asset creators. So the interest apparently exists on both sides, even though we probably should not expect the complete Unity Asset Store or Fab catalogue to appear overnight.

For 3D developers especially, this could make a huge difference. At the moment I can often make assets from other stores work, but it involves checking licenses, converting FBX files, fixing materials, retargeting animations and sometimes rebuilding parts of the package. Huge hassle ofen, but worth the result!

Having proper Godot versions directly from the original creators could remove a lot of that friction. The engine is already becoming more capable, but a healthy commercial asset ecosystem might be one of the things that makes it significantly easier for more developers to actually finish and ship larger projects with it. Really looking forward to it and wanted to share with you, cause I am so hyped about that!

reddit.com
u/Gl4dr3x — 3 months ago