Optimisation problems with altering mesh.vertices

Hey guys,

For the past week or so I’ve been spending my spare time trying different methods to create a “fog of war” type effect for a RTS type game.

I have found numerous posts on here with plentyful information, and through them have found the most optimised method out of the ones suggested.

Notes:

-I do not have Unity Pro (yet) and would much prefer to build this feature on my own (please no suggestions that require Unity Pro, or someone elses work from the Asset Store).

-The game I am working on will require a vast amount of units to be on the screen at any given time. Hence the performance issues.

So, the most optimised method that I have found out of many that I have so far tried is to place a single plane just above the walkable area and raycast onto the plane. Then iterate through each vertex of the plane and make each vertice within range have an alpha of 0 in color, ultimately creating a transparent circle(ish) around the unit.

This works really well visually, The plane that I am currently using has 1089 vertice in total. I could potentially shave a some vertices off of the plane however making it any smaller would cause unpreferrable accuracy due to the space between the vertices.

The major issue is that although I am currently working on the game entirely using the basic geometry that comes with Unity (I haven’t yet built any models to use in the game), after spawning roughly 5 units, each raycasting onto the plane every 0.5 seconds, the fps drops way too much. Particularly considering that the game would ideally need to support far more units than this.

Here is the basis of my code:

	void calculateVision()
	{
		//because the plane's normal is facing up the way, we our ray to collide from above, downwards.
		ray = new Ray(transform.position+(transform.up*5f),-transform.up);
		
		if(cnfg.fogcollider.Raycast(ray,out hitinfo, 5f))
		{
			//get the relative position of the hit point on the fogplane's mesh
			relPoint = cnfg.fogmesh.transform.InverseTransformPoint(hitinfo.point);
			
			Color[] colors = cnfg.fogmesh.mesh.colors;
			
			//iterate through each vertice
			for(int i = 0; i < cnfg.fogmesh.mesh.vertices.Length; i++)
			{				
				//if the distance between the vertice and the hit point is less than vision range, grant vision
				if(Vector3.Distance(cnfg.fogmesh.mesh.vertices*, relPoint) < visionRange)*
  •  		{*
    

_ colors*.a = 0f;_
_
}_
_
}*_

* //apply the changes*
* cnfg.fogmesh.mesh.colors = colors;*
* }*

* //rerun the function*
* Invoke(“calculateVision”,cnfg.minionFogIteration);*
* }*
cnfg.fogmesh is the meshFilter of the fog plane.
So ultimately my question is, other than further reducing the cnfg.minionFogIteration time and lowering the vertex count in the fog plane, is there a more optimised method to achieve what it is that I am trying to do, or am I just plain stupid for trying to do this in Unity Free?
I will be happy to provide a package of what I have so far if that would be any use to anyone.
Many thanks in advance for any suggestions.

cnfg.fogmesh.mesh.colors = colors;

is expensive operation - modify colors for all units and then set it on the mesh.

You should use Mesh.colors32 rather than Mesh.colors. Also, if the plane doesn’t change in size, there’s no need to get a new Colors32 array from the mesh every time; just use a global Colors32 array and upload that to the mesh when needed. Getting the mesh every loop iteration isn’t good (and Length can also be optimized a bit by not using it), so instead: int end = cnfg.fogmesh.mesh.vertices.Length; for(int i = 0; i < end....

A better idea overall would probably be to not iterate through every possible vertex, but use some kind of bucket system, so you just iterate though some of the nearer ones.

Thanks for all the tips guys. It would appear that we all had a similar goal in mind, which was to lower the number of iterations as much as possible. You will be pleased to know that I have lowered the iterations to a big fat ZERO!! Haha yeah, i’m pretty happy about that.

If anyone wants to actually see code, please let me know and I will be happy to share it. However, to keep things short, here’s how I have done it:

  1. At startup, I am creating a plane from scratch. The one major reason for doing this is so that the distance between each vertex is a value which can be easily converted to Unity world units. Initially I was basing the method on this entirely, but later this was simply used for optimisation.

  2. While I add a vertex to the mesh, I am also instantiating a “node” into the world at the exact position of the vertex in the world. This will later be used to trigger a collision.

  3. IMPORTANT: To each node, I save the index value of the vertex that is in the same position as the node.

  4. To each unit, I then add a capsule collider and increase the range of the capsule collider to the vision range of that unit (the range that should remove the fog of war effect). IMPORTANT: Set this collider to be a trigger and add a rigidbody to it.

  5. OnTriggerEnter, I am checking for fogNodes. I then activate them and keep them activated during OnTriggerStay, and deactivate them OnTriggerEnter. Each node is running an Update loop and fading in and out the transparency based on whether it is activated or not.

Also, thanks to @Paulius Leikis for the suggestion regarding making sure that each unit accesses a publically visibly color array. This has increased performance roughly 16%.

After stress testing the above process, with a whopping 16236 vertice plane and well over 100 units, I am struggling to lower the fps!!

You can try it out here:
http://towerdefense.pixelpug.co.uk/TD.html

Thanks again for the help guys.