09-09-2023, 10:49 AM (This post was last modified: 10-09-2023, 10:56 AM by creekat.)
Hi!
I have been using Obi Softbody for quite sometime now, and I always have a hard time optimizing the entire Obi system. I changed the backend setting to burst already, downloaded all the required packages (Burst, Collections, Mathematics and Jobs) and set all the constraint iterations to minimum parameters (if possible, 1), but the game still lags PARTICULARLY when two or more softbodies are in contact. I cannot attach a screenshot of the game, because it is still under development, but I will try my best to describe the game system.
Upon level start, there is one Obi solver in the scene. Multiple softbody prefabs will be instantiated as children of this solver. Upon instantiation, the softbody component is disabled to save memory and is only enabled once a certain condition is met. The softbodies are enabled one by one. I attached a screen capture of the solver (solver.png).
Upon meeting another condition, the softbody prefab as a whole is deleted. Including all the Obi-related components. The softbody prefab's heirarchy is included below (heirarchy.png). Center and KeyHolder are just empty transforms, while Skin (skin.png) and Player (softbody.png) are where Obi components are included. I attached a screen capture of these two as well.
The mesh of the softbody I am using has 3328 vertices, 3332 triangles and 2 submeshes.
The softbody blueprint parameters are attached below. Please refer to blueprint.png.
I took a screenshot of the Profiler during the time when the game lags and attached it below. During this time, the game is practically unplayable and just freezes. The weird thing about this is if you set backend to Oni, the freeze issue disappears on the editor, but freezes nonetheless when you build the game on Android. Setting backend to Burst freezes on either environments. For the screenshot, please refer to solver.png.
I can probably send the entire project to you if you have a personal e-mail address to which I can send it to. My observation is that the Burst mode is fine as long as there are no colliding softbodies. Maybe the computation for Obi just overloads with all the collisions happening? If this is the case, might the softbody be subscribed to the OnParticleCollision event? (I did not perform any subscription via script.)
I would appreciate any advice from you, as I have been struggling quite some time with this problem. Even with just 2 softbodies enabled, the game lags and I do not know what to do anymore. Also, the Jobs settings return to default everytime I open the editor and because of this, I have to set it every single time. Is this normal behavior?
11-09-2023, 07:57 AM (This post was last modified: 11-09-2023, 08:09 AM by josemendez.)
Hi!
(09-09-2023, 10:49 AM)creekat Wrote: The mesh of the softbody I am using has 3328 vertices, 3332 triangles and 2 submeshes.
Mesh density has zero impact on simulation, since the mesh isn't simulated: a particle-based representation of it is. Amount of vertices/triangles/submeshes/etc only has an impact on rendering. How many particles does your softbody have?
All other parameters in your screenshots look ok to me.
(09-09-2023, 10:49 AM)creekat Wrote: I took a screenshot of the Profiler during the time when the game lags and attached it below.
The profiler screenshot shows 1.68 ms spent on the player loop: that's around 600 frames per second, hardly a performance problem. I guess you sampled a specific frame that had normal performance, amongst frames that did exhibit the issue? In any case, this profiler pic is of no use whatsoever. Could you export the profiling data and share that instead? (there's buttons at the top of the profiler to export/import data). That way I can navigate your profiling session and view all useful info, you can send the profiler data file to support(at)virtualmethodstudio.com.
(09-09-2023, 10:49 AM)creekat Wrote: I can probably send the entire project to you if you have a personal e-mail address to which I can send it to. My observation is that the Burst mode is fine as long as there are no colliding softbodies. Maybe the computation for Obi just overloads with all the collisions happening? If this is the case, might the softbody be subscribed to the OnParticleCollision event? (I did not perform any subscription via script.)
Collision detection between particles is quite cheap, certainly a lot cheaper that the actual softbody simulation or collider collision: it's just pairs of point-point distance tests. Unless there's several thousand particles in the scene and they're all colliding with each other, chances are particle collision won't ever be a performance bottleneck.
12-09-2023, 03:01 AM (This post was last modified: 12-09-2023, 03:10 AM by creekat.)
(11-09-2023, 07:57 AM)josemendez Wrote: Hi!
Mesh density has zero impact on simulation, since the mesh isn't simulated: a particle-based representation of it is. Amount of vertices/triangles/submeshes/etc only has an impact on rendering. How many particles does your softbody have?
Oh! I see. The softbodies I use are averaging at 190-200 particles. I don't think this is a lot?
(11-09-2023, 07:57 AM)josemendez Wrote: The profiler screenshot shows 1.68 ms spent on the player loop: that's around 600 frames per second, hardly a performance problem. I guess you sampled a specific frame that had normal performance, amongst frames that did exhibit the issue? In any case, this profiler pic is of no use whatsoever. Could you export the profiling data and share that instead? (there's buttons at the top of the profiler to export/import data). That way I can navigate your profiling session and view all useful info, you can send the profiler data file to support(at)virtualmethodstudio.com.
I sent the profiler data file already via e-mail. Thank you very much in advance for checking!
(11-09-2023, 07:57 AM)josemendez Wrote: Collision detection between particles is quite cheap, certainly a lot cheaper that the actual softbody simulation or collider collision: it's just pairs of point-point distance tests. Unless there's several thousand particles in the scene and they're all colliding with each other, chances are particle collision won't ever be a performance bottleneck.
If one softbody has approximately 200 particles and 9 softbodies (1,800~ particles total) are in the scene at any one time, could it be that performance might slow down during this time? Or maybe because I did surface sampling only for the blueprint then they are like fusing with one another and giving the engine a hard time computing? These are just thoughts because I can't quite wrap my head around the cause for this performance bottleneck. ?
One more thing also. I mentioned this in the original message, but everytime I restart Unity, the settings for Jobs always return back to default. This means I have to disable the jobs debugger, safety checks and leak detection every single time. When I build an Android version of the game, how are these settings set? What are the settings of Jobs in-game when users play with a smartphone?
Your help is always appreciated! Thank you very much.
(11-09-2023, 08:03 AM)josemendez Wrote: Just noticed there's a "ObiParticleFinder" component in your softbody. What does this script do?
This script just makes accessing particle groups (and the particles assigned to it) easier. Also, a particle's exact world position, particle's solver index, and other information are accessible here. Sorting of particles are also sometimes done here.
12-09-2023, 07:19 AM (This post was last modified: 12-09-2023, 07:23 AM by josemendez.)
(12-09-2023, 03:01 AM)creekat Wrote: Oh! I see. The softbodies I use are averaging at 190-200 particles. I don't think this is a lot?
Hi!
No it's not a lot, but depending on how many softbodies you have it can get costly. The ObiSolver component shows some basic statistics in the inspector (amount of particles, amount of simplices, amount of contacts). With just 9 softbodies, you shouldn't have any trouble whatsoever.
Took a look at your profiler data, the cause of performance degradation is obvious: all physics are being updated 16 times every frame!
This is called "death spiraling", and happens when a frame takes longer than usual to render. As a result, Unity is forced to update physics multiple times per frame in order to catch up with the extra time, but this may cause the next frame to take even longer which exacerbates the problem. You can tell Unity to stop updating physics after a given time threshold, this is called "maximum allowed timestep" and can be found in the Time settings:
Lowering the maximum allowed timestep to a small multiple of the fixed timestep will prevent bad cases of death spiraling. Eg, if your fixed timestep is 0.02, setting the maximum allowed to 0.06 will ensure physics is updated at most 3 times per frame (0.06/0.02 = 3).
Now, typically frames should not take too long in the first place. However in your case it happens because collision detection isn't being compiled by Burst, but being run in a single thread using regular C#. This is extremely slow (in the following picture, green bars are the time taken by Burst methods, while the darker ones is time taken by non-Burst methods. You can see Burst takes a tiny amount of time to do its job, while most of the time is spent on the blue bars):
As to why this is the case, no idea. Maybe you've unintentionally disabled Burst compilation for these specific jobs, or your Burst version is too old (these methods require generic method support, which older Burst versions didn't support). I'd suggest updating both Obi and Burst, see if that makes a difference.
(12-09-2023, 03:01 AM)creekat Wrote: One more thing also. I mentioned this in the original message, but everytime I restart Unity, the settings for Jobs always return back to default. This means I have to disable the jobs debugger, safety checks and leak detection every single time. When I build an Android version of the game, how are these settings set? What are the settings of Jobs in-game when users play with a smartphone?
These settings are editor-only. In standalone builds, Burst is enabled, safety checks and debugger disabled (since your players can't debug your game or get warnings in the console). See Unity's Burst documentation for details.
Oh wow! I just had a feeling that Burst was not working properly. Thank you so much for checking the profiler data.
This question might not be an Obi-related question, but how were you able to tell via the Profiler that all physics are being updated 16 times every frame? Where can the value 16 be found? I have always struggled where to look specifically when referring to the Profiler and this gives me a hard time to debug. Maybe you have good references you can recommend on how to read profiler data?
Thank very much and I will keep you updated on whether or not I will be able to solve the performance problem!
14-09-2023, 06:26 AM (This post was last modified: 14-09-2023, 06:37 AM by josemendez.)
(14-09-2023, 03:18 AM)creekat Wrote: This question might not be an Obi-related question, but how were you able to tell via the Profiler that all physics are being updated 16 times every frame? Where can the value 16 be found? I have always struggled where to look specifically when referring to the Profiler and this gives me a hard time to debug. Maybe you have good references you can recommend on how to read profiler data?
If in Timeline view, the horizontal axis represents time and each bar is a method call, the vertical axis represents the call stack (so a bar/method will have all methods called by it immediately below, if there's nested calls you'll see multiple rows). You can see 16 horizontal bars with the name "FixedUpdate.ScriptRunBehaviourFixedUpdate", which means that FixedUpdate has been called 16 times in a row:
If in Hierarchy view, there's a "Calls" column that tells you how many times a method has been called during that frame. You'll see a "16" there for "FixedUpdate.ScriptRunBehaviourFixedUpdate". The other columns are:
-"Total" (percentage of the total frame time spent in that method or methods called by it)
-"Self" (percentage of the total frame time spent in that method, excluding methods called by it)
-"GC Alloc" (amount of memory allocated by that method during the frame)
-"Total ms" (milliseconds of time spent in that method or methods called by it, just like "Total")
-"Self ms" (milliseconds of time spent in that method excluding methods called by it, just like "Self")