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

Using MeshCollider without physics [SOLVED]

Discussion in 'Scripting' started by jogus84, Apr 13, 2017.

  1. jogus84

    jogus84

    Joined:
    Feb 8, 2015
    Posts:
    13
    Hi, I'm currently trying to implement hit detection for a tank game. Tanks are rigid bodies with a simple convex MeshCollider, however for hit detection, i.e. shot projectiles I need to perform mesh accurate hit detection. But simply adding a MeshCollider with a separate layer does not work since i get the following error:

    Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported in Unity 5.

    But I'm not trying to use this MeshCollider with the physics system, I only want to perform a second raycast (after my crude convex hull) to exactly determine if/where the projectile hit. Are there another collider class available that does not involve the physics system?

    Is there any way of achieving my goal without having to resort to hacks like creating another empty game-object with my mesh collider that I sync to the actual tank?

    How are people usually solving this kind of problems?
     
  2. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,695
    I had to add multiple box colliders to closer match my shape
     
  3. jogus84

    jogus84

    Joined:
    Feb 8, 2015
    Posts:
    13
    Thanks for the feedback francois85 but thats not an option for me since I would need thousands of boxes and I also need to support slanted surfaces.
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Why not just apply a kinematic rigidbody to it, like it's asking for? Since it's a child of your tank object, the collider will move with it no problem in Kinematic mode.
     
  5. jogus84

    jogus84

    Joined:
    Feb 8, 2015
    Posts:
    13
    I would prefer little to no overhead since each tank would need atleast 2 of theese colliders in average (turret + hull), so having to use 2 convex + 1 rigid body for the physics and then another 2 mesh + 2 rigid (kinematic) for the damage model seems like overkill.

    I only need to use these high-res colliders when a projectile hits so having them all update each frame + extra rigid bodies seems like a huge waste of processor resources.

    If I could simply keep some kind of reference to a mesh collider that is never instanced in the actual scene and simply transform my projectile hit data into that local frame of reference I would be set but I'm new to Unity and cant find the correct API / method for accomplishing this task.
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    How do you imagine you're going to transform that projectile hit data into the static context of the higher-detail collider mesh data? On hit detection of your lower-poly collider, you would then have to transform your referenced high-poly mesh data into the same rotation/space, then trigger your own programmed raycast through this referenced mesh data from the angle and point it hit on the lower-poly version... This would include having to iterate through all the vertices on the high-poly to triangulate a new hit-point.

    You should just model a detailed collider version of your meshes that lack any finer detailing that isn't important to your collision detection and simply use those as your raycast colliders on a sub-object with a kinematic rigidbody. Have the simplified physics collider on your active rigidbody be set to a layer that your projectile raycasts ignore by utilizing a LayerMask in the raycast operation.

    PhysX runs on a separate core (and is multi-threaded unlike the single-threaded nature your code would likely be and that Unity is for the most part), so if you did all those calculations manually you'd be doing it on the main Unity thread instead, and then you'd really be wasting performance.

    But if that's the approach you want to try, then what you want is still your own custom made meshes to import that will act as your offline colliders, and reference these with a Mesh variable.

    edit: To discuss this further, PhysX is already doing all of this for you. If a raycast comes within the bounding box of a mesh collider, it then does an intersection test on the actual mesh collider. It's not going to get much more efficient than that for you. It's only testing when a raycast is close enough, otherwise there is very little overhead from that kinematic rigidbody (especially if you make it a Trigger so it has no movement influence on other objects, you can still raycast against a trigger).
     
    Last edited: Apr 13, 2017
  7. jogus84

    jogus84

    Joined:
    Feb 8, 2015
    Posts:
    13
    Hi Invertex, thanks for the feedback!

    I figured instead of transforming the entire mesh data into the projectile space I would instead transform the projectile into the local mesh/collider space, should cost next to nothing but maybe I'm missing something?

    Yes, I really should model a "lower" detailed mesh but I lack the required skills for this so until I get the time and training the actual high-res 3D model will suffice. Since projectiles hit are very rare, the performance hit of issuing a 2nd raycast is not a problem atm.

    Here is the problem! Given a mesh reference, how can I issue a raycast against it without having a mesh collider? As a side note, I also require the UV coordinates of the hit since I'm using a armor thickness lookup from a secondary texture.

    Yeah I agree, my "concern" is the object and complexity bloat with all additional colliders and rigid bodies that will be processed every frame when they are ONLY ever needed whenever a projectile hits. Maybe I'm over-estimating this cost and the overhead is actually very low as you state.

    Thanks for the great input, until I find a way of actually testing my first idea I will implement what you propose.
     
  8. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    You can't. Raycast is a function of PhysX (or Box2D if 2D colliders). For you to be able to use the Raycast function against something, that thing needs to be running inside of the PhysX engine, it needs to be active in the scene. Something sitting as a mere reference is not known to PhysX, it's just data sitting in your memory (assuming it's even loaded into the scene).

    You could have the meshcollider instantiated in scene and merely disabled until you need to use it, so that the data is at least loaded into the PhysX engine and referable. But, then you may as well just do as I mentioned, make a sub-object with the Kinematic rigidbody, but simply disable it until needed.

    As I mentioned, PhysX is literally already going to do for you what you're trying to do manually here, and will do it much faster than your code will. Moving around a collider isn't much worse than moving around any ol' mesh. It's only when its bounds interact with something does any serious processing happen.
     
  9. jogus84

    jogus84

    Joined:
    Feb 8, 2015
    Posts:
    13
    Ok, fair enough, I was hoping unity provided a similar API for picking against meshes without any PhysX involvement at all. You have convinced me and I thank you for your great help.
     
  10. stanzy

    stanzy

    Joined:
    Dec 12, 2016
    Posts:
    17
    Hi, how about using the NonConvexMeshCollider script. That should solve your problem.
    You can use it to automatically generate a compound collider made of boxes for your mesh. You can configure the accuracy (=nr of boxes) to match your need.
    Disclaimer: I am the author of this script. Don't want to spam, but really believe it might help.