`
jjfat
  • 浏览: 285747 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【unity 5学习记录】 可编辑地形 网格 原理讲解 17.8.8

 
阅读更多

 

这是效果

附上源码 我的csdn博客是http://blog.csdn.net/zhong1213/article/details/76904263

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class TerrainManager : MonoBehaviour
{
    Mesh mesh;

    //材质
    public Material diffuseMap;

    //顶点、uv、索引信息
    private Vector3[] vertives;
    private Vector2[] uvs;
    private int[] triangles;
    private ushort[] blockData;

    //生成信息
    private Vector3 chunkSize;//长宽高
    private int groundHeight;//地面高度

    //区块主体
    private GameObject terrain;

    void Start()
    {
        SetTerrain(10, 10, 10, 5);
    }

    // 通过参数生成地形

    public void SetTerrain(float width, float height, float length, int groundH)
    {
        Init(width, height, length, groundH);//初始化数据
        GetVertives();
        DrawMesh();
        terrain.AddComponent<MeshCollider>();
    }

    /// 初始化计算某些值
    private void Init(float width, float height, float length, int groundH)
    {
        chunkSize = new Vector3(width, height, length);//初始化区块尺寸并赋值
        groundHeight = groundH;//给地面高度赋值
        if (terrain != null)
        {
            Destroy(terrain);
        }
        terrain = new GameObject();//初始化区间
        terrain.name = "plane";//设置chunk名字
        terrain.layer = 8;//设置区间所在层数。只有这一层内的碰撞体才会被射线检测到
        blockData = new ushort[(int)(chunkSize.x * chunkSize.y * chunkSize.z)];//初始化方块数据,方括号内是该区间内所容纳方块数,该数组的容量
        //该循环遍历0,0,0 到 (chunksize-1,chunksize-1,chunksize-1)的方块位置。并根据地面高度。分配方块对应的数字。0是空,1是有方块
        for (int x = 0; x < chunkSize.x; x++)
        {
            for (int y = 0; y < chunkSize.y; y++)
            {
                for (int z = 0; z < chunkSize.z; z++)
                {
                    if (y <= groundH)
                    {
                        blockData[getBlockIndex(x, y, z)] = 1;
                    }
                    else
                    {
                        blockData[getBlockIndex(x, y, z)] = 0;
                    }


                }

            }

        }
        //用于测试
        blockData[getBlockIndex(5, 1, 5)] = 0;
        blockData[getBlockIndex(5, 2, 5)] = 0;
        blockData[getBlockIndex(5, 3, 5)] = 0;
        blockData[getBlockIndex(5, 4, 5)] = 0;
        blockData[getBlockIndex(5, 5, 5)] = 0;
        blockData[getBlockIndex(5, 5, 6)] = 0;
        blockData[getBlockIndex(5, 5, 7)] = 0;
        blockData[getBlockIndex(6, 5, 5)] = 0;
        blockData[getBlockIndex(7, 5, 5)] = 0;
    }
    public void BuildBlock(float px, float py, float pz, int blockID)
    {
        //获取对应的方块并且赋值blockID
        blockData[(int)((pz + py * ((int)chunkSize.z) + (px * (int)(chunkSize.y) * (int)(chunkSize.z))))] = (ushort)blockID;

        //这里开始重绘网格
        GetVertives();
        //给mesh 赋值
        mesh.Clear();
        mesh.vertices = vertives;//,pos);
        mesh.uv = uvs;
        mesh.triangles = triangles;
        //重置法线
        mesh.RecalculateNormals();
        //重置范围
        mesh.RecalculateBounds();
        //更新网格碰撞体
        terrain.GetComponent<MeshCollider>().sharedMesh = mesh;
    }
    /// <summary>
    /// 绘制网格
    /// </summary>
    private void DrawMesh()
    {
        mesh = terrain.AddComponent<MeshFilter>().mesh;//添加网格组件,并且添加到本地mesh变量里
        terrain.AddComponent<MeshRenderer>();//添加网格渲染
        if (diffuseMap == null)
        {
            Debug.LogWarning("No material,Create diffuse!!");
            diffuseMap = new Material(Shader.Find("Diffuse"));
        }

        terrain.GetComponent<Renderer>().material = diffuseMap;

        mesh.Clear();

        //给mesh 赋值
        mesh.vertices = vertives;//,pos);
        mesh.uv = uvs;
        mesh.triangles = triangles;
        //重置法线
        mesh.RecalculateNormals();
        //重置范围
        mesh.RecalculateBounds();
    }

    /// <summary>
    /// 生成顶点信息
    /// </summary>
    /// <returns></returns>
    private Vector3[] GetVertives()
    {
        int index = 0;//顶点初始序号
        //GetUV();

        vertives = new Vector3[(int)((chunkSize.x + 1) * (chunkSize.y + 1) * (chunkSize.z + 1))];//初始化顶点序号
        for (int x = 0; x < chunkSize.x + 1; x++)
        {
            for (int y = 0; y < chunkSize.y + 1; y++)
            {
                for (int z = 0; z < chunkSize.z + 1; z++)
                {

                    if (y == 0)//底面一定绘制
                    {
                        vertives[index] = new Vector3(x, y, z);

                    }
                    else
                    {
                        if (!ifIsSide(x, y, z, 0))
                        {
                            if (ifDifFromAround(x, y, z))
                            {
                                vertives[index] = new Vector3(x, y, z);
                            }
                        }
                    }
                    index++;//即将进行下一个遍历,顶点序号加一,这样是为了每一个坐标都有唯一对应的顶点序号。便于后面绘制三角形通过坐标计算顶点序号

                }
            }
        }
        GetTriangles();//生成三角形信息
        return vertives;
    }
    //这个包含方块序号和坐标的对应规则,可以直接通过方块坐标获得方块序号
    private int getBlockIndex(int x, int y, int z)
    {
        return (z + y * ((int)chunkSize.z) + (x * (int)(chunkSize.y) * (int)(chunkSize.z)));
    }

    //这部分是为了接下来多区块准备的,就是避开绘制周围一圈方块,因为周围一圈方块的绘制需要根据相邻chunk里的方块来绘制
    private bool ifIsSide(int x, int y, int z, int VorT) //v =0 t=1
    {
        if (VorT == 0)//0是给顶点遍历用的
        {
            if (x == 0 || y == 0 || z == 0 || x >= (int)chunkSize.x || y >= (int)chunkSize.y || z >= (int)chunkSize.z)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else//1是给三角形遍历用的
        {
            if (x == 0 || y == 0 || z == 0 || x >= (int)chunkSize.x - 1 || y >= (int)chunkSize.y - 1 || z >= (int)chunkSize.z - 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    }

    //这部分是顶点遍历的时候。判断顶点周围八个方块是不是一样。只有不一样的情况。这个顶点才会被加载
    private bool ifDifFromAround(int x, int y, int z)
    {
        if (blockData[getBlockIndex(x, y, z)] == 0)
        {

            if (blockData[getBlockIndex(x - 1, y, z)] > 0 ||
                    blockData[getBlockIndex(x, y - 1, z)] > 0 ||
                    blockData[getBlockIndex(x, y, z - 1)] > 0 ||
                    blockData[getBlockIndex(x - 1, y - 1, z)] > 0 ||
                    blockData[getBlockIndex(x, y - 1, z - 1)] > 0 ||
                    blockData[getBlockIndex(x - 1, y, z - 1)] > 0 ||
                    blockData[getBlockIndex(x - 1, y - 1, z - 1)] > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {

            if (blockData[getBlockIndex(x - 1, y, z)] == 0 ||
                    blockData[getBlockIndex(x, y - 1, z)] == 0 ||
                    blockData[getBlockIndex(x, y, z - 1)] == 0 ||
                    blockData[getBlockIndex(x - 1, y - 1, z)] == 0 ||
                    blockData[getBlockIndex(x, y - 1, z - 1)] == 0 ||
                    blockData[getBlockIndex(x - 1, y, z - 1)] == 0 ||
                    blockData[getBlockIndex(x - 1, y - 1, z - 1)] == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        return false;

    }
    /// <summary>
    /// 生成UV信息
    /// </summary>
    /// <returns></returns>
    /*private Vector2[] GetUV()
    {
        int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));
        uvs = new Vector2[sum];
        float u = 1.0F / segment.x;
        float v = 1.0F / segment.y;
        uint index = 0;
        for (int i = 0; i < segment.y + 1; i++)
        {
            for (int j = 0; j < segment.x + 1; j++)
            {
                uvs[index] = new Vector2(j * u, i * v);
                index++;
            }
        }

        return uvs;
    }*/

    /// <summary>
    /// 生成三角形信息
    /// </summary>
    /// <returns></returns>
    private int[] GetTriangles()
    {
        int sum = Mathf.FloorToInt(chunkSize.x * chunkSize.y * chunkSize.z * 6);
        triangles = new int[sum];//初始化三角形数组
        uint index = 0;//初始三角形序号

        for (int x = 0; x < chunkSize.x; x++)
        {
            for (int y = 0; y < chunkSize.y; y++)
            {
                for (int z = 0; z < chunkSize.z; z++)
                {
                    /*if (blockData[z + (y * (int)chunkSize.z) + (x * (int)chunkSize.y * (int)chunkSize.z)] != 0){
                        if (y == 0){
                            int self = z + y * ((int)chunkSize.z+1)+ (x * (int)(chunkSize.y+1) * (int)(chunkSize.z+1));
                            int next = z + (y * (int)(chunkSize.z + 1) + ((x+1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));

                            triangles[index] = self;
                            triangles[index + 1] = self + 1;
                            triangles[index + 2] = next + 1;
                            triangles[index + 3] = self;
                            triangles[index + 4] = next + 1;
                            triangles[index + 5] = next;
                            index += 6;
                        }
                    }*/
                    if (y == 0)
                    {
                        int self = z + y * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                        int next = z + (y * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));

                        triangles[index] = self;
                        triangles[index + 1] = self + 1;
                        triangles[index + 2] = next + 1;
                        triangles[index + 3] = self;
                        triangles[index + 4] = next + 1;
                        triangles[index + 5] = next;
                        index += 6;
                    }
                    else
                    {

                        if (!ifIsSide(x, y, z, 1))
                        {
                            if (blockData[getBlockIndex(x, y, z)] == 0)
                            {

                                //下面是判断当前坐标方块上下左右前后的方块是不是实心的
                                //如果是实心的就把面绘制出来。而且要注意三角形面的绘制是一侧的。取决于你取点的顺序。顺时针就是正面,逆时针就是反面

                                //check up and draw triangle

                                if (blockData[getBlockIndex(x, y + 1, z)] != 0)
                                {
                                    int self = z + (y + 1) * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + ((y + 1) * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));

                                    triangles[index] = self;
                                    triangles[index + 1] = next + 1;
                                    triangles[index + 2] = self + 1;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = next;
                                    triangles[index + 5] = next + 1;
                                    index += 6;
                                }
                                //check doawn and draw triangle
                                if (blockData[getBlockIndex(x, y - 1, z)] != 0)
                                {
                                    int self = z + (y) * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + ((y) * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));

                                    triangles[index] = self;
                                    triangles[index + 1] = self + 1;
                                    triangles[index + 2] = next + 1;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = next + 1;
                                    triangles[index + 5] = next;
                                    index += 6;
                                }
                                //side
                                if (blockData[getBlockIndex(x, y, z - 1)] != 0)
                                {
                                    int self = z + (y) * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + ((y) * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));
                                    int sup = self + (int)chunkSize.z + 1;
                                    int nup = next + (int)chunkSize.z + 1;
                                    triangles[index] = self;
                                    triangles[index + 1] = nup;
                                    triangles[index + 2] = sup;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = next;
                                    triangles[index + 5] = nup;
                                    index += 6;
                                }
                                if (blockData[getBlockIndex(x, y, z + 1)] != 0)
                                {
                                    int self = z + 1 + (y) * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + 1 + ((y) * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));
                                    int sup = self + (int)chunkSize.z + 1;
                                    int nup = next + (int)chunkSize.z + 1;
                                    triangles[index] = self;
                                    triangles[index + 1] = sup;
                                    triangles[index + 2] = nup;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = nup;
                                    triangles[index + 5] = next;
                                    index += 6;
                                }
                                if (blockData[getBlockIndex(x - 1, y, z)] != 0)
                                {
                                    int self = z + (y) * ((int)chunkSize.z + 1) + (x * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + ((y) * (int)(chunkSize.z + 1) + ((x + 1) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));
                                    int sup = self + (int)chunkSize.z + 1;
                                    int nup = next + (int)chunkSize.z + 1;
                                    triangles[index] = self;
                                    triangles[index + 1] = sup;
                                    triangles[index + 2] = sup + 1;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = sup + 1;
                                    triangles[index + 5] = self + 1;
                                    index += 6;
                                }
                                if (blockData[getBlockIndex(x + 1, y, z)] != 0)
                                {
                                    int self = z + (y) * ((int)chunkSize.z + 1) + ((x + 1) * (int)(chunkSize.y + 1) * (int)(chunkSize.z + 1));
                                    int next = z + ((y) * (int)(chunkSize.z + 1) + ((x + 2) * (int)((chunkSize.y + 1) * (chunkSize.z + 1))));
                                    int sup = self + (int)chunkSize.z + 1;
                                    int nup = next + (int)chunkSize.z + 1;
                                    triangles[index] = self;
                                    triangles[index + 1] = sup + 1;
                                    triangles[index + 2] = sup;
                                    triangles[index + 3] = self;
                                    triangles[index + 4] = self + 1;
                                    triangles[index + 5] = sup + 1;
                                    index += 6;
                                }
                            }
                        }
                    }
                }
            }
        }
        return triangles;
    }
}
0
0
分享到:
评论

相关推荐

    Unity地形转网格

    通过此脚本可以使地形跟网格贴合,通过此脚本可以使地形跟网格贴合

    Unity引擎开发:地形生成与编辑-(10).地形LOD技术.docxUnity引擎开发:地形生成与编辑-(11).地形碰撞与导航.docxUnity引擎开发:地形生成与编辑-(12).地形在不同

    Unity引擎开发:地形生成与编辑_(10).地形LOD技术.docx Unity引擎开发:地形生成与编辑_(11).地形碰撞与导航.docx Unity引擎开发:地形生成与编辑_(12)....Unity引擎开发:地形生成与编辑_(8

    Unity游戏项目源码 强大的地形生成 完整版.zip

    1. **地形编辑器(Terrain Editor)**:Unity内置的地形编辑器提供了一套工具,用于绘制、平滑、升高或降低地形。开发者可以调整高度图,添加纹理贴图,以及种植树木和植被。 2. **脚本(Scripts)**:为了实现动态...

    Unity地形制作共27页.pdf.zip

    这份名为"Unity地形制作共27页.pdf.zip"的压缩包很可能包含了一份详细的教程或指南,教授如何在Unity中高效、精美地创建和编辑地形。 首先,我们要了解Unity中的地形系统。Unity的地形系统允许开发者通过一个集成的...

    Unity地形改变插件 Curve World .unitypackage

    Unity地形改变插件 Curve World .unitypackage,能够将平面地形直接渲染成为上下坡道,或者左右弯道

    Mesh to Terrain 2.12 - 网格转换地形的插件 Unity3D

    用于将使用3dmax,Terragen或任何其他编辑器创建的3D地形模型快速转换为Unity Terrain的组件。 特征: •支持Unity v5.2 - Unity 2018.x •组件中使用的模型和地形数量无限; •地形在网格的相同位置创建; •将模型的...

    Unity地形导出.obj格式模型文件

    1.在Unity中制作好地形; 2.选中场景中的地形,点击Tools菜单下的地形导出即可; 3.导出的地形是obj格式。

    unity3d 游戏插件 terrainComposer 地形编辑 5A级别 地貌 制作 工具.zip模型资源unity模型资

    unity3d 游戏插件 terrainComposer 地形编辑 5A级别 地貌 制作 工具.zip模型资源unity模型资unity3d 游戏插件 terrainComposer 地形编辑 5A级别 地貌 制作 工具.zip模型资源unity模型资unity3d 游戏插件 terrain...

    unity3d 游戏场景模型 地形地貌素材包 Landscapes Part2.zip

    Unity3D内置了强大的地形编辑器,允许开发者通过简单的操作创建复杂的地形地貌。它支持绘制高度图、添加纹理、种植植被、雕刻山体等,为游戏设计师提供了极大的创作自由度。在这个素材包中,你可以找到各种预设的...

    Unity地形编辑器

    通过这个文件,你可以学习到如何使用Unity地形编辑器进行实际项目开发,了解其各项特性和操作流程。 总之,Unity地形编辑器是一个强大的工具,它提供了丰富的功能,帮助开发者快速创建出令人惊叹的3D环境,同时保持...

    Unity地形转换Mesh

    Unity的Terrain组件允许开发者通过编辑器的地形编辑器绘制高度图,添加细节(如草、树木等),并设置地形的纹理贴图。这些操作都是基于数据驱动的,而不是生成一个实际的Mesh。这种设计使得大型地形的渲染变得高效,...

    Unity5.x....

    第 5 章Unity编辑器 35 第 6 章创建基本的3D游戏场景 79 第 7 章创建基本的2D游戏场景 115 第 8 章资源导入导出流程 147 第 9 章游戏对象、组件和Prefabs 193 第 10 章Shuriken粒子系统 213 第 11 章Mecanim动画系统...

    Unity3D教程:Unity3D中网格合并示例2

    总结来说,Unity3D中的网格合并是优化场景性能的重要手段,特别是在处理复杂的角色模型或地形时。理解网格、材质、骨骼和子网格之间的关系以及如何正确地使用`CombineMeshes`函数,是实现这一技术的关键。通过合理地...

    Unity协程(Coroutine)原理深入剖析.pdf

    Unity协程(Coroutine)原理深入剖析.pdf Unity协程(Coroutine)原理深入剖析.pdf Unity协程(Coroutine)原理深入剖析.pdf Unity协程(Coroutine)原理深入剖析.pdf Unity协程(Coroutine)原理深入剖析.pdf

    (源码)基于Unity的六边形网格地图生成系统.zip

    # 基于Unity的六边形网格地图生成系统 ## 项目简介 本项目是一个基于Unity引擎的六边形网格地图生成系统,旨在提供一个灵活且功能丰富的工具,用于创建和管理六边形网格地图。该系统涵盖了从地图生成、地形编辑到...

    Unity即时战略/塔防 网格建造系统

    使用Unity制作的网格建造系统,请参看文章和效果视频。相关文章参见:https://blog.csdn.net/sdhexu/article/details/129767967

    Unity3d_实现地形上挖洞

    Unity3d_实现地形上挖洞 Unity3d_实现地形上挖洞 Unity3d_实现地形上挖洞

    【Unity】Mesh网格编程万能网格几何形体.docx

    Unity Mesh网格编程万能网格几何形体 本文分享了一个使用 Unity 的 Mesh 网格编程实现万能网格几何形体的代码,通过设置不同的参数,可以生成各种锥、柱、管状体的网格。下面是我们从代码中总结出的知识点: 1. ...

Global site tag (gtag.js) - Google Analytics