Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Question Are CompositeCollider2Ds always regenerated at enter play mode?

Discussion in 'Physics' started by Baste, Nov 27, 2023.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    I've got a scene with a pretty bad mess - tons of BoxCollider2Ds that's combined into one single large CompositeCollider2D.

    This scene takes 40+ seconds to enter play mode, and it seems to all be in the collider:
    upload_2023-11-27_9-25-52.png

    Now, I can clean this up, but I am a bit perplexed - we have reload scene turned off:
    upload_2023-11-27_9-27-17.png

    So I wonder why this is even happening. Shouldn't the CompositeCollider survive from edit mode to play mode without having to be destroyed and then recreated?


    I'll for sure rewrite the hacky script that places all of the BoxCollider2D's into one that just generates a big PolygonCollider2D, but we will probably want to use CompositeCollider2D in the future, and I'd hope that it doesn't have an impact on enter play mode times that it doesn't need to have.
     

    Attached Files:

  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Nothing survives from Edit->Play->Edit. The components are destroyed/disabled and created/enabled.

    The composite stores the combined shape data though (serialized) and it has to create all the shapes only, not combine all the colliders though.

    I'd be curious to look at this or another test project though to make sure that something has not happened that is triggering a regeneration.

    If you have or could put together an example of this and send it me either here or DM or if you'd like me to create a workspace where you can upload then please let me know.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Happy to take a look at the above but also wanted to mention the CustomCollider2D as well which gives you pretty low-level access to creating shapes so performs much better in many scenarios.

     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331

    According to the docs, destroying and resetting is "simulated" with scene reloading disabled. I don't quite know what that means, but I assumed that it meant that objects are not unloaded, but only have methods called on them. I know that for our own objects, a reference from before enter play mode is the same as the reference after enter play mode. Does this mean that the 2D physics system will destroy and then recreate Box2D stuff even without scene reloading?

    I've attached a UnityPackage with just the collider setup, which is enough to reproduce things being slow. Import it into a Unity project, drag it into a scene, and watch the editor hang for a while. This is because the CompositeCollider are trying to compose 2255 BoxCollider2Ds and 56 PolygonColliders. The same long hang happens on enter play mode, even without scene reloading.

    Thanks! I think we'll be good by just generating the correct PolygonCollider2Ds we need instead of outputting thousands of BoxColldier2Ds and throwing a CompositeCollider2D at them. So don't take this thread as "Unity/Physics2D is being too slow", more as a "Our code is bad, but it does seem like Unity is doing more work than I assumed it had to"
     

    Attached Files:

  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    2D physics has no control over what might and might not happen here because obviously everything is exposed as components. If Unity itself didn't touch the components then 2D physics wouldn't do anything. If it disables a component then that, as it always has, would destroy the respective "Box2D" things etc.

    Let's see what's happening here though! :)

    Yes, maybe so but if something odd is happening here that shouldn't then I'll fix it so I'll look at the attached package today for you and get back to you.

    Naw, don't worry. Everything is too slow at one scale or another. :)
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    btw, what version of Unity are you using as I'd like to test with that?
     
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    We're on 2022.3.10f1. I got the same slowdown when I added it to 14f1.
     
    MelvMay likes this.
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Just to confirm that I've duplicated the issue over here. There's no way it should take that long.

    I'll dig further to find out what the heck is going on.
     
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    Should I post a bug report as well?
     
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Best to let me invesigate first.

    I can confirm that when you load the scene, none of this happens because everything is inactive then but when you enter play mode, each component is individually deactivated (which removes all physics stuff) and then are activated (which adds all physics stuff). Normally when you unload a scene ("fast" play-mode off) this is all bypassed because it's seeeing a flag saying (kGameObjectWillBeDeleted) so it's all being destroyed anyway and none of these incremental deactivations happen.

    Unfortunately, the internal Unity calls don't say that this is anything to do with entering playmode so the components have no way to differentiate between the components being disabled or entering play mode.

    All I can do is see if there's some hook I can figure out to "know" this is happening.

    Right now, with the "fast" enter play mode it's deactivating each collider in turn so the composite is informed too which is terrible. Normally that wouldn't happen with the scene being unloaded.

    It actually takes along time to load this well before anything physics is involved too. :(
     
  11. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    So actually, please go ahead and submit a bug report but looking at it, there's a good chance there's nothing I can do here because I don't know it's anything other than all those colliders being deactivated so I see it the same as if you would deactivate them i.e. delete or disable them.

    We do have awake/destroy queues and I might be able to request ordering for this destroy set-up i.e. have the composite done before its children which might avoid this issue.

    This "Fast Play Mode" thing came in years after the CompositeCollider2D thing was created and not many components in Unity do this kind of thing.

    Maybe there is something though, I can ask around.

    Thanks!
     
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    Update! This relates to prefabs.

    Here's my timings when the Collider Parent object is a prefab:
    Code (csharp):
    1.  
    2.     Reload Scene Turned On:
    3.         Enter Play Mode: 13 seconds
    4.         Enter Edit Mode: 13 seconds
    5.  
    6.     Reload Scene Turned Off::
    7.         Enter Play Mode: 31
    8.         Enter Edit Mode: 13
    9.  
    Here's my timings when the Collider Parent object is not a prefab:

    Code (csharp):
    1.  
    2.     Reload Scene Turned On:
    3.         Enter Play Mode: instant
    4.         Enter Edit Mode: instant
    5.  
    6.     Reload Scene Turned Off:
    7.         Enter Play Mode: 37
    8.         Enter Edit Mode: instant
    9.  
    So somehow integrating the prefab into the scene has an immense cost in most instances, except entering play mode without reloading scenes, where it somehow saves time

    This is, uh, absurd. It smells like there's some side effects in here doing some very silly things.

    Oh, and note that in the actual game this is from, the colliders are not prefabs, so we only see the long enter play mode time. The only reason why I sent it as a prefab was that I had to make it into a prefab to make it into a .unityPackage. Wouldn't have figured it out otherwise.
     
    Last edited: Nov 27, 2023
    MelvMay likes this.
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    Bug report is IN-61935
     
  14. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Normally there's what is known in Unity-land as an "AwakeFromLoad" queue and these are split-up into queue priorities and the CompositeCollider2D has its own priority set to run before any Rigidbody2D or Collider2D. This means it can be activated and deactivated (these queues deal with deactivation too) prior to things that might change. This was implemented way before "Play Mode" options were.

    The problem with the "Play Mode" thing is that it's essentially a hack where it bypasses the queues and "fakes" a scene unload/load. Unfortunately it doesn't deal with this using the established queues and their orders which is why this is "breaking". Also, it's made worse by the fact that it's essentially deactivating then activating components which means, each of those BoxCollider2D being deactivated are removed from the composite which, because it's still a live object, it does what it's meant to do and regenerates the geometry! It does this for each collider being deactivated.

    Normally, this wouldn't happen because AwakeFromLoadQueues/Priorities and the deactivation operation states it's being destroyed/unloaded not deactivated.

    The only way this could be fixed would be to request that the Scene Management team fix this behaviour so we'll see if that could be changed easily.
     
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Yes, prefab changing seems to be expensive and none of that involves physics. I unpacked the prefab and any change is quick then.

    Adding to the above, if I change the CompositeCollider2D "Generate Type" to "Manual" then, when each of those child colliders are deactivated in turn (ugh) it makes no difference to the composite and it won't be regenerated so entering/exiting Play Mode should be faster.

    Would you mind trying that on your end to see what difference it makes?

    Maybe it's a workaround you could use but would mean hitting that button when you wanted it to regenerate. It was added for particularly complex composites.
     
  16. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    Yup, that makes it instant. Thanks!

    Our colliders in this instance are actually placed out by a tool based on a level editor, so any manual movement of the colliders at all would be an error. So we never have to press the button, we just add the CompositeCollider2D to the gameObject, set the mode to manual, and then we're happy.

    I mean the issue should probably be fixed on the Scene Management side, because if fast enter play mode makes it impossible for Unity devs to write code that runs in an optimal order, then that's a very big problem. But it's at least not breaking our workflow anymore.

    As always, appreciate how helpful you are!
     
    MelvMay likes this.
  17. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Well we've got you a workaround so that's the best part.

    I'll wait for the case to come through from QA and will absolutely be pushing for that change. There's likely much more subtle breakages in Unity here because those queues are not there just for fun and should be used in all cases. ;)
     
  18. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,331
    Hi! This bug got marked as won't fix.

    I sent a follow-up response - I realized that I never mentioned in my original bug report that there was a related forum thread, so it might not have been passed to you at any point.
     
  19. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    I've not seen it no but looking, since your response, it's been reopened by CQA.

    To note though, there's still a good chance that this cannot be fixed because of significant changes required inside Unity but I'd like to see what could be done to maybe work around it.
     
  20. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,409
    Hi!

    The bug was sent across to me being a few days ago being as our interaction here on the forum was noticed. I'll take another look at this however I'm pretty sure this one isn't going to be easy to resolve as it would require significant changes to the fundamental mechanisms of how objects are destroyed; at least from what I recall from previous investigations.

    The CompositeCollider2D is fairly unique in the Unity world in that it's a component that maintains relationships with other components on children GO and changes on them can cause significant work to be done within it.

    I will verify that there's not another way we could know that this is happening in this scenario and therefore ignore the per-collider changes that cause the composite to be continually updated.