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

Question Can't Bake Skinned Mesh Renderer in Build

Discussion in 'Editor & General Support' started by BrokenShekel, Dec 29, 2022.

  1. BrokenShekel

    BrokenShekel

    Joined:
    Feb 28, 2017
    Posts:
    3
    Over the last few weeks I've run into many problems while trying to convert my blendshapes into a single mesh with a single material. In editor it runs the code, bakes the skinned mesh renderers to mesh filters with new custom meshes. And then bakes it all into one mesh. But when I go to build it doesn't apply any textures, and even the code I wrote to reapply the textures doesn't seem to work anymore. From my research I believe one issue I'm running into may be that Read/Write is disabled for the meshes generated from skinned mesh renderers. So I spent the day learning about static classes to write this bit of code inspired by a different thread.

    Code (CSharp):
    1. //using System.Collections;
    2. //using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using System.Linq;
    6.  
    7. public static class AlterMeshStatic
    8. {
    9.   public static Mesh[] MeshArray;
    10.   static Mesh myMeshAsset;
    11.   static int x;
    12.   static int length;
    13.  
    14.   [RuntimeInitializeOnLoadMethod] //awake doesn't actually run on awake in static classes
    15.   public static void Awake()
    16.   {
    17.     MakeReadable();
    18.   }
    19.  
    20.   public static void MakeReadable()
    21.   {
    22.     for(x = 0; x < length; x++)
    23.     {
    24.       myMeshAsset = MeshArray[x];
    25.       SerializedObject s = new SerializedObject(myMeshAsset);
    26.       s.FindProperty("m_IsReadable").boolValue = true;
    27.     }
    28.   }
    29.  
    30.   public static void AssignMesh(Mesh[] passedMeshArray)
    31.   {
    32.     MeshArray = passedMeshArray;
    33.   }
    34.  
    35.   public static void SetArrayLength(int arrayLength)
    36.   {
    37.     length = arrayLength;
    38.   }
    39. }
    40.  
    But now I get this error. And not understanding Editor and Static Classes very well I'm at a loss.

    Code (CSharp):
    1. Assets\Scripts\AlterMeshStatic.cs(33,7): error CS0246: The type or namespace name 'SerializedObject' could not be found (are you missing a using directive or an assembly reference?)
    2.  
    I'm quite ready to strangle all of Unity as a whole.
    If anyone has a better way to go about this whole thing, or small tips that may allow my code to work I'd be so appreciative. Below is the main code for meshBaking

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(MeshFilter))]
    6. [RequireComponent(typeof(MeshRenderer))]
    7. [RequireComponent(typeof(MeshCollider))]
    8.  
    9. public class MeshOptimize : MonoBehaviour
    10. {
    11.     //List<GameObject> ObjectList;
    12.     Transform parent;
    13.     GameObject parentObject;
    14.     public bool bakeBlendshapes = false;
    15.     public bool bakeAsOneMesh = false; //for manual bake testing
    16.     bool bakingorbaked = false;
    17.     [SerializeField] int secondsTilStart;
    18.     [SerializeField] Material mat;
    19.     List<Material> matList;
    20.     [SerializeField] Material[] matSet;
    21.     int materialIndex = 0;
    22.     [SerializeField] string BlendMeshName;
    23.     [SerializeField] bool blendshapeColliders = false;
    24.     List<Mesh> MeshList;
    25.     Mesh[] MeshArray;
    26.  
    27.     void Start()
    28.     {
    29.       matList = new List<Material>();
    30.       MeshList = new List<Mesh>();
    31.       parent = this.transform;
    32.       parentObject = new GameObject();
    33.       parentObject.AddComponent<MeshFilter>();
    34.       parentObject.AddComponent<MeshRenderer>();
    35.       parentObject.AddComponent<MeshCollider>();
    36.       if(!bakingorbaked){TestOptimization();}
    37.     }
    38.  
    39.     public void TestOptimization()
    40.     {
    41.       bakingorbaked = true;
    42.       if(bakeBlendshapes)
    43.       {
    44.         BakeBlendshape();
    45.       }
    46.       if(bakeAsOneMesh)
    47.       {
    48.         BakeObject();
    49.         DestroyChildren();
    50.       }
    51.     }
    52.  
    53.     void ListUniqueMaterials(Material materialToAdd)
    54.     {
    55.       bool matchedMaterial = false;
    56.       for(int x = 0; x < matList.Count; x++)
    57.       {
    58.         if(materialToAdd = matList[x])
    59.         {
    60.           matchedMaterial = true;
    61.         }
    62.       }
    63.       if(!matchedMaterial)
    64.       {
    65.         matList.Add(materialToAdd);
    66.       }
    67.  
    68.     }
    69.  
    70.     void MaterialListToArray()
    71.     {
    72.       //Material[] matSet = new Material[matList.Count];
    73.       matSet = matList.ToArray();
    74.       //if(mat = null){mat = matSet[0];}
    75.       if(matSet[0] != null){mat = matSet[0];}
    76.       //Debug.Log("mat: " + mat + " matSet0: " + matSet[0]);
    77.     }
    78.  
    79.     public void AddObject(GameObject addObj)
    80.     {
    81.       addObj.transform.SetParent(parentObject.transform, true);
    82.     }
    83.  
    84.     void RemoveTriangles()
    85.     {
    86.  
    87.     }
    88.  
    89.     //for some reason custom meshes cannot be baked and will appear invisible with functioning TextureReapply
    90.     //
    91.     public void BakeBlendshape()
    92.     {
    93.       List<SkinnedMeshRenderer> BlendMeshes = new List<SkinnedMeshRenderer>();
    94.  
    95.       foreach(Transform child in parent)
    96.       {
    97.         if(child.gameObject.GetComponent<SkinnedMeshRenderer>() != null)
    98.         {
    99.           Material[] startingMaterials = child.gameObject.GetComponent<SkinnedMeshRenderer>().sharedMaterials;
    100.           ListUniqueMaterials(startingMaterials[0]); //not the best way to do this here
    101.           //Debug.Log("starting material 0 is " + startingMaterials[0]);
    102.           Mesh mesh = new Mesh();
    103.           var bMesh = child.gameObject.GetComponent<SkinnedMeshRenderer>();
    104.           BlendMeshes.Add(bMesh);
    105.           bMesh.BakeMesh(mesh, true);
    106.           MeshFilter filter = child.gameObject.AddComponent<MeshFilter>();
    107.           MeshRenderer renderer = child.gameObject.AddComponent<MeshRenderer>();
    108.           if(blendshapeColliders)
    109.           {
    110.             MeshCollider collide = child.gameObject.AddComponent<MeshCollider>();
    111.             collide.sharedMesh = mesh;
    112.           }
    113.  
    114.           Destroy(bMesh);
    115.           filter.mesh = mesh;
    116.           mesh.name = BlendMeshName;
    117.           //SerializedObject s = new SerializedObject(mesh);
    118.           //meshFile = new SerializedObject(mesh);
    119.           //meshFile.FindProperty("m_IsReadable").boolValue = true;
    120.  
    121.           MeshList.Add(mesh);
    122.           renderer.materials = startingMaterials;
    123.         }
    124.       }
    125.       MaterialListToArray();
    126.       MeshListToArray();
    127.     }
    128.  
    129.     void MeshListToArray()
    130.     {
    131.       MeshArray = MeshList.ToArray();
    132.       AlterMeshStatic.AssignMesh(MeshArray);
    133.       AlterMeshStatic.SetArrayLength(MeshArray.Length);
    134.     }
    135.  
    136.     //private void possible submesh texture baker here
    137.     //https://www.youtube.com/watch?v=XSdwuLvChRg
    138.  
    139.     public void BakeObject() //variant of above, converting meshfilters to list to fix the null0 problem
    140.     {//code taken from https://docs.unity3d.com/ScriptReference/Mesh.CombineMeshes.html
    141.       MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
    142.       List<MeshFilter> meshFilterList = new List<MeshFilter>();
    143.       foreach(var M in meshFilters){if(M.sharedMesh != null){meshFilterList.Add(M);}}
    144.       CombineInstance[] combine = new CombineInstance[meshFilterList.Count];
    145.  
    146.       int i = 0;
    147.       while (i < meshFilterList.Count)
    148.       {
    149.           combine[i].mesh = meshFilterList[i].sharedMesh;
    150.           combine[i].transform = meshFilterList[i].transform.localToWorldMatrix;
    151.           meshFilterList[i].gameObject.SetActive(false);
    152.           i++;
    153.       }
    154.       transform.GetComponent<MeshFilter>().mesh = new Mesh();
    155.       transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine, true, true);
    156.       //transform.GetComponent<MeshCollider>().sharedMesh = transform.GetComponent<MeshFilter>().mesh;
    157.       transform.gameObject.SetActive(true);
    158.  
    159.       transform.localScale = new Vector3(1,1,1);
    160.       transform.rotation = Quaternion.identity;
    161.       transform.position = Vector3.zero;
    162.       transform.gameObject.GetComponent<MeshRenderer>().material = mat;
    163.       //StartCoroutine(TextureReapply());
    164.     }
    165.  
    166.     public IEnumerator TextureReapply()
    167.     {
    168.       yield return new WaitForSeconds(secondsTilStart);
    169.       transform.gameObject.GetComponent<MeshRenderer>().material = mat;
    170.       //CycleMaterial();
    171.       StartCoroutine(TextureReapply());
    172.     }
    173.  
    174.     public void DestroyChildren()
    175.     {
    176.       foreach(Transform child in parent)
    177.       {
    178.         Destroy(child.gameObject);
    179.       }
    180.     }
    181.  
    182.     void CycleMaterial() //to test which materials can display on the baked mesh
    183.     {
    184.       if(materialIndex >= matSet.Length-1){materialIndex = 0;}
    185.       else{materialIndex++;}
    186.       mat = matSet[materialIndex];
    187.     }
    188. }
    189.  
     
  2. BrokenShekel

    BrokenShekel

    Joined:
    Feb 28, 2017
    Posts:
    3
    Update. I realized I needed to put the editor in an editor folder. So I did that, and referenced the variables in the static class. This got rid of the errors. But all the baked objects are still invisible, even when only baking the individual blendshapes to new meshes, so back to.... having no clues on what could be causing the issue.