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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Add MeshCollider in AssetPostprocessor.OnPostrocessModel

Discussion in 'Scripting' started by Derakon, Jul 3, 2019.

  1. Derakon

    Derakon

    Joined:
    Jul 3, 2019
    Posts:
    20
    I'm working on setting up a workflow to get 3D models from Blender into Unity. I want to be able to define custom collider meshes in Blender as well -- these will be compositions of simple convex meshes that, once decomposed, can use MeshCollider. So the FBX file I export contains two meshes, and I'm using an AssetPostprocessor to identify the collision mesh, decompose it into its connected components, and create MeshColliders from those component meshes.

    What I'm finding though is that the MeshCollider has no mesh in it after the postprocessor runs. In the Inspector for the MeshCollider, the "Mesh" field says "None (Mesh)" instead of having an actual mesh.

    I've tried a simple dummy mesh, like this:

    Code (CSharp):
    1.     public void OnPostprocessModel(GameObject g) {
    2.         Mesh m = new Mesh();
    3.         var verts = new Vector3[4];
    4.         verts[0] = new Vector3(0, 0, 0);
    5.         verts[1] = new Vector3(1, 0, 0);
    6.         verts[2] = new Vector3(0, 0, 1);
    7.         verts[3] = new Vector3(.5f, 1, .5f);
    8.         var tris = new int[] { 0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3 };
    9.         m.vertices = verts;
    10.         m.triangles = tris;
    11.         foreach (Transform t in g.transform) {
    12.             var mc = t.gameObject.AddComponent<MeshCollider>();
    13.             mc.sharedMesh = m;
    14.             mc.convex = true;
    15.         }
    16.     }
    That gives the same results (i.e. a MeshCollider with no mesh) as my more complicated code. However, if I make a new MonoBehaviour, attach it to a GameObject, and copy that code into the Start function (and change "g" to "gameObject"), then I get a proper pyramidal MeshCollider. So I know that the code *should* work for producing a MeshCollider with a custom mesh. It just doesn't seem to work in AssetPostprocessor.OnPostprocessModel.

    Is this some limitation of AssetPostprocessors? Or is there something special I need to do to create a custom mesh for my MeshCollider?

    Thank you!
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    In Unity a reference is file guid + asset id in file. That's why in asses you may reference only assets. Similary you cant reference scene objects in prefabs. Create mesh asset and reference it.
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    You should get what @palex-nx is suggesting with a very simple modification. Stick this to the end of your OnPostProcessModel:

    Code (csharp):
    1. AssetDatabase.AddObjectToAsset(m, assetPath);
    I'd suggest giving the mesh a name as well, so you don't get an unnamed subasset in your model. You're also going to handle that OnPostProcessModel gets called if the model gets reimported, ie. every time you change it in blender, so you'll need to find and replace the old mesh instead of adding a new one if that's the case. But the code line above should get you started.
     
    palex-nx likes this.
  4. Derakon

    Derakon

    Joined:
    Jul 3, 2019
    Posts:
    20
    Aha, thank you very much! I can confirm that AddObjectToAsset does indeed allow the mesh to be referenced by the MeshCollider.
     
  5. Derakon

    Derakon

    Joined:
    Jul 3, 2019
    Posts:
    20
    For the sake of anyone else who might run into this issue, I've attached my implementation. The way this works is:

    * Add the attached file as an asset.
    * In Blender, make two meshes, one of which has the same name as the first except with ".collider" appended to its name. For example, mesh 1 is named "gun" and mesh 2 is named "gun.collider". Mesh 2 must consist solely of convex meshes with fewer than 255 triangles, otherwise Unity will be upset with you.
    * Select both meshes (and in my case an armature used to animate the gun) and export them as a single FBX file whose name must end in ".gun.fbx".
    * Import the FBX file as an asset.

    The imported asset will automatically get a set of convex MeshColliders based on the connected components in the second mesh. For example, if the second mesh consists of two cubes, then two MeshColliders will be created, one for each cube.

    I had to throw in a -90 rotation about X (line 36 of the file), which might be because of my armatures, so if you're not using armatures maybe you don't need that part.
     

    Attached Files:

  6. Derakon

    Derakon

    Joined:
    Jul 3, 2019
    Posts:
    20
    Well, this *was* working. I'm now getting this error when I try to import files:

    Failed to load <path to file> because it was serialized with a newer version of Unity. (Has a higher SerializedFile version)
    UnityEditor.AssetDatabase:AddObjectToAsset(Object, String)
    Autocollider:DeriveColliderAndUpdateAssetDB(String, GameObject, Mesh, Vector3) (at Assets/Scripts/Math/Autocollider.cs:91)
    ImportShip:OnPostprocessModel(GameObject) (at Assets/Scripts/ImportShip.cs:29)
    UnityEditor.AssetPostprocessingInternal:postprocessMesh(GameObject)

    As best I can recall, this started happening when I updated my Unity version to 2018.4 from 2017.something, which I did because I wanted better shader support. As far as I can tell, it's now impossible for me to invoke AddObjectToAsset; as a result, none of my objects have colliders, which is obviously problematic.

    All of the searching I've done points to people having trouble with Git LFS support. I'm pretty sure that doesn't apply to me though; while I have a git repository set up, I've only ever used it to push files to a private GitHub repo; I've never pulled nor reverted files.

    I've tried deleting and recreating assets, I've tried removing .meta files, I uninstalled the 2017 version just to make sure it wasn't somehow interfering. I can try re-installing it and opening the project with it, but I'm a little scared of breaking everything even more than it's already broken.

    Any ideas?

    EDIT: dangit, can't figure out how to remove the emojis from the error message. I'm sure y'all can figure it out though.
    EDIT2: created a new 2017.1 project, added my importer postprocessor and a model to it, and the postprocessor worked. Tried the same in a 2018.4 project, and the postprocessor gives the error message shown above. So I guess AssetDatabase broke somewhere in between those two versions. Is it possible for me to cleanly downgrade my project to 2017.1, or am I going to have to wipe and recreate it?
     
    Last edited: Jul 25, 2019
  7. Ogdy

    Ogdy

    Joined:
    Dec 26, 2014
    Posts:
    21
    Is there any news on this ? This function is still broken from Unity 2018 and until now. context.AddObjectToAsset does not work either.