Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion Advice on scaling explosions to prevent overwhelming/freezing/crashing Physx

Discussion in 'Physics' started by I5, Aug 5, 2023.

  1. I5

    I5

    Joined:
    Feb 15, 2015
    Posts:
    17
    I have an "oil energy extraction system" in my game that is comprised of multiple large "storage tanks" that can explode. If significant damage is done to one, they all explode, adding explosion force and causing damage to nearby objects (by way of a sphere cast), which may also explode from the resulting damage. Sometimes this crashes both the editor and the profiler (even when running in standalone mode), and sometimes it just freezes the player (40+ secs per frame, causing the fixedUpdate death spiral).

    I'm considering a code design that puts all explosions on a Queue. In Update, I would estimate the current FPS, and if it's above 30 FPS I would then allow the next explosion in the Queue to init. I'm not concerned about how it will look/behave, initial tests look pretty cool. BUT...I've been down the code refactoring so many times with Unity, only to find out months later that Unity is still chocking on the rendering/physx/whatever. So, anyone got hard lessons learned about the idea of trying to scale physics by monitoring FPS and Queue'ing explosions? Any time/effort greatly appreciated.
     
  2. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    Not sure if I can contribute anything to an actual solution, but unless we’re talking thousands of rigidbodies affected by the explosion and assuming you’re just adding one single impulse to each object, there should not be any drop in framerate. Are you sure that this is actually caused by the physics system?

    maybe one tank exploding will make another tank explode and this will make the first tank explode “again”, causing a large loop?

    maybe tell us more about your setup, how many objects are involved, how you’re calculating Explosion force, how you’re finding affected objects etc
     
  3. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    This sounds like it may be a logic error in your code. I suspect object A is triggering object B which is triggering object A which is triggering object B which is triggering object A which is triggering object B which is.... okay okay you get it..
     
  4. I5

    I5

    Joined:
    Feb 15, 2015
    Posts:
    17
    @tjmaul, @zulo3d , thanks for the feedback.
    In regards to it likely being a code/logic flaw/error/bug, that's what I was hoping it was (would be much quicker/easier to fix). Here's why I don't believe the crashing and freezing is due to a game code/logic/recursion bug/flaw: (but rather due to a design flaw that overwhelms the physics)

    1. I've put counters in all loops/recursions, and log and break out of the loops if recursions exceed 20 to 100 (depending on what the code is doing) - Based on the log and profiler data (when it didn't also crash :), there's nothing to indicate any game code is the source of the problem (see below for screenshots of profiler and scene view of explosion.
    2. The profiler stack trace shows that the player is freezing on Physx calls, and no game code/logic is being called excessively
    3. I then removed all recursion and instead put explosions on a Queue
    4. I put logic/code in explosion code to allow explosions to be inited only 1 time per object ex:

    Code (CSharp):
    1. public virtual void die(bool alreadyDead, bool killedByWeapon) {
    2.             if (processingDeath) return;
    3.             processingDeath = true;
    4.             dying = true;
    5.             .....
    Below are screenhots of the explosion (scene view) and profiler (calls sorted by processing time)



     
  5. I5

    I5

    Joined:
    Feb 15, 2015
    Posts:
    17
    I would post the code, but it covers over 1500 lines and includes 3rd party assets from the asset store (such as a very popular asset used for cutting meshes for explosions). I've added debug output though, and the logs don't indicate that infinite recursion is the issue. One potential issue (not sure) may be that the explosions (above) generate 50+ active "frags" (cut mesh parts with a non-kinematic rigidbody added), and over half of the frags are being resized (minimized to a small size and then deactivated) while they are still moving and colliding. Maybe that's what's chocking the Physx? Throwing darts in the dark at this point.
     
  6. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Yes, this is a big problem!. Resizing colliders can be quite costly for the physics engine.
     
  7. I5

    I5

    Joined:
    Feb 15, 2015
    Posts:
    17
    Thanks for the feedback, "...unless we’re talking thousands of rigidbodies affected...", that helpful to know for future debugging (to know that 50+ colliding rigidbodies shouldn't be the problem) - I think I found problem, a design flaw with resizing game objects with rigidbodies, while they were under explosive force - posting the fix now...
     
  8. I5

    I5

    Joined:
    Feb 15, 2015
    Posts:
    17
    Thanks for the confirmation! Wow, this design flaw (mine) cost me weeks - another hard Unity lesson learned - this was a tough one to debug (esp. with the editor and profiler crashing so many times) - I just added logic to the "frag" game objects being resized/minimized, so that resizing doesn't occur unless the frag has stopped moving for at least 100 frames - sweeet! Explosions work and look great now, with FPS never falling below 30 (which is acceptable for brief periods). Code fix snippet is below (taken from Update method, not worried about getting Velocity in Update instead of FixedUpdate because not concerned about precision, only if velocity is 0). Thanks All for the discussion. Greatly appreciated.

    Code (CSharp):
    1. if (Time.time > startFadeOrMinizeAtTime) {
    2.                 if (rb.velocity == Vector3.zero) {
    3.                     ++stoppedMovingForFrames;//don't modify frag while it's moving, it kills the physics engine
    4.                     if (stoppedMovingForFrames > 100) {
    5.                         startFadeOrMinizeAtTime = float.MaxValue;
    6.                         if (minimizeSpeed > 0f) {
    7.                             I5GameManager.instance.resizeGO(this, gameObject, (gameObject.transform.localScale * 0.2f), minimizeSpeed);
    8.                         }
    9.                         if (fadeOutSpeed > 0f) {
    10.                             Material m = mr.sharedMaterial;
    11.                             if (fadeMaterial != null) m = fadeMaterial;
    12.                             I5GameManager.instance.fadeOut(mr, m, fadeOutSpeed, this);
    13.                         }
    14.                     }
    15.                 } else {
    16.                     stoppedMovingForFrames = 0;
    17.                 }
    18.             }
     
    tjmaul likes this.