Jump to content

KSP 1.4.1 Performance


Warezcrawler

Recommended Posts

9 minutes ago, Warezcrawler said:

That said I've gone through my own mod these last day, and have concluded that it does not generation much garbage, or I'm simply missing it. I've changed a few foreach loops, but there was not that much else I could do.

Ping me in a few days and I should have more time to explain how to find out your code actual garbage 

Link to comment
Share on other sites

6 minutes ago, sarbian said:

Ping me in a few days and I should have more time to explain how to find out your code actual garbage 

That's very nice of you. Any methods to isolating the problem is very welcome indeed.

I hope I was clear in, that it is generated in my current game, which has a lot of mods, not only my own. So in the end my goal i to isolate the source of the problems, and then deciding on what to do. If my own than find out how to reduce, if another consider removing it and maybe look into hope the clean it a bit.

Spoiler

Mod DLLs found:
Stock assembly: Assembly-CSharp v0.0.0.0
ModuleManager v3.0.6.0
MiniAVC v1.0.3.2
aaa_Toolbar v1.7.17.5
USITools v1.0.0.0
ToolbarControl v0.1.5.7 / v1.0.0.0
B9_Aerospace_WingStuff v1.0.0.0
BetterTimeWarp v2.3.10.0
BonVoyage v0.13.2.1
CameraFocusChanger v1.0.3.0 / v1.0.1.0
Chatterer v0.9.94.2077
ClickThroughBlocker v0.1.6.1 / v1.0.0.0
CommNetVisualisation v1.0.0.0 / v1.0.2
CCK v2.0.2.0 / v2.0.2.0 for KSP 1.3
ContractConfigurator v1.0.0.0 / v1.24.0
AGExt v2.3.3.0 / v1.0.0.0
TWR1 v1.0.0.0
DistantObject v1.9.1.39037
DMagic v1.3.0.12 / vv1.3.12
ProgressParser v1.0.9.0 / vv9.0
ContractParser v1.0.8.0 / vv8.0
CapCom v1.0.2.8 / vv2.8
ContractsWindow v1.0.8.2 / vv8.2
ContractsWindow.Unity v1.0.8.2
DockRotate v1.4.1.10
EditorExtensionsRedux v3.3.19.3
Atmosphere v1.4.0.1
CelestialShadows v1.4.0.1
EVEManager v1.4.0.1
PartFX v1.4.0.1
PQSManager v1.4.0.1
ShaderLoader v1.4.0.1
Terrain v1.4.0.1
TextureConfig v1.4.0.1
Utils v1.4.0.1
_BuildManager v1.4.0.1
Firespitter v7.3.6652.37613
FlexoTubes v1.0.6.0 / v6.0
FTLDriveContinued v0.2.1.1 / v1.0.0.0
GTI_MultiModeConverter v2.8.0.0
GTI_MultiModeEngine v2.8.0.0
GTI_MultiModeHarvester v2.8.0.0
GTI_MultiModeIntake v2.8.0.0
GTI_Utilities v2.8.0.0
InterstellarFuelSwitch v2.11.1.0 / v2.11.1
Scale_Redist v1.0.0.0
KAS v0.6.4.0 / v0.6.4 for KSP 1.4+
MiniAVC v1.0.3.1
KerbalEngineer v1.1.3.0
KerbalEngineer.Unity v1.0.0.0
KerbalJointReinforcement v3.3.3.0
KIS v1.10.6640.40620 / v1.10 for KSP 1.4
KSPDev_Utils.0.31 v0.31.6640.37756 / v0.31 for KSP v1.4
MiniAVC v1.0.3.0
KRnD v0.0.0.0
MechJeb2 v2.5.1.0 / v / v2.7.1.0
MemGraph v1.1.0.3
NavHud v1.3.5.0
PreciseNode v1.2.9.0 / v1.2.4.0
ProjectManager v1.0.0.0
ProgressiveCBMaps v0.1.25.0
ResearchBodies v1.9.7.0
SCANsat v1.8.5.0 / vv18.5
SCANmechjeb v1.8.5.0 / vv18.5
SCANsat.Unity v1.8.5.0
CLSInterfaces v1.2.0.0
ShipManifest v5.2.1.0
SmokeScreen v2.8.0.0
Stock assembly: KSPSteamCtrlr v0.0.1.35
Stock assembly: Steamworks.NET v9.0.0.0 / v9.0.0
TarsierSpaceTech v7.3.0.0
BetterTracking v1.0.2.0 / v2.0
BetterTracking.Unity v1.0.2.0
KerbalAlarmClock v3.9.0.0
TransferWindowPlanner v1.6.3.0
DynamicTanks v1.0.0.0
Konstruction v0.0.0.0
WaypointManager v1.0.0.0 / v2.7.2
WorldStabilizer v1.0.6652.42492
[x] Science! v5.13.6649.40338

 

Link to comment
Share on other sites

25 minutes ago, Warezcrawler said:

When it comes to the UI, I'm still on trying to compile my first test UI... I have not succeeded... I'm trying to follow your tutorial, but I'm pretty sure that I'm missing some step or something...

In my latest attempt I get the below error when trying to build the UI.

I actually don't even bother with the Part Tools for UI stuff. It's only for KSPedia and parts that really need it. I guess it's probably best to get working correctly, but it's not strictly necessary for UI creation. 

A simple build script (just make sure that it is in a folder called "Editor", otherwise it won't run) will handle everything you need to get the UI components out of Unity and ready for KSP: https://github.com/DMagic1/KSP_BetterTracking/blob/master/Unity/Better Tracking/Assets/Editor/Bundler.cs

25 minutes ago, Warezcrawler said:

And I'm not gonna learn the old OnGUI() methods, and if it does create a lot of garbage, then that's probably for the better.

Another thing worth pointing out is that learning the OnGUI system basically useless if you don't already know it. It's almost completely esoteric and has no value outside of legacy Unity UI. The regular UI system is just standard Unity stuff, so maybe still not very useful outside of that case, but at least a little more valuable knowledge than OnGUI.

Edited by DMagic
Link to comment
Share on other sites

3 minutes ago, DMagic said:

I actually don't even bother with the Part Tools for UI stuff. It's only for KSPedia and parts that really need it. I guess it's probably best to get working correctly, but it's not strictly necessary for UI creation. 

A simple build script (just make sure that it is in a folder called "Editor", otherwise it won't run) will handle everything you need to get the UI components out of Unity and ready for KSP: https://github.com/DMagic1/KSP_BetterTracking/blob/master/Unity/Better Tracking/Assets/Editor/Bundler.cs

Are you telling me that I've been wasting hours getting this to work for nothing..... (I'm not doing part models or KSPedia stuff)........ :confused:

Thanks.... So I just need to learn Unity UI stuff, keeping in mind it should go in a specific folder. I'm guessing it's the .cs hookup of the UI that goes there?

Link to comment
Share on other sites

Just now, Warezcrawler said:

Are you telling me that I've been wasting hours getting this to work for nothing..... (I'm not doing part models or KSPedia stuff)........ :confused:

Thanks.... So I just need to learn Unity UI stuff, keeping in mind it should go in a specific folder. I'm guessing it's the .cs hookup of the UI that goes there?

An asset bundle is just a collection of stuff exported from Unity. Just select the assets you want exported, assign them to a bundle, and then run the build script (it puts a menu in the toolbar along the top of the window with a button to build the bundle). I assume that KSPedia files need some specific formatting, but anything else is just an asset bundle, you can load it from KSP yourself without any problems. You can attach a file extension, or not, a .ksp file will be loaded by KSP asset loader, I've never worked with that so I always attach my own extension and just load it myself.

Also, the thing about the specific folder in only for this small build script. Any of the other stuff covered in my tutorial (the assembly you make to interface with the UI) might have to go in the Plugins folder, that's where I always put it, but I don't know if it's required.

Link to comment
Share on other sites

1 minute ago, DMagic said:

An asset bundle is just a collection of stuff exported from Unity. Just select the assets you want exported, assign them to a bundle, and then run the build script (it puts a menu in the toolbar along the top of the window with a button to build the bundle). I assume that KSPedia files need some specific formatting, but anything else is just an asset bundle, you can load it from KSP yourself without any problems. You can attach a file extension, or not, a .ksp file will be loaded by KSP asset loader, I've never worked with that so I always attach my own extension and just load it myself.

I guess I'm going to try again then.... If I can just get a simple box with a button to work, then I can go from there... Then it's just building using similar blocks.

thanks

Link to comment
Share on other sites

1 minute ago, Warezcrawler said:

I guess I'm going to try again then.... If I can just get a simple box with a button to work, then I can go from there... Then it's just building using similar blocks.

thanks

Keep the popup dialog system in mind for simple UIs. It can be stretched and warped pretty far beyond just a simple list of buttons. Check out Astrogator for a good example.

Link to comment
Share on other sites

On 30/3/2018 at 11:41 AM, Naeku said:

I had a similar problem. In my case the guilt mod was "[X] Science!". The shutter only occurs when "Now and Here" windows is open. I recommend you to explore their post. A guy recompile the mod to reduce the shuttering.

I had a look at X-Science. On the X-Science page you can find a stutter reduced unofficial build for 1.4.2.

To combat the Garbage Collector I've identified a few mods, which was heavy in creating garbage. (no particular order)

  • Kerbal Engineer
  • ScanSat
  • X-Science

After having rebuild and done some changes to them, based on the great input I got in this thread (+some more studying of the topic online) I managed to reduce my stutter from every 2-3 seconds to 10-15 second intervals. Mostly I went through the executions of the update functions that run often, and moved class references from local to global area. Hence paying for better performance with a little extra memory.

I think ScanSat does create a lot a garbage alone, since it create reference variables inside loops. To my understanding this is not the best.

Question, since this topic is still new to me. I know creating a lot of local class instances/references to the heap generates a lot of garbage. How does the function with primitives like int, string, float etc. and struct in general. Any advise on the.

For now that let all creating of the latter be, since it is my understanding, that this does not affect the GC. Is this correct in any way?

Link to comment
Share on other sites

1 hour ago, Warezcrawler said:

I think ScanSat does create a lot a garbage alone, since it create reference variables inside loops. To my understanding this is not the best.

Which loops are generating garbage? There is a bug in how some of the text in generated when you mouse-over a map which generates a lot of garbage, but otherwise I'm not aware of any major sources of garbage in the part modules or scanning system. There are probably lots of garbage generating loops in there, but in things related to loading or saving, or things that only happen once, where extra garbage generation doesn't really matter so much.

Link to comment
Share on other sites

2 minutes ago, DMagic said:

Which loops are generating garbage? There is a bug in how some of the text in generated when you mouse-over a map which generates a lot of garbage, but otherwise I'm not aware of any major sources of garbage in the part modules or scanning system. There are probably lots of garbage generating loops in there, but in things related to loading or saving, or things that only happen once, where extra garbage generation doesn't really matter so much.

I'm new at this GC thingy, and I did changes to all three mods at the same time, so I can be wrong about ScanSat. But, I did changes several places.

I'll try to summarize as best as I remember it. I only looked at stuff I tracked from the "scanFromAllVessels()" method, since I identified that it is called from "Update()", hence running often.

Spoiler

class SCANcontroller

scanFromAllVessels() 
I moved the following to global. They where created in a loop, and I figured that could not be good for GC.
        private SCANvessel vessel;
        private Vessel v;
        private SCANdata data;

doScanPass(SCANvessel vessel, double UT, double startUT, double lastUT, double llat, double llon)
I moved the following to global. It is called from scanFromAllVessels() under certain criteria and can run often. So same argument as above. The two in italic dashed over is because they where already global from "scanFromAllVessels()". I just made sure it used them.
        private Orbit o;
        private SCANsensor sensor;
        private Vessel v;
        private SCANdata data;

class SCANdata

updateCoverage()
I moved the following to global
SCANtype t;

 

Class ModuleSCANresourceScanner

override protected void Update()
I changed a foreach loop to for loop
foreach (ModuleOrbitalSurveyor m in mSurvey) --> for (int i = 0; i < mSurvey.Count; i++)
foreach (ModuleOrbitalScanner m in mScanner) --> for (int i = 0; i < mScanner.Count; i++)

I did the same i DisableModule() and EnableModule()

That's all I remember doing.

If I'm wrong about some or all of the stuff above generating garbage, please enlighten me, I'm still trying to figure out how to reduce it best :confused:

thanks

Link to comment
Share on other sites

Those are unlikely to have much of an effect. The foreach loops, and the way that module is written in general, is a bit sloppy, but that section of Update and the other code only runs periodically, I think in response to when a resource scanner is deployed or retracted.

In SCANdata that is an enum, which is a value type and shouldn't be allocated. 

The changes in SCANcontroller could help, that method only runs once every second though, so unless you have a huge number of vessels it wouldn't affect much. That method is, however, responsible for some serious performance problems, just not garbage related.

Like I said, the biggest problem in the current version is related to the information that appears when you hover the mouse over some of the maps. It's doing something silly when looking for contract waypoints that generates a lot of garbage. That will be fixed in the next version.

Edited by DMagic
Link to comment
Share on other sites

7 minutes ago, DMagic said:

Those are unlikely to have much of an effect. The foreach loops, and the way that module is written in general, is a bit sloppy, but that section of Update and the other code only runs periodically, I think in response to when a resource scanner is deployed or retracted.

In SCANdata that is an enum, which is a value type and shouldn't be allocated. 

The changes in SCANcontroller could help, that method only runs once every second though, so unless you have a huge number of vessels it wouldn't affect much. That method is, however, responsible for some serious performance problems, just not garbage related.

Performance hits that are not because of garbage can possibly be countered by running them in a parallel thread. I've actually tried that for SCANcontroller and it does not seem to cause problems.

Link to comment
Share on other sites

7 minutes ago, Warezcrawler said:

Performance hits that are not because of garbage can possibly be countered by running them in a parallel thread. I've actually tried that for SCANcontroller and it does not seem to cause problems.

Separate threads aren't always a good idea for Unity. Anything that reads or writes to a Unity object might be a problem if run from a different thread, like reading a vessel position, or writing to database that is being read from something else.

SCANsat uses threading for some math-heavy operations, like interpolation for some of the maps, but that works because everything is kept strictly separated, which you can't do when dealing with Unity objects. For that methods there may be simpler ways of improving performance, I just have never gotten around to it.

Edited by DMagic
Link to comment
Share on other sites

1 minute ago, DMagic said:

Separate threads aren't always a good idea for Unity. Anything that reads or writes to a Unity object might be a problem if run from a different thread, like reading a vessel position, or writing to database that is being read from something else.

SCANsat uses threading for some math-heavy operations, like interpolation for some of the maps, but that works because everything is kept strictly separated, which you can't do when dealing with Unity objects.

True... Just saying that I have not had problems so far. I'm I right in assuming that SCANcontroller does not write to unity/KSP object? Only reads? As far as I gather it just writes to it's own objects.

Link to comment
Share on other sites

I had ship exploding from heat just because I edited a value from a thread in MJ. Anything derived from monobehaviour is NOT thread safe. 

An even read can be tricky since you may access a property that does more than read. 

And anyways a thread does not make the garbage go away by magic. If some code generate garbage in the main thread it will do the same thing in a thread 

Edited by sarbian
Link to comment
Share on other sites

  • 3 weeks later...

I had the most problems with ContractConfigurator, some of the contractpacks generated a huge pile of garbage. try to "reset all contracts", and check if this changes something.

all my experience comes from a 1.2.2 build.. don't know if something really changed in the last version in this topic 

Link to comment
Share on other sites

On 3/30/2018 at 12:51 PM, DMagic said:

Another thing worth pointing out is that learning the OnGUI system basically useless if you don't already know it. It's almost completely esoteric and has no value outside of legacy Unity UI. The regular UI system is just standard Unity stuff, so maybe still not very useful outside of that case, but at least a little more valuable knowledge than OnGUI.

I beg to differ. From my times on Orbiter, we use to use GDI directly to draw 2D (essential for HUD and MFDs). Then O2016 came, changing everything, and absolutely all the plugins that draw 2D became useless.

O2016 provides now a 2D API, that is not that pretty, but it's guaranteed to work in future versions (local or remote). If anything changes badly, we will bash our heads on the wall only once (to update that 2D API), and then everything works again.

I think that keeping on OnGui will prevent such problem, mainly due Unity itself.

Edited by Lisias
TL;DR: I'm wrong on all of this.
Link to comment
Share on other sites

4 minutes ago, Lisias said:

I beg to differ. From my times on Orbiter, we use to use GDI directly to draw 2D (essential for HUD and MFDs). Then O2016 came, changing everything, and absolutely all the plugins that draw 2D became useless.

O2016 provides now a 2D API, that is not that pretty, but it's guaranteed to work in future versions (local or remote). If anything changes badly, we will bash our heads on the wall only once (to update that 2D API), and then everything works again.

I think that keeping on OnGui will prevent such problem, mainly due Unity itself.

What I mean is, the only valuable thing learned while using OnGUI is how to use OnGUI. That skill, and the knowledge required to use it, doesn't really translate to any other area of coding.

So if you know how to use OnGUI for making KSP mods that's fine, it will probably continue to be supported, but if you don't then you would almost certainly be better off learning how to use the new Unity UI. It relates much more directly to how systems work generally in Unity.

Learning OnGUI won't really help you to understand any other aspect of Unity coding, or UI work in general. For instance, as far as I know, the Unreal engine has a UI system that is at least broadly similar to how Unity's new system works. Or for Android, there are a mess of different layout systems, all of which have their different uses (and one of them, the Constraint Layout, is a little bit similar to how a Unity UI is laid out, at least visually), but none of them are anything like OnGUI.

Link to comment
Share on other sites

On 4/24/2018 at 10:13 AM, DMagic said:

Learning OnGUI won't really help you to understand any other aspect of Unity coding, or UI work in general. For instance, as far as I know, the Unreal engine has a UI system that is at least broadly similar to how Unity's new system works. Or for Android, there are a mess of different layout systems, all of which have their different uses (and one of them, the Constraint Layout, is a little bit similar to how a Unity UI is laid out, at least visually), but none of them are anything like OnGUI.

Yes, but the argument I'm counter-arguing is that it's useless. My argument is that learning it can worth the pain on the long run.

I agree that OnGui is somewhat esoteric (believe me, I worked with "worse" things that worked better), but IMGUI has it uses - mainly, by using just code to handle things instead of creating GameObjects (and all the clutter) just for simple widgets on the Editor screen.

What, well... Helps performance.

Edited by Lisias
TLDR; I'm wrong on half of this. See below.
Link to comment
Share on other sites

3 minutes ago, Lisias said:

by using just code to handle things instead of creating GameObjects (and all the clutter) just for simple widgets on the Editor screen.

And KSP provides a simple system for doing this that doesn't require OnGUI, the PopupDialog classes. It provides an easy, fast method for creating simple windows, and, if you want, it can be extended and bent to create something more customized, like Astrogator.

Of course, for performance effects, little simple windows like this don't make a difference either way. It's the complicated windows with lots of text, or, in the worst case, a scroll view with an unbound amount of elements contained, which can be potentially disastrous for performance, either because of garbage, or just the raw number of draw calls generated by OnGUI and GUILayout.

Link to comment
Share on other sites

7 minutes ago, DMagic said:

And KSP provides a simple system for doing this that doesn't require OnGUI, the PopupDialog classes. It provides an easy, fast method for creating simple windows, and, if you want, it can be extended and bent to create something more customized, like Astrogator.

From my times on Windows 3 programming, I learnt that using Modal Windows (what PopupDialog is) to do Modeless Windows job is rarely a good idea. But, granted, things may had changed.

8 minutes ago, DMagic said:

Of course, for performance effects, little simple windows like this don't make a difference either way. It's the complicated windows with lots of text, or, in the worst case, a scroll view with an unbound amount of elements contained, which can be potentially disastrous for performance, either because of garbage, or just the raw number of draw calls generated by OnGUI and GUILayout.

This is the time in which one need to call for numbers using Benchmarks. :-)

Calling drawing functions, by itself, is not a problem necessarily. But this discussion is going to the same places as the Stacking versus Composite GUI debacle: it depends essentially on the environment you are running them and how you are running them. It's better to find some time to do that benchmarking I mentioned before further talking about, otherwise I would be just exchanging opinions.

Link to comment
Share on other sites

Old versions of Contracts Window + were essentially unbound GUILayout scroll views. You could potentially have dozens of active contracts, each with an unbound number of contract parameters, each potentially having sub-parameters and notes. 

When using a GUILayout scroll view all of the elements contained within are generated for each frame, even if they are not displayed in the window. So the strings and textures for each element are allocated, and draw calls for each GUILayout element are generated (it's actually two draw calls for each element, I think). For CW+ each contracts had several icon elements, the title button, contract parameter text elements, note buttons, etc... and so could generate dozens of draw calls per contract. Performance problems quickly limited the amount of contracts you could reasonably display for those early versions.

The solution for this using OnGUI is to manually position elements withing the scroll view using the GUI controls, not GUILayout. This is also what X Science does, which is a good thing, as it can potentially display hundreds of elements for all of the various possible science results. Then you only have to worry about allocating resources for what is actually shown in the window.

A simpler example of this is when I made a window to show all of the XKCD colors, it was just a scroll view with a few lines of text for each color, but since there are about 1000 of these colors it absolutely crippled performance. Just a single window in the main menu screen dropped the FPS down to about 10, presumably because of the excess draw calls.

Ironically, of course, the new Unity UI still has some problems with scroll views. The default masking system used to only show what is within the window is inefficient, but an alternative is available that will prevent draw calls being made by elements outside of the window. And there is some potential for problems caused by the Pixel Perfect flag (which aligns all of the image elements with pixels, so that they aren't blurred between neighboring pixels), but those can be worked around.

I don't have numbers for any of the scroll view problems mentioned above, the performance difference was obvious at the time. But I did do some garbage generation comparisons when I remade the SCANsat UI. Just having a few of the old windows open would generate 5-10MB of garbage / sec, whereas the new windows generate basically 0 garbage (except for a bug in one aspect of the current version :blush:). The trade-off for not generating garbage constantly is a spike when instantiating all of the UI objects when the window is opened, but that generally only occurs for a single frame and still results in less garbage during that one frame than OnGUI was generating for every frame.

 

Link to comment
Share on other sites

On 4/24/2018 at 11:55 AM, DMagic said:

I don't have numbers for any of the scroll view problems mentioned above, the performance difference was obvious at the time. But I did do some garbage generation comparisons when I remade the SCANsat UI. Just having a few of the old windows open would generate 5-10MB of garbage / sec, whereas the new windows generate basically 0 garbage (except for a bug in one aspect of the current version :blush:). The trade-off for not generating garbage constantly is a spike when instantiating all of the UI objects when the window is opened, but that generally only occurs for a single frame and still results in less garbage during that one frame than OnGUI was generating for every frame.

 

There's only one thing better than benchmarks for a old far... I mean... guy like me. Source code. :-) THANKS! :-)

I choose to give a peek on a older version than 17.9, since you stated that already made the performance improvements, and I need to see the older way in order to understand what happened. So I gone for the 16.11 version, and this is what I saw:

  1. On SCANsettingsUI.cs, there's a function called DrawWindow, that does the heavy lifting of drawing .. the Window.
  2. There're a lot of gui_settings_<something> being called, where (obviously) the heavy lifting is being done.
  3. And here is where things gone... not the best way possible:
    1. The widgets are being created and thrown away every frame!

I already had inferred this (really, I used to program C++ and Delphi for Windows 3, and GUIs hadn't changed at all since them, only their abstractions), but know I'm sure: this is not the best way to handle event driven GUIs.

Event Driven code needs to control states. So, the window is in "uncreated" state at startup. When you need to show it, you change its state to "creating" and, when this state is completed, you change it to "visible". You can change the state to "hidden" (where it still exists and are being updated, but not drawn on screen) or you can "close" it, when then you delete everything and change the state back to "uncreated".

So you need to write "state change handlers" (yes, this is essentially a FSM - Finite State Machine): you code one function to handle "creating", another one to handle "visible", one for "hidden" (if applicable) and one for "close". More complicated FSMs needs 3 handles for each state: phase_in, level and phase_out (this helps to keep the states number to a minimum, but it's not exactly necessary here).

So, you just create the widgets in the "creating" handler. And from now on, you call the "visible" handler instead - where you just update what's already created and show it. This prevents the Garbage Collector from going havoc.

I followed up the code, tracking what interface/abstract class the DrawWindow belongs, and got into SCAN_MBW.cs. It is called inside a function called DrawWindowInternal, that it's passed as a parameter (so it's a handler itself) on the DrawGUI, that it is itself another handler that the Visible attribute uses to put on the current window's draw queue. Interesting enough, the SCAN_MBW originally relied on SCAN_MBE to be called on the event changes. Even better, there's a DrawWindowPre and DrawWindowPost hooks for the phase in and phase out event handlers for what I called "Visible state", but in this code they were "short circuited" into the same event handler as the DrawWindow in the present implementation.

Pheeew. This was almost a full-blown Window Management toolkit! :-) Something I will look on again for sure.

The problem I see on this is that the event driven support from SCAN_MBE is not being used anymore, and another subsystem were "hammered" on it, overruling the previous life cycle. This new lifecycle is the one recreating the world on every frame instead of reusing what was created in the previous state (PHP style!).

So, it's not a surprise your GC is going nuts. :-)

While far from ideal in the present implementation (from the code style point of view), the UbioWeld (I'm also mangling it on my own fork) plugin does the right thing on this. Ideally, each Window should be implemented in his own class (that would prevent some mess while debugging the thing), but the way how things are done (controlling states, and just updating what's already created on a OnGUI call) is there.

Edited by Lisias
forgot some whistles and bells; TLDR; I'm wrong on some of this. See below.
Link to comment
Share on other sites

27 minutes ago, Lisias said:

And here is where things gone... not the best way possible:

  1. The widgets are being created and thrown away every frame!

 

That's the whole problem with IMGUI. You recreate the entire UI multiple times every frame.

 

28 minutes ago, Lisias said:

This new lifecycle is the one recreating the world on every frame instead of reusing what was created in the previous state (PHP style!).

I'm not sure what this means as it relates to IMGUI. All of the UI elements are generated by calling the GUI and GUILayout functions somewhere within the OnGUI method attached to a MonoBehaviour (don't ask me about all of that SCAN_MBW/MBE stuff, I didn't write that, though I know it has its origin in TriggerAu's plugin framework code; it has all since been removed), I don't see how you can cache or store any of that information. Recreating it on every frame is just how it works, unless there is some alternate way of doing it that I am completely unaware of. You can, of course, cache certain components of the UI, strings (or StringBuilder instances), textures, etc... but if you want to draw a button you just have to call GUI/GUILayout.Button on every frame.

I don't see where UbioWeld is doing it any differently. It looks like it has a lot of data stored in constants, but its UI code is still being drawn with GUILayout, and not every bit of text, or component of the UI can be cached at compile time like that.

 

33 minutes ago, Lisias said:

Event Driven code needs to control states. So, the window is in "uncreated" state at startup. When you need to show it, you change its state to "creating" and, when this state is completed, you change it to "visible". You can change the state to "hidden" (where it still exists and are being updated, but not drawn on screen) or you can "close" it, when then you delete everything and change the state back to "uncreated".

This sounds suspiciously like the Unity UI.

Generally when a scene is loaded in KSP you would either start a MonoBehaviour to control your window, or just add a toolbar button. Then when you open the window you create everything, which, for a UI generally means instantiating a bunch of GameObjects, either tediously through manually coding everything*, or by loading a prefab created in the Unity editor from an asset bundle. Then your UI is in the visible state, the Unity canvas system just draws whatever is on screen each frame. Scripts attached to those UI objects can handle updating the UI or processing events, etc...

*

Spoiler

This is where the real problem in using the Unity UI lies. It is extremely difficult to make any kind of complex UI only through code. The RectTransform doesn't lend itself well to being manually manipulated like that. Which means that you have to use the Unity Editor to make the UI prefabs, which introduces lots of complexity in how you actually tie together the KSP code with the UI code. The trade-off, though, is that you can get near instant feedback into how your UI looks and behaves without having to constantly reload KSP.

For most of my UI's I destroy everything when the window is closed. Creating and destroying the UI isn't generally that intensive, and it simplifies some things. For some, like Contracts Window +, the opening process is particularly intensive (meaning poorly thought out and coded ;.;) so I just hide it when the window is closed.

There are a few different ways to go about hiding a UI. You can just turn off the GameObject using SetActive, which stops all of the attached scripts from running and hides the window, but calling SetActive itself can be a problem.

Another way is to use a CanvasGroup script attached to the window. If you set the alpha for a CanvasGroup down to 0, and make it non-interactable and not block ray casts, then (supposedly, I don't think I've every actually tried this) all child objects in the CanvasGroup will be ignored by the UI (they won't generate any draw calls), but the attached scripts will still be running, so it could be a trickier way of handling hiding the UI.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...