Search Unity

PhysX 4.1 in Unity - experimental builds

Discussion in 'Physics Previews' started by yant, Feb 25, 2019.

  1. AndrewRH

    AndrewRH

    Joined:
    Jan 24, 2012
    Posts:
    2,592
    Thanks @yant for all of the hard work :) I have a few cloth questions:

    1) I was just wondering whether the change from PxCloth to NvCloth would bring any benefits?

    2) Also, I noticed that the previous PxCloth seemed to be using only the software solver, but I know NvCloth at least has a Cuda and DX11 option - is Unity only using the CPU solver for simplicity? I imagine with GPU support you would have to deal with GPU readback issues to update the meshes each frame, or change the shader pipeline to allow for direct usage of these buffers....

    3) What are the limits in terms of number of colliders and vertex count for a cloth mesh currently? I heard that there was some limits, and that the mesh might be only up to 65536 vertex but I couldn't find that written anywhere in the docs.

    4) Last question - any plans to allow for GPU cloth solver?

    Thanks!
     
    nemodemos likes this.
  2. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    762
    Sorry for some reason sometime alterts on new post dont work. For what concern joints, everything seem to work as expected. For what concern articulations, not sure about that.
    Anyway, even if its not ready for production, you can enable build with "development build" checkbox forced on.
    It wqould be nice to test the new features on our target platforms, also to check performances.
     
  3. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    1,159
    @yant I'm going to be totally honest here and will probably get a lot of dislikes but I think official PhysX 4.1 update should be postponed to 2020.1. Not because it wouldn't be ready for 2019.3 but because then it wouldn't possibly screw over engine users if there's a regression on some feats they've used extensively on 2019.x so far.

    I also think it was a mistake to upgrade to PhysX 3.4 in the last TECH stream last year as well (along with prefab change) as it forced all people on earlier 2018.x versions to jump aboard as well (there were many unhappy users for those 2018.3 changes). Since last TECH stream and first TECH streams are so close to eachother, I feel that bigger changes that can potentially affect most engine users (and that are not optional feats to the users) would be better to postpone to the start of next years cycle as then it would be fair game for all.

    Apart from the schedule, I do have a question about the integration as well: you said most considered feats are in now, does this mean there will not be support for connecting regular joints to articulated joints at first?
     
    Last edited: Jun 30, 2019
    hitmanchoi likes this.
  4. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    I'll take articulations out of 2019.3, that bit is clearly not ready. We lack some tools and I'm pending on a new PhysX version that has a ton of fixes to articulations code. It's been good to have it in preview, but I'll try to make it for the next release.
     
  5. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    1,159
    Commenting here if some missed it, PhysX 4.1 is now in 2019.3.0a10.
     
  6. DrSeltsam

    DrSeltsam

    Joined:
    Jul 24, 2019
    Posts:
    5
    Really looking forward to this :) Thanks @yant for the hard work!

    This sounds very promising! Is this referring to the initial MeshCollider creation (when assigning the sharedMesh of a MeshCollider), or to the Mesh cooking? Procedural MeshCollider creation takes quite long (even if cooking is disabled), so it would be awesome if this works faster now (or can be offloaded to another thread)
     
  7. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Mesh cooking, you're right.
     
  8. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Just to build up on that point - articulations were excluded from 19.3 and delayed to a future milestone. Clearly not ready for production now.
     
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    Somebody linked this somewhere, so I'd figure I'd chip in:

    We have used trigger<->trigger checks extensively in all our games. We need those, and we need raycasts. We don't actually need collisions or physics simulations. It has never, not a single time, been relevant to us how fast plates stack or all of the other things physics engines think are important.

    In other words, PhysX is not useful for us without trigger-to-trigger interactions. Using overlap spheres or similar methods is out the window, because that's super-slow at scale. We also don't have the time or know-how to build our own dots-based trigger overlap system.


    All of that being said, it's always been a hack that at least one of them needs a rigidbody. We have so many kinematic rigidbodies that utterly doesn't need to be rigidbodies floating around, because two trigger colliders doesn't cause a trigger message.

    So replacing trigger<->trigger interactions with a proper system for checking overlaps or distances at scale would be preferable. It's also be clear when looking at the component what it's for. It'd also probably be faster, since it's not interacting with all of the physics objects.

    But, before that system is in place, or trigger interactions are back, you're not shipping an engine that we can use.
     
    hitmanchoi and Prodigga like this.
  10. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    That's the kind of feedback I'm watching out for. Priorly in this thread you can see that the opinions were split. Also, I guess you saw the Nvidia's advice to clone shapes, what do you think about that? (in Unity speak: take a trigger Collider that you need to received trigger messages with, add a copy of it, but remove the trigger checkbox).

    Thanks for your interest in physics.
     
    jerotas likes this.
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    I didn't see that, no. I tried to scan through the thread again, nothing jumps out. Do you have a link?

    Colliders that are not triggers have a bunch of downsides when used for trigger-like checks. They collide with stuff! That's obviously no good if you don't want a barrier there that the player runs into. They also get hit by raycasts.

    Both of those things can be worked around with layers, but if I'm using some layers for collision-collisions, and some layers for trigger-collisions, then I'm down to 15 layers to work with. Oh, and those layers are also used by the lighting system, and 6 or so are reserved internally, so in reality I have something like 8 layers for collision-collision, 8 layers for trigger-collisions, and 8 layers for lights. Then I can hope that there's some overlap between these that I can abuse, but eh.
     
  12. Sposito

    Sposito

    Joined:
    May 4, 2014
    Posts:
    16
    Hey, my only interest here in PhysX 4 is using articulations with ml-agents for simulating robotic physics in machine learning environments. We are trying to migrate from ros/gazebo to Unity but physics is definitely our biggest barrier. Any chance of posting more recent builds that includes articulations so we can evaluate feasibility of using Unity?
     
  13. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Yes, the plan is to release the articulations stuff once it's ready so I'll be sharing another build later. I can't commit to dates yet.
     
  14. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    I don't know in Unity, but in PhysX you wouldn't need "layers" to solve this. Collision response is controlled by the PxPairFlag::eSOLVE_CONTACT flag in the collision filter, and raycasts/etc are controlled by the PxShapeFlag::eSCENE_QUERY_SHAPE flag in shapes. Omit these two flags and that's it.
     
    yant likes this.
  15. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    The reason is, well, historical. It wasn't exactly that way in PhysX 2.8 IIRC, and we had a layered collision response system that was easy to use and understand in the early days of Unity. Now, it's clear everything's grown and evolved over the years but changing layers has always been a somewhat lower priority (if not maintaining compatibility) compared to some other features/changes in our small team. There was always more pain to solve than manpower available, if you may. Fortunately, layers are not part of the new Unity Physics. As to the future of layers in this integration of PhysX, we'll have to see. It's obviously clear everyone, and their dog, don't like how layers are used now.

    Thanks for your comment Pierre, appreciated!
     
    Baste likes this.
  16. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    I don't know how things work in Unity but maybe it doesn't need "changing layers". At least in theory, these things should be fairly orthogonal & independent.

    For example the second part about raycasts is just a flag to expose on the shapes. Even with layers staying exactly the way they are, that flag would prevent raycasts from reporting trigger shapes. If it's not exposed yet, that's just one checkbox in the geometry/shape UI, controlling whether you can hit that shape or not with scene queries - regardless of how everything else is setup.

    It's a bit more involved for collision response but also independent from "layers" if done like, for example, in our PxDefaultSimulationFilterShader. This default filter shader emulates the layers from PhysX2, but the first section of its code actually intercepts triggers and disables collision response - before the layers code is even executed. See https://github.com/NVIDIAGameWorks/...src/ExtDefaultSimulationFilterShader.cpp#L228. So I think all you'd need to do is add something similar before your layers-logic, either in your filter shader or in your filter callback.
     
    hippocoder and yant like this.
  17. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Right, I'll do my homework here, thanks! However, I'm not inclined to expose collider flags like "won't be hit by a query", that's way too low-level for this abstraction I think.

    Anyways, what caught my attention is your comment on my twitter post (https://twitter.com/PierreTerdiman/status/1159455057336786944?s=20). I'd love to check if a good and performant way to go is to emulate triggers completely on the integration side of things, based on the onContact messages. There are benefits right off the top of my head - we'd get OnTriggerStay automatically. Currently it's added in the integration code, and causes quite a bit of complexity.
     
    hippocoder likes this.
  18. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    That's up to you, of course.

    On my side I don't see why this would be considered "low-level" (in PhysX it's actually the highest-level of filtering you can do) and/or why exposing a low-level flag is not an option. But I'm sure you have good reasons.

    Maybe I can create a new "trigger" snippet to investigate both options, if that helps.
     
    yant likes this.
  19. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Sounds interesting.
     
  20. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    The thing is, if that works well in 4.1 -- that might be my compatibility solution for triggers vs trigger I guess? The one that doesn't require extra heavy layers on top of what PhysX provides already
     
  21. zhouzhq7

    zhouzhq7

    Joined:
    Mar 13, 2019
    Posts:
    1
    @yant Hi, yant, I am trying to use Unity (2018.3.14f, intergrated with PhysX3.4) to perform robotic control simulation, however the control effect is not that statisfied when I use characterJoint to connect skeletons on PhysX3.4.Therefore I am trying to migrate my project into PhysX 4.0, and try Articulation Body. Many thanks to your great work which makes my thought possible.

    There is one problem that I usually develop my project on Windows Platform, and then build a Linux executable file to run on Linux server. On your lastest built Unity, it seems that it is not able to build a Linux package. Can you provide the corresponding Linux build support? I would be very grateful if you can help.

    Thanks for your time in advance!
     
  22. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    Speaking of which, could you describe one use-case for trigger-vs-trigger?
     
  23. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    A very common one is range-checks.

    We're using a navmesh-based approach to movement, so npc's doesn't ever need to collide with anything. What we do need to know, though, is which npc's can see each other or the player.

    This implemented by each NPC having two trigger colliders on them - one that's about their size, and a large one that defines their sight range. The player also has the small collider. This is set up with layers, such that the sight range colliders doesn't generate trigger messages when hitting each other.

    When we get a trigger enter message for these trigger-to-trigger messages, we add the npc (or player) from the trigger message to a list of things potentially in range. We then use additional raycasts against (non-trigger) colliders attached to the world geometry to check if the NPC actually can see each target.

    We could solve this by just doing distance checks, but it's a large world, and PhysX is very optimized, so we'd have to do quite a bit of work to get a custom distance check as fast as using PhysX trigger messages like this. Unity has previously recommended using trigger colliders for this kind of checks for this exact reason.

    We could also set the small collider on the NPC's to not be trigger colliders. But, as I said, we're moving them with a navmesh, and we don't need them to collide with things. In fact, if the NPC's could collide with things, those collisions would start fighting against the navigation system, which would be all kinds of bad.



    It might be that this can be solved by exposing some PhysX internals that's currently not exposed. Currently, what I have access to in Unity is a bunch of settings, as well as this:

    upload_2019-8-14_14-38-23.png

    There's nothing else that's exposed in the API; so it's a bit of a black box. None of the flags you mentioned upthread looks like anything I've ever seen.
     
  24. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,476
    I don't know why trigger checks exist (I don't actually have any), instead preferring to just do primitive or AABB overlap checks, I mean isn't that way more efficient? Not being negative, just genuinely interested in the answers for trigger to trigger too.

    It's not even a reliable thing with Physx since it'd likely skip it having no form of CCD.
     
  25. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    I'm guessing triggers is effecient if they have to happen every (fixed) frame anyway.

    If they happen as a part of the physics engine, then they can be resolved all in one big swoop, using all of the caching and culling and optimization goodness in the engine. Then, when they're done, all the information can be passed out in one go.

    If you're doing this a bunch of times from user scripts, then every one of those have to stop the world, pass info from C# to C++, create the same check in the physics engine (but now out-of-order, which probably rules out some optimizations), and then pass the info back.

    I'm super not sure about any of that, though, so I guess this is the time to actually write a performance comparison. I'll be back with that.
     
  26. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    Exactly, you can emulate this using scene queries (e.g. overlap checks).

    It's very hard to tell which approch is going to be better for performance.

    If you use regular triggers, you increase the amount of objects in the broadphase. Triggers, by nature, tend to overlap other objects a lot more than regular shapes (because they have no collision response repositioning them in an empty space). So that's a lot of potential "broadphase pollution", which in practice means the per-frame broadphase cost might increase.

    There are additional concerns with built-in triggers (i.e. PxShapeFlag::eTRIGGER_SHAPE) because they use a dedicated codepath that hasn't received as much attention over the years as the other codepaths for regular rigid bodies and/or scene queries. So the overlap checks used there are currently suboptimal. This is why emulating triggers using regular rigid bodies and the flags I mentioned sometimes gives you better performance than the built-in triggers. Plus, indeed, that way you get CCD working, and yes, trigger-trigger notifications.

    Now if you use scene queries instead, you remove all the triggers from the broadphase so that's a potential speedup there. On the other hand you need to run additional scene queries, which is a new cost you didn't have before. On the plus side, you can often run them from time to time instead of all the time (while triggers tend to stay in the broadphase the whole time). Whether scene queries will be faster is anybody's guess, it depends how many triggers you have, how large they are and how much they overlap regular shapes, etc, etc, etc.
     
    Last edited: Aug 15, 2019
  27. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    The settings in the linked page seem quite limited. There are a number of things there that really should be defined per shape, not per scene (e.g. the number of solver iterations: you often want to increase that for jointed objects, but not for e.g. debris).

    As for the missing flags, I'm afraid I can only suggest exposing them. Otherwise you're using PhysX with one hand tied in the back, and there are problems you won't be able to solve. Obviously if we did put something in the PhysX API, we had a reason to do so and thought it was useful.
     
  28. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    Here it is.
     
  29. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    I did a test, and tl;dr: doing Physics.OverlapSphere takes more than twice as long as having Trigger Colliders.

    Here's the test setup. Trigger-based script:
    Code (csharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class TriggerCheck : MonoBehaviour
    5. {
    6.     public List<Collider> colliders = new List<Collider>();
    7.  
    8.     private void OnTriggerEnter(Collider other)
    9.     {
    10.         colliders.Add(other);
    11.     }
    12.  
    13.     private void OnTriggerExit(Collider other)
    14.     {
    15.         colliders.Remove(other);
    16.     }
    17. }
    Overlap based script:
    Code (csharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class OverlapCheck : MonoBehaviour
    5. {
    6.     public float checkDistance;
    7.     public int overlapLayerMask;
    8.     public List<Collider> colliders = new List<Collider>();
    9.  
    10.     private static Collider[] overlapBuffer = new Collider[100];
    11.  
    12.     private void FixedUpdate()
    13.     {
    14.         int numHit = Physics.OverlapSphereNonAlloc(transform.position, checkDistance, overlapBuffer, overlapLayerMask);
    15.  
    16.         // This is faster than trying to remove the elements that are not hit anymore, and add the new elements. Much faster - I didn't even bother to wait for the first 100 frames to pass with the manual remove/add setup
    17.         colliders.Clear();
    18.         for (int i = 0; i < numHit; i++)
    19.         {
    20.             colliders.Add(overlapBuffer[i]);
    21.         }
    22.     }
    23. }
    They're all spawned and moved about by this script:
    Code (csharp):
    1.  
    2. using TMPro;
    3. using UnityEngine;
    4. using Random = UnityEngine.Random;
    5.  
    6. public class BenchmarkController : MonoBehaviour
    7. {
    8.     public int   numToSpawn             = 100;
    9.     public bool  useTriggers            = true;
    10.     public float worldSize              = 10f;
    11.     public float minSpeed               = 1f;
    12.     public float maxSpeed               = 5f;
    13.     public float checkRadius            = 3f;
    14.     public int   numFramesToAverageOver = 1000;
    15.  
    16.     public TMP_Text timeOutput;
    17.  
    18.     private Rigidbody[] spawnedRigidbodies;
    19.  
    20.     private float minFrameTime = Mathf.Infinity;
    21.     private float maxFrameTime = -Mathf.Infinity;
    22.     private float lastFrameTime;
    23.     private float avgFrameTime;
    24.  
    25.     private int     frameTimeIndex;
    26.     private float[] lastFrameTimes;
    27.     private int numFramesCounted;
    28.  
    29.     private void Start()
    30.     {
    31.         lastFrameTimes = new float[numFramesToAverageOver];
    32.         spawnedRigidbodies = new Rigidbody[numToSpawn];
    33.         for (int i = 0; i < numToSpawn; i++)
    34.         {
    35.             var position = new Vector3(Random.value * worldSize, Random.value * worldSize, Random.value * worldSize);
    36.             var instance = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    37.             instance.GetComponent<Collider>().isTrigger = true;
    38.             instance.layer = LayerMask.NameToLayer("Agent");
    39.             instance.transform.position = position;
    40.  
    41.             if (useTriggers)
    42.             {
    43.                 //Note that there's a sparse collision matrix in place - the only collision active is Agent/Vision Check.
    44.                 var checker = new GameObject();
    45.                 checker.layer = LayerMask.NameToLayer("Vision Check");
    46.                 checker.transform.parent = instance.transform;
    47.                 checker.transform.localPosition = Vector3.zero;
    48.                 checker.AddComponent<TriggerCheck>();
    49.                 var checkerCollider = checker.AddComponent<SphereCollider>();
    50.                 checkerCollider.radius = checkRadius;
    51.                 checkerCollider.isTrigger = true;
    52.             }
    53.             else
    54.             {
    55.                 var checker = instance.AddComponent<OverlapCheck>();
    56.                 checker.checkDistance = checkRadius;
    57.                 checker.overlapLayerMask = LayerMask.GetMask("Agent");
    58.             }
    59.  
    60.             var rb = instance.AddComponent<Rigidbody>();
    61.             rb.useGravity = false;
    62.             rb.velocity = Random.onUnitSphere * Random.Range(minSpeed, maxSpeed);
    63.  
    64.             spawnedRigidbodies[i] = rb;
    65.         }
    66.     }
    67.  
    68.     private void Update()
    69.     {
    70.         if (Time.frameCount < 100)
    71.             return; // Don't let start up times cause outliers.
    72.  
    73.         lastFrameTime = Time.deltaTime;
    74.         lastFrameTimes[frameTimeIndex++] = lastFrameTime;
    75.         numFramesCounted++;
    76.         if (frameTimeIndex >= lastFrameTimes.Length)
    77.             frameTimeIndex = 0;
    78.  
    79.         if (lastFrameTime < minFrameTime)
    80.             minFrameTime = lastFrameTime;
    81.         if (lastFrameTime > maxFrameTime)
    82.             maxFrameTime = lastFrameTime;
    83.  
    84.         var average = 0f;
    85.         var count = Mathf.Min(numFramesCounted, numFramesToAverageOver);
    86.         for (int i = 0; i < count; i++)
    87.             average += lastFrameTimes[i];
    88.  
    89.         average /= count;
    90.  
    91.         timeOutput.text =
    92.             $@"Frame time {lastFrameTime:F7} FPS: {(1f / lastFrameTime):F2}
    93. Avg (over {count} frames) {average:F7} FPS: {(1f / average):F2}
    94. Min: {minFrameTime:F7} FPS: {(1f / minFrameTime):F2}
    95. Max: {maxFrameTime:F7} FPS: {(1f / maxFrameTime):F2}
    96.  
    97. FrameCount: {Time.frameCount}";
    98.     }
    99.  
    100.     private void FixedUpdate()
    101.     {
    102.         foreach (var rb in spawnedRigidbodies)
    103.         {
    104.             var position = rb.position;
    105.             var velocity = rb.velocity;
    106.  
    107.             if ((position.x < 0 && velocity.x < 0) || (position.x > worldSize && velocity.x > 0))
    108.             {
    109.                 velocity.x = -velocity.x;
    110.                 rb.velocity = velocity;
    111.             }
    112.  
    113.             if ((position.y < 0 && velocity.y < 0) || (position.y > worldSize && velocity.y > 0))
    114.             {
    115.                 velocity.y = -velocity.y;
    116.                 rb.velocity = velocity;
    117.             }
    118.  
    119.             if ((position.z < 0 && velocity.z < 0) || (position.z > worldSize && velocity.z > 0))
    120.             {
    121.                 velocity.z = -velocity.z;
    122.                 rb.velocity = velocity;
    123.             }
    124.         }
    125.     }
    126. }
    127.  

    Here's the collision matrix:
    upload_2019-8-14_16-31-7.png

    When running with 1000 spheres with a world size of 20, the frame time with triggers end up at ~0.0195 (fps of 51.5), while using the overlap checks ends up at ~0.0390 (fps of 25.5).

    Edit: Doing overlap checks in a single manager script yields a frame time of ~0.032 (fps of 31), which shouldn't be surprising at all. But that's clunkier, and now you have to remember to register and deregister your agents, because in the real world they don't have a constant count. That adds a bunch of complexity. It's also still way worse than the triggers.


    This could probably be sped up massively by writing a DOD-based overlap sphere check manager using DOTS. Maybe it'd even be as fast as the trigger check script, which is 6 lines of code pluss braces. Dots code have more boilerplate than that per statement ;)

    Let's speed this up by not spending a bunch of time copying over to a list. If we imagine that we're speed-conscious and just keep an array-based buffer.

    Trigger version, using swapback:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class TriggerCheck : MonoBehaviour
    4. {
    5.     private const int MAX_NUM_COLLIDERS = 20;
    6.  
    7.     public int currentColliderCount;
    8.     public Collider[] colliderBuffer = new Collider[MAX_NUM_COLLIDERS];
    9.  
    10.     private void OnTriggerEnter(Collider other)
    11.     {
    12.         if (currentColliderCount == MAX_NUM_COLLIDERS)
    13.             return;
    14.         colliderBuffer[currentColliderCount++] = other;
    15.     }
    16.  
    17.     private void OnTriggerExit(Collider other)
    18.     {
    19.         for (int i = 0; i < currentColliderCount; i++)
    20.         {
    21.             if (colliderBuffer[i] == other)
    22.             {
    23.                 colliderBuffer[i] = colliderBuffer[currentColliderCount - 1];
    24.                 colliderBuffer[currentColliderCount - 1] = null;
    25.                 currentColliderCount--;
    26.             }
    27.         }
    28.     }
    29. }
    Overlap script, which literally just does the overlap sphere check and nothing else:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class OverlapCheck : MonoBehaviour
    4. {
    5.     private const int MAX_NUM_COLLIDERS = 20;
    6.  
    7.     public float checkDistance;
    8.     public int   overlapLayerMask;
    9.  
    10.     public int        currentColliderCount;
    11.     public Collider[] colliderBuffer = new Collider[MAX_NUM_COLLIDERS];
    12.  
    13.     private void FixedUpdate()
    14.     {
    15.         currentColliderCount = Physics.OverlapSphereNonAlloc(transform.position, checkDistance, colliderBuffer, overlapLayerMask);
    16.     }
    17. }
    This gives a ~108 fps for the trigger script. The overlap script consistently starts out at ~80 FPS before falling down to ~55 after a few seconds, I don't quite understand why.

    The point still stands - triggers is massively faster than doing manual overlap checks.
     
    Last edited: Aug 14, 2019
  30. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    For the overlaps it would be interesting to see where the time is spent (inside PhysX or in the glue code around).
     
  31. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    I'm going to guess that a large part of the extra cost of the overlaps is crossing the C#/c++ boundary. As far as i understand things, every overlap check has to be marshaled, and the result has to be marshaled back.

    The deep profiler looks like this:
    upload_2019-8-14_17-13-51.png

    If you want a profile of what's happening on the engine side, you'll have to ask @yant or someone else - I don't have source access to Unity.
     
  32. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    "The overlap script consistently starts out at ~80 FPS before falling down to ~55 after a few seconds, I don't quite understand why." => could it be something like garbage collection kicking in?

    I'm not sure I understand the profiling results correctly, it seems that 40% of the time is spent before even reaching the Unity C++ code? (i.e. not even PhysX). That seems like a huge amount of overhead yeah........
     
  33. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    Nope. The only gc pressure in the test project is writing the frame times to the screen, which takes 2.1KB a frame. That's not enough to cause the gc to kick in regularly enough to be visible in the averaged fps.

    What's happening is that the number of fixed timesteps increases. I should have spotted this - the overhead of the deep profiler causes the frame time to be long enough that several fixed timesteps is required per frame, which again slows down the frame time.

    The deep profiling results are not completely reliable, as it has a huge overhead, so I believe that spending 40% before getting out of C# land might be quite a bit harsher than reality.


    So I did some further digging, and it might be confirmation bias kicking in, but this is what it looks like for me:

    - When using the triggers, the time spent in physics is about 1/2 in PhysX, 1/3 in user scripts, and the rest in Unity syncing with PhysX (that's what I assume Unity's Physics.ProcessReports and Physics.UpdateBodies) does.

    The vast majority of PhysX work is happening in these methods
    PhysX.ScNPhaseCore.triggerInteractionWork (happens100-150 times for each timestep, takes most of the time)
    PhysX.BpSAP.updateWork
    PhysX.ScScene.processLostContact3
    PhysX.ScScene.postBroadPhaseCont

    Here's an example. I cut all the PhysX calls that take less than 0.01 ms.
    upload_2019-8-15_10-52-49.png

    Note that I could stop here, and you'd kinda already know why this is faster than doing manual overlap spheres. The amount of times triggerInteractionWork happens caps at 150 with 1000 agents - and that's a worst case. PhysX is being smart about these things. The overlap test happens 1000 times, every frame.

    This is also a very, very stupid test, because there's 1000 agents inside a 20x20x20 cube. In a real game, those agents are more spread out, causing fewer trigger interactions to happen.

    upload_2019-8-15_10-59-39.png

    - When using the overlap check script, PhysX is doing a lot less simulation work. That makes a bunch of sense - it's a scene with a ton of rigidbodies that doesn't have gravity and doesn't have colliders. At this point the PhysX simulation is being used as an incredibly over-engineered way of doing
    position += velocity * deltatime
    . PhysX time is down to 0.7 ms per fixed frame in deep profiling (which, again, slows everything down).

    Now all the time is being spent, as in my last post, in calling OverlapSphereNonAlloc 1000 times. Not only is there an enormous overhead for each call crossing the C#/C++ boundary.

    Now, you could argue that we should do stuff like a broad phase and some spatial partitioning and whatnot sending the overlap queries. I'd argue that PhysX is probably better at that than I am, by orders of magnitude.

    Edit:
    Now, it seems clear that the overlap tests are also much faster when the spheres are more spread out. Which makes sense, you're not throwing away all of your information about the physics scene between frames. It's still always slower than triggers.
     
  34. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
  35. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
  36. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    I couldn't post my answer without it being seen as spam (wtf) so here are screenshots instead.
     
  37. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    1,159
  38. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    I filed that case on behalf of Nvidia. Apparently, if you check the About dialogue, it shows the copyright notice from 2011, which is, of course, outdated. Now that this case is public, I see I should update it to reflect intent more clearly. Thanks for the heads up.
     
  39. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    1,159
    oh, so it's for the copyright message itself, yeah that makes more sense now :)
     
  40. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    290
    Sorry for the confusion, but hope it's payed off by the fun from reading the bug description ;-)
     
  41. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,224
    Yeah, the forums are a bit bad at handling bots - overly restrictive on users, while letting bots create a ton of threads.

    I don't think you're right, though. The problem with triggers vs. overlap checks is not on PhysX' side, it's on Unity's implementation side, and crossing. There's so much overhead involved in each single overlap check that increasing the numbers won't make much of a difference.

    Diagram for Trigger Checks, red lines are expensive crossings into the engine:
    Trigger.png
    Diagram for overlap checks:
    Overlap.png

    Overlap checks would probably be way faster than Triggers if we could could this:
    Desired.png
    Ie. bundle all of our calls to PhysX in a single call rather than having to do them one-by-one.

    I'm not sure if this is how the job system commands are implemented, or if they're still doing a ton of boundary crossings, just off the main thread. @yant, you seem to have been involved in jobifying the PhysX queries, could you share some insight?
    Also, I can't spot any OverlapSphereCommands, just SpherecastCommand. Am I blind, or have you not gotten around to implementing that yet?
     
  42. segant

    segant

    Joined:
    May 3, 2017
    Posts:
    83
    I get this error on android build [Physics.PhysX] BV4 midphase only supported on Intel platforms.
    and physics don't work.
     
  43. PierreTerdiman

    PierreTerdiman

    Joined:
    May 9, 2017
    Posts:
    14
    I guess the problem is obvious from the error message. You must use PxMeshMidPhase::eBVH33 on Android. There is a setting for this in PxCookingParams. If Unity hardcoded BVH34 on all platforms and doesn't let you override this setting, then this is a problem in Unity's PhysX wrapper.
     
  44. segant

    segant

    Joined:
    May 3, 2017
    Posts:
    83
    This version messed up all mechanics in my game. It can't detect thin mesh colliders which is under 200 polygons. Collision detection is worse than old system. Will this be fixed in 0a13 or future versions?
     
  45. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    1,159
    If you have issues, making a nice repro project for Unity is way more efficient than listing random issues on your specific project (it's not easy for Unity to test things based on what you said here).

    I'd guess that in ideal case, you'd make a minimal repro project on 2019.2 that will fail on 2019.3 and share that with Unity.
     
  46. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    4,981
    I couldn't care less if it's an "ugly hack" as long as it works reliably and doesn't grind performance to a halt. In past Unity versions the performance of it has been more than acceptable. Would it be any different if a workaround was built now?
    Removing this will break all my games ever made as well as the one we're working on, as well as all the example scenes in all the Asset Store plugins I sell.

    I think Unity will need to make OnTriggerEnter and other similar events still function, even if it's a less than desirable option. At the very least, If it won't be supported please don't even allow it to compile (or spam the Console at runtime telling them to remove OnTriggerEnter methods etc) so people don't spend a long time trying to figure out why (I don't read 10 page release notes and I'm sure a lot of others don't either).

    In general we don't use many gravity rigidbodys because they are a lot heavier on performance and generally not needed for most scenarios in our games.

    I would like to hear about ways to do the same things without using OnTriggerEnter so I can eventually stop using it if the workarounds are feasible. I didn't really understand what I read about that so far on page 1....

    Also, I agree entirely with everything Baste said further up the page.
     
    Last edited: Aug 29, 2019
  47. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    114
    Pretty crucial, my friend.

    Please support OnTriggerEnter and similar events so we don't have to foundationally rebuild every game and plugin we've ever made.
     
  48. DavidLieder

    DavidLieder

    Joined:
    Feb 14, 2016
    Posts:
    83
    Break essential features while pushing forward with hundreds of experimental projects. WTF.

    Please fix OnTriggerEnter and related events in 2019.x because I urgently need it. Not that the Unity company really cares about what I need... But still.
     
  49. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    311
    I definitely agreed that Trigger-to-Trigger collision event is key feature for game logic. Many developers used Unity for creating just a game, not real physics simulator. Trigger (does not interact with other objects) is used very often for implementing game-logic (range check, event placeholder, and all of non-realistic circumstances). I hope that Unity makes workaround for it, within 2019.x cycles.
     
  50. pinkhair

    pinkhair

    Joined:
    Dec 17, 2010
    Posts:
    129
    This really cuts to the heart of things. It feels like PhysX is chasing benchmarks that look impressive rather than features people actually use - especially in a game engine where trigger-on-trigger collisions don't have a good replacement out of the box.

    Is it more performant than having a million overlapspheres and boxes?