1. Logic World
  2. News

Logic World News

Logic World Wednesdays: The Advancedly Queryable Edition

Super Sortable Issues - Felipe


I've been working on improvements to the Logic World issue tracker that make it easier to navigate the growing list of tracked issues. You can now input an advanced query that sorts issues based on their status, type, tags, title, and body contents.



The '|' and '&' characters can be used, respectively, as "or" and "and" operators. When querying issue title and body contents, regex is supported.

This new querying helps us immensely in finding specific issues, viewing issues in a specific category, and determining what issues to work on next. In the future I plan to add a UI for generating these advanced queries, similar to what Github has for issue sorting.

Status Shenanigans - Felipe


I created a new status page at https://status.logicworld.net/. This page monitors for outages in the Logic World services, and provides a place for us to announce any planned downtime.



There's also a feed in the Logic World discord server that automatically posts status updates using webhooks.

As Logic World grows, we will have more services, and more people will rely on them, making it important to have this status page.

Less Forgettable Image Attachments - Felipe


The logicworld.net system for including images in forum posts or tracker issues requires you to first upload an image, then insert that image into the body of the post. However, many users did not immediately understand this flow, and assumed that once they'd uploaded an image, it was already part of the post. The users were confused when they made the post and the image was not included with it.

To help users understand the flow better, I've added a little warning when an image has been uploaded but not included in the post.



Beating Up Bugs like they Owe me Money - Jimmy


In preparation for the release of update 0.91 -- which I think I'm going to christen "The Less Buggy Update" -- I've been hammering away on more bugs and stability fixes. This has been made much easier thanks to Felipe's work on improving the issue tracker, thank you Felipe!

Notably, this week I fixed some nasty simulation glitches that were plagueing Dynamic Components (components with a variable number of input/output pegs, such as AND gates). #104 and #250 are no more (#104 had a pretty interesting cause, click to read my comment about it). And I also fixed the game not properly detecting supported network protocols, which was causing various nasty bugs that made the game unplayable in certain network setups or when no external network interfaces are available (#204, #333, #229, and others). I'm VERY sorry those issues were in the game for so long, I know they've caused a lot of frustration :(

We are on track for a 0.91 release in late September, and I expect we'll start public previews of the update next week.


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

To make sure you don't miss the next blog post, you can sign up for our newsletter. Be sure also to wishlist Logic World on Steam and join the official Discord.

See you next Wednesday!

View this post on logicworld.net

More Logic World Wednesdays

Logic World Wednesdays: The Uneventful Edition

Greetings Gamers,

I haven't been able to work on Logic World much this week, but in the time I've been able to carve out for it I've been plugging away at bugfixes and stability improvements. My current task is sorting out the various networking issues with the game. I hate networking. What a mess it all is. Can somebody remind me why I decided to make this game multiplayer?

This week I made a decision I'd like to share with you: we'll be reducing the scope of update 0.91 in order to get it out to you faster. I'm aiming to publish 0.91 around the end of September, with a public preview sometime before that. 0.91 will contain performance enhancements, a whole lot of bugfixes & stability improvements, and a few smallish features like the simulation controls. Meanwhile, the new building mechanics I've been planning -- included the much-coveted ability to save and load subassemblies -- will be coming in update 0.92 a few months later.

More development updates soon! Not too soon, though -- I'll be on holiday with my family next week, so I won't be around for a LWW. I expect the blog will return on the 31st.

Keep on Gamin'

Logic World Wednesdays: The Hot-Reloadable Edition

GREETINGS! It's been another fairly unexciting week for me, but I've continued to plug away at miscellaneous maintenance tasks. Although Hofstadter's Law continues to out-Hofstadter's Law me, lots of work is getting done on Logic World and I am super excited about how development is going.

Here are some highlights from my work week:

[h3]Hot-reloadable SUCC files[/h3]
If you've poked around in the Logic World game files, you've probably noticed that there's a lot of data stored with my custom SUCC file format. In order to assist with development & debugging, I've made most of these files hot-reloadable: you can edit them on disk, and when you save the file, the game will reload the appropriate data and even update the user interface to reflect it. This includes `settings_master.succ` and its 100+ secret settings -- you no longer need to restart the game to change them.

Note that this change applies to SUCC files outside the `GameData` folder. `GameData` files (i.e. mods) already have some SUCC hot-reloading support in 0.90.

[h3].NET 6[/h3]
I've upgraded the server runtime from .NET Core 3.1 to .NET 6.0. This is a more modern .NET and brings with it gratuitous performance improvements. I haven't really tested to see how it affects LW, but it seems kinda faster!

[h3]The Most Important Video Game Feature in the History of Video Game Features, Maybe Ever[/h3]
I made the inverter output render as "on" in the item thumbnail.



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

Thanks for reading! More soon. Love, Jimmy

Logic World Wednesdays: Thrilling Thumbnails

Hello Logicians! I've had a fairly pedestrian week of development, working on miscellaneous maintenance tasks. For example, I polished off last week's work on fixed point positions by updating the save format version: position data is now saved and loaded as fixed-point instead of floating-point, matching the new data structures that are used internally. I also added a save converter to the new format so that you can use all your 0.90 saves in 0.91, and I updated the sandbox list UI to notify the user of which saves are using the old format and need to be converted.



But my biggest task this week by far was to make some major updates to the world objects shader. This all started when I decided to address an issue with how thumbnails (the little isometric component graphics that appear in the Selection Menu and on the hotbar) are rendered. In 0.90, thumbnails look different depending on the scene in which they are generated. This is because the thumbnail renders use exactly the same materials as are used to render objects in the world. World objects are affected by environment lighting, so thumbnails are too.



This is kind of weird, but it's not a big deal in 0.90; I'm not sure if anybody but me has even noticed it. However, for some upcoming features I plan to add for 0.91, thumbnails really ought to be generated consistently and reliably, and look identical no matter where the generation happens.

So, I've upgraded the shader I wrote for GPU instancing. It now has two lighting modes: environment lighting and custom lighting. We use this new "custom" lighting mode for thumbnail renders, and so now it doesn't matter where they're created, they always have consistent lighting. I also added support to the shader for rendering in non-instanced mode, so we can use it for non-instanced decorations like the clicky part of buttons and switches, and these decorations will also have consistent, custom lighting applied to them in thumbnail renders.

Here's the result:



If you look closely, you'll notice a few more differences in the appearance of thumbnails between 0.90 and 0.91:
  • Thumbnail renders are now anti-aliased, so the lines are smooth instead of jaggy. I already did this a few months ago, but I remember it was REALLY HARD so please appreciate it anew!
  • I fixed some artifacts along the edges of thumbnail renders, most noticeably in components with pegs that go right to the edge like D-Latches and Sockets.
  • The lighting is softer, with less contrast between the sides and tops of blocks. For now, the lighting otherwise emulates the 0.90 Grasslands appearance, but I'm still tweaking this. There will be secret settings for all the variables of thumbnail lighting, in case you want to customize it :)

Also: while I was mucking around in the shader code, I found a way to make it run a little bit faster! So that's nice.

It's such a small, subtle change, but it took hours and hours of banging my head against the code to make it happen. I'm still very new to graphics programming; I'm learning quickly, but this stuff is still taking me 10x longer than it would for someone experienced. However, it's all done now. Thumbnail lighting is independent of environment lighting, my shader is faster and more capable, and the shader code is much more organized & reusable. I'm happy with the graphics work I've done this week.

I've got a few more small maintenance tasks on my list -- none of them nearly as daunting as shader work, thankfully. After those are taken care of, I'll spend most of the next two weeks on bugfixing. Thank you to everyone who's reported a bug in 0.90 (especially Ecconia
Thanks for reading. See you next Wednesday.

-Jimmy

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