Coal Wall Creation And Code Optimization

Code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using ZongCaiGongZuoMian;

public class CoalWall : MonoBehaviour
{
	[SerializeField]
	Material mat;

	float zjInternal;//支架间隔
	float zjHeightMax;
	Transform trWheel01;//第一个滚筒
	Transform trWheel02;//第二个滚筒
	Transform[] gbTrans;//刮板机组
	float vertInternal;//点间隔
	float vertInternalSqrt;
	[SerializeField]
	float wheelRadius = 1f;//滚筒半径
	public float radiusOfWheel { get { return wheelRadius; } }
	float wheelRadiusSqrt;
	[SerializeField]
	float distGBToWall = 1;

	Vector3 curPos01;
	Vector3 curPos02;
	List<Vector3> listPos01 = new List<Vector3>();
	List<Vector3> listPos02 = new List<Vector3>();

	Mesh mesh;
	int wVertCount;
	int hVertCount;
	float wSize;
	float hSize;
	int countWRadius;
	int countHRadius;

	Transform trCoalWall;

	IEnumerator Start()
	{
		zjInternal = ZongCaiManager.instance.zjInternal;
		zjHeightMax = 3;
		//
		yield return new WaitUntil(delegate { return ZongCaiManager.instance.caiMeiJi; });
		trWheel01 = ZongCaiManager.instance.caiMeiJi.coalWallPointLeft;
		trWheel02 = ZongCaiManager.instance.caiMeiJi.coalWallPointRight;
		//curPos随便赋值一下,最好远离煤壁实际位置,这样在更新的时候直接发现位置有区别,就开始计算了。
		curPos01 = Vector3.left * 100;
		curPos02 = Vector3.left * 100;
		listPos01.Add(curPos01);
		listPos02.Add(curPos02);
		wheelRadiusSqrt = wheelRadius * wheelRadius;
		//
		yield return new WaitUntil(delegate { return ZongCaiManager.instance.gbTrans.Length > 0; });
		gbTrans = ZongCaiManager.instance.gbTrans;
		vertInternal = zjInternal * 0.12f;
		vertInternalSqrt = vertInternal * vertInternal;
		//
		Create(zjInternal * (gbTrans.Length + 1), zjHeightMax, vertInternal);
	}

	public void Create(float width, float height, float unitSize)
	{
		GameObject objCoalWall = new GameObject("CoalWall");
		trCoalWall = objCoalWall.transform;
		trCoalWall.SetParent(transform);
		trCoalWall.position = gbTrans[0].position + Vector3.forward * distGBToWall;

		int wCount = Mathf.CeilToInt(width / unitSize);
		int hCount = Mathf.CeilToInt(height / unitSize);
		wVertCount = wCount + 1;
		hVertCount = hCount + 1;
		wSize = width / wCount;
		hSize = height / hCount;
		countWRadius = (int)(wheelRadius / wSize) + 1;
		countHRadius = (int)(wheelRadius / hSize) + 1;

		Vector3[] vs = new Vector3[wVertCount * hVertCount];
		for (int i = 0; i < wVertCount; i++)
		{
			for (int j = 0; j < hVertCount; j++)
			{
				vs[i * hVertCount + j] = new Vector3(i * wSize, j * hSize, 0);
			}
		}

		int[] ts = new int[wCount * hCount * 6];
		int k = 0;
		for (int i = 0; i < wCount; i++)
		{
			for (int j = 0; j < hCount; j++)
			{
				ts[k + 0] = i * hVertCount + j;
				ts[k + 1] = ts[k + 0] + 1;
				ts[k + 2] = (i + 1) * hVertCount + j;
				ts[k + 3] = ts[k + 1];
				ts[k + 4] = ts[k + 2] + 1;
				ts[k + 5] = ts[k + 2];
				k += 6;
			}
		}

		Vector2[] uvs = new Vector2[vs.Length];
		for (int i = 0; i < uvs.Length; i++)
		{
			uvs[i] = vs[i] * 0.2f;
		}

		mesh = new Mesh();
		mesh.vertices = vs;
		mesh.triangles = ts;
		mesh.RecalculateNormals();
		mesh.uv = uvs;

		MeshFilter filter = objCoalWall.AddComponent<MeshFilter>();
		filter.mesh = mesh;
		MeshRenderer render = objCoalWall.AddComponent<MeshRenderer>();
		render.material = mat;
	}

	void Update()
	{
		UpdateListPos();
		UpdateMeshByLastPos();
		UpdateByGuaBan();
	}

	int listMaxCount = 16;

	void UpdateListPos()
	{
		if (!trCoalWall) return;
		if (!trWheel01) return;
		if (!trWheel02) return;
		//
		Vector3 pos = trCoalWall.InverseTransformPoint(trWheel01.position);
		if ((pos - listPos01[listPos01.Count - 1]).sqrMagnitude > vertInternalSqrt)
		{
			listPos01.Add(pos);
			while (listPos01.Count > listMaxCount)
			{
				listPos01.RemoveAt(0);
			}
		}

		pos = trCoalWall.InverseTransformPoint(trWheel02.position);
		if ((pos - listPos02[listPos02.Count - 1]).sqrMagnitude > vertInternalSqrt)
		{
			listPos02.Add(pos);
			while (listPos02.Count > listMaxCount)
			{
				listPos02.RemoveAt(0);
			}
		}
	}

	UnityAction<Transform> onCutLeft;
	public void AddActCutLeft(UnityAction<Transform> act) { onCutLeft -= act; onCutLeft += act; }
	public void RemoveActCutLeft(UnityAction<Transform> act) { onCutLeft -= act; }
	UnityAction<Transform> onCutRight;
	public void AddActCutRight(UnityAction<Transform> act) { onCutRight -= act; onCutRight += act; }
	public void RemoveActCutRight(UnityAction<Transform> act) { onCutRight -= act; }

	void UpdateMeshByLastPos()
	{
		if (!mesh) return;
		//
		bool changed01 = false;
		bool changed02 = false;

		if (!Mathf.Approximately((curPos01 - listPos01[listPos01.Count - 1]).sqrMagnitude, 0))
		{
			changed01 = true;
			curPos01 = listPos01[listPos01.Count - 1];
		}

		if (!Mathf.Approximately((curPos02 - listPos02[listPos02.Count - 1]).sqrMagnitude, 0))
		{
			changed02 = true;
			curPos02 = listPos02[listPos02.Count - 1];
		}

		if (changed01 || changed02)
		{
			Vector3[] vs = mesh.vertices;

			if (changed01)
			{
				UpdateVerticeByWheel(vs, trWheel01, curPos01, onCutLeft);
			}

			if (changed02)
			{
				UpdateVerticeByWheel(vs, trWheel02, curPos02, onCutRight);
			}

			mesh.vertices = vs;
			mesh.RecalculateNormals();
		}
	}

	void UpdateVerticeByWheel(Vector3[] vertices, Transform trWheel, Vector3 curPos, UnityAction<Transform> act)
	{
		Vector3 posToWall = trCoalWall.InverseTransformPoint(trWheel.position);
		//
		int iW = Mathf.RoundToInt(posToWall.x / wSize);
		int iWMin = Mathf.Clamp(iW - countWRadius, 0, wVertCount);
		int iWMax = Mathf.Clamp(iW + countWRadius, 0, wVertCount);
		//
		int iH = Mathf.RoundToInt(posToWall.y / hSize);
		int iHMin = Mathf.Clamp(iH - countHRadius, 0, hVertCount);
		int iHMax = Mathf.Clamp(iH + countHRadius, 0, hVertCount);

		for (int i = iWMin; i < iWMax; i++)
		{
			for (int j = iHMin; j < iHMax; j++)
			{
				int index = i * hVertCount + j;
				Vector2 v2 = vertices[index] - curPos;
				if (v2.sqrMagnitude > wheelRadiusSqrt) continue;
				if (vertices[index].z < curPos.z) vertices[index].z = curPos.z;
				act?.Invoke(trWheel01);
			}
		}
	}

	float timeUpdateByGuaBan = -100;
	void UpdateByGuaBan()
	{
		if (!mesh) return;

		if (Time.time - timeUpdateByGuaBan < 5) return;
		timeUpdateByGuaBan = Time.time;

		Vector3[] vs = mesh.vertices;
		Vector3[] colPs = new Vector3[gbTrans.Length];
		for (int i = 0; i < gbTrans.Length; i++)
		{
			colPs[i] = trCoalWall.InverseTransformPoint(gbTrans[i].position);
			colPs[i].z += distGBToWall;
		}

		int indexGB = 0;
		for (int i = 0; i < wVertCount; i++)
		{
			int indexW = i * hVertCount;
			Vector3 v = vs[indexW];
			while (v.x > colPs[indexGB].x)
			{
				if (indexGB >= colPs.Length - 1) break;
				indexGB++;
			}
			for (int j = 0; j < hVertCount; j++)
			{
				vs[indexW + j].z = colPs[indexGB].z;
			}
		}
		//
		float xMin = float.MaxValue;
		float xMax = float.MinValue;
		float yMin = float.MaxValue;
		float yMax = float.MinValue;
		foreach (Vector3 pos in listPos01)
		{
			if (xMin > pos.x) xMin = pos.x;
			if (xMax < pos.x) xMax = pos.x;
			if (yMin > pos.y) yMin = pos.y;
			if (yMax < pos.y) yMax = pos.y;
		}
		foreach (Vector3 pos in listPos02)
		{
			if (xMin > pos.x) xMin = pos.x;
			if (xMax < pos.x) xMax = pos.x;
			if (yMin > pos.y) yMin = pos.y;
			if (yMax < pos.y) yMax = pos.y;
		}

		int iWMin = Mathf.Clamp(Mathf.RoundToInt(xMin / wSize) - countWRadius, 0, wVertCount);
		int iWMax = Mathf.Clamp(Mathf.RoundToInt(xMax / wSize) + countWRadius, 0, wVertCount);
		int iHMin = Mathf.Clamp(Mathf.RoundToInt(yMin / hSize) - countHRadius, 0, hVertCount);
		int iHMax = Mathf.Clamp(Mathf.RoundToInt(yMax / hSize) + countHRadius, 0, hVertCount);

		for (int i = iWMin; i < iWMax; i++)
		{
			for (int j = iHMin; j < iHMax; j++)
			{
				int index = i * hVertCount + j;
				foreach (Vector3 pos in listPos01)
				{
					Vector2 v2 = vs[index] - pos;
					if (v2.sqrMagnitude > wheelRadiusSqrt) continue;
					if (vs[index].z < pos.z) vs[index].z = pos.z;
				}

				foreach (Vector3 pos in listPos02)
				{
					Vector2 v2 = vs[index] - pos;
					if (v2.sqrMagnitude > wheelRadiusSqrt) continue;
					if (vs[index].z < pos.z) vs[index].z = pos.z;
				}
			}
		}
		//
		mesh.vertices = vs;
		mesh.RecalculateNormals();
	}
}

猜你喜欢

转载自blog.csdn.net/ttod/article/details/132574893
今日推荐