Unity3D 通过代码导入自定义格式地形的方法
2013-05-22 00:23
399 查看
最近有点空闲时间,就打算把以前项目的场景资源转移到Unity3D里面去,首先第一步做的就是地形的移植,在这过程中绕了不少弯路,专门记录下。
场景地形的移植首先想到的办法是通过高度图来进行中转,但由于Unity文档中对导入高度图的格式说明不够详细,试验了很多次都没能正确导入,最后只好作罢,转为直接通过c#脚本载入。
1) 导出。首先第一步是将地形的高度数据导出到文件中,由于这个文件等下读取的代码也是自己做,所以格式自己清楚就可以了,我是将每一个顶点的高度值以一个float依次保存在了一个二进制文件中。
2) U3D读取2进制文件。 现在我们有了存有地形高度信息的文件,接下来要做的事就是通过U3D去读取并解析这个二进制文件,这里我们通过TextAsset来载入。这里需要注意,需要通过TextAsset来载入的二进制文件,要将后缀名改为.bytes再加入到工程中。
3) U3D中地形的高度信息是保存在terrain.terrainData中的,起初认为只需要将读到的数据塞进去就可以了,后来发现也并非如此,主要存在下面几个问题:
HeightmapResolution的大小,也就是导入的顶点数据的多少,需要和你数据的大小对应,并且其大小应为2n +1。
U3D中地形所存储的数据并不是一个绝对的高度数值,而是一个相对的高度值,这个高度的分母应当是当前地形中最高值与最低值之间的差值。也就是这个值决定了这块地形的高度上限。对应的代码中的属性是terrain.terrainData.size.y。
U3D地形中是不存在负值的,如果你导入的地形数据中有负值,那么请将他们通过整体向上提升的方式,在保证相互之间高度的同时提升到0以上。
最后放上截图一张
具体的实现代码如下:
场景地形的移植首先想到的办法是通过高度图来进行中转,但由于Unity文档中对导入高度图的格式说明不够详细,试验了很多次都没能正确导入,最后只好作罢,转为直接通过c#脚本载入。
1) 导出。首先第一步是将地形的高度数据导出到文件中,由于这个文件等下读取的代码也是自己做,所以格式自己清楚就可以了,我是将每一个顶点的高度值以一个float依次保存在了一个二进制文件中。
2) U3D读取2进制文件。 现在我们有了存有地形高度信息的文件,接下来要做的事就是通过U3D去读取并解析这个二进制文件,这里我们通过TextAsset来载入。这里需要注意,需要通过TextAsset来载入的二进制文件,要将后缀名改为.bytes再加入到工程中。
3) U3D中地形的高度信息是保存在terrain.terrainData中的,起初认为只需要将读到的数据塞进去就可以了,后来发现也并非如此,主要存在下面几个问题:
HeightmapResolution的大小,也就是导入的顶点数据的多少,需要和你数据的大小对应,并且其大小应为2n +1。
U3D中地形所存储的数据并不是一个绝对的高度数值,而是一个相对的高度值,这个高度的分母应当是当前地形中最高值与最低值之间的差值。也就是这个值决定了这块地形的高度上限。对应的代码中的属性是terrain.terrainData.size.y。
U3D地形中是不存在负值的,如果你导入的地形数据中有负值,那么请将他们通过整体向上提升的方式,在保证相互之间高度的同时提升到0以上。
最后放上截图一张
具体的实现代码如下:
using UnityEngine; using System.Collections; using System.IO; public class TerrainLoader : MonoBehaviour { public string HeightDataFile; public int MapSize; public Terrain terrain; // Use this for initialization void Start () { // 读取资源 TextAsset TA = Resources.Load(HeightDataFile) as TextAsset; byte[] buff = TA.bytes; buff[buff.Length-1] = 0; float[,] data = new float[MapSize,MapSize]; int index = 0; float min = 0; float max = 0; // 将二进制转换为float for(int i = 0; i<MapSize; i++) { for(int j = 0; j<MapSize; j++) { data[i,j] = System.BitConverter.ToSingle( buff, index ); index += 4; if(min > data[i,j]) min = data[i,j]; if(max < data[i, j]) max = data[i,j]; } } // 计算出地形最大值与最小值的高度差 float detailHeight = max - min; // 设置地形的最大高度 terrain.terrainData.size = new Vector3(512,detailHeight,512); // 将地形整体上移,消灭负值 for(int i = 0; i<MapSize; i++) { for(int j = 0; j<MapSize; j++) { if(min < 0) { data[i,j] = data[i,j] - min; } data[i,j] = data[i,j] / detailHeight; } } // 设置分辨率 terrain.terrainData.heightmapResolution = MapSize; // 导入高度数据 terrain.terrainData.SetHeights(0, 0, data); } // Update is called once per frame void Update () { } }
相关文章推荐
- 高度地形Unity3D 通过代码导入自定义格式地形的方法
- 代码中设置excel自定义格式为[红色]的处理方法
- 通过Navicat向MySQL导入Excel文件格式数据的方法及遇到的问题
- JS: 重新组织 mongoDB数据库中的 数据格式的方法 / 导入导出 / 附案例代码
- Unity3D 自定义地形插件(支持FBX导入模型的编辑)
- Unity3d之无缝地形场景切换–解决方法和代码
- unity3d 中文乱码解决方法——cs代码文件格式批量转化UTF8
- unity3d 无缝地形场景切换 解决方法和代码
- Unity3d之无缝地形场景切换–解决方法和代码
- 自定义UITableViewCell (通过代码实现:每个CELL格式不一样)
- Unity3d之无缝地形场景切换–解决方法和代码
- [导入]Asp.net 2.0 实现自定义Email格式有效性验证(示例代码下载)
- iOS时间以yyyy-MM-dd格式输出的两种方法代码
- ORA-01810:格式代码出现两次 解决方法
- 通过AngularJs自定义服务实现代码共用实例
- 一起谈.NET技术,提供第三种代码生成方式——通过自定义BuildProvider为ASP.NET提供代码生成
- 通过代码自定义cell(cell的高度不一致)
- 通过自定义方法减少findViewById方法使用的次数
- C++ - 智能指针(smarter pointer)自定义删除器(deleter) 的方法 详解 及 代码
- Access文件(.mdb)导入SQL Server时"错误代码为 0xC0202009"的解决方法