Unity3D动态地形网格一

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

首先直接把脚本拖到某物体上面,运行,就会出现了上图所示的一个面片。这是因为为了方便大家测试,我在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();

}

///

/// 生成默认地形

///

public void SetTerrain()

{

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

}

///

/// 通过参数生成地形

///

/// 地形宽度

/// 地形长度

/// 宽度的段数

/// 长度的段数

/// 最低高度

/// 最高高度

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

{

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

GetVertives();

DrawMesh();

}

///

/// 初始化计算某些值

///

///

///

///

///

///

///

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";

}

///

/// 绘制网格

///

private void DrawMesh()

{

Mesh mesh = terrain.AddComponent().mesh;

terrain.AddComponent();

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();

}

///

/// 生成顶点信息

///

///

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;

}

///

/// 生成UV信息

///

///

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;

}

///

/// 生成索引信息

///

///

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;

}

}

///

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

///

///

///

///

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;

}

///

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

///

///

public void SetPos(Vector3 pos)

{

if (terrain)

{

terrain.transform.position = pos;

}

else

{

SetTerrain();

terrain.transform.position = pos;

}

}

}

时间: 2024-11-24 16:29:54

Unity3D动态地形网格一的相关文章

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

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

Unity3D动态对象优化代码分享

具体解释请仔细看注释里已经讲解的很细致了,这里就不多废话了 代码如下: using UnityEngine; using System.Collections; using System.Collections.Generic; /// <summary> /// 动态对象优化 /// </summary> public class DynamicOptimization : MonoBehaviour { // Use this for initialization void S

Unity3d 动态批处理的问题

这段时间做unity3d的优化,主要的入手是减少draw call.    1.代码上主要是把一些零碎的同材质的合并成一个大的mesh.    2.减少不必要的全屏后期处理.把摄像机的rendering path,由deferred修改为forward.这样修改的原因是,我们场景中只是使用了一个灯光,延迟渲染并没有很有发挥其优势,另外使用向前渲染的话,引擎的动态合并会有很好的作用.     经过上面两部分的操作,draw call 减少的非常多,并且游戏在目标平台上也能流畅的运行.但是发现一个非

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使用心得(2):Unity3d 动态下载动画资源——AnimationClip 的使用 - 斯玛特琦

引言: 在使用 Unity3d 开发微端.或者网页游戏的时候常常须要将资源打包成 AssetBundle ,然后通过 www 的方式动态的下载资源.今天要分享的是我再动态下载 Animation 骨骼动画的时候走的一些弯路和自己最后的解决方式. 我们的项目中的动画资源有上百套之多,每一套动画大概在300KB 到 900KB 之前,所以有一个非常重要的需求就是动态的下载须要的动画. 错误的方法: 我看到需求后想到的第一种方法是将 FBX 倒入的 Prefab 实例化,将当中的 Animation

Unity3D动态加载外部资源

最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别.Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的. 其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了. 详细说一下细节概念:AssetBundle运行时加载:来自

unity3d动态加载dll的API以及限制

Unity3D的坑系列:动态加载dll 一.使用限制 现在参与的项目是做MMO手游,目标平台是Android和iOS,iOS平台不能动态加载dll(什么原因找乔布斯去),可以直接忽略,而在Android平台是可以动态加载dll的,有了这个就可以实现代码更新,不过实际上,在unity里要用上动态加载dll是有很多限制的(不了解的话就是坑). 限制1:在Android手机里动态加载dll不能使用Assembly.LoadFile(string path),只能使用Assembly.Load(byte

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深入浅出 - 导航网格自动寻路(Navigation Mesh)

NavMesh(导航网格)是3D游戏世界中用于实现动态物体自动寻路的一种技术,将游戏中复杂的结构组织关系简化为带有一定信息的网格,在这些网格的基础上通过一系列的计算来实现自动寻路..导航时,只需要给导航物体挂载导航组建,导航物体便会自行根据目标点来寻找最直接的路线,并沿着该线路到达目标点. 下面通过一个简单的Sample来介绍NavMesh的应用: 1.在Scene中新建三个Cube,如下图摆放. 2.选中上图三个Cube,并在Inspector面板中选中为静态(static)下拉选项的Navi