I need a way of performing the same super accurate selection behavior that the Unity IDE exhibits when using the Scene view and clicking on any visible object.
This functionality is required for a non-gaming project, and the majority of the scene contents is generated from user data. 50k objects is realistic.
I have tried a few approaches. All involve ray casting from the screen click point:
1) For each generated object with a mesh, also add a MeshCollider. This is quite slow (takes 10 minutes when doing 50k), and for some reason the ray-casting quite often misses certain meshes (usually pipe like cylinders).
2) Use BoxColliders instead. This is faster to add, and never misses a raycast, but obviously causes a mis-match between the visible shape and the clickable area. This causes problems when trying to select objects behind other objects, but the box collider of the object in front is in the way.
But if I go into the Unity IDE Scene view after generating all these objects, selection works perfectly. The Unity IDE only has access to the same information as me (the meshes) so it must be possible.
So firstly, does anyone know what approach Unity takes for selection under the covers in the IDE? Secondly, and preferably, is there any way to access this via APIs so I don't have to redo work.
I'm thinking they use some triangle -> mesh map where every time a mesh is added, all the triangles it contains are added to some global map that points back to that mesh. Then the ray cast only has to find the first triangle intersected, and the map points to the containing mesh, and hence object. But that is an uneducated hunch and I'm not even sure searching for intersections between triangles and lines is efficient, or how to do it.
asked Nov 17 '11 at 05:06 AM
I don't know how Unity scene raycast works, but I suppose that this triangle approach can be too slow. I have a suggestion: use box colliders, but do a RaycastAll instead of a simple Raycast - this will return an array of RaycastHits containing all objects hit by the ray. Since the number of objects in this first selection is relatively small, for each RaycastHit in the array you could replace the object's box collider with a mesh collider and do a raycast from hit.point (use the same ray, but change the ray.origin); if the object hit's transform == hit.transform, this is the object clicked; if the transform is different, the actual body was not hit, thus repeat the procedure for the next RaycastHit.
answered Nov 17 '11 at 12:05 PM