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

Question Physics.BakeMesh question

Discussion in '2019.3 Beta' started by Peter77, Sep 7, 2019.

  1. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    577
  2. Andreas88

    Andreas88

    Joined:
    Dec 22, 2015
    Posts:
    67
    hi there. thought i would pop in here, i have been following this thread for a while. i´m trying to use the Bakemesh with the jobsystem, but i´m having some issues with the baking happening in the main thread.After i upgraded to the newest unity version 2019.10 i hoped it solved my problem. Nope, i´m still baking in the main thread.

    out of curiosity, i made a test with the code from the docs.
    it seems like it´s baking on one of the other threads, but for some reason i can´t debug it in the profiler. nothing shows up there.
    if i change the code to be running on start method or awake instead of Onenable, it starts baking on the main thread again.
    Does anyone have any ideas what is happening ?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Collections;
    4. using Unity.Jobs;
    5. using UnityEngine;
    6. using Debug = UnityEngine.Debug;
    7. using System.Diagnostics;
    8.  
    9.  
    10. public class jobtest : MonoBehaviour
    11. {
    12.     public Mesh[] meshes;
    13.     public int meshesPerJob = 10;
    14.     public GameObject hex;
    15.     // Bake all the Meshes off of the main thread, and then instantiate on the main thread.
    16.  
    17.     private void Awake()
    18.     {
    19.      // insert code here and it will run on main thread
    20.     }
    21.  
    22.     private void Start()
    23.     {
    24.      // insert code here and it will run on main thread
    25.     }
    26.  
    27.     private void OnEnable()
    28.     {
    29.  
    30.         Stopwatch timer = new Stopwatch();
    31.         timer.Start();
    32.  
    33.         NativeArray<int> meshIds = new NativeArray<int>(meshes.Length, Allocator.TempJob);
    34.  
    35.         for (int i = 0; i < meshes.Length; ++i)
    36.         {
    37.             meshIds[i] = meshes[i].GetInstanceID();
    38.         }
    39.  
    40.         // This spreads the expensive operation over all cores.
    41.         var job = new BakeJob(meshIds);
    42.         job.Schedule(meshIds.Length, meshesPerJob).Complete();
    43.  
    44.         meshIds.Dispose();
    45.  
    46.         // Now instantiate colliders on the main thread.
    47.         for (int i = 0; i < meshes.Length; ++i)
    48.         {
    49.             hex.AddComponent<MeshCollider>().sharedMesh = meshes[i];
    50.         }
    51.         timer.Stop();
    52.         Debug.Log(timer.ElapsedMilliseconds + " milliseconds");
    53.     }
    54.  
    55.     public struct BakeJob : IJobParallelFor
    56.     {
    57.         private NativeArray<int> meshIds;
    58.  
    59.         public BakeJob(NativeArray<int> meshIds)
    60.         {
    61.             this.meshIds = meshIds;
    62.         }
    63.  
    64.         public void Execute(int index)
    65.         {
    66.             Physics.BakeMesh(meshIds[index], false);
    67.         }
    68.     }
    69. }
    70.  
     
  3. coidevoid

    coidevoid

    Joined:
    Oct 26, 2017
    Posts:
    55
    Yes it's on windows, I don't understand the exemple provided on the documentation was never tested or we are just really unlucky that it's doesn't work on our machines ?

    (Btw yes it's the same error that you linked)
    Is there any work around ? Maybe using a more traditional way to multi-thread the baking ?

    Thanks :)
     
    Last edited: Apr 17, 2020
  4. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    612
    I use vanilla C# Threading without error:

    Check the pattern in the "KeyCode.Alpha3"-branch
    https://forum.unity.com/threads/physics-bakemesh-question.741257/#post-5545537
    how it works:
    - i start a thread doing BakeMeshCollider_Threaded
    - for callback, BakeMeshCollider_Threaded enqueues something into a queue of the main thread when it has finished
    - During Update(), i check that queue for new entries and handle the mesh assignment
    (the normal callback handling in C# is done with Control.BeginInvoke afaik, but i never used that)​


    Now i also want to recalculate normals in another thread.
    But testing without threading shows that somehow using
    Vector3.Normalize(Vector3.Cross(v1 - v0, v2 - v0))
    is way slower than what unity does in mesh.RecalculateNormals().
    Is anyone enlightened about that? Is there some optimization available?
     
    Last edited: Apr 18, 2020
    coidevoid likes this.
  5. coidevoid

    coidevoid

    Joined:
    Oct 26, 2017
    Posts:
    55
    I would say implement your own ReculateNormalJob and use the math class for your code to be compatible with the burst compiler

    Code (CSharp):
    1.    
    2. [BurstCompile]
    3. RecalculateNormalJob : IJob
    4. {
    5.  
    6. void Cross(float3 lhs, float3 rhs )
    7. {
    8.   return new float3(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
    9. }
    10.  
    11. void Execute()
    12. {
    13. // your job
    14. }
    15.  
    16. }
    17.  
    18.  
    Btw I'm gonna try using the Classic C# Threading thanks
     
    Marrt likes this.
  6. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    So if you search for jobtest.OnEnable in hierarchy view and scrub over the frames, can you find a frame with that sample in it?
    Staying on that frame and switch to Timeline view, can you find the sample there?
    If you frame that sample (select it or draw up a time span and press f) and go through all threads, is there anything executing in parallel and is that not BakeJob.Execute?
    (BTW, in 2020.1 you can use the three-dots More Items menu of timeline view to toggle on flow visualization, that might help find these more easily.)
    Also, do you have more than 10 meshes to bake? Because if not, you'll only start one job and immediately ask it to Complete so the main thread is very likely to be executing it itself.
     
  7. Andreas88

    Andreas88

    Joined:
    Dec 22, 2015
    Posts:
    67
    Hi, thanks for helping me out :)
    i tried your suggestion, i can find the jobtest on the frame. But if i look at the job threads, nothing is going on. But the weird thing is that it actually does the job and assign a new collider mesh.
    I am actually just baking one big mesh, around 67 k verts.

    the confusing part is, if i toggle the script on and off manually nothing much happens in the main thread. However, if i make a script calling the enable method of my jobtest script, it does run on the main thread and i can clearly see it in the timeline.
     
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    In this case, you'll want to take out the
    .Complete()
    call and store the job handle returned by the
    Schedule()
    call in a class variable and only request it to Complete 1 or 2 frames later, depending on when you need it. Otherwise you're not benefiting from moving it off the main thread, because you aren't moving it of the main thread. If you had 2 meshes and would set the meshesPerJob = 1 and still call Complete immediately, you'd get two jobs and one would very likely get pulled onto the main thread (it should show up as a subsample of the jobtest.OnEnable sample in the Profiler) and the other would likely end up on a job thread. But if it's only one job, you'd need to give the JobSystem a chance to execute it asynchronously to the main thread and not demand it to be done immediately ;)

    Not exactly sure why toggling the script doesn't trigger the OneEnable and therefore the job execution though.
     
  9. Andreas88

    Andreas88

    Joined:
    Dec 22, 2015
    Posts:
    67
    Hi thank you for clearing that out.
    maybe i should have explained my goal a little better.
    the solution to wait a fraime or two to give the jobsystem time to process won´t work for me, because i need it to be done baking in the same frame.

    to clarify what i really need this for.
    i´m doing some Fog of War stuff. to reveal the map, i just shoot a ray onto a polygon mesh that has a hexagonal pattern. when the ray hits the surface it removes the first set of triangles. this operation is done twice to get all the triangles on the hex mesh. However after the first set of triangles has been removed, i need to update the collision mesh in order to get the correct triangle index.

    Right now it takes roughly 35 ms to remove the part of the mesh i need, including the collision baking.
    i know the method i use to remove triangles seem inefficient but i have never really dealt with triangles before. and my math knowledge is not very good.

    hope my explanation makes sense.
     
  10. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    @Andreas88 sounds like the wrong approach to the problem. I'd check out these excellent resources on hexagonal grid math and solve this purely mathematically, not with physics. That is, calculate the hex field to uncover by checking if the point would be in the field. There's functions described there to just find a hex grid tile from an x,y position.
     
  11. Andreas88

    Andreas88

    Joined:
    Dec 22, 2015
    Posts:
    67
    funny, i have been looking at the exact same site for weeks. I do have a hex field and using cube coordinates to find my hexes. i was hoping i could avoid using any math, that´s why i was using ray casting ;)
    thanks for pointing me in the right direction.
     
  12. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    Well, it is quite excellent xD

    I mean it's an approach but as you noticed, there's quite some overhead, e.g. by changing the one big physics mesh. You could break it into smaller parts but then, you still wouldn't gain anything from jobifying it because you'd still just change one mesh at a time. But at least renaming it could be faster. Im certain it might come with other drawbags so... Yeah. Wouldn't be my approach.
     
  13. Andreas88

    Andreas88

    Joined:
    Dec 22, 2015
    Posts:
    67
    Yeah i had thought about breaking it into smaller pieces, but as you mentioned i might not gain much from jobify it. I might as well improve my skills and learn the right way to do this.
     
  14. TheJavierD

    TheJavierD

    Joined:
    Jan 6, 2017
    Posts:
    50
    [Physics.PhysX] Foundation: Invalid deregistration detected happens a lot still with 2019.3.10

    When you try to close Unity after that error happens, it crashes with this:
    GetManagerFromContext: pointer to object of manager 'PhysicsManager' is NULL (table index 9)
     
  15. coidevoid

    coidevoid

    Joined:
    Oct 26, 2017
    Posts:
    55
  16. Andresmonte

    Andresmonte

    Joined:
    Nov 22, 2014
    Posts:
    37
    any work around this error?

    Edit:C# Threading produce this error as well, there is no work around...
     
    Last edited: Apr 29, 2020
  17. Dinamytes

    Dinamytes

    Joined:
    Nov 3, 2016
    Posts:
    51
    After entering Playmode some times:

    Code (CSharp):
    1. [Physics.PhysX] Foundation: Invalid deregistration detected.
    2. UnityEditor.SceneView:OnDisable()
    3.  
    4. [Physics.PhysX] Foundation: Invalid registration detected.
    5. UnityEditor.SceneView:OnEnable()
    6.  
    7. [Physics.PhysX] Foundation: Invalid deregistration detected.
    8. [Physics.PhysX] Foundation: Invalid registration detected.
     
    Andresmonte likes this.
  18. Amandin-E

    Amandin-E

    Joined:
    Feb 4, 2015
    Posts:
    451
    Hi there!

    I reproduce it with 2020.2.0a10.

    For me, the message "[Physics.PhysX] Foundation: Invalid registration detected" first shows up after I quit play mode (I think Physics.BakeMesh doesn't like to be interrupted).

    Once it has happened, the message will show up tons of times as soon as play mode is active.

    The only way to get back to normal is to close Unity, which causes the crash described in this bug report.

    So there are actually 3 issues:
    1. the message should just never show up, even when we exit play mode
    2. if for any reason it shows up, it should be safely restored to a working state so we don't need to close Unity
    3. when we close Unity, it should not crash

    Hope this can help!
     
    Andresmonte likes this.
  19. bugshake

    bugshake

    Joined:
    Oct 4, 2012
    Posts:
    7
    I've also been struggling with this in the procedural voxel world I"m working on. It's clearly related to how much baking work is being done at the same time.

    This was not easy to reproduce in an isolated scene!

    I managed to reproduce it in 2019.3.4f1.

    It only happens when generating colliders for 'ugly' meshes and only when at least two bake jobs are running concurrently.

    To reproduce: create a new scene, add the attached script to a GameObject, and run.

    Eventually you will get the PhysX errors mentioned above. You will also have to restart the editor to get rid of them and it will also crash when you exit Unity.

    I hope this also helps!

    edit: This happens in the exact same way in the latest 2020 alpha 2020.2.0a10.1205
     

    Attached Files:

    Last edited: May 12, 2020
    Andresmonte and Amandin-E like this.
  20. Amandin-E

    Amandin-E

    Joined:
    Feb 4, 2015
    Posts:
    451
    I reproduce it as well after some time. It works well and after a few minutes, errors start appearing. What's surprising is that except the error message, everything works fine and my colliders respond well (I dropped a sphere with a rigid body and it reacts well with the meshes).
     
    coidevoid likes this.
  21. Amandin-E

    Amandin-E

    Joined:
    Feb 4, 2015
    Posts:
    451
    @MartinTilo @yant Hi! Do you want/need us to create a new bug report about "[Physics.PhysX] Foundation: Invalid registration detected" / "[Physics.PhysX] Foundation: Invalid deregistration detected" error messages? (I'm not talking about Unity crashing when we close it, but about the errors themselves).

    Please let us know, and thanks for the amazing work. The Physics.BakeMesh method is a game changer for procedural generation in Unity :)
     
    coidevoid likes this.
  22. beatdesign

    beatdesign

    Joined:
    Apr 3, 2015
    Posts:
    137
    Very confused about this one.
    Following the example in the doc page:

    If I use
    Physics.BakeMesh(m.GetInstanceID(), true);
    in my Update, I see Mesh.Bake PhysiX Collision Data task in profiler. And that is expected to show.

    After this, if I call in FixedUpdate:
    mc = gameObject.AddComponent<MeshCollider>();
    mc.sharedMesh = m;


    I see again Mesh.Bake PhysiX Collision Data task in profiler. This shouldn't appear, because the collision data for the mesh m should already be computed. Why this happen?
    Using Unity 2020.1.9f1
     
  23. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    577
    Could you check that all of the settings in your MeshCollider instance are exactly the default ones? Physics.BakeMesh() cooks with the default settings only, so .sharedMesh will be able to reuse data only in that case.
     
    TheGameNewBie and beatdesign like this.
  24. beatdesign

    beatdesign

    Joined:
    Apr 3, 2015
    Posts:
    137
    Thank you for your reply yant.
    After calling BakeMesh(), when I add the MeshCollider components, it has the cooking settings that you can see in the attached image turned on.
    Are they the default ones?
     

    Attached Files:

  25. TheGameNewBie

    TheGameNewBie

    Joined:
    Jul 27, 2017
    Posts:
    92
    That worked! Thanks.
    I was setting the Mesh Collider settings to 'None' in the code. And it was baking twice due to that.

    Yes.
     
  26. beatdesign

    beatdesign

    Joined:
    Apr 3, 2015
    Posts:
    137
    Then, if these are the default settings, this is not working for me. May I ask you to list the steps you did to confirm that bakeMesh() is working?
     
  27. TheGameNewBie

    TheGameNewBie

    Joined:
    Jul 27, 2017
    Posts:
    92
    As I Said, before I was setting the MeshCollider options to 'None'
    chunkMeshCollider.cookingOptions = MeshColliderCookingOptions.None;


    The profiler :
    Profiler Mesh Baking.PNG .

    After Changing the code to this,
    chunkMeshCollider.cookingOptions = MeshColliderCookingOptions.CookForFasterSimulation | MeshColliderCookingOptions.EnableMeshCleaning | MeshColliderCookingOptions.UseFastMidphase | MeshColliderCookingOptions.WeldColocatedVertices;


    It was working as Intended
    Profiler Mesh Fixed.PNG
     
    Just_Lukas likes this.
  28. Aka_ToolBuddy

    Aka_ToolBuddy

    Joined:
    Feb 25, 2014
    Posts:
    525
    Marrt and yant like this.
  29. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,049
    Is there anyway we could specify cooking option with this api?

    It should just have API
    Physics.BakeMesh(int id,CookingOptions options)
    and so we could specified the option from collider and send to baker along with the mesh id into the job, making it more flexible and avoiding the error in the same time
     
    rcrsnt likes this.
  30. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    577
    I agree about this. Just a matter of other priorities, hope it's understandable. Will bump it up per your request.
     
    rcrsnt and Thaina like this.
  31. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    577
    Just a heads up that cooking options were added to Physics.BakeMesh in 2022.1.0a14.
     
    TerraUnity, joshcamas, Thaina and 2 others like this.
  32. Carpet_Head

    Carpet_Head

    Joined:
    Nov 27, 2014
    Posts:
    254
    how should we use it? do we need to make sure the MeshCollider has identical options?
     
  33. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    577
    Yes, the cooking options have to match.
     
  34. Aka_ToolBuddy

    Aka_ToolBuddy

    Joined:
    Feb 25, 2014
    Posts:
    525
    Hi @yant
    I tried integrating this change in my codebase, but encountred weird behaviour: the mesh baking happens too often.

    In my code, my goal is to bake meshes in parallel, and then assign them to colliders I instantiate. In the code bellow, for simplicity, I work only with one collider, and no parallelization.

    In the steps above, Physics ends up baking either twice or thrice every mesh, depending on the order of execution. My goal is to have each mesh baked only once.

    This version of the code does 3 bakes:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class MeshBakingTest : MonoBehaviour
    5. {
    6.     void Update()
    7.     {
    8.         //non default cooking options
    9.         MeshColliderCookingOptions cookingOptions = MeshColliderCookingOptions.UseFastMidphase;
    10.  
    11.         //the GO has a Mesh Filter with a valid Mesh assigned to it
    12.         Mesh sharedMesh = GetComponent<MeshFilter>().sharedMesh;
    13.  
    14.         Physics.BakeMesh(sharedMesh.GetInstanceID(), false, cookingOptions); //first bake
    15.  
    16.         MeshCollider meshCollider = gameObject.AddComponent<MeshCollider>(); //second bake
    17.         //at this point, meshCollider has the default cooking options
    18.  
    19.         meshCollider.cookingOptions = cookingOptions;//third bake
    20.  
    21.         Destroy(meshCollider);
    22.     }
    23. }
    24.  
    this one only 2:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class MeshBakingTest : MonoBehaviour
    4. {
    5.     void Update()
    6.     {
    7.         //non default cooking options
    8.         MeshColliderCookingOptions cookingOptions = MeshColliderCookingOptions.UseFastMidphase;
    9.  
    10.         //the GO has a Mesh Filter with a valid Mesh assigned to it
    11.         Mesh sharedMesh = GetComponent<MeshFilter>().sharedMesh;
    12.  
    13.         MeshCollider meshCollider = gameObject.AddComponent<MeshCollider>(); //first bake
    14.         //at this point, meshCollider has the default cooking options
    15.  
    16.         Physics.BakeMesh(sharedMesh.GetInstanceID(), false, cookingOptions); //second bake
    17.  
    18.         meshCollider.cookingOptions = cookingOptions;
    19.  
    20.         Destroy(meshCollider);
    21.     }
    22. }
    23.  
    Tests done with Unity 2022.1.20f1. I attached the reproduction code/scene.

    Am I doing something wrong?
    Thanks
     

    Attached Files: