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:
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.
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:
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.