Unity Mesh 生成图形(三)

本文详细介绍了Unity中的Mesh数据结构,包括其组成(顶点、三角形),并展示了如何在游戏开发中生成多个面,通过生成顶点和计算顶点下标来实现波浪效果和动态物体的改变。
摘要由CSDN通过智能技术生成

一、概述

Unity 的 Mesh 是用于表示三维物体的网格数据结构。它是由一系列顶点和三角形组成的网格,用于描述物体的形状和外观。

Mesh 是由顶点、三角形和其他相关信息组成的,它用于在 Unity 中创建和渲染三维对象。顶点是网格的基本构建单元,它们定义了物体的形状,每个顶点都有三维坐标和其他可选属性,如法线、 UV 坐标和颜色。三角形则是由三个顶点组成的,它们定义了网格表面的平面,形成了物体的可见表面。

Mesh 类提供了许多方法来操作顶点和三角形,例如添加、删除、移动顶点和三角形,以及调整网格的大小和形状。这些操作可以在 Unity 编辑器中进行,也可以在代码中通过使用 Unity 的 API 来实现。

使用 Mesh 可以创建各种类型的三维对象,如静态物体、动态物体、碰撞检测对象等。在 Unity 中,Mesh 还支持各种纹理和光照技术,以便更好地渲染物体的外观和效果。
 

参考:

Unity Mesh 生成图形(一)-CSDN博客

Unity Mesh 生成图形(二)-CSDN博客

二、生成多个面

在游戏开发中,使用 Mesh 同时生成多个面也是经常有的,比如游戏中的海水,就是使用多种算法改变 Mesh 来实现波浪效果的,另外在游戏中,比如破坏树木、石头等,同样是通过改变 Mesh 来实现的,结合前面几篇文章,这次我们来看看 Mesh 生成多个面是如何完成的。

1.生成多个顶点

生成多个顶点的算法不算太难,在平面上,一般只用 X 轴和 Z 轴,Y轴不用计算,从左往右依次生成顶点,每次将 X 轴的距离 + 1 就行了(可以根据指定的距离),当 X 轴循环完成后,将 Z + 1,就可以生成第二行的顶点位置了。

顶点的生成算法,可以参考下图:

为了更好的观察顶点位置是否正确,我用了一个球来标记每个顶点的位置,代码:

using UnityEngine;

public class Test5 : MonoBehaviour
{
    void Start()
    {
        int row = 3;//行
        int column = 3;//列
        float interval = 1f; //间隔

        //生成顶点
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                Vector3 vector = new Vector3();
                vector.x = j * interval;
                vector.y = 0;
                vector.z = i * interval;

                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = vector;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }
    }
}

这样就生成了 9 个顶点,效果:

2.生成多个顶点下标

生成多个顶点下标要复杂一些,光看文章可能有点难以理解,最好是跟着帖子手动去操作一遍,多思考和实践,本篇文章只是展示了一个面,如果换成立方体其他的面,所有的顶点和索引下标都得改,不理解操作起来就有点困难。

在添加完顶点后,接下来就要计算顶点的下标了,这次由于是代码生成的顶点,并不是和前面文章中的手动去添加顶点,所以它的下标也不能使用 0,1,2,2,1,3 这样排序,结合前面文章的知识点,参考下图:

当前顶点下标正确的顺序是

第1个面:

0,3,1,1,3,4

第2个面:

1,4,2,2,4,5

第3个面:

3,6,4,4,6,7

第4个面:

4,7,5,5,7,8

根据上面的规律,可以从一个面的左下角开始计算顶点,每一行只计算行数 - 1 个顶点,比如上图中,0,1,2,我们只需要计算 0,1 的顶点就行了,第二行,只需要计算 3,4 就行了,这样看,使用二维数组来存储顶点的下标最合适不过了,下面就用代码来实现效果。

代码:

using UnityEngine;

public class Test5 : MonoBehaviour
{
    void Start()
    {
        int row = 3;//行
        int column = 3;//列
        float interval = 1f; //间隔

        List<Vector3> vertices = new List<Vector3>();

        int[,] dindex = new int[row,column];

        //生成顶点
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                Vector3 vector = new Vector3();
                vector.x = j * interval;
                vector.y = 0;
                vector.z = i * interval;

                dindex[i, j] = (i * column) + j;
                vertices.Add(vector);

                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = vector;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }
    }
}

加一个断点,看看 dindex 数据结构是什么样的

为了更好的观察二维数组,我们把上图 dindex 的数据变一下位置:

0,  1,  2

3,  4,  5

6,  7,  8

第 1 个面的顶点下标数组是:0,3,1,1,3,4

如果 dindex 用 dindex[x, y] 来表示 [0,0] ,那么它的顶点下标为:

[x, y], [x + 1, y], [x, y + 1],  [x, y + 1],  [x + 1, y],  [x + 1, y + 1]

其他的面以此类推,直接上代码:

using System.Collections.Generic;
using UnityEngine;

public class Test5 : MonoBehaviour
{
    void Start()
    {
        int row = 3;//行
        int column = 3;//列
        float interval = 1f; //间隔

        List<Vector3> vertices = new List<Vector3>();
        int[,] dindex = new int[row, column];

        //生成顶点
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                Vector3 vector = new Vector3();
                vector.x = j * interval;
                vector.y = 0;
                vector.z = i * interval;

                dindex[i, j] = (i * column) + j;
                vertices.Add(vector);

                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = vector;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }

        //生成顶点下标
        List<int> triangles = new List<int>();
        for (int i = 0; i < dindex.GetLength(0) - 1; i++)
        {
            for (int j = 0; j < dindex.GetLength(1) - 1; j++)
            {
                triangles.Add(dindex[i, j]);
                triangles.Add(dindex[i + 1, j]);
                triangles.Add(dindex[i, j + 1]);
                triangles.Add(dindex[i, j + 1]);
                triangles.Add(dindex[i + 1, j]);
                triangles.Add(dindex[i + 1, j + 1]);
            }
        }

        string indexStr = string.Join(",", triangles);
        Debug.Log(indexStr);
    }
}

运行:

可以看到,结果是对的。

3.最终效果

结合前面几篇文章的知识点,现在我们把最终的效果实现:

using System.Collections.Generic;
using UnityEngine;

public class Test5 : MonoBehaviour
{
    void Start()
    {
        int row = 3;//行
        int column = 3;//列
        float interval = 1f; //间隔

        List<Vector3> vertices = new List<Vector3>();
        int[,] dindex = new int[row, column];

        //生成顶点
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                Vector3 vector = new Vector3();
                vector.x = j * interval;
                vector.y = 0;
                vector.z = i * interval;

                dindex[i, j] = (i * column) + j;
                vertices.Add(vector);

                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = vector;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }

        //生成顶点下标
        List<int> triangles = new List<int>();
        for (int i = 0; i < dindex.GetLength(0) - 1; i++)
        {
            for (int j = 0; j < dindex.GetLength(1) - 1; j++)
            {
                triangles.Add(dindex[i, j]);
                triangles.Add(dindex[i + 1, j]);
                triangles.Add(dindex[i, j + 1]);
                triangles.Add(dindex[i, j + 1]);
                triangles.Add(dindex[i + 1, j]);
                triangles.Add(dindex[i + 1, j + 1]);
            }
        }

        //创建一个游戏物体
        GameObject obj = new GameObject();
        obj.name = "TestMesh";
        obj.transform.position = Vector3.zero;

        //网格渲染器
        MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();
        //创建无光影材质
        Material material = new Material(Shader.Find("Unlit/Color"));
        //设置材质颜色为白色
        material.color = Color.white;
        meshRenderer.material = material;
        //网格过滤器
        MeshFilter meshFilter = obj.AddComponent<MeshFilter>();

        //用列表数据创建网格 Mesh 对象
        Mesh mesh = new Mesh();
        mesh.name = "MestTest";
        //设置顶点
        mesh.SetVertices(vertices);
        //设置顶点索引
        mesh.triangles = triangles.ToArray();
        // 自动计算法线
        mesh.RecalculateNormals();
        // 自动计算物体的整体边界
        mesh.RecalculateBounds();
        // 将mesh对象赋值给网格过滤器,就完成了
        meshFilter.mesh = mesh;
    }
}

运行后, Game 视图

Scene 视图(Shaded 改为 Shaded Wireframe)

这样就实现了想要的结果了,这次只生成了 4 个面(3 排 3 列),如果想生成多个面,只需要改变 row, column 的值就行了,比如:

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言

end

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

熊思宇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值