- Home /
Best way to optimize mesh updating through code?
I am generating a tilemap on a mesh by making new vertices, triangles and uv maps to a mesh. However I'd like to update the mesh whilst playing the game, like changing a tile texture for example. I have a way of doing this but it feels like there is a much better way to do so, which is less of a hassle on the system. Here is my way, any thoughts on how I could optimize this?
private int squareCount;
private float tUnit = 0.125f;
private List<Vector3> objVertices = new List<Vector3>();
private List<int> objTriangles = new List<int>();
private List<Vector2> objUV = new List<Vector2>();
void GenObjMesh(int x, int y, Vector2 texture)
{
objVertices.Add(new Vector3(x, y, 0));
objVertices.Add(new Vector3(x + 1, y, 0));
objVertices.Add(new Vector3(x + 1, y - 1, 0));
objVertices.Add(new Vector3(x, y - 1, 0));
objTriangles.Add(squareCount * 4);
objTriangles.Add((squareCount * 4) + 1);
objTriangles.Add((squareCount * 4) + 3);
objTriangles.Add((squareCount * 4) + 1);
objTriangles.Add((squareCount * 4) + 2);
objTriangles.Add((squareCount * 4) + 3);
objUV.Add(new Vector2(tUnit * texture.x, tUnit * texture.y + tUnit));
objUV.Add(new Vector2(tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
objUV.Add(new Vector2(tUnit * texture.x + tUnit, tUnit * texture.y));
objUV.Add(new Vector2(tUnit * texture.x, tUnit * texture.y));
squareCount++;
}
public void changeObjData(int[,] mapToChange, float x, float y , int obj)
{
x = Mathf.FloorToInt(x);
y = Mathf.CeilToInt(y);
mapToChange[(int)x, (int)y] = obj; //set info for buildmesh()
objVertices.Clear();
objTriangles.Clear();
objUV.Clear();
squareCount = 0;
GenObjMesh((int)x, (int)y, new Vector2(7, 6)); //new texture
BuildMesh(); //generate map with new info
}
void UpMesh()
{
objMesh.Clear();
objMesh.vertices = objVertices.ToArray();
objMesh.triangles = objTriangles.ToArray();
objMesh.uv = objUV.ToArray();
objMesh.Optimize();
objMesh.RecalculateNormals();
}
//buildmesh() just gathers data to form the entire mesh
The problem with this is that it rebuilds the entire mesh, instead of one object/tile. Any ideas?
You always have to recreate the complete mesh, no way around it. As long as you don't assign colliders as well, it shouldn't be a problem.
alright, won't that cause any lag with big meshes? around 100x100 tiles on a mesh
I know you already have an answer marked, but I thought I'd mention a slightly different solution that may help with the performance hit...of course, it's a "trade off".
There's no requirement that says you have to build the whole replacement mesh in one frame....unless YOU need to. Unity doesn't care. If you can afford to spread the workload across several frames and just update when done, you could use a Finite State $$anonymous$$achine, and do a little work each frame. Build the mesh gradually over several frames, then swap it out.
So you would have different states that the machine would be in... Idle, Initializing, building, Optimize, RecalcNormals, finish-and-apply. You would have some self-selected limits as to how many iterations of "building" you want to do each frame. Just count them and update the counters as you go for the next iteration. So one state, like building, could be spread over several frames too.
Idle would just return. Initializing would set the initial values for your loops. This is also true for the other steps you do. Optimize() could be one state/frame. RecalculateNormals() another. Etc. You'd finish off with the final assignment.
You can even get clever and decide on the # of build iterations per frame based on some arbitrary max-time-limit that you decide on and the average frame rate. Of course, the Optimize() call is still one hit, but at least you can isolate it to its own frame.
All depends on your requirements. And this doesn't solve much of the "send to cpu" issue, but it distributes the calcs for everything. If you don't also update the texture every regen, 100 x 100 tiles may not be that bad.
Answer by FortisVenaliter · May 04, 2016 at 05:22 PM
Unfortunately, Unity does not support updating meshes partially. You set everything or nothing. I've tried running large mesh regeneration, and even with all the optimization in the world, you're still going to have a hitch when sending the data to the GPU. The best way to minimize that, in my experience, is to try to break up the meshes into smaller ones, rotate through the updates, and stitch them together at runtime.
I'd like to add that a major cause of performance hickups are reassignments of collision meshes. If you only update the meshfilter's mesh, chances are that you won't notice it at all.
Your answer
Follow this Question
Related Questions
Mesh adaption 1 Answer
Any articles about mesh's vertices,uv,triangles ? 1 Answer
Easy way to convert a bunch of vertices to triangles or uv's? 1 Answer
Problem Creating a 2D Mesh 1 Answer
Connecting flatshaded vertices 0 Answers