Mesh.triangles and frame rate (deformable vision cone)

Hi Unity gurus.

Me and my group are working on a game project in Unity, and have come across a problem.

We want to have deformable vision cones on our enemies, so that they are shaped according to obstacles. Some of the aliens are detecting in a radius around themselves, utilize by the same function.

The way we have done it is by shooting out rays, and then drawing triangles using mesh.triangles - it is working, but it is severely impacting our frame rate. Especially the aliens that has a circle drawn around them gives a huge hit.

Is the triangles even the way to go? Can anything be done to lower the impact on the frame rate? Is there an easy alternative to do this and why is this seemingly simple operation so heavy on the CPU?

Apologies in advance for the messy code - I’m still learning. :slight_smile:

EDIT: Disabling the Debug.Log helped a lot - still, the frame rate suffers, so the issue stands.

using UnityEngine;
using System.Collections;

public class simpleCone : MonoBehaviour {
	public Transform target;
	private float length;
	private Color coneColor;
	public float angle;
	public int segments;
	float triCount;
	float lastHitDistance;
	int imax;
	int xmax;
	int zmax;
	int check;
	int[] twiangles;
	Mesh mesh;
	Vector3[] checkShape;
	//public Color colors[];
	//public Transform alienTrans = transform;
	
	
	void Start () {
		length = 2.0f;
		gameObject.AddComponent("MeshFilter");
		gameObject.AddComponent("MeshRenderer");
		mesh = GetComponent<MeshFilter>().mesh;
		mesh.Clear();
		Color colors = new Color();
		checkShape = new Vector3[segments+2];
	}
	void Update () {
	}
	
	
	
	void FixedUpdate(){
		calculateCone();
		
	}
	
	
	public void setTypeValues(int _type){
		imax = 2;
		xmax = 6;
		switch(_type){
			case 0:
				zmax = 1;
				coneColor = Color.red;
				break;
			case 1:
				zmax = 6;
				coneColor = Color.yellow;
				break;
			case 2:
				zmax = 1;
				coneColor = Color.blue;
				break;
		}
	}
	
	void drawCone(){
		mesh.vertices = checkShape;		
	}
	
	void calculateCone(){
		
		Stack pointStack = new Stack();
		Stack hitStack = new Stack();
		Color colors = new Color();
		colors = Color.Lerp(Color.red, Color.red, 1);
		
		Vector3 lastHit = new Vector3();
		
		Vector3 tempHit = new Vector3();
		Ray lastRay = new Ray();
		
		int numHits = 0;
		bool wasHit = false;
		bool noHit1 = true;
		bool noHit2 = true;
		bool noHit3 = true;
		transform.Rotate(transform.up, 330F);

		for(int z = 0; z<zmax; z++)
		for(int x = 0; x<xmax; x++){

		for(int i=0; i<imax+1; i++){
			Debug.Log("Check no: "+ check);

			
			Ray ray = new Ray(transform.position, transform.forward);
			

				RaycastHit hit = new RaycastHit();
				
				/*
				if(i==0)
				Debug.DrawRay(transform.position, transform.forward*5, Color.yellow, 0.5F);
				if(i==imax)
				Debug.DrawRay(transform.position, transform.forward*5, Color.yellow, 0.5F);
				 */
				if(Physics.Raycast(ray, out hit, length) && wasHit && hit.distance < 2F){
					Debug.Log("HIT, was HIT" + " at ray: " +i);
				
					lastHit = hit.point;
					lastHitDistance = hit.distance;
					
					wasHit = true;
					
					if(i==imax)
						pointStack.Push(hit.point);
						Debug.Log("ADDED POINT: " + hit.point + " to the stack at ray: " +x +" and " +i);
					} else if(Physics.Raycast(ray, out hit, length) && !wasHit && hit.distance < 2F) {
							Debug.Log("HIT, was NOT hit" + " at ray: " +x +" and " +i);
							if(i==0){
								pointStack.Push(hit.point);
								Debug.Log("ADDED POINT: " + hit.point + " to the stack at ray: " +x +" and " +i);
								
								} else if(i==imax) {
									pointStack.Push(hit.point);
									pointStack.Push(lastRay.GetPoint(length));
									pointStack.Push(lastRay.GetPoint(hit.distance));
									Debug.Log("ADDED POINT: " + hit.point + " to the stack at ray: " +x +" and " +i);
									Debug.Log("ADDED POINT: " + lastRay.GetPoint(length) + " to the stack at ray: " +x +" and " +i);
									Debug.Log("ADDED POINT: " + lastRay.GetPoint(hit.distance) + " to the stack at ray: " +x +" and " +i);
									} else {
								pointStack.Push(lastRay.GetPoint(length));
								pointStack.Push(lastRay.GetPoint(hit.distance));
								Debug.Log("ADDED POINT: " + lastRay.GetPoint(length) + " to the stack at ray: " +x +" and " +i);
								Debug.Log("ADDED POINT: " + lastRay.GetPoint(hit.distance) + " to the stack at ray: " +x +" and " +i);
										}
							lastHitDistance = hit.distance;
					
					wasHit = true;
						} else if(!Physics.Raycast(ray, out hit, length) && wasHit) {
							Debug.Log("NOT, was HIT" + " at ray: " +x +" and " +i);
							if(i==imax){
								pointStack.Push(ray.GetPoint(lastHitDistance));
							}else{
								pointStack.Push(ray.GetPoint(lastHitDistance));
								pointStack.Push(ray.GetPoint(length));
							}
							Debug.Log("ADDED POINT: " + lastRay.GetPoint(length) + " to the stack at ray: " +x +" and " +i);
							Debug.Log("ADDED POINT: " + lastRay.GetPoint(hit.distance) + " to the stack at ray: " +x +" and " +i);
							lastRay = ray;
					
							wasHit = false;
							} else if(!Physics.Raycast(ray, out hit, length) && !wasHit){
								Debug.Log("NOT, was NOT hit" + " at ray: " +x +" and " +i);
								lastRay = ray;
								wasHit = false;
								if(i==0){
									pointStack.Push(ray.GetPoint(length));
					
									Debug.Log("ADDED POINT: " + lastRay.GetPoint(length) + " to the stack at ray: " +x +" and " +i);
									
								}
								
									
								if(i==imax){
									pointStack.Push(ray.GetPoint(length));
									Debug.Log("ADDED POINT: " + lastRay.GetPoint(length) + " to the stack at ray: " +x +" and " +i);
									
								
									}
								}
			if(i<imax)
				transform.Rotate(transform.up * 5F);
				
				}
		}
		
			
		Debug.Log("Slut stckstr: " +pointStack.Count);
		
		transform.localRotation = Quaternion.identity;
		
		checkShape = new Vector3[pointStack.Count+1];
		Vector3 temp = new Vector3(0,0,0);
		
		checkShape[0] = temp;
		
		
		triCount = pointStack.Count + 1;
		
		if(triCount>0){
			for(int b = pointStack.Count; b > 0; b--){
				temp = (Vector3)pointStack.Pop();
				temp = transform.InverseTransformPoint(temp);
				checkShape **= temp;**

** }**
** mesh.vertices = checkShape;**

** for(int b = 0; b < checkShape.Length; b++)**
__ Debug.Log("Vert " +b + “:” + checkShape**);**__

__ int twiangles = new int[((checkShape.Length-2)*3)];__

** Debug.Log(“Twi Length” + twiangles.Length);**
** Debug.Log(“check Length” + checkShape.Length);**

** for(int v = 0; v < twiangles.Length; v++){**

** if(v < 3) {**
** twiangles[v] = v;**

** }**

** if(v >=3){**
** if((v%3) == 0){**
** twiangles[v] = 0;**

** } else if((v%3) == 1) {**
** twiangles[v] = twiangles[v-2];**
** } else if((v%3) == 2){**
** twiangles[v] = twiangles[v-1]+1;**
** }**
** }**

** }**

** mesh.triangles = twiangles;**

** Debug.Log("Number of Triangles to be drawn: " + ((twiangles.Length-1)/2));**

** renderer.material.color = coneColor;**

** Debug.Log("Number of vertices with origin: " + checkShape.Length + " - so the number of triangles drawn should be: " + ((checkShape.Length-1)/2));**

** }**

}

}

Tying the function to the physics update rate in FixedUpdate probably isn’t something you want to do. Assuming you have physics updating at the default 50fps, do you really need this vision cone to be updated that often? I’d recommend using InvokeRepeating, and 10 times per second is probably enough.

A couple things I see: Since you’re using the transform component repeatedly, you can get a bit of a speedup by caching it in a variable. Also you’d want to use a generic Stack, so you don’t have to box/unbox all the time.