▶
Logic World Wednesdays: Return of the Jimmy
It's true: I've been away for a while. I feel like I should talk about that. A few months ago, I took a break from Logic World because I was forced to by carpal tunnel syndrome. Because of the break, I started doing all sorts of fun things with my life: I was playing new sports, making new friends, learning new skills, and working on new projects. Without really planning to, my quick break to let my wrists heal turned into an extended sabbatical, in which enjoying my life was my only priority. I hadn't taken a real break from working on this project since I started it in 2017. In hindsight, I think I really needed this one. But I'm back, baby, and I'm so freaking excited to be working on my dream game again! Going forward, I'm gonna strive to have a better work-life balance. One lesson I've learned this year is that I'm actually way more productive if I work a little less and play a little more. I'm also investing in an ergonomic workspace, so I don't injure my wrists again :) Let's take a look at what I've been working on recently!
As I've written much about on this blog, a big priority for update 0.91 is to *make game go fast*, especially for larger worlds. I have pretty much completed the optimization work for 0.91, so here's a quick comparison! World: FML-8 by Stenodyon (~70k components, ~78k wires) Settings: 3840x2160, default graphics but with post-processing and shadows disabled Hardware: Ryzen 7 2700X, RX Vega 64
A major improvement indeed! The game isn't quite as fast as I wanted to get it for this update, but I've decided to not let perfect be the enemy of good here, and just move on to other features. Read below for confusing technical info about the few remaining performance issues I wasn't able to solve.
Something about instanced rendering makes the depth textures significantly slower compared to the old combined meshes approach. I'm not entirely sure why -- I'm still very new to hardcore graphics programming -- but I think it has to do with how the game needs to do a depth pass over every single instance, whereas with combined meshes, the engine could automatically cull faces and even entire meshes. The end result of this is that 0.91 is slightly slower in the following situation:
Colliders are the system that allow for collision with components. They prevent the player from walking straight through walls, and they allow us to detect which object the player is looking at. As I've talked about on this blog before, colliders are a big reason for performance problems in Logic World, especially for the slow loading times. I've spent a lot of time trying to implement a "virtual colliders" system, where colliders only exist for objects nearby the player. Unfortunately, I just have to give up on this idea. Logic World sandboxes are too collider-dense, and Unity colliders just have too much overhead; they can't be moved around quickly enough for this application. For now, I've done a lot of research and testing, and I'm dealing with collider setup about as efficiently as it's possible to. Note the loading time improvement in the table above; the gains were mostly due to improved collider efficiency. But still, about 8 seconds of loading time are taken up on JUST colliders, and that number gets ever worse with bigger worlds. Not to mention the appalling RAM usage... In the future, we're going to totally replace the Unity collider system with an all-custom collider system hyper-optimized for Logic World's use case. This system should take approximately zero seconds of loading time, no matter how big your world is. Unfortunately, that is really hard to code, so it'll be a while before it gets implemented.
I've done a pass on Logic World's text rendering capabilities! Most notably, text can now display mathematics symbols (like ), music notation symbols (like ), and EMOJIS!!!!!!!
I freakin love emojis and I'm so happy that Logic World can now display them. Eventually, I want to display colored emojis with Twemoji. However, I need to wait for TextMeshPro (Unity's advanced text rendering system) to properly support colored glyphs. In the meantime, Google's Noto project has released a full set of uncolored emojis. TMP has no problem rendering them, since they're just regular uncolored glyphs, and in my opinion they look pretty good, so we're now using them in Logic World. In addition:
If you've built a large complex structure in Logic World, you've probably run into this issue: past a certain depth of parent-child component relationships, positions and rotations start to get screwy. Even before things entirely break down into nonsense, the components aren't perfectly lined up, which causes all sorts of issues while building. This issue has plagued many a Logic Worlder, and this week I FIXED IT!!! [previewyoutube=WdTXgrcSnqE;full][/previewyoutube] Here's how I did it. Turns out it actually takes a lot of work to make a video game work in the way you would intuitively expect it to.
The imprecision issues are caused by the inherent imprecision of [floating point numbers], also known as "floats". As you continue to manipulate floats, the tiny imprecisions compound on each other until they've built up to noticeable levels. I've switched component positions to using fixed points, which have a specific and constant level of precision (in this case, one millimeter). You can manipulate fixed point numbers as much as you like, and they will never lose precision -- unless you have to round them...
Positions in 3D space are pretty straightforward, and it was relatively simple to switch them to fixed points. However, rotations in 3D space are really bloody complicated. I am not nearly smart enough to use fixed points in a rotation matrix. Thankfully, it doesn't seem to be necessary here. The game now rounds component rotations (to the nearest 0.1 degrees along each 3D axis) at two points: when assigning a new local rotation relative to the parent component, and after calculating the cumulative rotation from the whole stack. As you can see in the video, this rounding keeps the rotations nicely aligned.
With the previous two changes implemented, I was still noticing a very very slight imprecision that built over time and nesting depth. However, this only occurred when the root component of a stack was not aligned with the world axes (i.e. placed on a Grasslands ground). The disadvantage of fixed point positions is that you have to round them to their precision level (in this case, one millimeter). You can't have a component at 420.69mm along the X axis; that number must be rounded to 421mm. This usually isn't noticeable, since every component in Logic World has dimensions in a whole number of millimeters, and almost every connection between components is at a right angle, so all components stay precisely aligned with the millimeter-scale grid. However, when components are rotated at non-right angles, they get pushed off of the millimeter grid. Their fixed-point positions, then, needed to be rounded, and these rounding imprecisions very slowly accumulated. I've fixed this issue by making components track their position and rotation not relative to the objective reference frame, but within the reference frame *of their root component*. Since component connections are almost always right angles, a component's position within the root reference frame will stay aligned with the millimeter grid and not accumulate imprecisions due to rounding errors. After calculating its position/rotation within the root reference frame, the rotation of that frame can then be applied to find a position/rotation within the objective reference frame. Shout out to PseudoGoose, who suggested this solution to me when we were discussing the problem some months ago :) --------------------------------------------- Thanks for being here. Thanks for caring about my crazy little video game that I love so much. It's good to be back. I'll see you next Wednesday. More Logic World Wednesdays
[ 2022-07-28 23:12:00 CET ] [ Original post ]
Im back, baby!
Acknowledging the Absence
It's true: I've been away for a while. I feel like I should talk about that. A few months ago, I took a break from Logic World because I was forced to by carpal tunnel syndrome. Because of the break, I started doing all sorts of fun things with my life: I was playing new sports, making new friends, learning new skills, and working on new projects. Without really planning to, my quick break to let my wrists heal turned into an extended sabbatical, in which enjoying my life was my only priority. I hadn't taken a real break from working on this project since I started it in 2017. In hindsight, I think I really needed this one. But I'm back, baby, and I'm so freaking excited to be working on my dream game again! Going forward, I'm gonna strive to have a better work-life balance. One lesson I've learned this year is that I'm actually way more productive if I work a little less and play a little more. I'm also investing in an ergonomic workspace, so I don't injure my wrists again :) Let's take a look at what I've been working on recently!
Poggers Performance
As I've written much about on this blog, a big priority for update 0.91 is to *make game go fast*, especially for larger worlds. I have pretty much completed the optimization work for 0.91, so here's a quick comparison! World: FML-8 by Stenodyon (~70k components, ~78k wires) Settings: 3840x2160, default graphics but with post-processing and shadows disabled Hardware: Ryzen 7 2700X, RX Vega 64
A major improvement indeed! The game isn't quite as fast as I wanted to get it for this update, but I've decided to not let perfect be the enemy of good here, and just move on to other features. Read below for confusing technical info about the few remaining performance issues I wasn't able to solve.
Depth texture slowness
Something about instanced rendering makes the depth textures significantly slower compared to the old combined meshes approach. I'm not entirely sure why -- I'm still very new to hardcore graphics programming -- but I think it has to do with how the game needs to do a depth pass over every single instance, whereas with combined meshes, the engine could automatically cull faces and even entire meshes. The end result of this is that 0.91 is slightly slower in the following situation:
- The world is medium sized (~50k-150k components)
- All post-processing is on
- Shadow cascades are set to 4
Colliders being little bastards
Colliders are the system that allow for collision with components. They prevent the player from walking straight through walls, and they allow us to detect which object the player is looking at. As I've talked about on this blog before, colliders are a big reason for performance problems in Logic World, especially for the slow loading times. I've spent a lot of time trying to implement a "virtual colliders" system, where colliders only exist for objects nearby the player. Unfortunately, I just have to give up on this idea. Logic World sandboxes are too collider-dense, and Unity colliders just have too much overhead; they can't be moved around quickly enough for this application. For now, I've done a lot of research and testing, and I'm dealing with collider setup about as efficiently as it's possible to. Note the loading time improvement in the table above; the gains were mostly due to improved collider efficiency. But still, about 8 seconds of loading time are taken up on JUST colliders, and that number gets ever worse with bigger worlds. Not to mention the appalling RAM usage... In the future, we're going to totally replace the Unity collider system with an all-custom collider system hyper-optimized for Logic World's use case. This system should take approximately zero seconds of loading time, no matter how big your world is. Unfortunately, that is really hard to code, so it'll be a while before it gets implemented.
Glorious Glyphs
I've done a pass on Logic World's text rendering capabilities! Most notably, text can now display mathematics symbols (like ), music notation symbols (like ), and EMOJIS!!!!!!!
I freakin love emojis and I'm so happy that Logic World can now display them. Eventually, I want to display colored emojis with Twemoji. However, I need to wait for TextMeshPro (Unity's advanced text rendering system) to properly support colored glyphs. In the meantime, Google's Noto project has released a full set of uncolored emojis. TMP has no problem rendering them, since they're just regular uncolored glyphs, and in my opinion they look pretty good, so we're now using them in Logic World. In addition:
- 46 new written scripts are supported! These are mostly historical writing systems like Mayan numerals or Old Hungarian.
- Miscellaneous fixes for how the game displays Arabic and Adlam scripts (these and other RTL scripts are still not properly displayed as right-to-left, but will be soon!)
- Added an option to display CJK characters in the Hong Kong style (in addition to the existing options of Traditional Chinese, Simplified Chinese, Japanese, and Korean)
- Updated Font Awesome to 6.1.2, with over 7,000 new icons!
Fixing Bugs by Fixing Points
If you've built a large complex structure in Logic World, you've probably run into this issue: past a certain depth of parent-child component relationships, positions and rotations start to get screwy. Even before things entirely break down into nonsense, the components aren't perfectly lined up, which causes all sorts of issues while building. This issue has plagued many a Logic Worlder, and this week I FIXED IT!!! [previewyoutube=WdTXgrcSnqE;full][/previewyoutube] Here's how I did it. Turns out it actually takes a lot of work to make a video game work in the way you would intuitively expect it to.
Switching to fixed points for positions
The imprecision issues are caused by the inherent imprecision of [floating point numbers], also known as "floats". As you continue to manipulate floats, the tiny imprecisions compound on each other until they've built up to noticeable levels. I've switched component positions to using fixed points, which have a specific and constant level of precision (in this case, one millimeter). You can manipulate fixed point numbers as much as you like, and they will never lose precision -- unless you have to round them...
Smart and consistent rounding for rotations
Positions in 3D space are pretty straightforward, and it was relatively simple to switch them to fixed points. However, rotations in 3D space are really bloody complicated. I am not nearly smart enough to use fixed points in a rotation matrix. Thankfully, it doesn't seem to be necessary here. The game now rounds component rotations (to the nearest 0.1 degrees along each 3D axis) at two points: when assigning a new local rotation relative to the parent component, and after calculating the cumulative rotation from the whole stack. As you can see in the video, this rounding keeps the rotations nicely aligned.
Root reference frames
With the previous two changes implemented, I was still noticing a very very slight imprecision that built over time and nesting depth. However, this only occurred when the root component of a stack was not aligned with the world axes (i.e. placed on a Grasslands ground). The disadvantage of fixed point positions is that you have to round them to their precision level (in this case, one millimeter). You can't have a component at 420.69mm along the X axis; that number must be rounded to 421mm. This usually isn't noticeable, since every component in Logic World has dimensions in a whole number of millimeters, and almost every connection between components is at a right angle, so all components stay precisely aligned with the millimeter-scale grid. However, when components are rotated at non-right angles, they get pushed off of the millimeter grid. Their fixed-point positions, then, needed to be rounded, and these rounding imprecisions very slowly accumulated. I've fixed this issue by making components track their position and rotation not relative to the objective reference frame, but within the reference frame *of their root component*. Since component connections are almost always right angles, a component's position within the root reference frame will stay aligned with the millimeter grid and not accumulate imprecisions due to rounding errors. After calculating its position/rotation within the root reference frame, the rotation of that frame can then be applied to find a position/rotation within the objective reference frame. Shout out to PseudoGoose, who suggested this solution to me when we were discussing the problem some months ago :) --------------------------------------------- Thanks for being here. Thanks for caring about my crazy little video game that I love so much. It's good to be back. I'll see you next Wednesday. More Logic World Wednesdays
[ 2022-07-28 23:12:00 CET ] [ Original post ]
Logic World
Mouse Hat Games
Developer
Mouse Hat Games
Publisher
2021-10-22
Release
Game News Posts:
106
🎹🖱️Keyboard + Mouse
Very Positive
(271 reviews)
Public Linux Depots:
- Logic World - Linux [1.75 G]
Build. Program. Simulate. Logic World teaches you how circuits do math.
Key Features
- Digital Logic - Build circuits that work the same way real world computer chips do.
- Challenges - Solve puzzles from simple logic gates to complex machines like calculators and data storage.
- Multiplayer - Logic World is built from the ground up for collaborative multiplayer. Take on Challenges with your friends or build together freely in Sandbox mode.
- Performance - Build massive circuits and simulate them at thousands of updates per second - all without lag.
- Modding - Logic World features powerful modding tools - the same tools the developers are using to make the game.
- Online Hub - Players can upload their builds, mods, and custom challenges and share them with other players.
MINIMAL SETUP
- OS: Ubuntu 14.04
- Processor: 2.4GHz Quad CoreMemory: 8 GB RAM
- Memory: 8 GB RAM
- Graphics: Intel HD Graphics 4000 or AMD Radeon R5 series
- Storage: 2 GB available spaceAdditional Notes: system requirements might be adjusted before release
GAMEBILLET
[ 6138 ]
GAMERSGATE
[ 3395 ]
FANATICAL BUNDLES
HUMBLE BUNDLES
by buying games/dlcs from affiliate links you are supporting tuxDB