已知两个点,绘制这条线所在的水平面(开始目的是根据网上的内容给LienRenderer添加Collider,结果Collider不匹配,就用了这个方法)

已知条件是:Point1、Point2

间接已知条件:这两个点的垂直面Plane1

这个时候计算Plane1的法线即可。

根据Point1和Point2获取垂直点,高度可以自定义

 private static Vector3 GetUpPoint(Vector3 point, float m_height)
 {
   return new Vector3(point.x, point.y + m_height, point.z);
 }

Vector3 Point3 = GetUpPoint(m_point1, m_height) - m_point1;//p1p2的垂直向量

暂时定义这个点为Point3

根据P1P2向量和P1P3的向量叉乘之后获取垂直向量,这个向量就是我们想要的水平面的一个点

 private static Vector3 GetCorner(Vector3 v1, Vector3 v2, Vector3 startPoint, float m_width)
{
  Vector3 forward = (Vector3.Cross(v1, v2).normalized * m_width + startPoint);
  return forward;
}

然后根据向量的方向,依次算出水平面的四个点

        Vector3 xl10 = m_point2 - m_point1;//p1p2向量
        Vector3 xl20 = GetUpPoint(m_point1, m_height) - m_point1;//p1p2的垂直向量
        Vector3 result1 = GetCorner(xl10, xl20, m_point1, m_width);

        Vector3 xl11 = m_point1 - m_point2;//p2p1向量
        Vector3 xl21 = GetUpPoint(m_point1, m_height) - m_point1;//p2p1在p1上的垂直向量
        Vector3 result2 = GetCorner(xl11, xl21, m_point1, m_width);

        Vector3 xl12 = m_point1 - m_point2;//p2p1向量
        Vector3 xl22 = GetUpPoint(m_point2, m_height) - m_point2;//p2p1在p2上的的垂直向量
        Vector3 result3 = GetCorner(xl12, xl22, m_point2, m_width);

        Vector3 xl13 = m_point2 - m_point1;//p1p2向量
        Vector3 xl23 = GetUpPoint(m_point2, m_height) - m_point2;//p1p2在p2上的垂直向量
        Vector3 result4 = GetCorner(xl13, xl23, m_point2, m_width);

再根据这四个点绘制平面即可

private static void DrawPlane(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Transform parent, string name, bool isClockwise = false)
    {
        List<Vector3> vector3s = new List<Vector3>();
        vector3s.Add(v1);
        vector3s.Add(v2);
        vector3s.Add(v3);
        vector3s.Add(v4);
        GameObject plane1 = new GameObject(name);
        plane1.AddComponent<MeshFilter>().mesh = CreateMesh(vector3s, isClockwise);
        plane1.AddComponent<MeshRenderer>().material = new Material(Shader.Find("Standard"));
        plane1.transform.parent = parent;
    }

public static Mesh CreateMesh(List<Vector3> points, bool isClockwise = false)
    {
        Mesh mesh = new Mesh();
        Vector3[] vertices = new Vector3[4]{
            points[0],
            points[1],
            points[2],
            points[3],
        };

        int[] triangles;
        if (!isClockwise)
        {
            triangles = new int[2 * 3]{
                0, 1, 2, 2, 3, 0
            };
        }
        else
        {
            triangles = new int[2 * 3]{
                1, 0, 3, 3, 2, 1
            };
        }

        Vector2[] uv = new Vector2[4]{
            new Vector2(1, 1),
            new Vector2(1, 0),
            new Vector2(0, 0),
            new Vector2(0, 1)
        };

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uv;
        return mesh;
    }

这个问题可以解决给LineRenderer的添加Collider的问题,然后出现很多小的Mesh,在网上找了个合并Mesh的方法。

using System.Collections.Generic;

using UnityEditor;

using UnityEngine;
using UnityEngine.Rendering;


public class MergeUtils
{

    /// <summary>
    /// 合并网格
    /// </summary>
    private static void MergeMesh2(GameObject parent, bool mergeSubMeshes = false)
    {
        MeshRenderer[] meshRenderers = parent.GetComponentsInChildren<MeshRenderer>();
        Material[] materials = new Material[meshRenderers.Length];
        for (int i = 0; i < meshRenderers.Length; i++)
        {
            materials[i] = meshRenderers[i].sharedMaterial;
        }

        MeshFilter[] meshFilters = parent.GetComponentsInChildren<MeshFilter>();   //获取 所有子物体的网格


        CombineInstance[] combineInstances = new CombineInstance[meshFilters.Length]; //新建一个合并组,长度与 meshfilters一致
        for (int i = 0; i < meshFilters.Length; i++)                                  //遍历
        {
            combineInstances[i].mesh = meshFilters[i].sharedMesh;                   //将共享mesh,赋值
            combineInstances[i].transform = meshFilters[i].transform.localToWorldMatrix; //本地坐标转矩阵,赋值
            GameObject.DestroyImmediate(meshFilters[i].gameObject);
        }
        Mesh newMesh = new Mesh();                                  //声明一个新网格对象
        newMesh.CombineMeshes(combineInstances, mergeSubMeshes, true);                    //将combineInstances数组传入函数
        parent.AddComponent<MeshFilter>().sharedMesh = newMesh; //给当前空物体,添加网格组件;将合并后的网格,给到自身网格

        parent.AddComponent<MeshRenderer>().sharedMaterials = materials;
    }



    public static GameObject[] MergeMesh(GameObject parent, bool mergeAll = true, bool deleteChildren = false, bool mergeSubMeshes = false)
    {
        List<GameObject> list = new List<GameObject>();
        int verts = 0;
        //存放要合并的父物体  
        Dictionary<int, GameObject> NewParent = new Dictionary<int, GameObject>();
        //获取所有网格过滤器;
        MeshFilter[] meshFilters = parent.GetComponentsInChildren<MeshFilter>();
        for (int i = 0; i < meshFilters.Length; i++)
        {
            verts += meshFilters[i].mesh.vertexCount;

            if (NewParent.ContainsKey((verts / 65536) + 1))
            {
                meshFilters[i].transform.parent = NewParent[(verts / 65536) + 1].transform;
            }
            else
            {
                GameObject wx = new GameObject("Combine");
                wx.transform.parent = parent.transform;
                NewParent.Add((verts / 65536) + 1, wx);
                meshFilters[i].transform.parent = NewParent[(verts / 65536) + 1].transform;
            }


        }
        foreach (var item in NewParent)
        {
            list.Add(MergeUtils.MergeMesh3(item.Value, true, true));
        }

        if (deleteChildren)
        {

            //合并完成后删除子项
            for (int i = parent.transform.childCount - 1; i >= 0; i--)
            {
                if (parent.transform.GetChild(i).name != "Combine")
                {
                    GameObject.Destroy(parent.transform.GetChild(i).gameObject);
                }
            }

        }

        return list.ToArray();
    }

    public static GameObject MergeMesh3(GameObject parent, bool mergeAll = true, bool deleteChildren = false, bool mergeSubMeshes = false)
    {
        //获取所有网格过滤器;
        MeshFilter[] meshFilters = parent.GetComponentsInChildren<MeshFilter>();
        //存放不同的材质球,相同的就存一个;
        Dictionary<string, Material> materials = new Dictionary<string, Material>();

        //存放要合并的网格对象;
        Dictionary<string, List<CombineInstance>> combines = new Dictionary<string, List<CombineInstance>>();
        for (int i = 0; i < meshFilters.Length; i++)
        {
            //构造一个网格合并结构体;
            CombineInstance combine = new CombineInstance();

            //给结构体的mesh赋值;
            combine.mesh = meshFilters[i].sharedMesh;
            combine.transform = meshFilters[i].transform.localToWorldMatrix;

            MeshRenderer renderer = meshFilters[i].GetComponent<MeshRenderer>();
            if (renderer == null)
            {
                continue;
            }
            Material mat = renderer.sharedMaterial;

            if (!materials.ContainsKey(mat.name))
            {
                materials.Add(mat.name, mat);
            }
            if (combines.ContainsKey(mat.name))
            {
                combines[mat.name].Add(combine);
            }
            else
            {
                List<CombineInstance> coms = new List<CombineInstance>();
                coms.Add(combine);
                combines[mat.name] = coms;
            }

            //Destroy(meshFilters[i].gameObject);
        }
        GameObject combineObj = new GameObject("Combine");
        combineObj.transform.parent = parent.transform;
        foreach (KeyValuePair<string, Material> mater in materials)
        {
            GameObject obj = new GameObject(mater.Key);
            obj.transform.parent = combineObj.transform;
            MeshFilter combineMeshFilter = obj.AddComponent<MeshFilter>();
            combineMeshFilter.mesh = new Mesh();

            //将引用相同材质球的网格合并;
            combineMeshFilter.sharedMesh.CombineMeshes(combines[mater.Key].ToArray(), true, true);
            Debug.LogError("网格定点数" + combineMeshFilter.sharedMesh.vertices);
            MeshRenderer rend = obj.AddComponent<MeshRenderer>();

            //指定材质球;
            rend.sharedMaterial = mater.Value;

            rend.shadowCastingMode = ShadowCastingMode.Off;
            rend.receiveShadows = true;
        }

        if (mergeAll)
        {
            MergeMesh2(combineObj);
            //Combine(combineObj)
        }


        if (deleteChildren)
        {

            //合并完成后删除子项
            for (int i = parent.transform.childCount - 1; i >= 0; i--)
            {
                if (parent.transform.GetChild(i).name != "Combine")
                {
                    GameObject.Destroy(parent.transform.GetChild(i).gameObject);
                }
            }

        }

        return combineObj;
    }
    public static GameObject MergeMesh4(GameObject parent, bool mergeAll = true, bool deleteChildren = false, bool mergeSubMeshes = false)
    {

        //获取所有网格过滤器;
        MeshFilter[] meshFilters = parent.GetComponentsInChildren<MeshFilter>();
        //存放不同的材质球,相同的就存一个;
        Dictionary<string, Material> materials = new Dictionary<string, Material>();

        //存放要合并的网格对象;
        Dictionary<string, List<CombineInstance>> combines = new Dictionary<string, List<CombineInstance>>();
        for (int i = 0; i < meshFilters.Length; i++)
        {
            //构造一个网格合并结构体;
            CombineInstance combine = new CombineInstance();

            //给结构体的mesh赋值;
            combine.mesh = meshFilters[i].sharedMesh;
            combine.transform = meshFilters[i].transform.localToWorldMatrix;

            MeshRenderer renderer = meshFilters[i].GetComponent<MeshRenderer>();
            if (renderer == null)
            {
                continue;
            }
            Material mat = renderer.sharedMaterial;

            if (!materials.ContainsKey(mat.name))
            {
                materials.Add(mat.name, mat);
            }
            if (combines.ContainsKey(mat.name))
            {
                combines[mat.name].Add(combine);
            }
            else
            {
                List<CombineInstance> coms = new List<CombineInstance>();
                coms.Add(combine);
                combines[mat.name] = coms;
            }

            //Destroy(meshFilters[i].gameObject);
        }
        GameObject combineObj = new GameObject("Combine");
        combineObj.transform.parent = parent.transform;
        foreach (KeyValuePair<string, Material> mater in materials)
        {
            GameObject obj = new GameObject(mater.Key);
            obj.transform.parent = combineObj.transform;
            MeshFilter combineMeshFilter = obj.AddComponent<MeshFilter>();
            combineMeshFilter.mesh = new Mesh();

            //将引用相同材质球的网格合并;
            combineMeshFilter.sharedMesh.CombineMeshes(combines[mater.Key].ToArray(), true, true);
            Debug.LogError("网格定点数" + combineMeshFilter.sharedMesh.vertices);
            MeshRenderer rend = obj.AddComponent<MeshRenderer>();

            //指定材质球;
            rend.sharedMaterial = mater.Value;

            rend.shadowCastingMode = ShadowCastingMode.Off;
            rend.receiveShadows = true;
        }

        if (mergeAll)
        {
            MergeMesh2(combineObj);
            //Combine(combineObj)
        }


        if (deleteChildren)
        {

            //合并完成后删除子项
            for (int i = parent.transform.childCount - 1; i >= 0; i--)
            {
                if (parent.transform.GetChild(i).name != "Combine")
                {
                    GameObject.Destroy(parent.transform.GetChild(i).gameObject);
                }
            }

        }

        return combineObj;
    }

}

之后再给这个合并的Mesh添加触发器就可以完美的添加Collider

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值