Search Unity

MeshCombineUtility.cs - UnityEngine.Mesh.SetTriangleStrip(int[], int)' is obsolete

Discussion in 'Scripting' started by Tiles, Feb 2, 2013.

  1. Tiles

    Tiles

    Joined:
    Feb 5, 2010
    Posts:
    2,481
    I´ve upgraded my project to Unity 4. And every now and then i get another warning about obsolete code now. Would be nice when this one would come at once, and not piece by piece. It`s very disturbing when such warnings pops up in the console when you are busy with something else.

    This time it is the MeshCombineUtility that tells me that the SetTriangleStrip method is obsolete.

    As usual i am totally lost with the scripting reference and their description, better said missing description, of how to use the method. I simply don`t get what is meant here. A very frustrating and often repeated experience when looking into the scripting reference. I wish there would be a comment function for the scripting reference ...

    This is the warning i get:

    Code (csharp):
    1. Assets/Standard Assets/Scripts/Utility Scripts/MeshCombineUtility.cs(177,30): warning CS0618: `UnityEngine.Mesh.SetTriangleStrip(int[], int)' is obsolete: `Use SetTriangles instead. Internally this function will convert the triangle strip to a list of triangles anyway.'
    2.  
    This is the original code at line 177:

    Code (csharp):
    1. mesh.SetTriangleStrip(strip, 0);
    And this doesn`t work:

    Code (csharp):
    1. mesh.SetTriangles (triangles : int[], submesh : int) : void
    Code (csharp):
    1. Assets/Standard Assets/Scripts/Utility Scripts/MeshCombineUtility.cs(177,59): error CS1525: Unexpected symbol `[', expecting `.'
    What do i need to do to fix this issue?
     
    Last edited: Feb 2, 2013
  2. Tiles

    Tiles

    Joined:
    Feb 5, 2010
    Posts:
    2,481
    Problem solved. This one does the trick:

    Code (csharp):
    1. mesh.SetTriangles(strip, 0);
    and the other two trouble lines can be fixed by:

    Code (csharp):
    1. int curStripCount = combine.mesh.GetTriangles(combine.subMeshIndex).Length;
    Thanks for listening.
     
  3. 1liverpool

    1liverpool

    Joined:
    May 8, 2013
    Posts:
    1
    hi there i have this problem also i am knew to unity and scripting how do i solve this? do i write that text in a knew script?
     
  4. graslany

    graslany

    Joined:
    Dec 26, 2012
    Posts:
    10
    Aaaaah, the good old "it compiles hence it is correct" thing :D

    The fact that a line does not raise a warning or an error does not imply it is correct, that's one of the first things you need to learn when studying programming. Your program will happily shoot its own foot if you instruct it to do so in a syntactically and semantically correct way.

    These annoying warnings pop up because the code in MeshCombineUtility uses an old function that is no longer supported. What you have to do to get cleanly rid of this warning is to replace the contents of the whole function whith something that does not use the deprecated functionnality. According to the (very useful) details provided in the console with the warning, you should not manipulate triangle strips directly in Unity 4 but rather work with plain triangles only. I propose the following fix : replace the original Combine function with this one ...

    Code (csharp):
    1.     public static Mesh Combine (MeshInstance[] combines)
    2.     {
    3.         int vertexCount = 0;
    4.         int triangleCount = 0;
    5.         foreach( MeshInstance combine in combines )
    6.         {
    7.             if (combine.mesh)
    8.             {
    9.                 vertexCount += combine.mesh.vertexCount;
    10.             }
    11.         }
    12.        
    13.         // Precompute how many triangles we need
    14.         foreach( MeshInstance combine in combines )
    15.         {
    16.             if (combine.mesh)
    17.             {
    18.                 triangleCount += combine.mesh.GetTriangles(combine.subMeshIndex).Length;
    19.             }
    20.         }
    21.        
    22.         Vector3[] vertices = new Vector3[vertexCount] ;
    23.         Vector3[] normals = new Vector3[vertexCount] ;
    24.         Vector4[] tangents = new Vector4[vertexCount] ;
    25.         Vector2[] uv = new Vector2[vertexCount];
    26.         Vector2[] uv1 = new Vector2[vertexCount];
    27.         Color[] colors = new Color[vertexCount];
    28.        
    29.         int[] triangles = new int[triangleCount];
    30.        
    31.         int offset;
    32.        
    33.         offset=0;
    34.         foreach( MeshInstance combine in combines )
    35.         {
    36.             if (combine.mesh)
    37.                 Copy(combine.mesh.vertexCount, combine.mesh.vertices, vertices, ref offset, combine.transform);
    38.         }
    39.  
    40.         offset=0;
    41.         foreach( MeshInstance combine in combines )
    42.         {
    43.             if (combine.mesh)
    44.             {
    45.                 Matrix4x4 invTranspose = combine.transform;
    46.                 invTranspose = invTranspose.inverse.transpose;
    47.                 CopyNormal(combine.mesh.vertexCount, combine.mesh.normals, normals, ref offset, invTranspose);
    48.             }
    49.                
    50.         }
    51.         offset=0;
    52.         foreach( MeshInstance combine in combines )
    53.         {
    54.             if (combine.mesh)
    55.             {
    56.                 Matrix4x4 invTranspose = combine.transform;
    57.                 invTranspose = invTranspose.inverse.transpose;
    58.                 CopyTangents(combine.mesh.vertexCount, combine.mesh.tangents, tangents, ref offset, invTranspose);
    59.             }
    60.                
    61.         }
    62.         offset=0;
    63.         foreach( MeshInstance combine in combines )
    64.         {
    65.             if (combine.mesh)
    66.                 Copy(combine.mesh.vertexCount, combine.mesh.uv, uv, ref offset);
    67.         }
    68.        
    69.         offset=0;
    70.         foreach( MeshInstance combine in combines )
    71.         {
    72.             if (combine.mesh)
    73.                 Copy(combine.mesh.vertexCount, combine.mesh.uv1, uv1, ref offset);
    74.         }
    75.        
    76.         offset=0;
    77.         foreach( MeshInstance combine in combines )
    78.         {
    79.             if (combine.mesh)
    80.                 CopyColors(combine.mesh.vertexCount, combine.mesh.colors, colors, ref offset);
    81.         }
    82.        
    83.         int triangleOffset=0;
    84.         int vertexOffset=0;
    85.         foreach( MeshInstance combine in combines )
    86.         {
    87.             if (combine.mesh)
    88.             {
    89.                 int[]  inputtriangles = combine.mesh.GetTriangles(combine.subMeshIndex);
    90.                 for (int i=0;i<inputtriangles.Length;i++)
    91.                 {
    92.                     triangles[i+triangleOffset] = inputtriangles[i] + vertexOffset;
    93.                 }
    94.                 triangleOffset += inputtriangles.Length;
    95.                
    96.                 vertexOffset += combine.mesh.vertexCount;
    97.             }
    98.         }
    99.        
    100.         Mesh mesh = new Mesh();
    101.         mesh.name = "Combined Mesh";
    102.         mesh.vertices = vertices;
    103.         mesh.normals = normals;
    104.         mesh.colors = colors;
    105.         mesh.uv = uv;
    106.         mesh.uv1 = uv1;
    107.         mesh.tangents = tangents;
    108.         mesh.triangles = triangles;
    109.        
    110.         return mesh;
    111.     }
    112.    
    113.     static void Copy (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
    114.     {
    115.         for (int i=0;i<src.Length;i++)
    116.             dst[i+offset] = transform.MultiplyPoint(src[i]);
    117.         offset += vertexcount;
    118.     }
    119.  
    120.     static void CopyNormal (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
    121.     {
    122.         for (int i=0;i<src.Length;i++)
    123.             dst[i+offset] = transform.MultiplyVector(src[i]).normalized;
    124.         offset += vertexcount;
    125.     }
    126.  
    127.     static void Copy (int vertexcount, Vector2[] src, Vector2[] dst, ref int offset)
    128.     {
    129.         for (int i=0;i<src.Length;i++)
    130.             dst[i+offset] = src[i];
    131.         offset += vertexcount;
    132.     }
    133.  
    134.     static void CopyColors (int vertexcount, Color[] src, Color[] dst, ref int offset)
    135.     {
    136.         for (int i=0;i<src.Length;i++)
    137.             dst[i+offset] = src[i];
    138.         offset += vertexcount;
    139.     }
    140.    
    141.     static void CopyTangents (int vertexcount, Vector4[] src, Vector4[] dst, ref int offset, Matrix4x4 transform)
    142.     {
    143.         for (int i=0;i<src.Length;i++)
    144.         {
    145.             Vector4 p4 = src[i];
    146.             Vector3 p = new Vector3(p4.x, p4.y, p4.z);
    147.             p = transform.MultiplyVector(p).normalized;
    148.             dst[i+offset] = new Vector4(p.x, p.y, p.z, p4.w);
    149.         }
    150.            
    151.         offset += vertexcount;
    152.     }
    ... and since I deleted the boolean parameter that used to indicate whever strips should be used (hey, they will never be used again since this is deprecated ;-) ), I also have to modify the Start() function if the CombineChildren class (in file CombineChildren.cs, located next to MeshCombineUtility.cs) accordingly so that it does not pass this parameter anymore :

    Code (csharp):
    1.     /// This option has a far longer preprocessing time at startup but leads to better runtime performance.
    2.     void Start () {
    3.         Component[] filters  = GetComponentsInChildren(typeof(MeshFilter));
    4.         Matrix4x4 myTransform = transform.worldToLocalMatrix;
    5.         Hashtable materialToMesh= new Hashtable();
    6.        
    7.         for (int i=0;i<filters.Length;i++) {
    8.             MeshFilter filter = (MeshFilter)filters[i];
    9.             Renderer curRenderer  = filters[i].renderer;
    10.             MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance ();
    11.             instance.mesh = filter.sharedMesh;
    12.             if (curRenderer != null  curRenderer.enabled  instance.mesh != null) {
    13.                 instance.transform = myTransform * filter.transform.localToWorldMatrix;
    14.                
    15.                 Material[] materials = curRenderer.sharedMaterials;
    16.                 for (int m=0;m<materials.Length;m++) {
    17.                     instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1);
    18.    
    19.                     ArrayList objects = (ArrayList)materialToMesh[materials[m]];
    20.                     if (objects != null) {
    21.                         objects.Add(instance);
    22.                     }
    23.                     else
    24.                     {
    25.                         objects = new ArrayList ();
    26.                         objects.Add(instance);
    27.                         materialToMesh.Add(materials[m], objects);
    28.                     }
    29.                 }
    30.                
    31.                 curRenderer.enabled = false;
    32.             }
    33.         }
    34.    
    35.         foreach (DictionaryEntry de  in materialToMesh) {
    36.             ArrayList elements = (ArrayList)de.Value;
    37.             MeshCombineUtility.MeshInstance[] instances = (MeshCombineUtility.MeshInstance[])elements.ToArray(typeof(MeshCombineUtility.MeshInstance));
    38.  
    39.             // We have a maximum of one material, so just attach the mesh to our own game object
    40.             if (materialToMesh.Count == 1)
    41.             {
    42.                 // Make sure we have a mesh filter  renderer
    43.                 if (GetComponent(typeof(MeshFilter)) == null)
    44.                     gameObject.AddComponent(typeof(MeshFilter));
    45.                 if (!GetComponent("MeshRenderer"))
    46.                     gameObject.AddComponent("MeshRenderer");
    47.    
    48.                 MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter));
    49.                 filter.mesh = MeshCombineUtility.Combine(instances);
    50.                 renderer.material = (Material)de.Key;
    51.                 renderer.enabled = true;
    52.             }
    53.             // We have multiple materials to take care of, build one mesh / gameobject for each material
    54.             // and parent it to this object
    55.             else
    56.             {
    57.                 GameObject go = new GameObject("Combined mesh");
    58.                 go.transform.parent = transform;
    59.                 go.transform.localScale = Vector3.one;
    60.                 go.transform.localRotation = Quaternion.identity;
    61.                 go.transform.localPosition = Vector3.zero;
    62.                 go.AddComponent(typeof(MeshFilter));
    63.                 go.AddComponent("MeshRenderer");
    64.                 go.renderer.material = (Material)de.Key;
    65.                 MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter));
    66.                 filter.mesh = MeshCombineUtility.Combine(instances);
    67.             }
    68.         }  
    69.     }
    This is a rather violent method since it involves modifying the signature of the Combine function and removing one of its parameter : if you use code that calls this function, it will have to be modified also to remove the boolean parameter else it will not compile. On the bright side, the resulting compilation errors will help you locating possible obsolete code that would need to be upgraded.

    If you do not want to have these errors, you can simply leave the old, now unused boolean parameter. The forst line of the Combine function would then be ...

    Code (csharp):
    1. public static Mesh Combine (MeshInstance[] combines, bool ignoredParameter)
     
    Dok101 likes this.
  5. AndyMartin458

    AndyMartin458

    Joined:
    Jul 15, 2012
    Posts:
    59
    Thanks so much for this!! I really don't know what is going on in the script because I don't have the time to delve into this concept. But, I recently started using MeshCombineUtilty and CombineChildren and reduced my draw calls by %40. I hated having those warnings though, and yeah you are right that just swapping in the different methods did not help at all. It was pretty dangerous and chaotic.

    Could you make some guidlines on why you made each and every change? That would be awesome! I think that Unity should start publishing your version instead of their outdated version.
     
  6. liveuk

    liveuk

    Joined:
    Nov 4, 2013
    Posts:
    3
    If you see the warning just replace the Word "GetTriangleStrip" for the word "GetTriangles"

    // SUBOPTIMAL FOR PERFORMANCE

    //int curStripCount = combine.mesh.GetTriangleStrip(combine.subMeshIndex).Length;

    int curStripCount = combine.mesh.GetTriangles(combine.subMeshIndex).Length;

    Same with the other Unity example standard asset scripts that have old code not updated.
    Change in trigger script
    Change this
    targetGameObject.active = false;
    For
    targetGameObject.SetActive(false);

    Mike
     
    root8888 likes this.
  7. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,734
    Awesome thread...
    Thanks a bunch!