Unity3D分割地形Terrain_成都骚壳壳的博客-程序员宝宝

技术标签: Unity3D  Terrain  unity3d  

在制作地形的时候通常是直接刷出整个地形,但是在实际使用中也许地形过大,我们不能直接把整个地形完全加载,这样对内存的消耗很高,所以有时需要一小块一小块的加载地形.这时就需要把制作好的地形分割成几块后,再来动态加载.


首先我制作了一个完整的地形,如下图:

这里写图片描述


直接上分割地形的代码

public class TerrainSlicing : Editor
{
    public static string TerrainSavePath = "Assets/Resources/" + TerrainLoad.TERRAIN_PATH;
    //分割大小
    public static int SLICING_SIZE = 4;

    //开始分割地形
    [MenuItem("Terrain/Slicing")]
    private static void Slicing()
    {
        Terrain terrain = GameObject.FindObjectOfType<Terrain>();
        if (terrain == null)
        {
            Debug.LogError("找不到地形!");
            return;
        }

        if (Directory.Exists(TerrainSavePath)) Directory.Delete(TerrainSavePath, true);
        Directory.CreateDirectory(TerrainSavePath);

        TerrainData terrainData = terrain.terrainData;

        //这里我分割的宽和长度是一样的.这里求出循环次数,TerrainLoad.SIZE要生成的地形宽度,长度相同
        //高度地图的分辨率只能是2的N次幂加1,所以SLICING_SIZE必须为2的N次幂
        SLICING_SIZE = (int)terrainData.size.x / TerrainLoad.SIZE;

        Vector3 oldSize = terrainData.size;

        //得到新地图分辨率
        int newHeightmapResolution = (terrainData.heightmapResolution - 1) / SLICING_SIZE;
        int newAlphamapResolution = terrainData.alphamapResolution / SLICING_SIZE;
        int newbaseMapResolution = terrainData.baseMapResolution / SLICING_SIZE;
        SplatPrototype[] splatProtos = terrainData.splatPrototypes;

        //循环宽和长,生成小块地形
        for (int x = 0; x < SLICING_SIZE; ++x)
        {
            for (int y = 0; y < SLICING_SIZE; ++y)
            {
                //创建资源
                TerrainData newData = new TerrainData();
                string terrainName = TerrainSavePath + TerrainLoad.TERRAIN_NAME + y+ "_" + x + ".asset";
                AssetDatabase.CreateAsset(newData, TerrainSavePath + TerrainLoad.TERRAIN_NAME + y + "_" + x + ".asset");
                EditorUtility.DisplayProgressBar("正在分割地形", terrainName, (float)(x * SLICING_SIZE + y) / (float)(SLICING_SIZE * SLICING_SIZE));

                //设置分辨率参数
                newData.heightmapResolution = (terrainData.heightmapResolution - 1) / SLICING_SIZE;
                newData.alphamapResolution = terrainData.alphamapResolution / SLICING_SIZE;
                newData.baseMapResolution = terrainData.baseMapResolution / SLICING_SIZE;

                //设置大小
                newData.size = new Vector3(oldSize.x / SLICING_SIZE, oldSize.y, oldSize.z / SLICING_SIZE);

                //设置地形原型
                SplatPrototype[] newSplats = new SplatPrototype[splatProtos.Length];
                for (int i = 0; i < splatProtos.Length;  ++i)
                {
                    newSplats[i] = new SplatPrototype();
                    newSplats[i].texture = splatProtos[i].texture;
                    newSplats[i].tileSize = splatProtos[i].tileSize;

                    float offsetX = (newData.size.x * x) % splatProtos[i].tileSize.x + splatProtos[i].tileOffset.x;
                    float offsetY = (newData.size.z * y) % splatProtos[i].tileSize.y + splatProtos[i].tileOffset.y;
                    newSplats[i].tileOffset = new Vector2(offsetX, offsetY);
                }
                newData.splatPrototypes = newSplats;


                //设置混合贴图
                float[,,] alphamap = new float[newAlphamapResolution, newAlphamapResolution, splatProtos.Length];
                alphamap = terrainData.GetAlphamaps(x * newData.alphamapWidth, y * newData.alphamapHeight, newData.alphamapWidth, newData.alphamapHeight);
                newData.SetAlphamaps(0, 0, alphamap);

                //设置高度
                int xBase = terrainData.heightmapWidth / SLICING_SIZE;
                int yBase = terrainData.heightmapHeight / SLICING_SIZE;
                float[,] height = terrainData.GetHeights(xBase * x, yBase * y, xBase + 1, yBase + 1);
                newData.SetHeights(0, 0, height);
            }
        }

        EditorUtility.ClearProgressBar();
    }
}

分割地形的操作肯定是在Editor模式下,所以这里我就直接使用Unity的Editor扩展了,直接添加进MenuItem.
然后分割后动态加载地形,这里我的整张地形宽度为1200,长度也是1200.分割出来的小块地形为300,所以我一共创建了16个小地形.现在来看看动态加载的效果
这里写图片描述
这里写图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_14903317/article/details/69835578

智能推荐

HDU 1010 Tempter of the Bone_小鸡炖蘑菇_的博客-程序员宝宝

HDU 1010 Tempter of the BoneProblem Description The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could fee

OpenCV——轮廓发现_chain_approx_simple_昨夜雨疏风骤z的博客-程序员宝宝

目录前言正文代码函数cv.GaussianBlurcv.thresholdfindContoursdrawContours参考前言从标题就可以看出我们写这篇文章的意义了,我们的目的就是为了通过对图像进行处理,绘制出图像中物体的轮廓。从而为后面,我们计算一些特殊图形的周长,面积打下基础。轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同 的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测查找轮廓

MDK 5 代码补全功能,使能 动态语法检查(Dynamic Syntax Checking)_deepwater_zone的博客-程序员宝宝

MDK 4.7版本开始支持代码补全功能,默认没有开启,需要手动设置。1、打开软件,单击【Edit】—&gt;【Configuration】;2、选择【Text Completion】选项,在【Show Code Completion List for】下面的三项全部勾选;3、单击【OK】确认,代码补全功能就可以使用了。...

阿里云服务器远程桌面连接提示凭证不工作解决办法_阿里云远程连接凭据不工作_没事儿呀的博客-程序员宝宝

新手入门弄了一个阿里云服务器用来自己学习在官网上点击远程链接出现了终端管理的画面,一切都好好的,小白表示很兴奋安装官网的步骤一步一步的在本机尝试远程连接(系统win7),输入ip地址,用户名,点击确定,弹框输密码然后就.....,有点难受啊之后各种百度,尝试各种方法可能导致此故障的原因 1、客户端本地网络异常 [出现概率:3%]这个就... 2、重置实例...

mysql. Oracle创建视图,Navicat 教程:Oracle 视图_weixin_39806388的博客-程序员宝宝

Navicat for Oracle 视图用于访问一组关联(表),就像一个单一的表,并限制访问。视图也可以用来限制访问行(一个特定表的子集)。点击“视图”按钮即可打开视图对象列表。Navicat for Oracle 视图用户可以创建视图快捷方式,在对象列表中的视图上右击,并在弹出的菜单中选择“创建打开视图快捷方式”,该选项是用来提供一个打开视图的便捷方式而无需打开主 Navicat。● 预览:预...

hdu 1010 Tempter of the Bone 简单带回溯的dfs+奇偶剪枝_hdu简单回溯_PoemK的博客-程序员宝宝

题目链接:http://acm.hdu.edu.cn/status.php题意:有一只小狗需要从N*M迷宫里逃离,出发点标记为'S','X'为不可走,'D'为出口,出口是一扇门,只有在T时刻才打开。问小狗能否逃离迷宫?T (1 简单带回溯的dfs,很久以前做过,时隔两年,为了复习算法又遇此题。结果还超时了,一脸懵逼,然后果断看以前的代码(我好菜),加了一个奇偶剪枝,AC

随便推点

Juniper Netscreen 防火墙支持IPV6 配置_ssg520配置转v6_ruild88的博客-程序员宝宝

原文链接:Juniper Netscreen 防火墙支持IPV6 配置(http://devops.weiminginfo.com/network/1155.html)版本升级Juniper 官方建议升级至screenOS 6.3.0以后版本,升级步骤详见另一篇文章http://devops.weiminginfo.com/network/1148.html配置步骤1.开启ipv6...

三国演义!CatBoost vs. LightGBM vs. XGBoost 到底谁更强?_ronghuaiyang的博客-程序员宝宝

点击上方“AI公园”,关注公众号,选择加“星标“或“置顶”作者:Alvira Swalin编译:ronghuaiyang前戏CatBoost,LightGBM,XGBoo...

Apache Common BeanUtils 2_xymyeah的博客-程序员宝宝

jakarta commons 下面有许多已经开发好的好用组 件 我沒记错的话, 应该是讨论到 Net Ftp, 但是你们连结到 Commons 的网页時候, 一定会吓了一跳, 哇

【数据可视化】AntV L7实现地图可视化,DrillDownLayer钻取异步获取数据,悬浮预警框_椰卤工程师的博客-程序员宝宝

中国地图展示demo如下:一、钻取地图的使用钻取地图支持两种可视化类型填充图:在地图上显示每个区域,根据区域值设置区块填充颜色气泡图:每个区域用气泡显示,根据区域值设置气泡的颜色和大小1)构造函数scene L7 scene 对象option 行政区划配置项drillDepth number 下钻深度 0 | 1 | 2 1 市级 2,县级customTrigger 是否自定义下钻交互,默认 falsedrillDownTriggerEvent 向下钻取的触发事件 custom

带网管工业交换机跟不带网管交换机的差别_杭州飞畅的博客-程序员宝宝

交换机是局域网的一种核心设备,可以自主工作的多个计算机系统连接在一起,实现局部的软硬件共享的网络。通常的交换机是利用第二层的MAC地址的进行工作的,所以一般的家庭交换机基本上都是二层交换机。交换机有带网管的也有不带网管的,那么,交换机带网管跟不带网管有哪些差别呢?接下来我们就一起来看看吧!二层交换机通常都比较便宜,不能也不需要进行任何的设置,只需要通电就可以正常工作。它主要的作用就是交换多彩设备之间的数据。用来构建局域网,进行文件和打印机的共享和互访。通常有五口八口,16口,24口。当你使用网线连接的台

Golang标准库_golang 标准库_古城小栈的博客-程序员宝宝

Go标准库的基础使用说明,借鉴GitHub相关文档,可以当做知识字典使用

推荐文章

热门文章

相关标签