1. Logic World
  2. News

Logic World News

Logic World Wednesdays: Return of the Jimmy

I’m 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.

[h3]Depth texture slowness[/h3]
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

If the world is small, the depth pass doesn't have to run as much. If the world is large, the advantages of instanced rendering overtake the depth disadvantages. And if post-processing or shadow cascades are reduced, the depth texture doesn't need to be used so much.

I think this small performance hit is acceptable for now, since it only applies to a situation where most folks aren't struggling with framerate anyway, and the gains in other situations are so significant.

In the future, we'll implement custom culling for instanced rendering, meaning that on a given frame the game will not try to draw any instances that are hidden (i.e. behind other instances). This will make everything faster across the board, but also it should fix the issues with slow depth textures.

Furthermore, I'm optimistic that the engine upgrade in 0.92 will do a lot to help with this issue. The newer versions of Unity and its Universal Render Pipeline have a lot of optimizations to shadows, post-processing, and depth textures themselves.

[h3]Colliders being little bastards[/h3]
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!

Most video games will give you tofu (β–‘) if you try to type esoteric characters. I'm proud that, to an ever-increasing extent, if it's supported by Unicode, it's supported by Logic World.

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][/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.

[h3]Switching to fixed points for positions[/h3]
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...

[h3]Smart and consistent rounding for rotations[/h3]
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.

[h3]Root reference frames[/h3]
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

Logic World Wednesdays: A Big Ball of Inverters

Framerate go brrrrr - Jimmy


I've spent the last several weeks working on major performance improvements for Logic World update 0.91. The primary goal of these improvements is to enable much bigger builds by shortening loading times, increasing framerates, and lowering RAM usage for worlds with a very high number of components.

I'm finally at the stage where I can demo these performance improvements in-game! Here's a video showing off a test save that contains 1,000,000 inverters and 10,000 wires -- something that would be completely impractical in 0.90.

[previewyoutube][/previewyoutube]

I was almost at this point last week, but I ran into two major roadblocks, the tales of which I will presently regale you with.

Annoying roadblock #1: shadows not working properly

I spent forever getting my instancing shader to render shadows, as I showed off last time. Imagine my dismay when I integrated the shader with Logic World and the shadows broke. After extensive investigation, the issue turned out to be with using multiple meshes. Instancing a single mesh many times, as I was doing in my demo scene where I developed the shader, would result in correct shadows. However, as soon as you introduced a second instancer with a different mesh, the shadows would break.

This made no sense and was extremely confusing. I'm still new to working with shaders & general graphics tech, so trying to fix a bug this outrageous was a daunting task. Nevertheless, I took the plunge; I read up on how shadowmaps work and tried everything I could think of to make them look normal again. After three days of this I had eliminated dozens of potential solutions, but was no closer to understanding the cause of the issue. Then, on a whim, I updated Unity to the latest patch release... and the bug was fixed!!!

ALL ALONG IT WAS A UNITY BUG AND NOT A JIMMY BUG. Three days trying to fix it when it was completely out of my hands, and all I had to do was press "update". Well, lesson learned: in the future, when my code doesn't work, I'll be much quicker to blame someone else.

Annoying roadblock #2: invisible thumbnail renders

Logic World renders thumbnails for the items on your hotbar. This thumbnail-rendering system broke when I made the switch to GPU instancing. The world renders itself using Unity's Graphics.DrawMeshInstancedIndirect function, but this unfortunately is incompatible with Camera.Render, which is what we were using to render the thumbnails. Camera.Render executes in the middle of a frame, but DrawMeshInstancedIndirect only actually instances the meshes at the end of a frame. Therefore, those instances couldn't be seen by Camera.Render, and all the thumbnails were empty images.

I did some reading, and I figured out that I should be able to instance the mesh during Camera.Render using something called camera command buffers. I wrote the code to do this, but it didn't work. I did some more reading, and it turns out that camera command buffers are not compatible with Unity's Scriptable Render Pipeline, which Logic World uses.

So instead I started mucking around with Scriptable Render Features, which as far as I can tell are the only way of executing command buffers during Camera.Render in SRP. I did get the mesh instancing to work with this, but I couldn't figure out how to make it work with any lighting, so all the thumbnail renders were dark and ugly.

Finally I gave up on doing things in a good clean way and implemented a crappy hacky solution. The only way I have of properly rendering the objects is with Graphics.DrawMeshInstancedIndirect, but that doesn't work until the end of the frame. So, we'll simply wait until the end of the frame to render the thumbnail. This unfortunately means that there will be one frame of delay between when we request a thumbnail and when it gets rendered; it also means that we can only render one thumbnail per frame, as otherwise the two items would overlap in the render. However, I believe I can mostly work around these issues by beginning thumbnail renders as soon as the game starts, so that every thumbnail you need is already rendered by the time you load into a world.

Overall it took about two days to fix all the issues with thumbnail renders. Bleh. While I was there, though, I took the opportunity to up the quality: thumbnail renders are now anti-aliased. It's a subtle change, but a nice one. You might be able to notice the difference in the above video; the edges are much softer and less jagged.

What's next?

After I'd finished with the above two issues, it's thankfully been relatively smooth sailing to integrate the new rendering tech with Logic World. I've carefully checked everything, and all the visuals in 0.91 are now identical to the visuals in 0.90, down to every channel of every pixel. Objects look exactly the same, but they're much faster to render in large-world scenarios.

I've still got a few more things to finish up with the optimizations, but I'm finally almost done with them. Once they're finished, I'll do a hefty round of bugfixing, and then I finally get to work on new features again!

The hardest part of 0.91 is finished, and the update will be in your hands soon.


---------------------------------------------


View this post on logicworld.net

More Logic World Wednesdays

https://store.steampowered.com/app/1054340/Logic_World/

Logic World Wednesdays: Season Premier

It's been sixteen wednesdays exactly since the previous LWW, and we're very excited to be back! Logic World update 0.91 development is underway, and we've got lots to talk about this week.


Configurable simulation speed - Jimmy


Logic World launched with the ability to change the simulation speed using console commands, but this was an awkward and unwieldly process. I've been working on a proper user interface for changing the speed, which also allows you to pause the simulation and then advance it step-by-step.

[previewyoutube][/previewyoutube]

Shoutout to @LOOPS99 for building the Fibonacci machine shown in the video. You can check out that build here.


Soundtrack publication


In case you missed it: this week, the Logic World Original Soundtrack was published on internet music websites! You can read more about the soundtrack, and find links to all your favorite music places, in this blog post.

[previewyoutube][/previewyoutube]

Since the initial soundtrack launch, there have been a few updates. First, the Logic World Theme is now available on Bandcamp and Soundcloud. Second, we've started working to get the soundtrack published as a Steam DLC. Thank you to the folks who've requested that; we hear you, and it is coming!

A few words from Logic World composer Markku Wainman on the soundtrack launch:

> A big thank you to those who have been listening to the album. The reception has been amazing and I really appreciate all the kind words.


Revamped changelog - Jimmy


You may not know this, but Logic World has an in-game information page to display the changelog. In 0.90.3 this is a simple, single page of text, like the Credits and Roadmap pages.



However, after just three updates, it's clear that this approach scales poorly. First, there's the performance issue: in 0.90.3, when you open the Changelog page, there is a lag spike as Unity converts the 13,000 characters into a single mesh for rendering. Second, there's the usability issue: a single-page giant block of text is not fun to navigate!

We make a lot of changes to Logic World, and our changelogs are very detailed, so these problems were only going to get worse with time. Thus I've remade the Changelog page from scratch. Starting in 0.91, the individual changelogs for each version can be expanded and collapsed by clicking on the headers. The giant block of text is no more, which fixes both issues described above.

[previewyoutube][/previewyoutube]


Better handling of exceptional SUCC - Jimmy


If you've gone digging around in the Logic World game files, you've probably encountered some files with the extension `.succ`. These files contain data formatted as text that is easy for humans to read and edit. They are generated and read using my custom data serialization library, SUCC.

Previously, a significant limitation of SUCC has been its poor error messages. When something went wrong, there were very few clues about what exactly that thing was. Well, this week I've finally added good error handling to SUCC! When something goes wrong, SUCC will now provide:
  • A description of the error
  • The path of the file in which the error occurred
  • The line number on which the error occurred

This change won't affect most players, but if you're a modder or tinkerer it will probably improve your life at some point. When you accidentally screw up your SUCC formatting, the new error messages will tell you exactly where to go and what to fix.

If you're a big nerd and want to look at these changes in more detail, you can check out the pull request here.


Optimization work - Jimmy


I've started working on some serious optimizations for Logic World. These will drastically improve loading times for large worlds, and significantly improve framerates while playing in large worlds.

This work is in the early stages and I don't have anything to show for it just yet, but things look very promising, and I expect to have more concrete news soon. Stay tuned :)


---------------------------------------------

That's all for this week, but we'll be back next Wednesday with another juicy blog post. To make sure you don't miss it, you can sign up for our newsletter. Consider also joining the official Discord.

See you next Wednesday!

View this post on logicworld.net

More Logic World Wednesdays

https://store.steampowered.com/app/1054340/Logic_World/

The Logic World Original Soundtrack is now available to stream and download!

You've played the game, you've loved the music. You've wished you could keep listening to the music even when you're not playing the game. Well, today that wish comes true: the Logic World Original Soundtrack is now available on all your favorite internet music websites!

[previewyoutube][/previewyoutube]

Where can I get it?


Wherever you get your music, Logic World is there!

If you like DRM-free video games like Logic World, you'll probably like DRM-free music. While most of the above platforms are streaming-only, you can purchase a DRM-free, ultra-high-quality download of the soundtrack at Bandcamp. It's the best way to directly support Markku and his work!


Wow that album art is beautiful! Tell me more about it!


The gorgeous artwork you see on the album cover was specially commissioned for this soundtrack. It was created by the insanely talented Michael Yoshimura. You should definitely check out michael's website, and follow him on instagram @yoshimura_mike. And if you need some art made, commission him!

You can get the album art in ultra high quality here, and you can get a clean version without the foreground text here.




Wait, I thought you said this would happen next Friday, on the 11th?


That we did, discerning one! But in the immortal words of the great Alanis Morissette, life has a funny way of sneaking up on you. Why did this happen a week early? We don't know! We're just reacting to it. Enjoy the early release!



Ok music is cool and all but when are we getting news about game updates


Our development blog, Logic World Wednesdays, will return next Wednesday, February 9th!


---------------------------------------------------


Enjoy the soundtrack! Stream it, add it to your playlists, tell all your friends about it. We're very proud of this music, and we're so happy to be sharing it with you today.

Logic World v0.90.3 is now available

Last week we released version 0.90.2 with lots of updates and fixes. Unfortunately, that version inadvertently introduced some new bugs, so today we’re releasing version 0.90.3 to squish them.




0.90.3 Changelog


  • Fixed ExtraData being reset every time a save was loaded. This caused impersistence of all the systems stored in ExtraData, such as Display configurations, the Flag order, and custom Gridlands settings.
  • Fixed volume slider values not being applied on game startup
  • Removed the secret settings regarding max audio voices, as making these values configurable is what caused the above bug
  • Fixed error screen when changing the number of pegs on a Panel Display when there are wires attached to it
  • 1x1 Panel Displays are now limited to a maximum of 3 pegs
  • Fixed servers allowing the placement of some invalid component types
  • Servers now have additional checks to ensure that components being placed are valid
  • Server-side checks now disallow making a component a child of its own children