通过管道mesh生成对应LineRender

起因

最近被告知需要对项目的所有管道进行流向标注,第一反应是给所有的管道替换材质球来实现目的,然而管道的mesh做的有些问题,直接替换材质球两边的流向是反的,只能退而求其次,使用lineRender给管道标注流向。然后我看着那几百根管道傻眼了。

方案

我是个非常懒的人,这种费力无聊还不讨好的工作不在我的考虑中,我决定做个插件,直接通过管道生成LineRender,在网上找了一下,发现根本没有人有这种奇怪的需求,那就只好自己造轮子了hhhh,于是便有了这篇博客。

思路

LineRender的核心是一串有序的位置,那我们要做的。便是在管道的mesh中找到这一串位置。

位置查找

说到位置,首先想到的就是mesh里面的顶点 vertices,通过mesh里的顶点,我们是不是能找出合适的作为LineRender的点呢,可mesh里的顶点太多了,没办法使用啊。

解决

我们可以通过分组的方式,根据距离,将mesh里的顶点分成N个组,然后每个组取其中的平均值,做为LineRender的点,emmm是个办法,但是。。。这个距离要怎么划分呢。

解决距离

我们可以取一个点,然后通过这个点去获取管道的直径,以直径做为顶点分组的依据,可行。这样LineRender的所有点位就都找到了。

排序

找到位置了,那我们要给这些位置排序,直接从第一个点开始,依次找最近的点好了,用过的就标记一下,ok,搞定了。也不难嘛hhh

后续

在我准备开始使用我的插件生成管道的时候,出现问题了。我遇到了这种管道

当他到1点位后,根据距离判断,下一个目标点变成了4,再下一个变成了3,然后是2,最后到5,这根实际的管道走向完全不对啊淦,看来点位之间的排序不是简单的比较距离就行了,有没有什么办法能知道点位之间的连接关系呢?

解决

mesh里有个属性叫做trianglesList,这里面存储的是三个点为一个单位的面片,每个点对应一个顶点,三个顶点确认一个面片。这不就是顶点之间的连接关系吗?
那我们三个点为一组遍历trianglesList,把如果三个点,分别位于之前划分的两个组,那我们就认为这两个组有联系(双向联系),确认联系后,我们就可以根据联系去找到组的下一个点,这样不就可以完美的实现我们的目的了吗?问题解决!

后续小问题

然后我就发现有些管道只画一半。。。找了下原因,发现这种管道的mesh起始点在中间。。。。(我真是想XXX那帮做模型的)。再加个方法,去找只有一个联系的点做起始点。这下总该没问题了吧。

后续2

当我继续生成管道的过程中,发现了T字的管道,两端甚至多段不相连的管道。类似这种在这里插入图片描述
emmmm,淦,继续优化。

问题拆解

LineRender是单线,只有单首尾。这种就需要生成多个LineRender来解决问题了。而且之前用的bool值标记的点位是否被使用也不能用了,一个点现在可以被使用多次了(T形节点)。

解决

既然这样,那就放弃掉bool值标记,转为使用本身的关联关系作为判断条件,通过删除已使用的关联关系来保证点位有序的往下走,在一条线路走完后,再重新生成一个LineRender,并且重新找起始点。

问题

本来顺利生成的单条管道,现在变成了往回退的多条管道,emmm,这就导致了B点可能同时连接ACD三点,而导致到D点后返回B点,然后该段结束。看来要删除掉重复的关联关系。。。。。怎么删呢?

解决

把当前LineRender上用到的点位记录下来,如果发现重复点位,则不使用,并且删除。啊这次总算顺利结束了。

总结

通过利用Mesh顶点整合出组;来确定LineRender的点位位置,通过trianglesList来确定每个组的关系,之后就可以按照关系生成LineRender了。
tips:如果需要相关代码请留言,这里只给出了思路

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用Unity自带的Mesh类来生成球体的Mesh,以下是示例代码: ```csharp using UnityEngine; public class SphereGenerator : MonoBehaviour { public int numSegments = 32; public float radius = 1f; void Start() { MeshFilter meshFilter = GetComponent<MeshFilter>(); Mesh mesh = new Mesh(); meshFilter.mesh = mesh; Vector3[] vertices = new Vector3[(numSegments + 1) * (numSegments + 1)]; Vector2[] uv = new Vector2[vertices.Length]; int[] triangles = new int[numSegments * numSegments * 6]; int index = 0; for (int i = 0; i <= numSegments; i++) { float y = (float)i / numSegments; for (int j = 0; j <= numSegments; j++) { float x = (float)j / numSegments; float xPos = Mathf.Cos(x * 2f * Mathf.PI) * Mathf.Sin(y * Mathf.PI); float yPos = Mathf.Cos(y * Mathf.PI); float zPos = Mathf.Sin(x * 2f * Mathf.PI) * Mathf.Sin(y * Mathf.PI); vertices[index] = new Vector3(xPos, yPos, zPos) * radius; uv[index] = new Vector2(x, y); if (i < numSegments && j < numSegments) { int topLeft = i * (numSegments + 1) + j; int topRight = topLeft + 1; int bottomLeft = (i + 1) * (numSegments + 1) + j; int bottomRight = bottomLeft + 1; triangles[index * 6] = topLeft; triangles[index * 6 + 1] = bottomLeft; triangles[index * 6 + 2] = topRight; triangles[index * 6 + 3] = topRight; triangles[index * 6 + 4] = bottomLeft; triangles[index * 6 + 5] = bottomRight; index++; } } } mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; mesh.RecalculateNormals(); } } ``` 这段代码会在场景中生成一个球体,并将其Mesh赋值给MeshFilter组件。你可以调整numSegments和radius来控制球体的细节和大小。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值