- Home /
A script that auto generated the box collider around a 3d model
Hi there, as mention on the title i really need some help/advice on how can i go about doing it. I have a 3DS Max 2009 model that is a .fbx being import into Unity3D. I hope to create a script which can auto create the box collider that will have the model place inside the box collider after the model is being import into Unity3D.
Please help me on this. Thanks. :)
Below is a example of what i am trying to do but throught a script automatically:
http://active.tutsplus.com/tutorials/unity/getting-started-with-unity-colliders-unityscript/
Thanks you guys for all the help/advice. I have updated my question with an example. Hope u guys can advice more on how i can go about achieve it. :)
Answer by Bunny83 · Sep 26, 2011 at 11:56 PM
Well, it depends on how exactly the box collider should fit the model. If it's sufficient when it matches the AABB of the model it's quite easy.
Just create an AssetPostProcessor and attach a BoxCollider. I would do it like this:
using UnityEngine;
using UnityEditor;
//C#
class AddBoxColliderPostProcessor : AssetPostprocessor
{
void OnPostprocessModel (GameObject g)
{
if (!assetPath.Contains("model")) // Just a simple restriction to only process models that contains the word "model" in it's path
return; // without a check it will do the following with every imported asset!
Renderer[] allRenderers = g.GetComponentsInChildren<Renderer>();
foreach(Renderer R in allRenderers)
{
R.gameObject.AddComponent<BoxCollider>();
}
}
}
Unity automatically resizes the BoxCollider to match the bounds of the attached Renderer (if there is one). You can also set the center and size manually (but it should give you the same result):
foreach(Renderer R in allRenderers)
{
BoxCollider BC = R.gameObject.AddComponent<BoxCollider>();
BC.center = R.bounds.center;
BC.size = R.bounds.size;
}
I've tested it on a simple model and it works as expected ;)
If you want you can do much more in the postprocessor. Adding scripts adding child objects, whatever... but keep in mind all AssetPostProcessors are executed for every imported model. You need some clever selection-condition. The easiest thing you can do is place the models that should get a BoxCollider in a seperate folder / subfolder that is called "AddBoxCollider" and check the asset-path:
if (!assetPath.Contains("AddBoxCollider"))
return;
It's not very nice to spread your assets like this since it's much harder to find something, but it's a way ;). Instead of using a folder you can rename your asset and include some kind of keyword in the name.
Ohh and don't forget that you have to reimport the asset ;) And if you dragged the model already into the scene you may have to press "revert" (to prefab) at the top in the inspector
Can this be done with a script that is applied to models without post possessing? I am writing code that adds labels to models when you hover your mouse over the mesh. Currently I have to add a box collider to each mesh and in many cases i have to add a $$anonymous$$esh renderer and a box collider then scale the box to fit all the children mesh parts. I would like to make the script create a box around the children,scaled and centered to the AABB of the selected mesh parts. This is simply to save time in applying 1 script to 80 plus models rather then applying colliders and the script over and over and over again. I have been looking into this for days and have not found a way to wrap my head around the code. (I'm new to program$$anonymous$$g) I have looked at bounds and gameObject.component documentation and many forum posts but Bunny 83's answer seems to be the closest to what I need.
Also I am adding this question here rather then creating a new question because I don't want to clutter the forum and because this question doesn't seem to be marked as having been official answered. If I should post this as a new question let me know and i will do so ASAP.
Thanks
@Giantbean: No, it's ok asking for more details on the same issue here ;).
I never was in need of this myself, but afaik when you use AddComponent to add a box collider to a gameobject which already has a $$anonymous$$eshRenderer it should resize the box automatically.
If not, my second piece of code should work as well. So yes, you should be able to do this at runtime.
I got it working with this:
gameObject.AddComponent < BoxCollider >();
BoxCollider collider = (BoxCollider)gameObject.collider;
Bounds bounds = new Bounds(Vector3.zero, Vector3.zero);
$$anonymous$$eshFilter[] filters = gameObject.GetComponentsInChildren();
foreach($$anonymous$$eshFilter f in filters) {
bounds.Encapsulate(f.shared$$anonymous$$esh.bounds);
bounds.center = Vector3.zero;
}
collider.size = bounds.size;
collider.center = bounds.center;
}
I'm Adding the script to a parent with multiple child objects and want the box to encompass the entire model set. So far its doing exactly what I need and fitting nicely to single mesh objects as well as multi mesh objects. I also tried without zeroing the bounds center and it was usually slightly off. (I may have had the pivot set to high when I imported the model from $$anonymous$$aya)
Anyways Its working so far. Thanks Bunny83
@Giantbean: Yes, sure, if you have multiple meshes you have to merge the bounds. However initializing the bounds with zero, zero will probably work with most meshes, but there are cases where the pivot is outside the mesh bounds and then it would give you the wrong result.
Also why do you reset the bounds center to zero? This could create some really strange sizes depending on the position / size of the sub-meshes.
Btw when you insert a space before and after the generic parmeter it should display correctly:
BoxCollider collider = gameObject.AddComponent< BoxCollider >();
ps: you can edit your comment as well ;)
Answer by yeoldesnake 1 · Sep 26, 2011 at 11:36 AM
When you attach a box collider on a mesh , it is automatically scaled to fit the model. At least it did with my models.
Same here, I have an animation on a mesh, the box collider automatically adjusts to the new size on the mesh. Thumbs+
Answer by LeEHil · Apr 13 at 12:02 PM
I assume that you want to create a box collider that can include multiple objects? Otherwise adding a box collider component to your object would already do the trick.
So in order to do so - as @Giantbean already pointed out - the optimal solution would be to use the MeshFilters to get the bounds of all child objects and unite them to one bound encapsulating the whole thing. If you simply add a box collider to the parent object which in most cases appears to have no mesh itself you will get a box that has the size Vector3(1,1,1) and is placed at the pivot of this object. Here is how you'd do it:
using UnityEngine;
using UnityEditor;
class AddBoxColliderPostProcessor : AssetPostprocessor
{
void OnPostprocessModel(GameObject gameObject)
{
MeshFilter[] childFilters = gameObject.GetComponentsInChildren<MeshFilter>();
if (childFilters.Length != 0)
{
Bounds bounds = childFilters[0].sharedMesh.bounds;
foreach (MeshFilter filter in childFilters) bounds.Encapsulate(filter.sharedMesh.bounds);
gameObject.GetComponent<BoxCollider>().center = bounds.center;
gameObject.GetComponent<BoxCollider>().size = bounds.size;
}
}
}
You could also combine the bounds of all the Renderers of your children. But that would cause problems if for whatever reason your objects are not at the very center of your scene or are rotated in world space. To correct that you would use:
gameObject.GetComponent<BoxCollider>().center = gameObject.transform.InverseTransformPoint(bounds.center);
gameObject.GetComponent<BoxCollider>().size = gameObject.transform.InverseTransformVector(bounds.size);
But this will only work if your object is rotated by 90deg steps, because the renderer will always use the worlds x-,y- and z-direction. So as mentioned in the beginning the MeshFilter is the way here.
Your answer
Follow this Question
Related Questions
Why is it so fast to move objects with collider collisions? 1 Answer
Collider Displacement Issue 0 Answers
How can I change animation with colliders? Using AR and Vuforia. 0 Answers
OnCollisionEnter2D is not working 0 Answers
npc collider 1 Answer