Unity教程 《我的世界》基础篇:生成方块

8
回复
844
查看
打印 上一主题 下一主题
[ 复制链接 ]
排名
8651
昨日变化

35

主题

117

帖子

470

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
75030
好友
13
蛮牛币
1001
威望
0
注册时间
2015-2-16
在线时间
132 小时
最后登录
2019-7-20

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
《我的世界》基础篇:生成数据块

系列概述
这套教程涵盖了Unity Mesh编程、模拟水算法(water simulations)、方块移动算法(marching-cubes)等等。这是一套比较有深度的教程,可能需要你了解一些Unity和C#相关的知识。

预备开始
首先,我们先来创建一个空的项目,命名随意即可。然后创建在Assets下创建一个文件夹,命名为“Scripts”,并创建三个C#脚本,如下图所示:


Chunk用于存储方块数据和创建网格,并且对网格进行渲染和碰撞;Block用于存放方块需要的信息;MeshData用于存储网格数据。

Chunk.cs脚本:
首先,我们要求该脚本必须包含上个组件:MeshFilter、MeshRenderer、MeshCollider。我们的数据块(就是由一堆方块组成的大方块~)需要这三个组件完成网格的创建和碰撞。

然后,我们有三个变量。我们有一个Block类型的三维数组变量 blocks,Block类用于存放方块需要的信息,因此我们这个blocks变量就是用于存放一个数据块的方块的信息。

chunkSize是一个静态变量,它用于表示我们的数据块各个方向的大小(就是长宽高的大小)。

最后我们有一个bool类型的变量,用于标志该数据块是否在每帧结束后更新。

其次有三个函数,分别为GetBlock、UpdateChunk、RenderMesh。GetBlock用于获取对应位置的方块;UpdateChunk用于更新数据块的网格数据,然后将更新的数据提供给RenderMesh去渲染。

MeshData.cs脚本:
由于这个脚本只是为了存储数据,因此不必继承自MonoBehaviour。        


前三个变量(vertices、triangles、uv)是用于渲染网格用的,后两个用于网格碰撞(colVetices、colTriangles)。


Block.cs脚本:

同样的,Block脚本也不需要继承自MonoBehaviour,并且它将会是所有方块的基类。主要用于存储方块所需信息。

BlockData函数用于生成该方块的网格信息。

我们来设想一下,假如我们的数据块是有25个方块组成的,那么在相邻的方块之间,有一些面就不必渲染出来,浪费系统资源。因此,接下来让我们进行剔除多余面数的处理。

首先,我们需要一个函数去判断两个方块是否相邻,如果相邻则对各个方向的面进行剔除处理。

在那之前,让我们先定一个表示方向的枚举(Block脚本中):

然后让我们为Block脚本添加判断的函数:

因为Block脚本是所有方块类的基类,所有我们在Block脚本中对IsSolid函数没有进行判断处理,全部返回true。

现在让我们开始写一些我们的BlockData函数,在这个函数中,我们会根据当前方块对应方向上相邻方块的面进行剔除处理。   


上图中的注释也说得很清楚了。举个栗子:判断当前方块顶上相邻的方块是否有底面,如果有则当前方块就不制作顶面,如下图分析所示:
PS:这个,,,图画得有点Low,希望大家能看懂它的意思。

接下来就是添加需要绘制对应的面的函数了。

上:


上面的注释也说得很清楚了,但是克森还是给你们秀一秀我的美术功底。

其它的面就不细讲,代码如下:

下:


东:

北:

南:

西:

添加点之后,我们还要把这些点组合成三角形,因此在函数的最后调用了MeshData里的AddQuadTriangles(),由名字可知道,该函数用于添加面片,因此我们要用这四个顶点组合成一个面片,让我们回到MeshData中添加该函数:


再给大家上一次克森的美术作品,相信大家都能理解了吧。


接下来,让我们创建一个新的脚本,命名为“BlockAir”,让它继承值Block类,如下所示:


Okey,现在让我们回到Chunk脚本中,开始添加方块进行测试咯。添加如下代码:


首先声明两个变量,一个为MeshFilter(网格过滤器)类型,另一个为MeshCollider(网格碰撞器)类型。分别用于存储和设置我们对应数据库上的组件属性。

首先通过GetComponent方法获取对应物体上的对应的组件,然后初始化了我们的数据块(blocks),我们的数据块是一个16*16*16大小的正方体,里面由一堆小方块组成。当前数据库的小方块类型为 BlockAir。

然后修改了该数据库blocks[3, 5, 2]的方块数据,修改为Block类型方块。

最后调用UpdateChunk函数进行数据的更新。

好的,接下来让我们完善我们的UpdateChunk函数:

首先声明一个类型为MeshData的变量。然后循环遍历blocks进行数据的更新(就是调用每一个方块的BlockData函数,而BlockData函数则是用来处理方块的网格数据,例如剔除面等等)。

最后就是调用RenderMesh函数将更新好的网格数据传入,然后进行网格的渲染。

那么,接下来让我们完成我们的RenderMesh函数:

这个函数很简单,就是先调用Clear函数清除上一次网格的数据,然后重新设置即可。

这一篇只是简单的介绍怎么生成数据块,还没涉及到贴图和碰撞,所以在RenderMesh函数里只是更新了网格数据。下一篇则教大家如何添加贴图到数据块上。

说那么多,先看看效果。

首先创建一个空物体,然后为该物体添加Chunk脚本。你将会发现如下效果:

该物体便会自动添加脚本中需要的那三个组件。对了,记得将positio属性置为0,不然你很可能看不到我们的方块,之后启动游戏,你将会看到如下效果:

为什么方块会跑那去了,为什么会是紫色的呢?因为该方块没有材质,所以是紫色的。因为我们设置了该方块的位置为(3,5,2),那我们是在哪里设置的呢,其实是在这个地方设置了,如下图所示:

这个时候你可以创建一个Cube物体去比对一下就知道了,下图演示:

看来是这样的没错。好,接下来克森带大家来走一走这个运行时候的步骤:

    1.首先我们先进行实例化数据块,也就是Chunk类里面的blocks变量。

    2.调用UpdateChunk更新网格数据,在UpdateChunk中又调用了各个方块的BlockData函数生成网格数据。

    3.在BlockData中我们对当前方块根据检测相邻方块进行剔除面操作。
(由于函数太大,所以只截一小部分)

    4.最后调用RenderMesh对网格数据进行更新。

在这里,为什么我们只生成了一个方块呢。因为要想生成方块,就必须调用BlockData函数,而BlockAir的BlockData函数里我们只做了一个返回,并没有生成网格数据,

因此只生成了一个方块,也就是我们在后面修改的那个位置为(3,5,2)的方块,因为在Block类里BlockData函数已经生成了网格数据。

为什么克森不直接将所有的方块实例化为Block类呢,原因是这样做会造成数组下标越界。大家还记得下面这个函数吗?

假设当前方块的y为16,这y+1便会越界。对于这个处理,后续的文章中会有介绍。敬请关注吧。

忘记说最后一点了,对于为什么会生成一个方块呢。原因就是在下图判断中,如果返回为false则制作该方块对应的面,然后我们的BlockAir的IsSolid函数返回的就是false,因此我们的方块就出来了。

好吧,就先到这儿吧。

原文作者: Unity墙外的世界
原文链接:https://mp.weixin.qq.com/s/daAhjLGfPlrkeXr45FE5ug
扫描下方二维码关注游戏蛮牛官方微信~每日都有精选干货与你分享哟~



本文由蛮牛驿馆倾情奉献,如有问题请及时联系,除 合作社区 及 合作媒体 外,禁止转载

0

主题

2

帖子

4

积分

Rank: 1

UID
319966
好友
0
蛮牛币
26
威望
0
注册时间
2019-4-18
在线时间
2 小时
最后登录
2019-5-30
沙发
2019-5-27 11:07:45 只看该作者
秀秀秀秀秀秀秀秀秀秀秀秀秀秀秀秀秀秀
7日久生情
2964/5000
排名
2230
昨日变化

1

主题

1932

帖子

2964

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119154
好友
0
蛮牛币
3334
威望
0
注册时间
2015-8-21
在线时间
401 小时
最后登录
2019-9-23
板凳
2019-5-28 23:11:18 只看该作者
谢谢楼主大大。
7日久生情
3182/5000
排名
253
昨日变化

0

主题

207

帖子

3182

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
113883
好友
0
蛮牛币
8589
威望
0
注册时间
2015-7-16
在线时间
973 小时
最后登录
2019-9-22
地板
2019-5-29 10:01:06 只看该作者
非常感谢楼主分享资源呀
2初来乍到
142/150
排名
31434
昨日变化

0

主题

46

帖子

142

积分

Rank: 2Rank: 2

UID
34263
好友
0
蛮牛币
9
威望
0
注册时间
2014-7-14
在线时间
86 小时
最后登录
2019-7-30
5#
2019-6-15 15:58:16 只看该作者
相当有用呢。谢谢翻译。
4四处流浪
357/500
排名
8245
昨日变化

0

主题

91

帖子

357

积分

Rank: 4

UID
171939
好友
0
蛮牛币
296
威望
0
注册时间
2016-9-24
在线时间
118 小时
最后登录
2019-9-21
6#
2019-6-15 17:19:23 只看该作者
lsidhfdsfg';dlsfjlaghsfksdrfgj
5熟悉之中
906/1000
排名
10707
昨日变化

0

主题

632

帖子

906

积分

Rank: 5Rank: 5

UID
301976
好友
1
蛮牛币
1358
威望
0
注册时间
2018-10-31
在线时间
176 小时
最后登录
2019-9-23
7#
2019-7-8 11:33:05 只看该作者
排名
48140
昨日变化
1

0

主题

31

帖子

65

积分

Rank: 2Rank: 2

UID
159908
好友
0
蛮牛币
59
威望
0
注册时间
2016-8-1
在线时间
30 小时
最后登录
2019-8-27
8#
2019-7-8 13:45:24 只看该作者
积分增长回复

0

主题

3

帖子

4

积分

Rank: 1

UID
327472
好友
0
蛮牛币
0
威望
0
注册时间
2019-7-18
在线时间
1 小时
最后登录
2019-7-20
9#
2019-7-20 10:15:41 只看该作者
tql,感谢楼主分享
您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则