I’m having a major performance issue in my editor tool. I’m trying to create a low-poly terrain editor. Currently I’m trying to figure out how to modify the terrain by manipulating vertex positions, which is turning out to hog a lot of CPU time. (A lot is an understatement)
The performance problem I’m having is due to the fact that I’m looping through a list of vertices of a mesh, every frame. This mesh can have several thousands of vertices. I’m sure you already see a problem here. One does not simply loop through a list consisting of thousands of values every single frame.
The reason I’m looping through this list is because I need to find the vertex that is closest to a specific point in space. I do this by looping through the vertices array of the mesh and compare each item in the array with another Vector3 (the point), and check which one is the closest. So what I need to do is to try to figure out a way to loop through this list more efficiently. The problem is that I’m really, really bad at algorithms, so I can’t seem to figure out a way to do this.
The current function I’m using looks like this:
public int GetVertexClosestToPoint(Vector3 point)
{
int closestIndex = -1;
float closestRange = Mathf.Infinity;
for (int i = 0; i < terrainMesh.vertices.Length; i++)
{
float currentDist = Vector3.Distance(terrainMesh.vertices*, point);*
I would use the fact that it’s a grid to your advantage. Rather than checking all points, check outward from the point you have just assigned.
Imagine a single line with a point every whole number from 1 to 10. If your click point is 5.249, you know logically that it is in between 5 and 6. The more you increase the brush size, the more points it encompasses. If you increase the brush size to three, you can now easily do the math and know which points exactly you will grab.
Just scale that up to a 2D grid using the same logic for both X and Y coordinates. The Z coordinate (up and down) can then be modified as a percentage of the distance each “in range” point is from the the click point.
Hi just to be sure: there is a common mistake with Unity’s Mesh: each time you call Mesh.vertices, it returns a new copy of the Vector3 array, so if in your code terrainMesh is of type Mesh, you are getting a new copy or the array for each vertex! and this is very slow (allocation etc…). Just use a local variable terrainVertices = terrainMesh.vertices outside the loop and see if there are improvements.
Now if the terrain mesh does not change, keep the vertices array in a local variable to your class to avoid asking/allocating the array at each call!
Second, computing the distance is not necessary: the squares distance is enough (distance uses a square root that is not the fastest math function). Avoiding to call a math function will also save a few cycles + memory operations: compute the (vector) difference between point and terrainVertices (.x - .x etc…), then multiply it by itself (x*x etc…) and sum x+y+z to get the squared distance. Also, if your mesh have or can have a mesh collider, check documentation for Collider.ClosestPoint! Edit: seeing your other comment: try use Mesh.GetVertices/SetVertices so you only alloc vertices once and work with the returned list of vertices.