generated box mesh collision causing convex hull init/computation failed error

I have been following a series of rts tutorials, currently up to 45 out of 81, the error started happening on the 41st video and was not resolved by the end of that series, perhaps an update to unity changed the way this works because the tutorial maker did not seem to have a problem. Here is that 41st vid, incase it helps someone to understand my issue. Unity - All About Trigger Events + Example

It deals with generating a mesh and applying it to the camera, moving the vertices and using the mesh collision to aid in detecting units selected with the mouse.

It works great until the error comes up, If I continue to play past the error it still works, however sometimes the framerate drops from over 1000 to about 4.

ConvexMesh::loadConvexHull: convex hull init failed!

createHull: convex hull computation failed!

those are the two errors that keep popping up, I can’t understand why… it is nowhere near 255 tris.

the errors refer to three lines of code right at the end of the UpdateDragBoxMesh function, each line getting both errors… but all the code does what it is supposed too, the errors are spread out and seem random

these are the lines.

meshc.sharedMesh = mesh;

DragSelectMesh.transform.Translate(0.1f, 0, 0);

DragSelectMesh.transform.Translate(-0.1f, 0, 0);

UpdateDragBoxMesh is being called from LateUpdate when I’m performing a mouse drag.

I’m not sure how much of the script I should put here, since these are pretty big I will just include the updatebox and createbox functions… Basically I’m just hoping someone will be able to spot why this is giving me such a headache at the moment.

********************************

public void UpdateDragBoxMesh()
{
MeshCollider meshc = DragSelectMesh.GetComponent();
meshc.sharedMesh = null;

	Vector2 p0Ratio = new Vector2(boxFinish.x / (Screen.width * 0.01f) * 0.01f, (boxFinish.y + Mathf.Abs(boxHeight)) / (Screen.height * 0.01f) * 0.01f);

	Vector2 p1Ratio = new Vector2(boxStart.x / (Screen.width * 0.01f) * 0.01f, boxStart.y / (Screen.height * 0.01f) * 0.01f);

	Vector2 p2Ratio = new Vector2(boxStart.x / (Screen.width * 0.01f) * 0.01f, (boxStart.y - Mathf.Abs (boxHeight)) / (Screen.height * 0.01f) * 0.01f);

	Vector2 p3Ratio = new Vector2(boxFinish.x / (Screen.width * 0.01f) * 0.01f, boxFinish.y / (Screen.height * 0.01f) * 0.01f);

	ClipPlanePoints nearClipPlanePoints = CameraClipPlanePoints(Camera.main.nearClipPlane + 30f);
	ClipPlanePoints farClipPlanePoints = CameraClipPlanePoints(DistanceFromCameraToGround());

	float nearPlaneWidth = Vector3.Distance(nearClipPlanePoints.LowerLeft, nearClipPlanePoints.LowerRight);
	float nearPlaneHeight = Vector3.Distance(nearClipPlanePoints.UpperRight, nearClipPlanePoints.LowerRight);
	float farPlaneWidth = Vector3.Distance(farClipPlanePoints.LowerLeft, farClipPlanePoints.LowerRight);
	float farPlaneHeight = Vector3.Distance(farClipPlanePoints.UpperRight, farClipPlanePoints.LowerRight);

	Pointer.transform.position = nearClipPlanePoints.LowerLeft;
	Pointer.transform.eulerAngles = Camera.main.transform.eulerAngles;
	Pointer.transform.Translate(nearPlaneWidth * p0Ratio.x, nearPlaneHeight * p0Ratio.y, 0f);

	Vector3 p0 = Pointer.transform.position;

	Pointer.transform.position = nearClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(nearPlaneWidth * p1Ratio.x, nearPlaneHeight * p1Ratio.y, 0f);

	Vector3 p1 = Pointer.transform.position;

	Pointer.transform.position = nearClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(nearPlaneWidth * p2Ratio.x, nearPlaneHeight * p2Ratio.y, 0f);
	
	Vector3 p2 = Pointer.transform.position;

	Pointer.transform.position = nearClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(nearPlaneWidth * p3Ratio.x, nearPlaneHeight * p3Ratio.y, 0f);
	
	Vector3 p3 = Pointer.transform.position;

	Pointer.transform.position = farClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(farPlaneWidth * p0Ratio.x, farPlaneHeight * p0Ratio.y, 0f);
	
	Vector3 p4 = Pointer.transform.position;
	
	Pointer.transform.position = farClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(farPlaneWidth * p1Ratio.x, farPlaneHeight * p1Ratio.y, 0f);
	
	Vector3 p5 = Pointer.transform.position;
	
	Pointer.transform.position = farClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(farPlaneWidth * p2Ratio.x, farPlaneHeight * p2Ratio.y, 0f);
	
	Vector3 p6 = Pointer.transform.position;
	
	Pointer.transform.position = farClipPlanePoints.LowerLeft;
	Pointer.transform.Translate(farPlaneWidth * p3Ratio.x, farPlaneHeight * p3Ratio.y, 0f);
	
	Vector3 p7 = Pointer.transform.position;

	Mesh mesh = DragSelectMesh.GetComponent<MeshFilter>().mesh;
	Vector3[] vertices = new Vector3[]
	{
		// Bottom
		p0, p1, p2, p3,
		
		// Left
		p7, p4, p0, p3,
		
		// Front
		p4, p5, p1, p0,
		
		// Back
		p6, p7, p3, p2,
		
		// Right
		p5, p6, p2, p1,
		
		// Top
		p7, p6, p5, p4
	};

	mesh.vertices = vertices;

	meshc.sharedMesh = mesh;

	DragSelectMesh.transform.Translate(0.1f, 0, 0);
	DragSelectMesh.transform.Translate(-0.1f, 0, 0);
}

And here is the Create method


    public void CreateDragBoxMesh()
    	{
    		DragSelectMesh = new GameObject();
    		DragSelectMesh.name = "DragSelectMesh";
    		DragSelectMesh.transform.position = Vector3.zero;
    
    		//MeshRenderer renderer = DragSelectMesh.AddComponent<MeshRenderer>();
    		//renderer.material = DragSelectMeshMat;
    
    		MeshFilter filter = DragSelectMesh.AddComponent<MeshFilter>();
    		Mesh mesh = filter.mesh;
    
    		mesh.Clear();
    		
    		float length = 20f;
    		float width = 20f;
    		float height = 20f;
    		
    		#region Vertices
    		Vector3 p0 = new Vector3( -length * .5f,	-width * .5f, height * .5f );
    		Vector3 p1 = new Vector3( length * .5f, 	-width * .5f, height * .5f );
    		Vector3 p2 = new Vector3( length * .5f, 	-width * .5f, -height * .5f );
    		Vector3 p3 = new Vector3( -length * .5f,	-width * .5f, -height * .5f );	
    		
    		Vector3 p4 = new Vector3( -length * .5f,	width * .5f,  height * .5f );
    		Vector3 p5 = new Vector3( length * .5f, 	width * .5f,  height * .5f );
    		Vector3 p6 = new Vector3( length * .5f, 	width * .5f,  -height * .5f );
    		Vector3 p7 = new Vector3( -length * .5f,	width * .5f,  -height * .5f );
    		
    		Vector3[] vertices = new Vector3[]
    		{
    			// Bottom
    			p0, p1, p2, p3,
    			
    			// Left
    			p7, p4, p0, p3,
    			
    			// Front
    			p4, p5, p1, p0,
    			
    			// Back
    			p6, p7, p3, p2,
    			
    			// Right
    			p5, p6, p2, p1,
    			
    			// Top
    			p7, p6, p5, p4
    		};
    		#endregion
    		
    		#region Normals
    		Vector3 up 	= Vector3.up;
    		Vector3 down 	= Vector3.down;
    		Vector3 front 	= Vector3.forward;
    		Vector3 back 	= Vector3.back;
    		Vector3 left 	= Vector3.left;
    		Vector3 right 	= Vector3.right;
    		
    		Vector3[] normals = new Vector3[]
    		{
    			// Bottom
    			down, down, down, down,
    			
    			// Left
    			left, left, left, left,
    			
    			// Front
    			front, front, front, front,
    			
    			// Back
    			back, back, back, back,
    			
    			// Right
    			right, right, right, right,
    			
    			// Top
    			up, up, up, up
    		};
    		#endregion	
    		
    		#region UVs
    		Vector2 _00 = new Vector2( 0f, 0f );
    		Vector2 _10 = new Vector2( 1f, 0f );
    		Vector2 _01 = new Vector2( 0f, 1f );
    		Vector2 _11 = new Vector2( 1f, 1f );
    		
    		Vector2[] uvs = new Vector2[]
    		{
    			// Bottom
    			_11, _01, _00, _10,
    			
    			// Left
    			_11, _01, _00, _10,
    			
    			// Front
    			_11, _01, _00, _10,
    			
    			// Back
    			_11, _01, _00, _10,
    			
    			// Right
    			_11, _01, _00, _10,
    			
    			// Top
    			_11, _01, _00, _10,
    		};
    		#endregion
    		
    		#region Triangles
    		int[] triangles = new int[]
    		{
    			// Bottom
    			3, 1, 0,
    			3, 2, 1,			
    			
    			// Left
    			3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1,
    			3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,
    			
    			// Front
    			3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2,
    			3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,
    			
    			// Back
    			3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3,
    			3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,
    			
    			// Right
    			3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4,
    			3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,
    			
    			// Top
    			3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5,
    			3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5,
    			
    		};
    		#endregion
    		
    		mesh.vertices = vertices;
    		mesh.normals = normals;
    		mesh.uv = uvs;
    		mesh.triangles = triangles;
    		
    		mesh.RecalculateBounds();
    		mesh.Optimize();
    
    		DragSelectMesh.AddComponent<DragMeshTrigger>();
    		Rigidbody rigidbody = DragSelectMesh.AddComponent<Rigidbody>();
    		rigidbody.useGravity = false;
    
    		MeshCollider meshc = DragSelectMesh.AddComponent<MeshCollider>();
    		meshc.isTrigger = true;
    		meshc.convex = true;
    
    		meshc.sharedMesh = filter.mesh;
    	}

Well, first of all that’s a horrible way to get the worldspace frustum of a selected screen rect. You actually just need Camera.ScreenToWorldPoint with each corner of your screen space box. Once with your near distance as z and once with your far distance as z.

Anyways your problem is simply a copy&past error. For each corner you used farClipPlanePoints.LowerLeft, so your mesh has effectively no size at all. The offending lines are 17, 23, 28, 33, 38, 43, 48 and 53.

ps:
Juat as a side note: changing a simple mesh at runtime actually works quite well in Unity, even complex meshes. However changing a meshcollider each Update can give you a huge performance hit since the physics system has to recreate the collider.

For performance it would be better to just use a fix mesh collider with the camera’s view frustum so you get all objects within the view and then just iterate through them, convert their position into screen space (with Camera.WorldToScreenPoint) and just do a 2d Rect.Contains check with your selection rect. This of course behaves slightly different to the collider approach, since the colliders will get in touch before the objects pivot is inside the selection. This approach can be modified to use an approximate screen space bounds rect which you could do a simple intersection check (AABB).