Unity3D动态创建地形网格(一)

最近一直都在搞flash3D,好像有点对不起Unity3D的朋友们了。这次简单的写一个动态创建地形网格的脚本给大家分享一下。

这次是第一部分,仅仅实现了通过高度图动态生成地形的部分。假如以后有心情和时间,再来慢慢的补充多通道刷地形材质、动态刷地形和保存高度图等的功能吧。以前我都不喜欢公开脚本源码,都是一个个部分的单独讲解然后让朋友们自己去组合起来的,但最近时间实在是不多,所以还是直接提供源码,然后在源码上面写注释,大家自行的观看吧。源码在最下面。

首先直接把脚本拖到某物体上面,运行,就会出现了上图所示的一个面片。这是因为为了方便大家测试,我在start里面调用了下面的SetTerrain方法。这个方法会创建一个默认的地形面板。长宽是100*100,段数是50*50,高度是-10米到10米的。

当然了,我们真正用的时候,是使用重载的SetTerrain方法自己制定长宽高和段数这些数值的,把start里面的方法注释掉就行了。

现在由于没有指定默认的地面材质和高度图,所以我写了个警告提示。

这两个变量就是材质和高度图了,大家可以自行想办法去赋值。我现在写成public只是为了方便赋值测试,最好还是写get/set方法赋值。

还有一点,现在没有做地面的多通道材质,所以只是用了一个默认的shader。以后假如需要混合通道材质,改这个shader。

好,先不管以后了,把一个有草地纹理的材质球付给脚本。

出来了一个草地

我随便的用黑白图刷了一个高度图,然后扔进脚本。

注意的是,作为高度图的图片,是需要设置读写权限的,不然获取不到像素的颜色

出现了一个小小的山坡了。

其实我这个脚本并不是必须针对黑白图的,我随便拿了一张木箱子贴图,一样可以做高度图的,这是因为我是做了灰度处理的,最后获取的是该图片像素点上的灰度值。

看,地形出来了。

实际效果

功能是简单了点,这里提供了一点点的思路,有需要或者有兴趣的朋友可以参考一下做法,自行的扩展吧。

源码:

TerrainManager.cs

using UnityEngine;

using System.Collections;

public class TerrainManager : MonoBehaviour {

//材质和高度图

public Material diffuseMap;

public Texture2D heightMap;

//顶点、uv、索引信息

private Vector3[] vertives;

private Vector2[] uvs;

private int[] triangles;

//生成信息

private Vector2 size;//长宽

private float minHeight = -10;

private float maxHeight = 10;

private Vector2 segment;

private float unitH;

//面片mesh

private GameObject terrain;

// Use this for initialization

void Start () {

//默认生成一个地形,如果不喜欢,注销掉然后用参数生成

SetTerrain();

}

/// <summary>

/// 生成默认地形

/// </summary>

public void SetTerrain()

{

SetTerrain(100, 100, 50, 50,-10,10);

}

/// <summary>

/// 通过参数生成地形

/// </summary>

/// <param name="width">地形宽度</param>

/// <param name="height">地形长度</param>

/// <param name="segmentX">宽度的段数</param>

/// <param name="segmentY">长度的段数</param>

/// <param name="min">最低高度</param>

/// <param name="max">最高高度</param>

public void SetTerrain(float width, float height, uint segmentX, uint segmentY,int min,int max)

{

Init(width, height, segmentX, segmentY,min,max);

GetVertives();

DrawMesh();

}

/// <summary>

/// 初始化计算某些值

/// </summary>

/// <param name="width"></param>

/// <param name="height"></param>

/// <param name="segmentX"></param>

/// <param name="segmentY"></param>

/// <param name="min"></param>

/// <param name="max"></param>

private void Init(float width, float height, uint segmentX, uint segmentY, int min, int max)

{

size = new Vector2(width, height);

maxHeight = max;

minHeight = min;

unitH = maxHeight - minHeight;

segment = new Vector2(segmentX, segmentY);

if (terrain != null)

{

Destroy(terrain);

}

terrain = new GameObject();

terrain.name = "plane";

}

/// <summary>

/// 绘制网格

/// </summary>

private void DrawMesh()

{

Mesh mesh = terrain.AddComponent<MeshFilter>().mesh;

terrain.AddComponent<MeshRenderer>();

if (diffuseMap == null)

{

Debug.LogWarning("No material,Create diffuse!!");

diffuseMap = new Material(Shader.Find("Diffuse"));

}

if (heightMap==null)

{

Debug.LogWarning("No heightMap!!!");

}

terrain.renderer.material = diffuseMap;

//给mesh 赋值

mesh.Clear();

mesh.vertices = vertives;//,pos);

mesh.uv = uvs;

mesh.triangles = triangles;

//重置法线

mesh.RecalculateNormals();

//重置范围

mesh.RecalculateBounds();

}

/// <summary>

/// 生成顶点信息

/// </summary>

/// <returns></returns>

private Vector3[] GetVertives()

{

int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));

float w = size.x / segment.x;

float h = size.y / segment.y;

int index = 0;

GetUV();

GetTriangles();

vertives = new Vector3[sum];

for (int i = 0; i < segment.y + 1; i++)

{

for (int j = 0; j < segment.x + 1; j++)

{

float tempHeight = 0;

if (heightMap != null)

{

tempHeight = GetHeight(heightMap, uvs[index]);

}

vertives[index] = new Vector3(j * w, tempHeight, i * h);

index++;

}

}

return vertives;

}

/// <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(segment.x * segment.y * 6);

triangles = new int[sum];

uint index = 0;

for (int i = 0; i < segment.y; i++)

{

for (int j = 0; j < segment.x; j++)

{

int role = Mathf.FloorToInt(segment.x) + 1;

int self = j +( i*role);

int next = j + ((i+1) * role);

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;

}

}

return triangles;

}

private float GetHeight(Texture2D texture, Vector2 uv)

{

if (texture != null)

{

//提取灰度。如果强制读取某个通道,可以忽略

Color c = GetColor(texture, uv);

float gray = c.grayscale;//或者可以自己指定灰度提取算法,比如:gray = 0.3F * c.r + 0.59F * c.g + 0.11F * c.b;

float h = unitH * gray;

return h;

}

else

{

return 0;

}

}

/// <summary>

/// 获取图片上某个点的颜色

/// </summary>

/// <param name="texture"></param>

/// <param name="uv"></param>

/// <returns></returns>

private Color GetColor(Texture2D texture, Vector2 uv)

{

Color color = texture.GetPixel(Mathf.FloorToInt(texture.width * uv.x), Mathf.FloorToInt(texture.height * uv.y));

return color;

}

/// <summary>

/// 从外部设置地形的位置坐标

/// </summary>

/// <param name="pos"></param>

public void SetPos(Vector3 pos)

{

if (terrain)

{

terrain.transform.position = pos;

}

else

{

SetTerrain();

terrain.transform.position = pos;

}

}

}

时间: 2024-10-05 18:07:54

Unity3D动态创建地形网格(一)的相关文章

Unity3D 动态创建Mesh(一)

1.Mesh.MeshFilter.MeshRenderer关系整理 在Unity3D中创建一个Cube,在Inspector可以看到其中含有MeshFilter.MeshRenderer组件. MeshFilter含有一个Public成员 Mesh. 在Mesh中存储着三维模型的数据:vertices(顶点数据数组Vector3[]).triangles(三角形顶点索引数组,int[]).normals(法线向量数组,Vector3[]).uv(纹理坐标数组,Vector2[]). 2.使用M

Unity3D动态地形网格一

最近一直都在搞flash3D,好像有点对不起Unity3D的朋友们了.这次简单的写一个动态创建地形网格的脚本给大家分享一下.        这次是第一部分,仅仅实现了通过高度图动态生成地形的部分.假如以后有心情和时间,再来慢慢的补充多通道刷地形材质.动态刷地形和保存高度图等的功能吧.以前我都不喜欢公开脚本源码,都是一个个部分的单独讲解然后让朋友们自己去组合起来的,但最近时间实在是不多,所以还是直接提供源码,然后在源码上面写注释,大家自行的观看吧.源码在最下面.更多内容,请访问狗刨学习网http:

Unity3D 动态改变地形

直接获取TerrainData进行修改即可 using System.Collections; using UnityEngine; using UnityEditor; public class DynamicCreateTerrain : MonoBehaviour { public TerrainData terrainData; private float[,] heightsBackups; void Start() { //var terrain = CreateTerrain();

【Unity3D】【NGUI】Atlas的动态创建

NGUI讨论群:333417608 NGUI版本:3.6.5 1.参见SZUIAtlasMakerRuntimeTest设置相应的值以上值需要提前设置好 2.没有检查是否atlas能够正确创建,自己可以改,加入返回值 3.代码都是在NGUI里面拷贝出来的,只是进行改动,没有新代码 4.适用与那种从网上下图片,之后还不想用UITexture的人,但是还是建议用UITexture如果drawcall不是问题的话 5.自己以后更新按我的方式改改就可以 6.动态创建速度较慢,建议在游戏启动的时候运行 7

unity3d通过代码动态创建销毁游戏对象

只能动态创建内部提供的游戏对象,代码如下: //按下C后创建 if (Input.GetKeyDown (KeyCode.C)) { GameObject s1 = GameObject.CreatePrimitive (PrimitiveType.Sphere);//创建 s1.name = "qiu";//命名 s1.GetComponent<MeshRenderer> ().material.color = Color.red;//网格渲染器 s1.transform

【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源(当然你也可以从官网下载). ========================================== 分割线 ========================================== 写在前面 我们已经学了很多关于反射的内容,但是我们现在的反射并不能实时反射,即当反射物体移动时它们不

于Unity3D动态创建对象和创建Prefab三种方式的原型对象

u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject orignal) 需要的对象为原型. 文提供三种方式获得prefab对象. 方式一:使用脚本的public字段 直接在Project视图里找到做好的prefab,将其拖拽到指定脚本的指定public GameObject 字段. 方式二:Resource类 1.在Assets目录下的任何位置创建一个名为resources的目录.将做好的prefab放到这个目录下,p

unity3d UGUI动态创建窗口获取窗口大小的问题

    private IEnumerator RefreshProcess(Vector2 worldPosition)     {         this.Renders();         yield return null;         yield return null;         mRootWidth = (mRoot as RectTransform).rect.width;         mrootHeigh = (mRoot as RectTransform).

Unity3D游戏开发 地形系统(四)

http://mahaile.blog.51cto.com/2891586/771167 上一章我们讲解了 如何创建一个简单的游戏世界 这一章我们来 看看unity3d中的地形系统 废话少说 赶紧开始吧,,哈哈   首先创建一个新的场景    点击菜单栏中的 Terrain-> create Terrain 菜单       完成后如 下图       创建地形系统的时候 unity会按默认的 宽高 图像分辨率,纹理分辨率 等创建一个地形  不过不怕 这些我们都可以修改滴    如果需要在gam