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

Question Splitting Mesh script bad performance

Discussion in 'Entity Component System' started by Spectra_7, Feb 26, 2021.

  1. Spectra_7

    Spectra_7

    Joined:
    Oct 17, 2017
    Posts:
    33
    I have a mesh that I cut it with another mesh using CSG boolean subtract operation. I use this asset for that: https://github.com/karl-/pb_CSG

    After performing subtract operation, the result is still one mesh. So in order to split that one mesh into two meshes, I use this code:

    Code (CSharp):
    1. public List<GameObject> SplitMesh(GameObject objectToSplit, bool disableObjectToSplit = false, string newTag = "Untagged", int newLayer = 0, Transform newParent = null)
    2.     {
    3.         List<GameObject> results = new List<GameObject>();
    4.  
    5.         MeshFilter objectToSplitFilter = objectToSplit.GetComponent<MeshFilter>();
    6.         Mesh objectToSplitMesh = objectToSplitFilter.sharedMesh;
    7.        
    8.         MeshRenderer objectToSplitRenderer = objectToSplit.GetComponent<MeshRenderer>();
    9.         Material objectToSplitMaterial = objectToSplitRenderer.sharedMaterial;
    10.  
    11.         Vector3 objectToSplitPos = objectToSplit.transform.position;
    12.         Vector3 objectToSplitScale = objectToSplit.transform.localScale;
    13.  
    14.         int[] indices = objectToSplitMesh.triangles;
    15.         Vector3[] verts = objectToSplitMesh.vertices;
    16.  
    17.         newVerts = new List<Vector3>();
    18.         vertsList = new List<Vector3>(verts);
    19.  
    20.         count = 0;
    21.         while(vertsList.Count > 0)
    22.         {
    23.             count++;
    24.  
    25.             newVerts.Clear();
    26.             newVerts.Add(vertsList[0]);
    27.             newVerts.Add(vertsList[1]);
    28.             newVerts.Add(vertsList[2]);
    29.  
    30.             for (int i = 3; i < vertsList.Count; i += 3)
    31.             {
    32.                 bool check = false;
    33.                 for (int j = 0; j < 3 && !check; j++)
    34.                 {
    35.                     print("newVerts[j]: " + newVerts[j] + ", vertsList[j]: " + vertsList[j]);
    36.                     for (int v = 0; v < newVerts.Count && !check; v++)
    37.                     {
    38.                         if(newVerts[v] == vertsList[i + j])
    39.                         {
    40.                             check = true;
    41.                         }
    42.                     }
    43.                 }
    44.  
    45.                 if(check)
    46.                 {
    47.                     for (int k = 0; k < 3; k++)
    48.                     {
    49.                         newVerts.Add(vertsList[i + k]);
    50.                     }
    51.  
    52.                     for (int k = 0; k < 3; k++)
    53.                     {
    54.                         vertsList.RemoveAt(i + 2 - k);
    55.                     }
    56.  
    57.                     i = 0;
    58.                 }
    59.             }
    60.  
    61.             vertsList.RemoveAt(0);
    62.             vertsList.RemoveAt(0);
    63.             vertsList.RemoveAt(0);
    64.  
    65.             //Vector3[] vertsR = new Vector3[newVerts.Count];
    66.             List<Vector3> vertsR = new List<Vector3>();
    67.             List<int> indR = new List<int>();
    68.  
    69.             for (int i = 0; i < newVerts.Count; i++)
    70.             {
    71.                 //vertsR[i] = newVerts[i];
    72.                 vertsR.Add(newVerts[i]);
    73.                 indR.Add(indices[i]);
    74.             }
    75.  
    76.             Mesh newMeshCG = new Mesh();
    77.             newMeshCG.name = objectToSplit.name + "(Clone)";
    78.             newMeshCG.vertices = vertsR.ToArray();
    79.             newMeshCG.triangles = indR.ToArray();
    80.             newMeshCG.RecalculateNormals();
    81.  
    82.             if(vertsList.Count == 0 && count == 1)
    83.             {
    84.                 results.Add(objectToSplit);
    85.             }
    86.             else
    87.             {
    88.                 GameObject newSplitObject = new GameObject(objectToSplit.transform.name + "(New)");
    89.                 newSplitObject.tag = newTag;
    90.                 newSplitObject.layer = newLayer;
    91.                 newSplitObject.transform.position = objectToSplitPos;
    92.                 newSplitObject.transform.localScale = objectToSplitScale;
    93.                 newSplitObject.transform.parent = newParent;
    94.                 newSplitObject.AddComponent<MeshFilter>().sharedMesh = newMeshCG;
    95.                 newSplitObject.AddComponent<MeshRenderer>().material = objectToSplitMaterial;
    96.  
    97.                 results.Add(newSplitObject);
    98.             }
    99.         }
    100.  
    101.         if (disableObjectToSplit)
    102.             objectToSplit.SetActive(false);
    103.  
    104.         return results;
    105.     }

    The problem I am facing is that the game freezes in between while performing the splitting operation.
    So I tried using C# job system single thread. There was quite improvement, but freezing was still there.

    Plus I am still a big noob with C# Jobs.

    Here is code for using single thread job:
    Code (CSharp):
    1. public List<GameObject> SplitMesh(GameObject objectToSplit, bool disableObjectToSplit = false, string newTag = "Untagged", int newLayer = 0, Transform newParent = null)
    2.     {
    3.         List<GameObject> results = new List<GameObject>();
    4.  
    5.         MeshFilter objectToSplitFilter = objectToSplit.GetComponent<MeshFilter>();
    6.         Mesh objectToSplitMesh = objectToSplitFilter.sharedMesh;
    7.  
    8.         MeshRenderer objectToSplitRenderer = objectToSplit.GetComponent<MeshRenderer>();
    9.         Material objectToSplitMaterial = objectToSplitRenderer.sharedMaterial;
    10.  
    11.         Vector3 objectToSplitPos = objectToSplit.transform.position;
    12.         Vector3 objectToSplitScale = objectToSplit.transform.localScale;
    13.  
    14.         int[] indices = objectToSplitMesh.triangles;
    15.         Vector3[] verts = objectToSplitMesh.vertices;
    16.  
    17.         m_Vertices = new NativeArray<Vector3>(verts, Allocator.Persistent);
    18.         m_Indices = new NativeArray<int>(indices, Allocator.Persistent);
    19.  
    20.         m_VerticesList = new NativeList<Vector3>(Allocator.Persistent);
    21.         m_IndicesList = new NativeList<int>(Allocator.Persistent);
    22.  
    23.         m_VerticesOne = new NativeList<Vector3>(Allocator.Persistent);
    24.         m_IndicesOne = new NativeList<int>(Allocator.Persistent);
    25.  
    26.         m_VerticesTwo = new NativeList<Vector3>(Allocator.Persistent);
    27.         m_IndicesTwo = new NativeList<int>(Allocator.Persistent);
    28.         //m_VerticesList.CopyFrom(verts);
    29.         //m_IndicesList.CopyFrom(indices);      
    30.  
    31.         SplitJob splitJob = new SplitJob()
    32.         {
    33.             jobOriginalVertices = m_Vertices,
    34.             jobOriginalIndices = m_Indices,
    35.  
    36.             jobNewVertices = m_VerticesList,
    37.             jobNewIndices = m_IndicesList,
    38.  
    39.             jobNewVerticesOne = m_VerticesOne,
    40.             jobNewIndicesOne = m_IndicesOne,
    41.  
    42.             jobNewVerticesTwo = m_VerticesTwo,
    43.             jobNewIndicesTwo = m_IndicesTwo
    44.         };
    45.  
    46.         m_JobHandle = splitJob.Schedule();
    47.         m_JobHandle.Complete();
    48.  
    49.         //m_VerticesModified = splitJob.jobNewVertices.ToArray();
    50.         //m_IndicesModified = splitJob.jobNewIndices.ToArray();
    51.  
    52.         m_VerticesModifiedOne = splitJob.jobNewVerticesOne.ToArray();
    53.         m_IndicesModifiedOne = splitJob.jobNewIndicesOne.ToArray();
    54.  
    55.         m_VerticesModifiedTwo = splitJob.jobNewVerticesTwo.ToArray();
    56.         m_IndicesModifiedTwo = splitJob.jobNewIndicesTwo.ToArray();
    57.  
    58.         if(m_VerticesModifiedOne.Length != 0 && m_IndicesModifiedOne.Length != 0)
    59.         {
    60.             Mesh newMeshCGOne = new Mesh();
    61.             newMeshCGOne.name = objectToSplit.name + "(Clone)";
    62.             newMeshCGOne.vertices = m_VerticesModifiedOne;
    63.             newMeshCGOne.triangles = m_IndicesModifiedOne;
    64.             newMeshCGOne.RecalculateNormals();
    65.  
    66.             GameObject newSplitObjectOne = new GameObject(objectToSplit.transform.name + "(New)");
    67.             newSplitObjectOne.tag = newTag;
    68.             newSplitObjectOne.layer = newLayer;
    69.             newSplitObjectOne.transform.position = objectToSplitPos;
    70.             newSplitObjectOne.transform.localScale = objectToSplitScale;
    71.             newSplitObjectOne.transform.parent = newParent;
    72.             newSplitObjectOne.AddComponent<MeshFilter>().sharedMesh = newMeshCGOne;
    73.             newSplitObjectOne.AddComponent<MeshRenderer>().material = objectToSplitMaterial;
    74.  
    75.             ProBuilderizeShape(newSplitObjectOne);
    76.  
    77.             results.Add(newSplitObjectOne);          
    78.         }
    79.        
    80.         if (m_VerticesModifiedTwo.Length != 0 && m_IndicesModifiedTwo.Length != 0)
    81.         {
    82.             Mesh newMeshCGTwo = new Mesh();
    83.             newMeshCGTwo.name = objectToSplit.name + "(Clone)";
    84.             newMeshCGTwo.vertices = m_VerticesModifiedTwo;
    85.             newMeshCGTwo.triangles = m_IndicesModifiedTwo;
    86.             newMeshCGTwo.RecalculateNormals();
    87.  
    88.             GameObject newSplitObjectTwo = new GameObject(objectToSplit.transform.name + "(New)");
    89.             newSplitObjectTwo.tag = newTag;
    90.             newSplitObjectTwo.layer = newLayer;
    91.             newSplitObjectTwo.transform.position = objectToSplitPos;
    92.             newSplitObjectTwo.transform.localScale = objectToSplitScale;
    93.             newSplitObjectTwo.transform.parent = newParent;
    94.             newSplitObjectTwo.AddComponent<MeshFilter>().sharedMesh = newMeshCGTwo;
    95.             newSplitObjectTwo.AddComponent<MeshRenderer>().material = objectToSplitMaterial;
    96.  
    97.             ProBuilderizeShape(newSplitObjectTwo);
    98.  
    99.             results.Add(newSplitObjectTwo);          
    100.         }
    101.  
    102.         m_Vertices.Dispose();
    103.         m_Indices.Dispose();
    104.  
    105.         m_VerticesList.Dispose();
    106.         m_IndicesList.Dispose();
    107.  
    108.         m_VerticesOne.Dispose();
    109.         m_IndicesOne.Dispose();
    110.  
    111.         m_VerticesTwo.Dispose();
    112.         m_IndicesTwo.Dispose();
    113.  
    114.         if (disableObjectToSplit)
    115.             objectToSplit.SetActive(false);
    116.  
    117.         return results;
    118.     }
    119.  
    120. public struct SplitJob : IJob
    121.     {
    122.         public NativeArray<Vector3> jobOriginalVertices;
    123.         public NativeArray<int> jobOriginalIndices;
    124.  
    125.         public NativeList<Vector3> jobNewVertices;
    126.         public NativeList<int> jobNewIndices;
    127.  
    128.         public NativeList<Vector3> jobNewVerticesOne;
    129.         public NativeList<int> jobNewIndicesOne;
    130.  
    131.         public NativeList<Vector3> jobNewVerticesTwo;
    132.         public NativeList<int> jobNewIndicesTwo;
    133.  
    134.         public void Execute()
    135.         {
    136.             List<Vector3> newVerts = new List<Vector3>();
    137.             List<Vector3> vertsList = new List<Vector3>(jobOriginalVertices);
    138.  
    139.             int count = 0;
    140.  
    141.             while(vertsList.Count > 0)
    142.             {
    143.                 count++;
    144.  
    145.                 newVerts.Clear();
    146.                 newVerts.Add(vertsList[0]);
    147.                 newVerts.Add(vertsList[1]);
    148.                 newVerts.Add(vertsList[2]);
    149.  
    150.                 for (int i = 3; i < vertsList.Count; i += 3)
    151.                 {
    152.                     bool check = false;
    153.                     for (int j = 0; j < 3 && !check; j++)
    154.                     {
    155.                         for (int v = 0; v < newVerts.Count && !check; v++)
    156.                         {
    157.                             if (newVerts[v] == vertsList[i + j])
    158.                             {
    159.                                 check = true;
    160.                             }
    161.                         }                      
    162.                     }
    163.  
    164.                     if (check)
    165.                     {
    166.                         for (int k = 0; k < 3; k++)
    167.                         {
    168.                             newVerts.Add(vertsList[i + k]);
    169.                         }
    170.  
    171.                         for (int k = 0; k < 3; k++)
    172.                         {
    173.                             vertsList.RemoveAt(i + 2 - k);
    174.                         }
    175.  
    176.                         i = 0;
    177.                     }
    178.                 }
    179.  
    180.                 vertsList.RemoveAt(0);
    181.                 vertsList.RemoveAt(0);
    182.                 vertsList.RemoveAt(0);
    183.  
    184.                 //Vector3[] vertsR = new Vector3[newVerts.Count];
    185.                 //List<int> indR = new List<int>();
    186.  
    187.                 //jobNewVertices = new NativeArray<Vector3>(newVerts.Count, Allocator.TempJob);
    188.                 //jobNewIndices = new NativeArray<int>(jobOriginalIndices.Length, Allocator.TempJob);
    189.  
    190.                 jobNewVertices.Clear();
    191.                 jobNewIndices.Clear();
    192.  
    193.                 for (int i = 0; i < newVerts.Count; i++)
    194.                 {
    195.                     jobNewVertices.Add(newVerts[i]);
    196.                     jobNewIndices.Add(jobOriginalIndices[i]);
    197.                     //indR.Add(jobIndices[i]);
    198.                 }
    199.  
    200.                 if(count == 1)
    201.                 {
    202.                     jobNewVerticesOne.Clear();
    203.                     jobNewIndicesOne.Clear();
    204.  
    205.                     for (int i = 0; i < newVerts.Count; i++)
    206.                     {
    207.                         jobNewVerticesOne.Add(newVerts[i]);
    208.                         jobNewIndicesOne.Add(jobOriginalIndices[i]);
    209.                     }
    210.                 }
    211.                
    212.                 if(count == 2)
    213.                 {
    214.                     jobNewVerticesTwo.Clear();
    215.                     jobNewIndicesTwo.Clear();
    216.  
    217.                     for (int i = 0; i < newVerts.Count; i++)
    218.                     {
    219.                         jobNewVerticesTwo.Add(newVerts[i]);
    220.                         jobNewIndicesTwo.Add(jobOriginalIndices[i]);
    221.                     }
    222.                 }
    223.             }
    224.         }
    225.     }
    226.    

    I really need some help how to improve the performance of splitting part. I thought of using C# parallel jobs, but I was finding it confusing.

    Thanks.
     
  2. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    1. Add the
      [BurstCompile]
      attribute to your job struct.
    2. Use the Unity.Mathematics types (float3, etc) in jobs, burst can optimize better with them.
    3. Don't try to use managed data (ie List<T>) in jobs/burst. You need to use native containers. You can allocate using Allocater.Temp to create one from inside a job.
    4. What part is causing the "freezing"? Do some profiling so you can narrow down where your bottle neck is.
     
    tmonestudio likes this.
  3. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    558
    you are doing
    .RemoveAt(0);
    inside a loop. that results in a O(N^2) time, where N is the number of vertices.
     
    Nyanpas likes this.
  4. Spectra_7

    Spectra_7

    Joined:
    Oct 17, 2017
    Posts:
    33
    Thanks for the reply. I did 1, 2, 3 steps like you said. The performance was greatly improved albeit they were still some microfreezes. But results are almost instant.

    However, a new problem arises that some faces are missing especially bottom/top faces of the meshes.
    After performing splitting operation.

    Code (CSharp):
    1. public void Execute()
    2.         {
    3.             //List<float3> newVerts = new List<float3>();
    4.             //List<float3> vertsList = new List<float3>(jobOriginalVertices);
    5.  
    6.             NativeList<float3> newVerts = new NativeList<float3>(Allocator.Temp);
    7.             NativeList<float3> vertsList = new NativeList<float3>(Allocator.Temp);
    8.  
    9.             for (int i = 0; i < jobOriginalVertices.Length; i++)
    10.             {              
    11.                 vertsList.Add(jobOriginalVertices[i]);
    12.             }
    13.  
    14.             int count = 0;
    15.             while(vertsList.Length > 0)
    16.             {
    17.                 count++;
    18.  
    19.                 newVerts.Clear();
    20.                 newVerts.Add(vertsList[0]);              
    21.                 newVerts.Add(vertsList[1]);
    22.                 newVerts.Add(vertsList[2]);              
    23.  
    24.                 for (int i = 3; i < vertsList.Length; i += 3)
    25.                 {
    26.                     bool check = false;
    27.                     for (int j = 0; j < 3 && !check; j++)
    28.                     {
    29.                         for (int v = 0; v < newVerts.Length && !check; v++)
    30.                         {
    31.                             if (/*newVerts[v] == vertsList[i + j]*/ newVerts[v].Equals(vertsList[i + j]))
    32.                             {
    33.                                 check = true;
    34.                             }
    35.                         }                      
    36.                     }                  
    37.  
    38.                     if (check)
    39.                     {
    40.                         for (int k = 0; k < 3; k++)
    41.                         {
    42.                             newVerts.Add(vertsList[i + k]);
    43.                         }
    44.  
    45.                         for (int k = 0; k < 3; k++)
    46.                         {
    47.                             vertsList.RemoveAt(i + 2 - k);
    48.                         }
    49.  
    50.                         i = 0;
    51.                     }
    52.                 }
    53.  
    54.                 vertsList.RemoveAt(0);
    55.                 vertsList.RemoveAt(0);
    56.                 vertsList.RemoveAt(0);
    57.  
    58.                 if(count == 1)
    59.                 {
    60.                     jobNewVerticesOne.Clear();
    61.                     jobNewIndicesOne.Clear();
    62.  
    63.                     for (int i = 0; i < newVerts.Length; i++)
    64.                     {
    65.                         jobNewVerticesOne.Add(newVerts[i]);
    66.                         jobNewIndicesOne.Add(jobOriginalIndices[i]);
    67.                     }
    68.                 }
    69.                
    70.                 if(count == 2)
    71.                 {
    72.                     jobNewVerticesTwo.Clear();
    73.                     jobNewIndicesTwo.Clear();
    74.  
    75.                     for (int i = 0; i < newVerts.Length; i++)
    76.                     {
    77.                         jobNewVerticesTwo.Add(newVerts[i]);
    78.                         jobNewIndicesTwo.Add(jobOriginalIndices[i]);
    79.                     }
    80.                 }              
    81.             }
    82.         }
    83.     }
    84.  
    85. public List<GameObject> SplitMesh(GameObject objectToSplit, bool disableObjectToSplit = false, string newTag = "Untagged", int newLayer = 0, Transform newParent = null)
    86.     {
    87.         List<GameObject> results = new List<GameObject>();
    88.  
    89.         MeshFilter objectToSplitFilter = objectToSplit.GetComponent<MeshFilter>();
    90.         Mesh objectToSplitMesh = objectToSplitFilter.sharedMesh;
    91.  
    92.         MeshRenderer objectToSplitRenderer = objectToSplit.GetComponent<MeshRenderer>();
    93.         Material objectToSplitMaterial = objectToSplitRenderer.sharedMaterial;
    94.  
    95.         Vector3 objectToSplitPos = objectToSplit.transform.position;
    96.         Vector3 objectToSplitScale = objectToSplit.transform.localScale;
    97.  
    98.         Vector3[] verts = objectToSplitMesh.vertices;
    99.         int[] indices = objectToSplitMesh.triangles;
    100.  
    101.         print(objectToSplitMesh.vertexCount);
    102.         print(objectToSplitMesh.triangles.Length);
    103.  
    104.         float3[] vertsFloat3 = new float3[verts.Length];
    105.         for (int i = 0; i < verts.Length; i++)
    106.         {
    107.             vertsFloat3[i] = verts[i];
    108.         }
    109.  
    110.         m_Vertices = new NativeArray<float3>(vertsFloat3, Allocator.Persistent);      
    111.         m_Indices = new NativeArray<int>(indices, Allocator.Persistent);
    112.  
    113.         m_VerticesOne = new NativeList<float3>(Allocator.Persistent);
    114.         m_IndicesOne = new NativeList<int>(Allocator.Persistent);
    115.  
    116.         m_VerticesTwo = new NativeList<float3>(Allocator.Persistent);
    117.         m_IndicesTwo = new NativeList<int>(Allocator.Persistent);
    118.  
    119.         //m_VerticesList.CopyFrom(verts);
    120.         //m_IndicesList.CopyFrom(indices);      
    121.  
    122.         SplitJob splitJob = new SplitJob()
    123.         {
    124.             jobOriginalVertices = m_Vertices,
    125.             jobOriginalIndices = m_Indices,
    126.  
    127.             jobNewVerticesOne = m_VerticesOne,
    128.             jobNewIndicesOne = m_IndicesOne,
    129.  
    130.             jobNewVerticesTwo = m_VerticesTwo,
    131.             jobNewIndicesTwo = m_IndicesTwo
    132.         };
    133.  
    134.         m_JobHandle = splitJob.Schedule();
    135.         m_JobHandle.Complete();
    136.  
    137.         m_VerticesModifiedOne = new Vector3[splitJob.jobNewVerticesOne.Length];
    138.         for (int i = 0; i < splitJob.jobNewVerticesOne.Length; i++)
    139.         {
    140.             m_VerticesModifiedOne[i] = splitJob.jobNewVerticesOne[i];
    141.         }
    142.  
    143.         m_VerticesModifiedTwo = new Vector3[splitJob.jobNewVerticesTwo.Length];
    144.         for (int i = 0; i < splitJob.jobNewVerticesTwo.Length; i++)
    145.         {
    146.             m_VerticesModifiedTwo[i] = splitJob.jobNewVerticesTwo[i];
    147.         }
    148.  
    149.         m_IndicesModifiedOne = splitJob.jobNewIndicesOne.ToArray();
    150.         m_IndicesModifiedTwo = splitJob.jobNewIndicesTwo.ToArray();
    151.  
    152.         //m_VerticesModified = splitJob.jobNewVertices.ToArray();
    153.         //m_IndicesModified = splitJob.jobNewIndices.ToArray();
    154.  
    155.         if (m_VerticesModifiedOne.Length != 0 && m_IndicesModifiedOne.Length != 0)
    156.         {
    157.             Mesh newMeshCGOne = new Mesh();
    158.             newMeshCGOne.name = objectToSplit.name + "(Clone)";
    159.             newMeshCGOne.Clear();
    160.             newMeshCGOne.vertices = m_VerticesModifiedOne;
    161.             newMeshCGOne.triangles = m_IndicesModifiedOne;
    162.             newMeshCGOne.Optimize();
    163.             newMeshCGOne.RecalculateNormals();
    164.             newMeshCGOne.RecalculateBounds();
    165.  
    166.             GameObject newSplitObjectOne = new GameObject(objectToSplit.transform.name + "(New)");
    167.             newSplitObjectOne.tag = newTag;
    168.             newSplitObjectOne.layer = newLayer;
    169.             newSplitObjectOne.transform.position = objectToSplitPos;
    170.             newSplitObjectOne.transform.localScale = objectToSplitScale;
    171.             newSplitObjectOne.transform.parent = newParent;
    172.             newSplitObjectOne.AddComponent<MeshFilter>().sharedMesh = newMeshCGOne;
    173.             newSplitObjectOne.AddComponent<MeshRenderer>().material = objectToSplitMaterial;
    174.  
    175.             ProBuilderizeShape(newSplitObjectOne);
    176.  
    177.             results.Add(newSplitObjectOne);          
    178.         }
    179.        
    180.         if (m_VerticesModifiedTwo.Length != 0 && m_IndicesModifiedTwo.Length != 0)
    181.         {
    182.             Mesh newMeshCGTwo = new Mesh();
    183.             newMeshCGTwo.name = objectToSplit.name + "(Clone)";
    184.             newMeshCGTwo.Clear();
    185.             newMeshCGTwo.vertices = m_VerticesModifiedTwo;
    186.             newMeshCGTwo.triangles = m_IndicesModifiedTwo;
    187.             newMeshCGTwo.Optimize();
    188.             newMeshCGTwo.RecalculateNormals();
    189.             newMeshCGTwo.RecalculateBounds();
    190.  
    191.             GameObject newSplitObjectTwo = new GameObject(objectToSplit.transform.name + "(New)");
    192.             newSplitObjectTwo.tag = newTag;
    193.             newSplitObjectTwo.layer = newLayer;
    194.             newSplitObjectTwo.transform.position = objectToSplitPos;
    195.             newSplitObjectTwo.transform.localScale = objectToSplitScale;
    196.             newSplitObjectTwo.transform.parent = newParent;
    197.             newSplitObjectTwo.AddComponent<MeshFilter>().sharedMesh = newMeshCGTwo;
    198.             newSplitObjectTwo.AddComponent<MeshRenderer>().material = objectToSplitMaterial;
    199.  
    200.             ProBuilderizeShape(newSplitObjectTwo);
    201.  
    202.             results.Add(newSplitObjectTwo);          
    203.         }
    204.  
    205.         m_Vertices.Dispose();
    206.         m_Indices.Dispose();
    207.  
    208.         m_VerticesOne.Dispose();
    209.         m_IndicesOne.Dispose();
    210.  
    211.         m_VerticesTwo.Dispose();
    212.         m_IndicesTwo.Dispose();
    213.  
    214.         if (disableObjectToSplit)
    215.             objectToSplit.SetActive(false);
    216.  
    217.         return results;
    218.     }
     
  5. Spectra_7

    Spectra_7

    Joined:
    Oct 17, 2017
    Posts:
    33
    Sorry for dumb question. What can I do to improve this?
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,579
    List clear operations are I think expensive. Specially in while loop.
    And in fact you don't need to clear at all.
    First set capacity to required number of elements, or maximum number of elements.
    Then either add, or use index, to iterate throu list / array.
    Increment that index accordingly.
    Not sure why you remove 3 first elements from the list you could skip it from adding.
    In next while iteration, you just rest index to 0 and use that index to write directly to corresponding location in the list / array. Avoiding clear, or removing elements. You will save some CPU cycles on that alone.

    Too much code, I won't be going trough it. Please narrow you problem down.
     
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    It's not. It's just
    Length = 0;
     
    Antypodish likes this.
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,579
    Ah good to know. I thought it also clears values.
    However, removing and then reading whole list (with holes), surely comes with the own cost.
     
  9. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    558
    assuming you already using
    NativeList<>
    /
    NativeArray<>
    :
    if you don't care about ordering, you can use
    RemoveAtSwapBack
    that replaces the element with the last element and decreases the length instead of copying the entire list.

    otherwise, you keep the list unchanged and use an index to keep track of where you are. e.g. instead of
    Code (CSharp):
    1. {
    2.     Foo(list[0]);
    3.     list.RemoveAt(0);
    4. }
    you do
    Code (CSharp):
    1. {
    2.     Foo(list[i]);
    3.     i++;
    4. }
    or use
    .Slice(start, length)
    to operate on a subrange of the data

    also try to reduce copying in general
     
    Nyanpas, Spectra_7 and Antypodish like this.
  10. UsmanMemon

    UsmanMemon

    Joined:
    Jan 24, 2020
    Posts:
    87
    You are scheduling a single threaded job and waiting for it to complete on main-thread right away, It would be better if you just did m_JobHandle.Run(); or schedule parallel jobs and then wait for em to complete.
     
  11. Spectra_7

    Spectra_7

    Joined:
    Oct 17, 2017
    Posts:
    33
    Can you show how to do parallel jobs? I am confused how to do parallel jobs for this case.

    Okay thanks.
     
    Last edited: Mar 10, 2021