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();}
}