Unity プロシージャル メッシュ ジオメトリの Rectangle II

前回の記事で手続き型グリッドに触れたのが初めてだったので、原理がわからないことも多く、慣れないことで発生する問題も多いですが、しばらく勉強したところ、以前にも多くの問題が発生しました。存在しません. 長方形の長さの関数は文書化されています.
実現機能:
1. 任意の長さの長方形を連続生成
2. 継ぎ目をシームレスに接続可能
実現効果:
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
実現コード:

using UnityEngine;

public class CreateStrechMesh3 : MonoBehaviour
{
    
    

    private void Update()
    {
    
    
        CreateCustomWallMod();
    }

    [SerializeField]
    private Material wallMat = null; //墙体材质
    [SerializeField]
    private LayerMask planeLayer = 0; //地面层
    [SerializeField]
    private float width = 1; //墙体宽度
    [SerializeField]
    private float height = 3.4f; //墙体高度
    private float length = 0; //墙体长度
    private RaycastHit hit; //
    private int clickCount = 0; //点击次数,第一次点击创建,以后每一次点击先结束创建,在创建新墙体
    private GameObject curWall = null; //创建的墙体
    private Mesh mesh = null; //墙体mesh
    private MeshRenderer meshRender = null; //墙体meshrender
    private MeshFilter meshFilter = null; //墙体meshfilter
    private bool isStartCreate = false; //开始创建
    private Vector3[] vertics = new Vector3[24]; //墙体顶点
    private int[] triangles = new int[36]; //墙体三角面
    private Vector2[] UVs = new Vector2[24]; //墙体uv
    private Vector3 originPos = Vector3.zero; //墙体起始点

    private GameObject preWall = null; //上一个墙体缓存
    private Mesh preMesh = null; //上一个墙体mesh
    private Vector3[] preVertics = new Vector3[24]; //上一个墙体顶点
    private float preLength = 0; //上一个墙体长度
    private void CreateCustomWallMod()
    {
    
    
        if (Input.GetMouseButtonDown(1))
        {
    
    
            if (curWall != null)
            {
    
    
                Destroy(curWall);
                curWall = null;
            }
            preWall = null;
            clickCount = 0;
            isStartCreate = false;
        }

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit, 100, planeLayer))
        {
    
    
            if (Input.GetMouseButtonDown(0))
            {
    
    
                isStartCreate = true;
                clickCount++;
                if (clickCount == 1)
                {
    
    
                    StartCreateCustomWall(hit.point);
                }
                else
                {
    
    
                    EndCreateCustomWall(hit.point);
                    StartCreateCustomWall(hit.point);
                }

            }

            if (isStartCreate)
            {
    
    
                RefreshMeshMod(hit.point);
            }
        }


    }

    /// <summary>
    /// 开始创建自定义墙体
    /// </summary>
    /// <param name="_pos"></param>
    private void StartCreateCustomWall(Vector3 _pos)
    {
    
    
        curWall = new GameObject();
        meshRender = curWall.AddComponent<MeshRenderer>();
        if (wallMat != null)
        {
    
    
            meshRender.sharedMaterial = wallMat;
        }
        else
        {
    
    
            meshRender.sharedMaterial = new Material(Shader.Find("Standard"));
        }
        meshFilter = curWall.AddComponent<MeshFilter>();
        mesh = meshFilter.mesh;

        curWall.transform.position = _pos;
        originPos = _pos;
        length = 0;

        vertics = new Vector3[] {
    
    
                //left
                new Vector3(0,0,0),
                new Vector3(0,height,0),
                new Vector3(0,height,-width),
                new Vector3(0,0,-width),

                //front
                new Vector3(0,0,-width),
                new Vector3(0,height,-width),
                new Vector3(0,height,-width),
                new Vector3(0,0,-width),

                //right
                new Vector3(0,0,-width),
                new Vector3(0,height,-width),
                new Vector3(0,height,0),
                new Vector3(0,0,0),

                //back
                new Vector3(0,0,0),
                new Vector3(0,height,0),
                new Vector3(0,height,0),
                new Vector3(0,0,0),

                //up
                new Vector3(0,height,-width),
                new Vector3(0,height,0),
                new Vector3(0,height,0),
                new Vector3(0,height,-width),

                //down
                new Vector3(0,0,0),
                new Vector3(0,0,-width),
                new Vector3(0,0,-width),
                new Vector3(0,0,0)

         };

        triangles = new int[] {
    
    
            //left
            0,1,2,
            2,3,0,

            //front
            4,5,6,
            6,7,4,

            //right
            8,9,10,
            10,11,8,

            //back
            12,13,14,
            14,15,12,

            //up
            16,17,18,
            18,19,16,

            //down
            20,21,22,
            22,23,20
            };

        UVs = new Vector2[] {
    
    
            //left
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),

            //front
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),

            //right
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),

            //back
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),

            //up
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),

            //down
            new Vector2(0,0),
            new Vector2(0,1),
            new Vector2(1,1),
            new Vector2(1,0),
            };

        mesh.vertices = vertics;  //绘制顶点
        mesh.triangles = triangles;  //绘制三角面
        mesh.uv = UVs; //绘制纹理
        mesh.RecalculateNormals();  //计算法线
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();

    }

    /// <summary>
    /// 结束创建自定义模型
    /// </summary>
    /// <param name="_pos"></param>
    private void EndCreateCustomWall(Vector3 _pos)
    {
    
    
        RefreshMeshMod(_pos);

        curWall.AddComponent<MeshCollider>();
        preLength = length;
        preWall = curWall;
        preMesh = mesh;
    }

    /// <summary>
    /// 刷新网格
    /// </summary>
    /// <param name="_pos"></param>
    private void RefreshMeshMod(Vector3 _pos)
    {
    
    
        vertics = mesh.vertices;

        var vEndCenterX = _pos.x - originPos.x;
        var vEndCenterZ = _pos.z - originPos.z;
        length = Mathf.Sqrt(vEndCenterX * vEndCenterX + vEndCenterZ * vEndCenterZ);

        var vros = _pos - originPos;
        curWall.transform.rotation = Quaternion.FromToRotation(Vector3.right, vros);

        vertics[6] = new Vector3(length, height, -width);
        vertics[7] = new Vector3(length, 0, -width);
        vertics[8] = new Vector3(length, 0, -width);
        vertics[9] = new Vector3(length, height, -width);
        vertics[10] = new Vector3(length, height, 0);
        vertics[11] = new Vector3(length, 0, 0);
        vertics[12] = new Vector3(length, 0, 0);
        vertics[13] = new Vector3(length, height, 0);
        vertics[18] = new Vector3(length, height, 0);
        vertics[19] = new Vector3(length, height, -width);
        vertics[22] = new Vector3(length, 0, -width);
        vertics[23] = new Vector3(length, 0, 0);

        mesh.vertices = vertics;
        mesh.RecalculateNormals();
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();

        RecalculateAngle();
    }

    /// <summary>
    /// 计算接缝处
    /// </summary>
    private void RecalculateAngle()
    {
    
    
        if (preWall != null)
        {
    
    
            var vrosdis = (curWall.transform.eulerAngles.y - preWall.transform.eulerAngles.y) / 2; //计算两个墙体相交的角度的一半
            vrosdis = vrosdis * Mathf.Deg2Rad;
            var vbevel = width / Mathf.Cos(vrosdis); //计算相交线
            var vx = vbevel * Mathf.Sin(vrosdis);
            //print("第一堵墙的角度:" + preObj.transform.eulerAngles.y + " 第二堵墙的角度:" + curObj.transform.eulerAngles.y + " 两堵墙相对角度:" + vrosdis + " 余弦值:" + Mathf.Cos(vrosdis) + " 斜边:" + vbevel + " 正弦值:" + Mathf.Sin(vrosdis) + " 对边:" + vx);
            preVertics = preMesh.vertices;
            preVertics[6] = new Vector3(preLength - vx, height, -width);
            preVertics[7] = new Vector3(preLength - vx, 0, -width);
            preVertics[8] = new Vector3(preLength - vx, 0, -width);
            preVertics[9] = new Vector3(preLength - vx, height, -width);
            preVertics[19] = new Vector3(preLength - vx, height, -width);
            preVertics[22] = new Vector3(preLength - vx, 0, -width);
            preMesh.vertices = preVertics;
            preMesh.RecalculateBounds();
            preMesh.RecalculateNormals();
            preMesh.RecalculateTangents();

            vertics = mesh.vertices;
            vertics[2] = new Vector3(vx, height, -width);
            vertics[3] = new Vector3(vx, 0, -width);
            vertics[4] = new Vector3(vx, 0, -width);
            vertics[5] = new Vector3(vx, height, -width);
            vertics[16] = new Vector3(vx, height, -width);
            vertics[21] = new Vector3(vx, 0, -width);
            mesh.vertices = vertics;
            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();
        }
    }

    private void OnGUI()
    {
    
    
        if (isStartCreate)
        {
    
    
            var v = Input.mousePosition;
            GUIStyle style = new GUIStyle();
            style.fontSize = 30;
            GUI.Box(new Rect(v.x, Screen.height - v.y - 30, 100, 30), length.ToString("f2") + "米", style);
        }

    }
}

おすすめ

転載: blog.csdn.net/qq_39353597/article/details/122100251
おすすめ