实现模型拖拽体积改变功能算法:
public Transform crossLeft; public Transform cro***ight; public Transform arrowUp; public Transform arrowDown; //模型结构子对象 public Transform legLeftUp; public Transform legRightUp; public Transform legLeftDown; public Transform legRightDown; public Transform arrow; /// /// 传动带模型MeshFilter /// public MeshFilter conveyorMeshFilter; /// /// 传送带边沿护栏模型MeshFilter /// public MeshFilter guardBarMeshFilter; public BoxCollider boxCollider; //Mesh保存 private Dictionary conveyorMeshLeftVertices; private Dictionary conveyorMeshRightVertices; private Dictionary conveyorMeshUpVertices; private Dictionary conveyorMeshDownVertices; private Dictionary guardBarMeshLeftVertices; private Dictionary guardBarMeshRightVertices; private Dictionary guardBarMeshUpVertices; private Dictionary guardBarMeshDownVertices; //交互所用变量 private float firstDistanceToOtherCross; private Vector3 nowInputMousePosition; float endDistance; private Transform otherCross; private Vector3 otherCrossScreenPostion; private Vector3 lastInputMousePoistion;
核心方法:
//初始化 void Init() { conveyorMeshLeftVertices = FiltrateVertices(conveyorMeshFilter.mesh, VecticeDir.Left); conveyorMeshRightVertices = FiltrateVertices(conveyorMeshFilter.mesh, VecticeDir.Right); conveyorMeshUpVertices = FiltrateVertices(conveyorMeshFilter.mesh, VecticeDir.Up); conveyorMeshDownVertices = FiltrateVertices(conveyorMeshFilter.mesh, VecticeDir.Down); guardBarMeshLeftVertices = FiltrateVertices(guardBarMeshFilter.mesh, VecticeDir.Left); guardBarMeshRightVertices = FiltrateVertices(guardBarMeshFilter.mesh, VecticeDir.Right); guardBarMeshUpVertices = FiltrateVertices(guardBarMeshFilter.mesh, VecticeDir.Up); guardBarMeshDownVertices = FiltrateVertices(guardBarMeshFilter.mesh, VecticeDir.Down); //length = 1; //heigth = 1; boxCollider = gameObject.GetComponent(); if (name.Contains("left")) { otherCross = converyEntityMediator.converyEntityView.cro***ight; isLeft = true; } else { otherCross = converyEntityMediator.converyEntityView.crossLeft; isLeft = false; } } /// /// 筛选顶点,分成左右两堆 /// /// 顶点方向 Dictionary FiltrateVertices(Mesh mesh, VecticeDir dir) { Dictionary result = new Dictionary(); for (int i = 0; i < mesh.vertices.Length; i++) { switch (dir) { case VecticeDir.Left: if (mesh.vertices[i].z > 0) { result.Add(i, mesh.vertices[i]); } break; case VecticeDir.Up: if (mesh.vertices[i].x > 0) { result.Add(i, mesh.vertices[i]); } break; case VecticeDir.Right: if (mesh.vertices[i].z < 0) { result.Add(i, mesh.vertices[i]); } break; case VecticeDir.Down: if (mesh.vertices[i].x < 0) { result.Add(i, mesh.vertices[i]); } break; } } return result; } //宽度 public void ChangeWidth(float width,Vector3 dir, bool isUp) { List conveyorMeshVertices = new List(conveyorMeshFilter.mesh.vertices); List guardBarMeshVertices = new List(guardBarMeshFilter.mesh.vertices); float halfWidth = width / 2; transform.position += halfWidth * (transform.rotation * dir).normalized; //this.length += length; //改变板和边栏的长度 foreach (KeyValuePair item in conveyorMeshUpVertices) { conveyorMeshVertices[item.Key] += Vector3.right * halfWidth; } foreach (KeyValuePair item in conveyorMeshDownVertices) { conveyorMeshVertices[item.Key] -= Vector3.right * halfWidth; } foreach (KeyValuePair item in guardBarMeshUpVertices) { guardBarMeshVertices[item.Key] += Vector3.right * halfWidth; } foreach (KeyValuePair item in guardBarMeshDownVertices) { guardBarMeshVertices[item.Key] -= Vector3.right * halfWidth; } if (isUp) { //设置子物体的位置 legLeftUp.localPosition += halfWidth * dir; legRightUp.localPosition += halfWidth * dir; legLeftDown.localPosition -= halfWidth * dir; legRightDown.localPosition -= halfWidth * dir; arrowUp.localPosition += halfWidth * dir; arrowDown.localPosition -= halfWidth * dir; } else { //设置子物体的位置 legLeftUp.localPosition -= halfWidth * dir; legRightUp.localPosition -= halfWidth * dir; legLeftDown.localPosition += halfWidth * dir; legRightDown.localPosition += halfWidth * dir; arrowUp.localPosition -= halfWidth * dir; arrowDown.localPosition += halfWidth * dir; } float arrowScale = Mathf.Clamp(((ConveyorEntity)entity).conveyorProperty.Width * 2f, 0.2f, 1); arrow.localScale = new Vector3(arrowScale, 1, arrowScale); conveyorMeshFilter.mesh.SetVertices(conveyorMeshVertices); guardBarMeshFilter.mesh.SetVertices(guardBarMeshVertices); //设置collider boxCollider.size += Vector3.right * width; } /// 改变传送带长度 /// /// 传送带长度 /// 是否选择的左边移动 public void ChangeLength(float length, Vector3 dir,bool isChoiceLeft = false) { List conveyorMeshVertices = new List(conveyorMeshFilter.mesh.vertices); List guardBarMeshVertices = new List(guardBarMeshFilter.mesh.vertices); float halfLength = length / 2; transform.position += halfLength *( transform.rotation * dir).normalized; //改变板和边栏的长度 foreach (KeyValuePair item in conveyorMeshLeftVertices) { conveyorMeshVertices[item.Key] += Vector3.forward * halfLength; } foreach (KeyValuePair item in guardBarMeshLeftVertices) { guardBarMeshVertices[item.Key] += Vector3.forward * halfLength; } foreach (KeyValuePair item in conveyorMeshRightVertices) { conveyorMeshVertices[item.Key] -= Vector3.forward * halfLength; } foreach (KeyValuePair item in guardBarMeshRightVertices) { guardBarMeshVertices[item.Key] -= Vector3.forward * halfLength; } if (isChoiceLeft) { //设置子物体的位置 legLeftUp.localPosition += halfLength * dir; legRightUp.localPosition -= halfLength * dir; legLeftDown.localPosition += halfLength * dir; legRightDown.localPosition -= halfLength * dir; crossLeft.localPosition += halfLength * dir; cro***ight.localPosition -= halfLength * dir; } else { //设置子物体的位置 legLeftUp.localPosition -= halfLength * dir; legRightUp.localPosition += halfLength * dir; legLeftDown.localPosition -= halfLength * dir; legRightDown.localPosition += halfLength * dir; crossLeft.localPosition -= halfLength * dir; cro***ight.localPosition += halfLength * dir; } //float arrowScale = Mathf.Clamp(((ConveyorEntity)entity).conveyorProperty.Length * 2f, 0.2f, 1); //arrow.localScale = new Vector3(arrowScale, 1, arrowScale); conveyorMeshFilter.mesh.SetVertices(conveyorMeshVertices); guardBarMeshFilter.mesh.SetVertices(guardBarMeshVertices); //设置collider boxCollider.size += Vector3.forward * length; ChangeBounds(100);//拉伸mesh会导致原bound不在摄像机视角下,造成传送带不渲染 (Frustum Culling) } private void ChangeBounds(float boundLength) { Vector3 bound = new Vector3(boundLength, boundLength, boundLength); conveyorMeshFilter.mesh.bounds = new Bounds(transform.position, bound); guardBarMeshFilter.mesh.bounds = new Bounds(transform.position, bound); }
交互输入:
private void OnMouseDown() { endAddDistance = 0; otherArrowScreenPostion = Camera.main.WorldToScreenPoint(otherArrow.position); lastInputMousePoistion = Input.mousePosition; lastDistanceToOtherCross = Vector2.Distance(otherArrowScreenPostion, lastInputMousePoistion); } private void OnMouseDrag() { nowInputMousePosition = Input.mousePosition; float distance = Vector2.Distance(nowInputMousePosition, lastInputMousePoistion) * 0.1f; float otherDistaceToNowInputMousePosition = Vector2.Distance(otherArrowScreenPostion, nowInputMousePosition); //减少宽度 if (lastDistanceToOtherCross > otherDistaceToNowInputMousePosition) { endAddDistance -= distance; ChangeWidth(-distance, (transform.localPosition - otherArrow.localPosition).normalized, isUp); } //增加宽带 else if (lastDistanceToOtherCross < otherDistaceToNowInputMousePosition) { endAddDistance += distance; ChangeWidth(distance, (transform.localPosition - otherArrow.localPosition).normalized, isUp); } if (otherDistaceToNowInputMousePosition otherDistaceToNowInputMousePosition) { if (Vector3.Distance(transform.localPosition, otherCross.localPosition) Vector3.Distance(transform.localPosition, otherCross.localPosition)) { return; } endDistance -= distance; converyEntityMediator.ChangeLength(-distance, (transform.localPosition - otherCross.localPosition).normalized, isLeft); } //增加长度 else if (firstDistanceToOtherCross < otherDistaceToNowInputMousePosition) { endDistance += distance; converyEntityMediator.ChangeLength(distance, (transform.localPosition - otherCross.localPosition).normalized, isLeft); } lastInputMousePoistion = Input.mousePosition; lastDistanceToOtherCross = Vector2.Distance(otherArrowScreenPostion, lastInputMousePoistion); } private void OnMouseUp() { if (endAddDistance != 0) { ChangeWidth(-endAddDistance, (transform.localPosition - otherArrow.localPosition).normalized, isUp); ChangeLength(-endDistance, (transform.localPosition - otherCross.localPosition).normalized, isLeft); } }