diff --git a/GameData/KSPCommunityFixes/Settings.cfg b/GameData/KSPCommunityFixes/Settings.cfg index a2cca41..51b457b 100644 --- a/GameData/KSPCommunityFixes/Settings.cfg +++ b/GameData/KSPCommunityFixes/Settings.cfg @@ -372,19 +372,25 @@ KSP_COMMUNITY_FIXES LogGameEventsSubscribers = false } - // Fix CommNet update throttling mechanism that exists in stock but doesn't work correctly. - // This is supposed to prevent full CommNet network updates from happening every frame, but instead to - // to happen at a regular real-world time interval of 5 seconds while in flight. Enabling this throttling - // mechanism has an detrimental impact on the precision of the simulation, so this patch isn't enabled by - // default to avoid issues in mods relying on the stock behavior. Enabling this can provide a decent - // performance uplift in games having a large amount of celestial bodies and/or vessels. - CommNetThrottling = false - - // Interval in real-world seconds between full CommNet network updates. + // Implement a throttling mechanism preventing CommNet network updates from happening every frame. + // When this patch is enabled, network updates will only happen at a set interval of in-game seconds, + // defined by below settings. This patch will cause events such as line of sight loss or acquisition, + // or comm link changes to happen with a delay, but provide a significant performance uplift in games + // having a large amount of celestial bodies and/or vessels. + CommNetThrottling = true + COMMNET_THROTTLING_SETTINGS { - unpackedInterval = 5 // interval when the active vessel is not timewarping - packedInterval = 0.5 // interval when the active vessel is timewarping + // Maximum duration in in-game seconds between CommNet updates. + // Increasing it further than the 2.5s default won't have any effect on framerate and will make + // CommNet situation changes (such as loss or acqusition of signal) increasingly sluggish. + maxGameTimeInterval = 2.5 + + // Minimum duration in real world *milliseconds* between CommNet updates. + // Increasing it will only affect medium to fast timewarp situations, and will improve framerate + // and significately reduce simulation precision. Recommended value is either 20 or 500 to 1000, + // values in between will likely result in stuttery framerate and no perceptible improvement. + minRealTimeInterval = 20 } // This tweak eliminates KSP's stock behavior of saving every time diff --git a/KSPCommunityFixes/Performance/CommNetThrottling.cs b/KSPCommunityFixes/Performance/CommNetThrottling.cs index 04c977c..b5763f2 100644 --- a/KSPCommunityFixes/Performance/CommNetThrottling.cs +++ b/KSPCommunityFixes/Performance/CommNetThrottling.cs @@ -1,13 +1,12 @@ -using HarmonyLib; -using System.Collections.Generic; -using UnityEngine; +using System.Diagnostics; namespace KSPCommunityFixes.Performance { class CommNetThrottling : BasePatch { - private static double packedInterval = 0.5; - private static double unpackedInterval = 5.0; + private static double maxGameTimeInterval = 2.5; + private static long minRealTimeInterval = 20; + private static Stopwatch realTimeUpdateTimer = new Stopwatch(); protected override void ApplyPatches() { @@ -15,31 +14,32 @@ protected override void ApplyPatches() if (settingsNode != null) { - settingsNode.TryGetValue("packedInterval", ref packedInterval); - settingsNode.TryGetValue("unpackedInterval", ref unpackedInterval); + settingsNode.TryGetValue("maxGameTimeInterval", ref maxGameTimeInterval); + settingsNode.TryGetValue("minRealTimeInterval", ref minRealTimeInterval); } - AddPatch(PatchType.Prefix, typeof(CommNet.CommNetNetwork), nameof(CommNet.CommNetNetwork.Update)); + AddPatch(PatchType.Override, typeof(CommNet.CommNetNetwork), nameof(CommNet.CommNetNetwork.Update)); } - static bool CommNetNetwork_Update_Prefix(CommNet.CommNetNetwork __instance) + static void CommNetNetwork_Update_Override(CommNet.CommNetNetwork commNetNetwork) { - if (!__instance.queueRebuild && !__instance.commNet.IsDirty) + double currentGameTime = Planetarium.GetUniversalTime(); + double currentGameTimeInterval = currentGameTime - commNetNetwork.prevUpdate; + if (!commNetNetwork.queueRebuild && !commNetNetwork.commNet.IsDirty + && currentGameTimeInterval >= 0.0 + && (currentGameTimeInterval < maxGameTimeInterval || realTimeUpdateTimer.ElapsedMilliseconds < minRealTimeInterval)) { - double timeSinceLastUpdate = Time.timeSinceLevelLoad - __instance.prevUpdate; - - if (FlightGlobals.ActiveVessel != null) - { - double interval = FlightGlobals.ActiveVessel.packed ? packedInterval : unpackedInterval; - if (timeSinceLastUpdate < interval) - { - __instance.graphDirty = true; - return false; - } - } + commNetNetwork.graphDirty = true; + return; } - return true; + // UnityEngine.Debug.Log($"CommNet update interval : {realTimeUpdateTimer.Elapsed.TotalMilliseconds:F0}ms"); + + commNetNetwork.commNet.Rebuild(); + realTimeUpdateTimer.Restart(); + commNetNetwork.prevUpdate = currentGameTime; + commNetNetwork.graphDirty = false; + commNetNetwork.queueRebuild = false; } } } diff --git a/README.md b/README.md index 30b5f26..b432edd 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ User options are available from the "ESC" in-game settings menu :