unity 线绳管道纯代码创建方法

unity 线绳管道纯代码创建方法

实现效果

原理思路

管线是由多边形横截面和路径线组成,只要在路径点上放置横截面就可以得到管线的网格点,通过网格点就可以生成管线模型。

以上的思路在生成只有两个节点的路径时,是没有问题,但是在生成有拐点的路径时,就会出现拐点的截面朝向问题,不管横截面朝向前一点或者后一点都会压缩变形。所以针对拐点必须分段处理,这里引用了内切圆的方法,在前后两个线段直接加入内切圆,将原先的拐点替换为两个切点和切圆上的三点,从而形成的新路径。

如上图,原始路径为a→b→c;取内切圆后,路径改为a→e→f→g→h→i→c;这样截面的朝向刚好为内切圆的切线方向。

核心代码

截面圆的建立

这里可以设置段数和半径;

        #region 横切圆创建
        /// <summary>
        /// 得到管线横切圆
        /// </summary>
        /// <param name="Count">段数</param>
        /// <param name="R">半径</param>
        /// <returns></returns>
        Vector3[] CircularSection(int Count, float R)
        {
            Vector3[] vector3s = new Vector3[Count];
            float angle = 360 / Count;
            Vector3 vector3 = new Vector3(R, 0, 0);
            for (int i = 0; i < Count; i++)
            {
                //根据角度得到圆的分布点
                vector3s[i] = vector3.ToAngle(angle * i, Vector3.zero, Vector3.forward);
            }
            return vector3s;
        }
        #endregion

路径线的转换

得到的路径线是没有做内切处理的,这里将路径拐点转换为内切圆;

#region 得到3d线的中心路径
        /// <summary>
        /// 设置中心路径
        /// </summary>
        /// <param name="createPoint">路径点</param>
        /// <param name="createPoint">拐点半径</param>
        /// <returns></returns>
        List<PipePoint> SetPipePoint(Vector3[] createPoint,float  elbowR)
        {
            List<PipePoint> pipePoints = new List<PipePoint>();
            int length = createPoint.Length;
            for (int i = 0; i < length; i++)
            {
                if (i == 0)
                {
                    AddPipePoints(createPoint[i], createPoint[i + 1] - createPoint[i], ref pipePoints);
                }
                else if (i == length - 1)
                {
                    AddPipePoints(createPoint[i], createPoint[i] - createPoint[i - 1], ref pipePoints);
                }
                else
                {
                    GetElbowPoint(createPoint[i], createPoint[i - 1], createPoint[i + 1], elbowR, ref pipePoints);
                }
            }
            return pipePoints;
        }
        /// <summary>
        /// 增加管线点
        /// </summary>
        /// <param name="location"></param>
        /// <param name="direction"></param>
        void AddPipePoints(Vector3 location, Vector3 direction, ref List<PipePoint> pipePoints)
        {
            PipePoint pipePoint = new PipePoint();
            pipePoint.Location = location;
            pipePoint.Direction = direction;
            pipePoints.Add(pipePoint);
        }
        /// <summary>
        /// 得到内切点
        /// </summary>
        /// <param name="focus"></param>
        /// <param name="front"></param>
        /// <param name="back"></param>
        /// <param name="r">内切圆半径</param>
        void GetElbowPoint(Vector3 focus, Vector3 front, Vector3 back, float r, ref List<PipePoint> pipePoints)
        {
            //拐点前后向量
            Vector3 frontVec = focus - front;
            Vector3 backVec = back - focus;
            //得到前后切点
            Vector3 tangencyFront = ((frontVec.magnitude - r) * frontVec.normalized) + front;
            Vector3 tangencyBack = (r * backVec.normalized) + focus;
            //得到内切圆圆心
            Vector3 circulPoint = GetCirculPoint(focus, tangencyFront, tangencyBack);
            //得到拐点分段
            Vector3[] circulSection = GetCirculSection(focus, tangencyFront, tangencyBack, circulPoint);
            //得到两个切点向量的法线
            Vector3 normal = Vector3.Cross(frontVec, backVec).normalized;
            //增加管线点
            AddPipePoints(tangencyFront, GetDirection(tangencyFront, circulPoint, normal), ref pipePoints);
            int length = circulSection.Length;
            for (int i = 0; i < length; i++)
            {
                AddPipePoints(circulSection[i], GetDirection(circulSection[i], circulPoint, normal), ref pipePoints);
            }
            AddPipePoints(tangencyBack, GetDirection(tangencyBack, circulPoint, normal), ref pipePoints);
        }
        /// <summary>
        /// 得到切点在内切圆上的切线方向
        /// </summary>
        /// <param name="self"></param>
        /// <param name="circulPoint"></param>
        /// <param name="normal"></param>
        /// <returns></returns>
        Vector3 GetDirection(Vector3 self, Vector3 circulPoint, Vector3 normal)
        {
            Vector3 vector = circulPoint - self;
            return Vector3.Cross(vector, normal).normalized;
        }
        /// <summary>
        /// 得到管线拐点内切圆分段点
        /// </summary>
        /// <param name="focus">交点</param>
        /// <param name="tangency1">切点1</param>
        /// <param name="tangency2">切点2</param>
        /// <param name="circulPoint">切圆圆心</param>
        /// <returns></returns>
        Vector3[] GetCirculSection(Vector3 focus, Vector3 tangency1, Vector3 tangency2, Vector3 circulPoint)
        {
            Vector3 vector0 = tangency1 - circulPoint;
            Vector3 vector4 = tangency2 - circulPoint;
            float dis = vector0.magnitude;
            Vector3 vector2 = (vector0 + vector4).normalized * dis;
            Vector3 vector1 = (vector0 + vector2).normalized * dis;
            Vector3 vector3 = (vector4 + vector2).normalized * dis;
            Vector3[] vector3s = new Vector3[3];
            vector3s[0] = vector1 + circulPoint;
            vector3s[1] = vector2 + circulPoint;
            vector3s[2] = vector3 + circulPoint;
            return vector3s;
        }
        /// <summary>
        /// 得到管线拐点内切圆圆心
        /// </summary>
        /// <param name="focus">拐点</param>
        /// <param name="tangency1">切点1</param>
        /// <param name="tangency2">切点2</param>
        /// <returns></returns>
        Vector3 GetCirculPoint(Vector3 focus, Vector3 tangency1, Vector3 tangency2)
        {
            Vector3 vector1 = tangency1 - focus;
            Vector3 vector2 = tangency2 - focus;
            Vector3 vector0 = (vector1 + vector2).normalized;
            float angle = Vector3.Angle(vector1, vector0);
            float dis = vector1.magnitude / Mathf.Cos(angle * Mathf.Deg2Rad);
            return (vector0 * dis) + focus;
        }
        #endregion

创建网格点

将横截面和路径点结合,创建网格点

      #region 创建网格点
        Vector3[] CreateMeshPoint(List<PipePoint> pipePoint, Vector3[] circular)
        {
            int length = pipePoint.Count;
            int circularCount = circular.Length;
            Vector3[] meshPoint = new Vector3[length * circularCount];
            for (int i = 0; i < length; i++)
            {
                for (int j = 0; j < circularCount; j++)
                {
                    meshPoint[(i * circularCount) + j] = circular[j].FromToMoveRotation(pipePoint[i].Location, pipePoint[i].Direction);
                }
            }
            return meshPoint;
        }
        #endregion

网格创建

    #region 网格创建
        Mesh CreatMesh(List<PipePoint> pipePoints, Vector3[] meshPoint, Vector3[] circular)
        {
            Mesh mesh = new Mesh();
            int circularCount = circular.Length;
            mesh.vertices = meshPoint;
            mesh.triangles = GetTriangles(pipePoints, circularCount);
            mesh.uv = GetUV(pipePoints, circular);
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            return mesh;
        }
        Vector2[] GetUV(List<PipePoint> pipePoints, Vector3[] circular)
        {
            int length = pipePoints.Count;
            int circularCount = circular.Length;
            Vector2[] uvs = new Vector2[(circularCount * length)];
            float lineDis = 0;
            float circularDis = Vector3.Distance(circular[0], circular[1]);
            int k = 0;
            for (int i = 0; i < length; i++)
            {
                if (i != 0)
                {
                    lineDis += Vector3.Distance(pipePoints[i].Location, pipePoints[i - 1].Location);
                }
                for (int j = 0; j < circularCount; j++)
                {
                    Vector2 vector2;
                    if (j%2!=0)
                    {
                         vector2 = new Vector2(circularDis, lineDis);
                    }
                    else
                    {
                         vector2 = new Vector2(0, lineDis);
                    }
                  
                    uvs[k] = vector2;
                    k+=1;
                }
            }
            return uvs;
        }
        int[] GetTriangles(List<PipePoint> pipePoints, int Count)
        {
            int length = pipePoints.Count;
            int[] triangles = new int[(Count * (length - 1)) * 6];
            int k = 0;
            for (int i = 0; i < length - 1; i++)
            {
                for (int j = 0; j < Count; j++)
                {
                    if (j == Count - 1)
                    {
                        triangles[k] = (i * Count) + j;
                        triangles[k + 1] = (i * Count) + 0;
                        triangles[k + 2] = ((i + 1) * Count) + 0;
                        triangles[k + 3] = (i * Count) + j;
                        triangles[k + 4] = ((i + 1) * Count) + 0;
                        triangles[k + 5] = ((i + 1) * Count) + j;
                    }
                    else
                    {
                        triangles[k] = (i * Count) + j;
                        triangles[k + 1] = (i * Count) + j + 1;
                        triangles[k + 2] = ((i + 1) * Count) + j + 1;
                        triangles[k + 3] = (i * Count) + j;
                        triangles[k + 4] = ((i + 1) * Count) + j + 1;
                        triangles[k + 5] = ((i + 1) * Count) + j;
                    }
                    k += 6;
                }
            }
            return triangles;
        }
        #endregion

最后创建线

       public GameObject CreateLine(Vector3[] createPoint, Material material, int circularCount, float circularR, float elbowR)
        {
            GameObject game = new GameObject();
            MeshFilter filter = game.AddComponent<MeshFilter>();
            Vector3[] circul = CircularSection(circularCount, circularR);
            List<PipePoint> pipePoints = SetPipePoint(createPoint, elbowR);
            Vector3[] meshPoint = CreateMeshPoint(pipePoints, circul);
            filter.mesh = CreatMesh(pipePoints, meshPoint, circul);
            MeshRenderer renderer = game.AddComponent<MeshRenderer>();
            renderer.sharedMaterial = material;
            return game;
        }

Demo下载地址

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
要在Unity创建IIS通讯网站,可以按照以下步骤进行: 1. 在Unity创建一个WebGL应用程序。在Unity中选择File -> Build Settings,然后选择WebGL作为目标平台,点击Build按钮,将项目生成为WebGL应用程序。 2. 在Unity中使用UnityWebRequest类与IIS进行通讯。UnityWebRequest类是一个用于发送HTTP和HTTPS请求的类,可以在Unity中使用它与Web服务器进行通讯。可以使用以下代码示例创建一个HTTP GET请求,并发送到IIS服务器: ``` IEnumerator GetRequest(string url) { UnityWebRequest www = UnityWebRequest.Get(url); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { Debug.Log(www.downloadHandler.text); } } ``` 3. 在IIS中创建一个Web API,以便Unity WebGL应用程序可以向该API发送HTTP请求,并获取响应数据。在Web API中,可以使用C#等语言编写业务逻辑,与数据库进行交互,以实现与Unity WebGL应用程序的通讯。 4. 在IIS中启用CORS。CORS是一种机制,允许Web应用程序在浏览器中向不同的域发送跨域请求。启用CORS可以使得Unity WebGL应用程序能够与IIS服务器进行跨域通讯。 5. 在Unity中使用以上步骤中创建的Web API进行通讯。可以使用以下代码示例创建一个HTTP POST请求,并发送到Web API: ``` IEnumerator PostRequest(string url, string data) { UnityWebRequest www = UnityWebRequest.Post(url, data); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { Debug.Log(www.downloadHandler.text); } } ``` 需要注意的是,以上代码示例仅供参考,具体实现需要根据具体的场景和需求进行调整。在实际开发中,应该尽量避免直接使用`LoadFromFile_Internal`函数,而是使用Unity的资源管理系统来加载资源文件。可以使用`Resources.Load`、`AssetBundle.LoadAsset`等函数来加载资源文件,这些函数会自动管理资源的生命周期和内存占用等问题,更加安全和高效。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小生云木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值