准备工作
如果大佬对ECS版的海克斯无限地图感兴趣,不妨参与进来,欢迎Star/Folk源码
0下载Unity编辑器(2019.1.12f1 or 更新的版本),if(已经下载了)continue;
1克隆:git clone https://github.com/cloudhu/HexMapMadeInUnity2019ECS.git --recurse
或下载Zip压缩包
2如果下载的是压缩包,需要先将压缩包解压。然后将HexMapMadeInUnity2019ECS添加到Unity Hub项目中;
3用Unity Hub打开的开源项目:HexMapMadeInUnity2019ECS,等待Unity进行编译工作;
4打开项目后,启动场景在Scenes目录下,打开AdvancedHexMap场景(优化重构的版本)。
前言
道路的制作过程是在河流的基础上的,所以相对更好理解,整个过程都是按照原版教程的思路走的,所以还是选择性的不去讲原作,而是讲随机的数据算法。同样的也不去做编辑器,因为最终目的是要实现无限地图,如果人为去编辑的话,是没办法实现无限这个概念的。为什么要实现无限,而不使用有限的艺术设计?就像Unity自带的地形编辑器那样,可以人为的创造出非常近似自然的地形环境。其实有两个原因:
- 我想要开发独立游戏,但是个人的精力有限,没有办法制作丰富多彩的场景,而且个人的美术能力恐怕无法满足玩家的审美需求。这应该是程序员的通病吧,我们有一定的场景编辑能力,但是离真正的艺术还是有不少差距。于是就用代码来弥补这方面的不足,当然,也想过购买美术资源,毕竟人工制作的场景更有设计感,奈何根本没有资金;
- 道法自然,所有人为设计的场景环境都是在向大自然致敬,站在造物主的角度去思考,自然环境是如何造就的呢?难道全部都是鬼斧神工等一流艺术工作者的设计,而这些设计还仅限于地球所见的环境,如果再加入无限宇宙中的无限奇观,那造物主的精力真是无限。然而我认为并非如此,整个宇宙只制定规则,这些规则包括物理/化学/生物/天文/地理等一切人类所知,这些知识毕竟都来自于自然。所以我们无法否则这些规则的存在,我们要做的就是尽量去实现这些规则,然后让这些规则自行去运行,最终生成无限的世界。而这些规则的媒介就是ECS中的System,把我们能够想到的自然规则都写成System,使其自动运行,也许就能创造无限。
基于以上两点,ECS应该是适合的,虽然目前还很不完善,我在使用过程中很难给出“满意”两个字来形容,但是先这样开发着,我相信Unity后面必然会给出一个使人满意的答卷。所以Hex Map只是在实现地图编辑器,而我要在其基础上实现规则。
综上所述,后面的笔记中都会跳过地图编辑相关内容,有兴趣的朋友可以去看原作,作者非常用心,可谓是步步为营,手把手的教学。所以原作是非常有学习价值的,我不应该重复原作者的表述,而是应该汲取需要的知识点,从而推陈出新。
数据
ECS是数据驱动的系统,所以数据的设计很重要,就像万物的存在最终可以转化成数字一样,未来将会有一个媲美现实的数字世界。不得不说数字是人类最伟大的创造,或者它原本就是自然的标尺,试想为什么会有一些常量存在,例如圆周率3.14,黄金分割0.618,引力常数G0(6.67×10-11)等等,未来的数字世界,这些常量将成为重要的标尺。
道路的数据设计比较简单,每个六边形单元有6条边、6个相邻的单元和6个对应的方向,因此可以总结出它能支持0到6条道路穿过该单元,也就是有上图所示的14中情况。我们在Data中,只关心对应6个方向有没有道路,所以是6个布尔值:
/// <summary>
/// 单元的六个方向是否有道路通过
/// </summary>
public struct RoadBools : IComponentData {
public bool NEBool;
public bool EBool;
public bool SEBool;
public bool SWBool;
public bool WBool;
public bool NWBool;
}
系统
数据的设计力求简洁,系统也是一样的,要求System功能单一,且可以重复利用。道路的随机算法仍然放在单元生成系统:
//生成道路数据,用一个临时数组来暂存
bool[] roads = new bool[6];
bool hasRoad = false;
//遍历6个方向,判断是否有道路通过
for (int j = 0; j < 6; j++)
{
roads[j] = false;
//首先确认该方向有相邻的单元
if (directions[j]!=int.MinValue)
{
//计算海拔差值,海拔相差过大的悬崖峭壁就不修路了
int tmpE = Elevations[i] -Elevations[directions[j]];
tmpE = tmpE > 0 ? tmpE : -tmpE;
//河流通过的地方不修路,后面会造桥
if (tmpE<=1 && directions[j]!=incomingRiver && directions[j] !=outgoingRiver)
{
roads[j] = true;
hasRoad = true;
}
}
}
道路的算法比较简单,因为目前的地貌还不够完善,没有充足的数据表明是否应该有道路存在。鲁迅先生曾经说过:
希望是本无所谓有,无所谓无的。这正如地上的路;其实地上本没有路,走的人多了,也便成了路。
后面会根据丰富的地貌数据来判断,是否应该有这条路,这里暂时先这样了。
ECS专题目录
ECS更新计划
作者的话
如果喜欢可以点赞支持一下,谢谢鼓励!如果有什么疑问可以给我留言,有错漏的地方请批评指证!
技术难题?加入开发者联盟:566189328(QQ付费群)提供有限技术探讨,以及,心灵鸡汤Orz!
当然,不需要技术探讨也欢迎加入进来,在这里劈柴、遛狗、聊天、撸猫!( ̄┰ ̄*)