0
\$\begingroup\$

I have objects that have multiple materials imported from blender as a .FBX.

I'd like to find the objects where materials are used, and destroy faces when a certain material name is used ("!null", in my case).

I know this is not the correct way to work. Normally I should delete the faces in Blender, but as I am building quite complex geometry using faces that I need in Blender but don't want the Unity engine to render, it seems the only way to go.

I tried "cutout", but although they are invisible, it does not make any difference in rendering times.

Is this at all possible? If it is, how do I do it?

\$\endgroup\$
2
  • \$\begingroup\$ can't you just find the models that use your specific material and disable the corresponding game object in the hierarchy? \$\endgroup\$
    – nyro_0
    Aug 22, 2016 at 12:48
  • \$\begingroup\$ no, my models use more than one Material often shared by multiple objects. I need to find all faces using a material and just destroy those. \$\endgroup\$ Aug 22, 2016 at 13:10

1 Answer 1

0
\$\begingroup\$

I have had this question answered on Unity Answers, though I needed to modify the original code to work properly.

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// Class: ClearNull Derived from MonoBehaviour
/// 
/// Purpose: Debugging of objects not yet completely finished in blender.
///          This class will destroy any face marked with !NULL to avoid  them to render
///          Restore the Original settings once destroyed
///          
/// Parameters DestroyString by default "!NULL" *** Warning this is case insensitive***
/// 
/// Notes: The code was inspired by Bunny83 in thread 
///        http://answers.unity3d.com/questions/1232964/
///        
///        This code should only be use for debugging and not for final products
///        
///        It will not work on children viewed from the parent.
///         
/// Further develepment ideas: 
///         - Make scene wide check on load to save and destroy 
///               every !NULLL face in the scene.
///         - Make it so it supports children 
/// 
/// Copyright: Code originally by Bunny83 adapted by Napivo on 2016/08/23 
///            free for anyone... Hope It help you as much as it does me
/// </summary>
public class ClearNull : MonoBehaviour 
{
    List<Material> oMats; // used to store the orriginal Materials
    List<int[]> oTris;    // used to store the orriginal triangles  
    public string DestroyString = "!NULL";

    void Start() 
    {
        //get the renderer
        MeshRenderer renderer = GetComponent<MeshRenderer>(); 
        //GetComponent the mesh
        Mesh mesh = GetComponent<MeshFilter>().sharedMesh;
        //Get the list of materials and save them for restore
        oMats = new List<Material>(renderer.sharedMaterials);
        List<Material> mats = new List<Material>(renderer.sharedMaterials);
        //Create a list to store the old and new triangles
        oTris = new List<int[]>();
        List<int[]> tris = new List<int[]>();

        int i = 0; // stores current number minus the one(s) lost
        int j = 0; // stores the current number 

        while (i < mats.Count) 
        {
            if (mats[i].name.ToUpper() == DestroyString.ToUpper()) 
            {
                Tris.Add(mesh.GetTriangles(j));  //Make a backup
                mats.Remove(mats[i]);
                j++;
            }
            else 
            {
                oTris.Add(mesh.GetTriangles(j)); //Make a backup
                tris.Add(mesh.GetTriangles(j));  //Copy to new triangles
                j++;
                i++;
            }
        }

        mesh.subMeshCount = tris.Count;         //Set new triangle count

        for (int n = 0; n < tris.Count; n++)    //Set new triangles without those lost 
        {  
            mesh.SetTriangles(tris[n], n);
        }

        renderer.sharedMaterials = mats.ToArray();  //Set the material without those lost
    }

    /// <summary>
    /// Purpose: Reset the object to the stati it was before
    /// </summary>
    void OnDestroy()
    {
        MeshRenderer renderer = GetComponent<MeshRenderer>();
        Mesh mesh = GetComponent<MeshFilter>().sharedMesh;

        mesh.subMeshCount = oTris.Count;
        for (int n = 0; n < oTris.Count; n++)
        {
            mesh.SetTriangles(oTris[n], n);
        }

        renderer.sharedMaterials = oMats.ToArray();
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Why would you say this? It works but only for individual objects... Implementing this system for scene wide or even child system, would be far beyond the scope of the question. not to mention most people would not even be able to grasp the basics of the system. \$\endgroup\$ Aug 23, 2016 at 23:40
  • \$\begingroup\$ This code woks now the original code coming off Site (answers.unity3d.com) the author of the code did set me on the right path but his original code did destroy my scene. I'll try and make the answer clearer. \$\endgroup\$ Aug 23, 2016 at 23:56
  • \$\begingroup\$ If this is the solution you used, and it worked, you should accept this as the answer. \$\endgroup\$
    – Gnemlock
    Dec 5, 2016 at 2:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .