Search Unity

How to update a mesh collider?

Discussion in 'Editor & General Support' started by rjarrier, Oct 20, 2009.

  1. rjarrier

    rjarrier

    Joined:
    Oct 20, 2009
    Posts:
    2
    Hello,

    I'm developing a video game student project.
    A feature consists to move a bridge like Tacoma bridge

    I move the mesh with bones, so the mesh moves correctly, but the mesh collider is not updated.
    My case : http://www.vimeo.com/7163412

    The bridges has a mesh collider and the cubes have got box colliders. The mesh collider of the bridge has got less than 255 faces.

    Do you know how I could do this?
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Hi - welcome to the forum!

    If you are using a boned animation created in a 3D application, the MeshCollider will not be updated as the animation plays, it will just stay in the initial position. However, you can update the collider if you are animating the mesh from a script with the Mesh API - you just need to assign the mesh to the sharedMesh property of the MeshCollider each frame.
     
  3. rjarrier

    rjarrier

    Joined:
    Oct 20, 2009
    Posts:
    2
    I tested to assign sharedMesh collider in Update:
    Code (csharp):
    1. function Update ()
    2. {
    3.     if(Input.GetButton ("Fire1"))
    4.     {
    5.         //init:
    6.         //get the bone
    7.         var bone2 = transform.Find("bone02");
    8.         //initial force
    9.         var upForce = Time.deltaTime * 10;
    10.         var rotForce = Time.deltaTime * 40;
    11.         //input
    12.         var inputH = Input.GetAxis("Horizontal2");
    13.         var inputV = Input.GetAxis("Vertical1");
    14.        
    15.         //move the bone
    16.         bone2.transform.Rotate(Vector3.right*inputH*rotForce);
    17.         bone2.transform.Rotate(Vector3.forward*inputV*upForce);
    18.     }
    19. }
    20.  
    21. function LateUpdate ()
    22. {
    23.     //update the mesh collider
    24.     var skinnedMeshRenderer = GetComponent (SkinnedMeshRenderer);
    25.     collider.sharedMesh = skinnedMeshRenderer.sharedMesh;
    26. }
    But nothing better, mesh collier is alway initial mesh pattern. Did I a mistake?
     
    hopetolive likes this.
  4. Bursar

    Bursar

    Joined:
    Oct 18, 2009
    Posts:
    50
    I'd be interested in the answer to this, as I don't understand why mesh colliders can't be updated. If I have a tank whose turret I want to rotate via a named bone, then it sounds like I need to manually deal with updating the mesh, or do away with it and use primitives instead.
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Mesh colliders need serious pre-processing to function, and are not suitable for updating in real-time. You can't get the updated mesh from a skinned mesh renderer for technical reasons that I forget exactly, but even if you could, it would still be very slow to compute the mesh collider. Something like a tank is trivial to do using primitive colliders, and that's definitely the way to go.

    --Eric
     
  6. pkamat

    pkamat

    Joined:
    Dec 13, 2009
    Posts:
    20
    not sure if you still on this. there seems to be some change with unity 3.0 Previously
    GetComponent<MeshCollider>().sharedMesh = meshFilter.mesh;

    would work but in unity3 u need to null the mesh before assigning a new one.

    GetComponent<MeshCollider>().sharedMesh = null;
    GetComponent<MeshCollider>().sharedMesh = meshFilter.mesh;
     
  7. shinriyo_twitter

    shinriyo_twitter

    Joined:
    Aug 12, 2011
    Posts:
    328
  8. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,790
    pkamat, thank you! I was pulling my hair out (and I don't have much left!)
     
    GHOST8476 likes this.
  9. greencindy

    greencindy

    Joined:
    May 10, 2012
    Posts:
    17
    Thank you so much!! I've been working on this for a whole day!
     
  10. karl_

    karl_

    Joined:
    Mar 4, 2010
    Posts:
    464
    Thanks for saving me a few hours of frustration!
     
  11. Deleted User

    Deleted User

    Guest


    Worked for me too!

    thanks
     
  12. b4cksp4ce

    b4cksp4ce

    Joined:
    Apr 13, 2011
    Posts:
    114
    Thanks you a lot. I lost a morning for that fix.

    It's solved it but it's kind of weird though to null the mesh before re-assigning it. :confused:
     
    RadeticTecgraf likes this.
  13. dogzerx2

    dogzerx2

    Joined:
    Dec 27, 2009
    Posts:
    3,967
    WOOHOO thanks!!! great tip!
     
  14. hitmax87

    hitmax87

    Joined:
    May 27, 2013
    Posts:
    12
    pkamat, thank you very much!
     
  15. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yep, I can confirm that this does indeed force the mesh collider to update...

    But I can also confirm that, in my case at least, the result really is too slow (as Eric5h5 predicted). I've got dynamic terrain sculpting, but I certainly can't call this on every frame while the terrain changes.

    Hmm, but maybe I don't need to... I may be able to call it only on mouse-up, at least for this particular case. Or, failing that, I'll have to walk the mesh myself, find the closest few vertices, and interpolate, but... ugh. That gets ugly fast.
     
  16. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    I know you posted this years but I didn't find anything else that answered my question and I hope you (or someone else who knows the answer) will still read this: If updating a MeshCollider is so costly, what alternatives and workarounds are there?

    In my case I'm working on a relatively simple "toon style" ocean (think Zelda:Wind Waker). I think I won't need very realistic and detailed wave forms so I'll try to go with just some sinus vertex deformations (probably with some perlin noise added on top) that I'll apply on a plane. But of course I'd also like to have the waves interacting with ships and such and I don't see how I'd do this without constantly updating the MeshCollider.

    Thank you very much for any pointers you can give me!

    Edit: I assume if the water isn't too stormy and sluggish enough it'd suffice to update the MeshCollider only every few frames but I'd still be quiet often i assume and hopefully there's a better way..
     
    Last edited: Dec 20, 2014
  17. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,790
    I think your best bet is to only calculate wave height where/when you need it, instead of calculating it across the entire mesh. It's frustrating that updating colliders is so slooooow, because it's the obvious and easiest way to do it. So for example with a boat object you need to build a function that will calculate the wave height at the boat's position, and then perform an offset to simulate buoyancy.

    This is what I do in Suimono, and it works really well, but I still wish I could have just used the original collider. It would have saved me months of work and frustration. I know Unity 5 has an improved physics system but I haven't tested if mesh collider updates work any faster.
     
  18. TonyT

    TonyT

    Joined:
    Mar 17, 2014
    Posts:
    20
    Thanks heaps ... I was soo stuck (still relevant with Unity 5)!
     
    RadeticTecgraf likes this.
  19. Sherasoft

    Sherasoft

    Joined:
    Nov 17, 2013
    Posts:
    8
    A small syntax error with all my respect:

    GetComponent<MeshCollider>().sharedMesh = null;
    GetComponent<MeshCollider>().sharedMesh = GetComponent<MeshFilter>().mesh;
     
  20. Mjbgtaad56

    Mjbgtaad56

    Joined:
    Aug 1, 2015
    Posts:
    4
    OMG THANKYOU!!!
     
  21. roryo

    roryo

    Joined:
    May 21, 2009
    Posts:
    1,479
    pkamat, this was REALLY helpful! Thanks!
     
  22. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,269
    I was wondering why I could not get a mesh collider to update and it was the same thing - set to null first.
    Surely this is a bug!
    I guess it checks if same mesh as before passed in but should check if the data within is same too...
     
  23. Deleted User

    Deleted User

    Guest

    Am on Unity 5.5 right now and I did not have to set it to null before (will do anyway just to be sure). Either way this is terribly cryptic.
     
  24. gransoporo

    gransoporo

    Joined:
    Oct 18, 2017
    Posts:
    4
    thanks a lot
    just it would be interesting to know this updating can or should be improved... is it a slow process? I would like to start and I have a basic idea using colliders, and I need to update frequently
     
  25. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    131
    Now it does not work in Unity 5.6.1. Any idea how to do this?
     
  26. surfcode

    surfcode

    Joined:
    Oct 10, 2018
    Posts:
    15
    trying to update the mesh collider, using Unity version 2017.4.15f1.
    the indicated scripting is not working for me, although my coding might be incorrect.

    i have imported a .fbx animated file from Blender, trying to animate the Mesh Collider by updating the shape in response to the changing shape of the object. The object (simple cube) was animated via shape keys in Blender.

    i tried writing this script and applying the script to the cube object in the hierarchy window.

    public class ObjectMeshToPhysicsSurface : MonoBehaviour {

    Mesh m;
    MeshCollider mc;
    MeshFilter mf;

    // Use this for initialization
    void Start () {

    Debug.Log ("Object mesh script is active.");

    mf = GetComponent<MeshFilter> ();

    m = mf.mesh;
    mc = GetComponent<MeshCollider> ();

    m.RecalculateBounds ();

    }

    // Update is called once per frame
    void Update () {

    m.RecalculateBounds ();
    mc.sharedMesh = null;
    mc.sharedMesh = m;


    }
    }
     
  27. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Shape keys? Is that like blend shapes?

    If so, then I don't think that'll work with a MeshCollider. You would have to use BakeMesh to get a snapshot of the current shape of the mesh, taking into account all the blend weights and bone positions, and then set that as the mesh collider mesh.

    Keep in mind that mesh colliders are very expensive and have some serious limitations — if you can get by with some combination of more primitive colliders, it's almost always better to do that.
     
    mcroswell and surfcode like this.
  28. surfcode

    surfcode

    Joined:
    Oct 10, 2018
    Posts:
    15
    Thank you, i must say cheers for mentioning BakeMesh, that is so directly applicable, used for getting a snapshot of a SkinnedMeshRenderer's mesh.

    if it were at all possible to update the shape of the MeshCollider.sharedMesh, using the Update() function to apply the current state of the object's mesh, then that would possibly be the most appropriate and desirably "accurate" solution. Hopefully BakeMesh is going to capture the information required. I should go try that now.

    the vertex count of the object required to update in a working version of this script would, at a guess, be somewhere between 300 - 500 vertices, with simple vertex colours applied to the faces.

    Not much else going on in the scene, one or two more objects that do not update their mesh colliders. So maybe it is possible. If the framerate maintains 30 per second or higher, that is acceptable.

    re/ simpler workarounds ... yes, currently working on a combination of more primitive colliders, and they might be somehow better for a couple of reasons.
     
  29. surfcode

    surfcode

    Joined:
    Oct 10, 2018
    Posts:
    15
    yes, blend shapes with morph targets.
    the resulting animated object (fbx) imports to Unity with an associated Skinned Mesh Renderer component.

    attached a MeshCollider and MeshFilter manually via Unity. Not sure if the MeshFilter is useful in this scenario.

    currently this code seems to apply the MeshCollider although does not update the MeshCollider shape (or maybe it is updating the mesh very slowly).


    public class ObjectMeshToPhysicsSurface : MonoBehaviour {

    public SkinnedMeshRenderer skinnedMeshRenderer;
    public Mesh bakedMesh;
    private MeshCollider meshCollider;

    private void Start() {

    skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer> ();
    meshCollider = GetComponent<MeshCollider> ();
    }

    private void FixedUpdate()
    {
    skinnedMeshRenderer.BakeMesh(bakedMesh);
    meshCollider.sharedMesh = bakedMesh;
    }
    }
     
    mcroswell likes this.
  30. unity_S5sbHsTF0N3uRA

    unity_S5sbHsTF0N3uRA

    Joined:
    May 31, 2021
    Posts:
    3
    upload_2021-6-12_11-41-58.png

    I tried many ways and this one worked for me

    neme "self" - is the object on which the mesh is being changed
     
  31. kumarsatyam17

    kumarsatyam17

    Joined:
    Jul 29, 2020
    Posts:
    3

    It works !! Thanks a Ton dude !!!!
     
  32. okadath

    okadath

    Joined:
    Jan 14, 2022
    Posts:
    2
    im new in unity,
    I never saw that editor, how do you do it and in what section or with what package?
     
  33. venom789

    venom789

    Joined:
    Apr 18, 2022
    Posts:
    178
    Visual scripting : Bolt
     
  34. Image3d

    Image3d

    Joined:
    Jun 20, 2008
    Posts:
    155
    Thanks...you saved my day...
     
    Last edited: Jan 22, 2024
  35. Image3d

    Image3d

    Joined:
    Jun 20, 2008
    Posts:
    155
    Hi do you have the equivalent Visual Scripting Graph to update for the Mesh Render?