Skip to content

DEV BLOG

Project Shakespeare

Everyone, meet The Secret Feature™, or as we like to call it, Project Shakespeare (to honor the never-implemented, never-explained mod type called Shakespeare that can be found in the stock game’s code).

This is a very basic KSP1 part-only mod loader with currently mostly functional command modules, deployables and animations, decouplers, fuel tanks, engines, gimbals, plumes, engine mode switching, variant switching, and more. It includes support for some popular modded part modules as well, such as B9 part switching and animated decouplers.

There’s a lot that doesn’t work properly yet, such as WIP control surfaces (that’s why I didn’t put on the grid fins yet, as they result in a funny, although very motion sickness-inducing death spin), or RCS thrusters. Engine plumes are also just using the default KSP2 methalox plume attached in place of where the KSP1/Waterfall plume would be, and for some parts (e.g. the booster fuel tank in the video) the textures don’t look right, either.

IMPORTANT: this is NOT going to be a “plug-and-play” feature where you just copy all 300 of your KSP1 mods into the Redux folder and can play without any issues. It is extremely limited with a small selection of part modules and types that it can handle, it’s only able to do handle basic Module Manager patching logic in order to support things like engine plumes defined in MM patches instead of the base .cfg file (which is a pattern often used in KSP1 mods), and also, it’s EXTREMELY slow. I’ve seen loading times of like 2-3 minutes with 3 part mods, and that will possibly get even slower as I iterate on it more and introduce more module translations and other functionality (though it can be somewhat mitigated by the caching of translated parts and modules).

The purpose of this feature is to be a proof-of-concept, technical demo that lets your imagination run wild with what could be possible if your favorite KSP1 mod authors ported their mods for KSP2 for real, and it also serves as a technical showcase of what sorts of authoring and conversion tools we can and will provide to KSP1 mod developers to help them with the process of converting their mods over to KSP2 Redux.

Note: this will not be a part of beta 5, you’ll need to wait a bit longer for us to polish this more.

Mods used in the showcase are Tundra Exploration and Kerbal Reusability Expansion, some of my favorite KSP1 mods.

SAS, Flight Input, and Precision Mode

Decided to take a short break from Redux (working on the rendering pipeline) and, for a change, work a bit on Redux. This time, I looked at a few flight-control related things:

  1. SAS oscillations
  2. Flight input
  3. Precision mode

The main one is SAS. In stock KSP2, SAS has a tendency to oscillate a lot more than it did in KSP1, especially on vessels with a lot of control authority, meaning that rockets and planes can sometimes wobble back and forth instead of smoothly settling in the target direction. This gets especially noticeable under physics warp.

After comparing the KSP1 and KSP2 implementations, the PID controller used for SAS is basically the same, and not really an issue. The bigger differences are in the surrounding logic: how SAS estimates when it should stop pushing, when the flight control state gets updated, and how often the telemetry system updates data that SAS needs.

The first fix was related to the “coasting” logic. Basically, SAS needs to predict when the vessel is already rotating fast enough that it should stop applying torque and let itself coast into the target direction. KSP2 had a small difference from KSP1 here that made it worse at predicting overshoot, so it would often push for too long, overshoot, correct back, overshoot again, and so on. Fixing the formula here to match KSP1 helped with making vessels settle down instead of wobbling forever.

The second fix was about timing. Gimbals, control surfaces, reaction wheels, RCS, etc. all consume the flight control state during FixedUpdate, and with this change, SAS now updates that control state earlier in the fixed update order. That means parts are working with fresher SAS commands, instead of commands that are slightly behind what the vessel is currently doing.

There was also a fun little physics warp rabbit hole. SAS depends on telemetry data, but that was normally refreshed through the regular Update path (there’s always 1 Update per frame, so the frequency changes with FPS). Under physics warp, especially at lower FPS, you can get multiple FixedUpdate ticks between regular Updates (FixedUpdate is, as the name suggests, fixed - by default at 50 per second - and it scales with time warp speed), meaning SAS ends up acting on stale telemetry data. This was fixed by updating the necessary telemetry data on FixedUpdate instead of Update.

Outside of SAS, I also tweaked the manual flight inputs. Stock KSP2 input is very instant, which can feel a bit twitchy with keyboard controls. The updated version is closer to KSP1, where pitch/yaw/roll ramp up and decay back down instead of snapping immediately to full input or zero.

Precision mode is completely reworked. In stock KSP2, it simply limited the control authority of user inputs to 10% of the maximum. Now it also acts closer to the KSP1 version, where you can still go from -100% to 100% of the input, but the buildup and decay are much slower, meaning it’s now much easier to make finer inputs, while still letting you go all the way to the max if you keep holding the key.

All in all, these changes should make vessel controls and SAS feel a lot better, though it’s obviously not an all-powerful fix that will get rid of all issues.

In the attached video, you can see all of these changes: SAS on a rocket with very high control authority at 1x, 2x, and 4x physics warp, SAS on a plane, and then the updated normal and precision input behavior (with SAS disabled).

Early URP Port Devlog

I thought I’d make a short devlog to show off what I’ve been working on the past couple of days.

To give a bit of context, KSP2 uses the Built-in Render Pipeline. In Unity, a render pipeline is the sequence of GPU steps (culling, batching, lighting, shading, post-processing, …) that turns scene data into pixels each frame. The original, old Built-in Render Pipeline is a hardcoded implementation of that sequence, where you can tweak the parameters, but not really the logic itself. Meanwhile, the newer Scriptable Render Pipeline (which is an umbrella term for both the Universal Render Pipeline and the High Definition Render Pipeline) exposes that logic in C#, so that you can define exactly how objects are drawn, how lighting is evaluated, how render passes are structured, etc.

Now, the issue is that the BRP is going to be deprecated in Unity 6.5, and completely removed possibly as early as Unity 6.8, which coincidentally is also the stable release of CoreCLR support (which we really, really, really want for the potential crazy performance boost and the access to modern C#). Generally, we also want to be able to keep upgrading the game and not be hard stuck on a specific Unity version.

So, in order to solve this issue, we’ll need to eventually port the game from BRP to URP or HDRP. While HDRP would make the most sense with its current feature set compared to URP, Unity just recently announced that it will no longer be developed, and that URP will eventually receive all of its features and become the single recommended pipeline to use. That means that for future use, it makes more sense to start with URP right away, rather than have to go through another port in a couple of months/years.

In our case, porting from BRP to SRP is not an easy task though, arguably much more difficult than our big upgrade from Unity 2022.3 to Unity 6.3 (and now 6.4 in development). That’s because we don’t have access to the source code of the game’s shaders, and shaders are often very particular about which render pipeline they work on. That said, there are some ways (dark magic) to “hack” around this and get stuff to render using these normally incompatible shaders, and the video in this post is a look at the first “playable” version of the very early and experimental URP port of the game. Many things are still missing, but it’s honestly been going much better than I expected, so I’m feeling positive about this little side-quest that I’m on!

Chipping Away at Map View Performance Issues

Chipping away at map view performance issues

Most of the speedups in Redux focus on the simulation and main UI. We haven’t really done much to try to improve the map situation. After all, the simulation has to run at time as the map being open, so any improvement in the simulation should imply a performance improvement in the map. However, with the sim performance getting better, the FPS drop when opening the map is getting increasingly noticeable. One piece of code in particular, called RelativeOrbitSolver jumped out at me as actually getting worse due to some changes in the way transforms are handled. The current version in redux takes up a whopping 4ms on my test setup.

RelativeOrbitSolver is used for predicting future locations in a hypothetical future orbit, and calculate where those points would be with respect to some given viewer. It’s used by the map to do things like draw projected intercept lines.

For example, let’s say a vessel in orbit of Kerbol is not currently intercepting Moho. The player adds a maneuver plan that would cause it to intercept Moho’s SOI but transit through it. So, the map has to draw a bunch of different lines.

  • The current orbit line.
  • The line starting at where the maneuver node is showing the change in Kerbol orbit as a result of the planned impulse. Ends at the predicted Moho SOI intercept.
  • A line near wherever Moho currently is that shows the vessel’s predicted transit through Moho’s SOI (relative to Moho). This is technically a hyperbolic trajectory (“orbit”) of Moho.
  • Another line relative to Kerbol that shows what the previous line actually like from Kerbol’s perspective. This is the one that uses RelativeOrbitSolver.
  • A line after the projected SOI ejection that shows yet another orbit of Kerbol, but this one having been modified by Moho’s gravitational pull.

The code uses several strategies depending on what kind of line it’s drawing, but the 2nd to last one here is the one that uses RelativeOrbitSolver. It’s also used for some other tasks, such as trying to find SOI transition points.

The code for RelativeOrbitSolver is one of the few things got somewhat slower after switching to ECS frames. It created a bunch of temporary TransformModels, would move them around, and then use them for doing relative position calculations. The individual point calculations were probably faster, however the setup/teardown of the temporary frames were quite expensive. Unfortunately, a few spots in the code (such as maneuver nodes) would create a RelativeOrbitSolver to solve for exactly one point and throw it away.

So, I rewrote the code to avoid using TransformModel. While I was in there, I noticed a bug where it would ignore a celestial body’s axialTilt, which caused some issues with the line related to Moho. Now the code just scrapes the spatial relationships into a simple temporary list, and runs a simple loop to do the same calculations the more complicated transform system would do.

Map view performance 1

Map view performance 2

Map view performance 3