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. Dismiss Notice

Problem getting a MeshFilter from a prefab's children

Discussion in 'Scripting' started by Glaskows, Sep 25, 2013.

  1. Glaskows

    Glaskows

    Joined:
    Mar 14, 2013
    Posts:
    9
    Hi, I have the following debug code
    Code (csharp):
    1.  
    2. // obj is a prefab reference as a GameObject       
    3. for ( int i = 0; i < obj.transform.childCount; ++i ) {
    4.     Debug.Log( obj.transform.GetChild(i).name );
    5.     Debug.Log( obj.transform.GetChild(i).GetComponent<MeshFilter>() ); 
    6. }
    7. Debug.Log ( obj.transform.GetComponentInChildren<MeshFilter>() != null );
    8.  
    In the loop I get the prefab children and its meshfilter component.
    In the last line code I get false, so it doesn't find any Component of type MeshFilter in its children.
    The prefab was created by importing an .fbx, then dragging it into the scene, and then the gameobject into the project.

    So the question is... why and how can I access the MeshFilter, without using the GetChild -> GetComponent route?

    Thanks!
     
  2. AlwaysSunny

    AlwaysSunny

    Joined:
    Sep 15, 2011
    Posts:
    260
    Someone better informed can correct or supplement this, but unless I'm badly mistaken, an extra step is required to achieve this behavior. I think Unity's import pipeline assumes you want to use a Skinned Mesh Renderer when you import 3d assets. Because I've never really needed or explored their functionality, I typically hand-edit imported models within a scene, ultimately creating a Unity-ready prefab as you've described. The magic step you may be missing involves changing each model part's components to reflect that you don't want to use a Skinned Mesh Renderer, but instead want each piece to have its own unique MeshFilter MeshRenderer component.

    Always a hassle to do this - maybe there's a easy fix I'm not aware of? Alternatively, if your scenario calls for it, you can refactor and make use of the Skinned Mesh Renderer features.
     
  3. Glaskows

    Glaskows

    Joined:
    Mar 14, 2013
    Posts:
    9
    I am not sure if I understand your answer. My final prefab is only composed by two elements, one root gameobject with a Transform and custom script components and one child gameobject with another transform (obviously), Mesh Filter and Mesh Renderer components. I don't need the Mesh Renderer at all, just for editor visualization, because I only need the vertices/tris/uvs info, which is used in other script for a morphing operation. If I used a prefab with a root element with a mesh filter component I can access it with GetComponent<MeshFilter>. To get the childs MeshFilters I need to do the transform.GetChild(), GetComponent()<MeshFilter>() operations, because GetComponentInChildren<MeshFilter>() gets me null.
     
  4. AlwaysSunny

    AlwaysSunny

    Joined:
    Sep 15, 2011
    Posts:
    260
    Sorry for the mix-up, I misunderstood the issue. Could it be that you need to use GetComponentsInChildren instead? Seems unintuitive, but I seem to recall encountering some similar issues in the past. Note that 'components' is plural here and that's a separate method from the singular version. Also note it should really be called GetComponentsInSelfAndChildren, since that's exactly what it does.

    I'm not sure why what you're doing isn't working at a glance, though. The syntax and intended usage are spot on afaik. However, I've avoided using the find/get-in-children methods because they negatively impact readability and control in my opinion, so I'm not especially familiar with their quirks. Sorry I don't have a more useful suggestion, but I circumvent these issues by doing things the hard way within a childcount based loop as you have.
     
    Last edited: Sep 26, 2013
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I use it all the time and it works fine. Is one of your transforms disabled in the hierarchy?
     
  6. Glaskows

    Glaskows

    Joined:
    Mar 14, 2013
    Posts:
    9
    KelsoMRK: no, double checked that.
    AlwaysSunny: tried that. It returns an array as expected (so its not null), but it is empty.

    The only step I didn't mention was that first I created a gameobject of the imported mesh, but then, I erased all the submeshes I didn't need (where siblings to the one I used) from the gameobject before making a new prefab from it. Maybe, somehow, it made something Unity didn't like. For now, I will keep using the two step procedure. Buuuh

    Thanks guys for the replay!
     
    Last edited: Sep 26, 2013
  7. QuarterMillion

    QuarterMillion

    Joined:
    Jul 18, 2020
    Posts:
    10
    I know this is an old thread and I know you've probably long since moved on but I've figured out how you would access the meshes from your transform children.
    Code (CSharp):
    1. //First you need to define a recipient List for the meshfilters
    2. List<MeshFilter> meshFilters = new List<MeshFilter>();
    3. //Then you need to grab the mesh filters from the transform children
    4. obj.GetComponentsInChildren<MeshFilter>(false, meshFilters);/*That last part takes two parameters
    5. the first is a boolean check for if it should include inactive transform children.
    6. The second is the list required to receive the components. IF THERE'S NO LIST THERE ARE NO COMPONENTS GRABBED. */
    7.  
    8. //You then create a CombineInstance Array
    9. CombineInstance[] combine = new CombineInstance[meshFilters.Count];
    10.  
    11. //Then you create a for loop to iterate over them
    12. for (int i = 0; i < meshFilters.Count; i++)
    13. {
    14. combine[i].mesh = meshFilters[i].sharedMesh;
    15. combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
    16. }
    17.  
    18. //Then you create a new mesh
    19. Mesh mesh = new Mesh();
    20. //There are 3 parameters possible but you could just use one
    21. mesh.CombineMeshes(combine,true,false);
    22. /*If you're interested those 3 parameters are:
    23. The CombineInstance Array,
    24. a boolean check for merging the Submeshes,
    25. and a boolean check for whether the matrices
    26. provided by the CombineInstance should be used.
    27.  But the only parameter that's required is the first one
    28.  the CombineInstance. The rest are optional*/
    29.  
    30. //At this point you could name the mesh whatever you want
    31. mesh.name = obj.name; // this is just an example
    32.  
    33. //Now pass the mesh on to the parent's meshfilter
    34. obj.GetComponent<MeshFilter>().sharedMesh = mesh;
    35.  
    Oh I and I see you said that you may have deleted your submeshes? You could probably reimport them and still do this. All of what I've coded above can be found in Unity's documentation. I just combined a couple of their sources.
     
    Last edited: Apr 19, 2023