ããŒã1ã3ïŒã°ãªãããè²ãã»ã«ã®é«ãããŒã4ã7ïŒç²ããå·ãããã³éè·¯ããŒã8-11ïŒæ°Žãå°åœ¢ãåå£ããŒã12ã15ïŒä¿åãšèªã¿èŸŒã¿ããã¯ã¹ãã£ãè·é¢ããŒã16ã19ïŒéãèŠã€ããããã¬ã€ã€ãŒããŒã ãã¢ãã¡ãŒã·ã§ã³ããŒã20-23ïŒæŠäºã®é§ãå°å³èª¿æ»ãæç¶ãçæããŒã24ã27ïŒæ°ŽåŸªç°ã䟵é£ããã€ãªãŒã ãåæ±å°å³ããŒã24ïŒå°åãšäŸµé£
- å°å³ã®åšãã«æ°Žã®å¢çç·ã远å ããŸãã
- ããããããã€ãã®é åã«åå²ããŸãã
- 䟵é£ã䜿çšããŠåŽãåãåããŸãã
- åå°ãåãããŠãå®reliefãæ»ããã«ããŸãã
åã®ããŒãã§ã¯ãæç¶ãåãããçæã®åºç€ãæ§ç¯ããŸããã ä»åã¯ãåå°ãçºçããå¯èœæ§ã®ããå Žæãå¶éãã䟵é£ãè¡ããŸãã
ãã®ãã¥ãŒããªã¢ã«ã¯Unity 2017.1.0ã§äœæãããŸããã
åå°ãåé¢ããŠæ»ããã«ããŸããå°å³ã®å¢çç·
åå°ãã©ã³ãã ã«äžãããããåå°ãå°å³ã®ç«¯ã«è§ŠããããšããããŸãã ããã¯æãŸãããªãå ŽåããããŸãã æ°Žã«å¶éã®ããå°å³ã«ã¯ããã¬ã€ã€ãŒã端ã«è¿ã¥ãã®ãé²ãèªç¶ã®éå£ãå«ãŸããŠããŸãã ãããã£ãŠãå°å³ã®ç«¯è¿ãã®æ°Žäœããäžã«åå°ãäžæãããããšãçŠãããšããã§ãããã
ããŒããŒãµã€ãº
åå°ã¯å°å³ã®ç«¯ã«ã©ããããè¿ãã¯ãã§ããïŒ ãã®è³ªåã«å¯Ÿããæ£ããçãã¯ãªãããããã®ãã©ã¡ãŒã¿ãŒãã«ã¹ã¿ãã€ãºå¯èœã«ããŸãã
HexMapGenerator
ã³ã³ããŒãã³ãã«2ã€ã®ã¹ã©ã€ããŒã远å ããŸãã1ã€ã¯Xè»žã«æ²¿ã£ããšããžã«æ²¿ã£ãå¢çç·ããã1ã€ã¯Zè»žã«æ²¿ã£ãå¢çç·ã«äœ¿çšããŸãã ããã©ã«ãå€ã®5ã§0ãã10ãŸã§ã®ééã䜿çšããŠã¿ãŸãããã
[Range(0, 10)] public int mapBorderX = 5; [Range(0, 10)] public int mapBorderZ = 5;
ãããå¢çç·ã¹ã©ã€ããŒãåå°ã®äžå¿ãå¶éããŸã
å¢çç·ããªããã°ããã¹ãŠã®ã»ã«ãæå¹ã§ãã å¢çãããå Žåãæå°èš±å®¹åº§æšã¯å¢å ããæå€§èš±å®¹åº§æšã¯æžå°ããŸãã ãããããçæããã«ã¯èš±å®¹ééãç¥ãå¿
èŠãããããã4ã€ã®æŽæ°ãã£ãŒã«ãã䜿çšããŠè¿œè·¡ããŸãããã
int xMin, xMax, zMin, zMax;
寿åžãäœæããåã«ã
GenerateMap
å¶çŽãåæåããŸãã
Random.Range
åŒã³åºãã®ãã©ã¡ãŒã¿ãŒãšããŠãããã®å€ã䜿çšãããããå®éã«ã¯æé«å€ã¯äŸå€çã§ãã å¢çç·ããªãå Žåããããã¯æž¬å®ã»ã«ã®æ°ã«çããããããã€ãã¹1ã§ã¯ãããŸããã
public void GenerateMap (int x, int z) { ⊠for (int i = 0; i < cellCount; i++) { grid.GetCell(i).WaterLevel = waterLevel; } xMin = mapBorderX; xMax = x - mapBorderX; zMin = mapBorderZ; zMax = z - mapBorderZ; CreateLand(); ⊠}
å¢çç·ãè¶ããåå°ã®åºçŸãå³å¯ã«çŠæ¢ããããšã¯ãããŸãããéãåãåããããšããžãäœæãããããã§ãã 代ããã«ãããããã®çæãéå§ããããã«äœ¿çšãããã»ã«ã®ã¿ãå¶éããŸãã ã€ãŸãããµã€ãã®ããããã®äžå¿ã¯å¶éãããŸããããµã€ãã®äžéšã¯å¢çãšãªã¢ãè¶
ããããšãã§ããŸãã ãããè¡ãã«ã¯ã
GetRandomCell
ã倿ŽããŠã蚱容ããããªãã»ããã®ç¯å²å
ã®ã»ã«ãéžæããŸãã
HexCell GetRandomCell () {
ãããã®å¢çã¯ã0Ã0ã5Ã5ã10Ã10ãããã³0Ã10ã§ãããã¹ãŠã®ããããã©ã¡ãŒã¿ãŒãããã©ã«ãå€ã«èšå®ãããŠããå Žåããµã€ãº5ã®å¢çç·ã«ããããããã®ç«¯ãåå°ã«è§Šããªãããã«ç¢ºå®ã«ä¿è·ãããŸãã ãã ããããã¯ä¿èšŒãããŸããã åå°ã¯ç«¯ã«è¿ã¥ãããšããããããã€ãã®å Žæã§åå°ã«è§ŠããããšããããŸãã
åå°ãåœå¢å
šäœã暪åãå¯èœæ§ã¯ãåœå¢ã®ãµã€ãºãšãµã€ãã®æå€§ãµã€ãºã«äŸåããŸãã ããããããšãªããã»ã¯ã·ã§ã³ã¯å
è§åœ¢ã®ãŸãŸã§ãã ååŸã®ããå®å
šãªå
è§åœ¢
å«ã
ã»ã«ã å¢çã®ãµã€ãºã«çããååŸãæã€å
è§åœ¢ãããå Žåããããã¯ãããæšªåãããšãã§ããŸãã ååŸ5ã®å®å
šãªå
è§åœ¢ã«ã¯91åã®ã»ã«ãå«ãŸããŸãã ããã©ã«ãã§ã¯ãã»ã¯ã·ã§ã³ããšã«æå€§100ã»ã«ãªã®ã§ãããã¯ãç¹ã«æ¯åãããå Žåã«ãåå°ã5ã»ã«ãä»ããŠæ©ãæ¶ããããšãã§ããããšãæå³ããŸãã ãããé²ãã«ã¯ãããããã®æå€§ãµã€ãºãå°ããããããå¢çç·ã®ãµã€ãºã倧ããããŸãã
å
è§åœ¢é åã®ã»ã«æ°ã®åŒã¯ã©ã®ããã«å°åºãããŸããïŒååŸã0ã®å Žåã1ã€ã®ã»ã«ãæ±ããŸãã äžå¿ãã1ã®ååŸã§ã6ã€ã®è¿œå ã®ã»ã«ããããŸãã
ã ãããã®6ã€ã®ã»ã«ã¯ãäžå¿ã«æ¥ãã6ã€ã®äžè§åœ¢ã®ç«¯ãšèããããšãã§ããŸãã ååŸã2ã®å Žåããããã®äžè§åœ¢ã«2çªç®ã®è¡ã远å ãããŸããã€ãŸããäžè§åœ¢ã§ããã«2ã€ã®ã»ã«ãååŸãããåèšã§

ã ååŸ3ã®å Žåã3çªç®ã®è¡ã远å ãããŸããã€ãŸããäžè§åœ¢ããšã«3ã€ã®ã»ã«ã远å ãããåèšã§

ã ãªã©ãªã©ã ã€ãŸããäžè¬çã«ãåŒã¯æ¬¡ã®ããã«ãªããŸã
ã
ãããããæç¢ºã«èŠãããã«ãå¢çãµã€ãºã200ã«èšå®ã§ããŸããååŸ8ã®å®å
šãªå
è§åœ¢ã«ã¯217åã®ã»ã«ãå«ãŸãããããåå°ã¯ãããã®ç«¯ã«è§Šããå¯èœæ§ããããŸãã å°ãªããšãããã©ã«ãã®å¢çãµã€ãºå€ïŒ5ïŒã䜿çšããå Žåã å¢çã10ã«å¢ãããšã確çã¯å€§å¹
ã«äœäžããŸãã
åå°åºç»ã®ãµã€ãºã¯äžå®ã§200ã§ãå°å³ã®å¢çç·ã¯5ãš10ã§ãããã³ã²ã¢
ãããã®å¢çç·ãå¢ãããŠåå°ã®å²åãåãã«ä¿ã€ãšãåå°ã匷å¶çã«å°ããªé åã圢æããããšã«æ³šæããŠãã ããã ãã®çµæãããã©ã«ãã§å€§ããªå°å³ã¯ãåäžã®å€§ããªåå°-è¶
倧éžãã³ã²ã¢-ãããã€ãã®å°ããªå³¶ã§äœæããå¯èœæ§ãéåžžã«é«ããªããŸãã å¢çã®ãµã€ãºã倧ãããªããšããã®å¯èœæ§ãé«ããªããç¹å®ã®å€ã§ã¯ãè¶
倧éžã«ãªãããšãã»ãŒä¿èšŒãããŸãã ãã ããåå°ã®å²åã倧ãããããšãå©çšå¯èœãªé åã®ã»ãšãã©ããã£ã±ãã«ãªãããã®çµæãã»ãŒé·æ¹åœ¢ã®åå°ã®å¡ãã§ããŸãã ãããé²ãã«ã¯ãåå°ã®å²åãæžããå¿
èŠããããŸãã
ã«ãŒãã®æ ç·ã10ã®å¯¿åž40ïŒ
ããã³ã²ã¢ãšããååã¯ã©ãããæ¥ãã®ã§ããïŒããã¯äœå¹Žãåã«å°çäžã«ååšããŠããæåŸã®æ¢ç¥ã®è¶
倧éžã®ååã§ããã ååã¯ã®ãªã·ã£èªã®ãã³ãšã¬ã€ã¢ã§æ§æãããããã¹ãŠã®èªç¶ããŸãã¯ããã¹ãŠã®åå°ãã®ãããªãã®ãæå³ããŸãã
ç¡çãªã«ãŒãããå®ã
ç®çã®åå°ã«å°éãããŸã§åå°ãæã¡äžãç¶ããã ãã§ãé©åãªéã®åå°ãçæããŸãã ããã¯ãé
ããæ©ãããåã»ã«ãæ°Žäœã§äžããããã«æ©èœããŸãã ãã ãããããã®å¢çç·ã䜿çšããå Žåããã¹ãŠã®ã»ã«ã«å°éã§ããããã§ã¯ãããŸããã é«ãå²åã®åå°ãå¿
èŠãªå Žåãããã¯çºé»æ©ã®ç¡éã®ã詊è¡ãšå€±æãã«ã€ãªãããããå€ãã®åå°ã調éããç¡éã®ãµã€ã¯ã«ã§è¡ãè©°ãŸããŸãã ãã®å Žåãã¢ããªã±ãŒã·ã§ã³ã¯ããªãŒãºããŸãããããã¯èµ·ãããŸããã
äžå¯èœãªæ§æãåãã£ãŠç¢ºå®ã«èŠã€ããããšã¯ã§ããŸããããç¡éã®ãµã€ã¯ã«ãã身ãå®ãããšã¯ã§ããŸãã
CreateLand
å®è¡ããããµã€ã¯ã«ã®æ°ãåçŽã«è¿œè·¡ã
CreateLand
ã ç¹°ãè¿ããå€ãããå Žåãã¹ã¿ãã¯ããŠããå¯èœæ§ãé«ãã忢ããå¿
èŠããããŸãã
倧ããªãããã®å Žåã1000åã®å埩ã¯èš±å®¹ã§ããããã«èŠãã1äžåã®å埩ã¯ãã§ã«äžåçã«æããŸãã ãã®ããããã®å€ãçµäºãã€ã³ããšããŠäœ¿çšããŸãããã
void CreateLand () { int landBudget = Mathf.RoundToInt(cellCount * landPercentage * 0.01f);
ç ŽæããããããååŸããå Žåãå€ãã®ã»ã«ãããã«æå€§ã®é«ãã«éããããã10,000åã®å埩ãå®è¡ããŠãããã»ã©æéã¯ããããŸãããããã«ãããæ°ããé åã®æé·ã劚ããããŸãã
ã«ãŒããäžæããåŸã§ããé©åãªããããååŸã§ããŸãã åå°ã®éãè¶³ãããããŸãããããããªãã§ãããã ããã«é¢ããéç¥ãã³ã³ãœãŒã«ã«è¡šç€ºããŠãæ®ãã®ã©ã®åå°ã䜿çšã§ããªãã£ããããç¥ããããŸãã
void CreateLand () { ⊠if (landBudget > 0) { Debug.LogWarning("Failed to use up " + landBudget + " land budget."); } }
ã«ãŒãå¢çç·ã10ã®åå°ã®95ïŒ
ã¯ãå
šé¡ã䜿ãããšãã§ããŸããã§ãããæ
éããã«ãŒãã«ã¯ãŸã ã°ãã€ããããã®ã¯ãªãã§ããïŒæµ·å²žç·ã«ã¯ã°ãã€ãããããŸããããã¯ãäœæé åå
ã®é«ããé«ããªãããããšãæ°ããé åã§ã¯å€åŽã«æé·ã§ããªãããã§ãã åãååã§ã¯ãåºç»ãæå€§ã®é«ãã«éããåã«æ¬ èœããŠããããšã倿ãããŸã§ãåºç»ãåå°ã®å°ããªé åã«æé·ãããããšã¯ã§ããŸããã ããã«ããããããäœããããšãã°ãã€ãã倧ãããªããŸãã
ãŠããã£ããã±ãŒãžã«ãŒããåå²ãã
ãããã®å¢çç·ãã§ããã®ã§ãããããåºæ¬çã«2ã€ã®å¥ã
ã®é åã«åå²ããŸãããå¢çç·é åãšãããããäœæãããé åã§ãã ç§ãã¡ã«ãšã£ãŠåµé ã®å°åã®ã¿ãéèŠã§ããããããã®ãããªå Žåã¯1ã€ã®å°åã®ç¶æ³ãšèããããšãã§ããŸãã ãªãŒãžã§ã³ã¯ãåã«ãããå
šäœãã«ããŒããŠããŸããã ãããããããäžå¯èœãªå Žåãå°å³ãåå°åµé ã®ããã€ãã®æ¥ç¶ãããŠããªãé åã«åå²ããããšã劚ãããã®ã¯ãããŸããã ããã«ããã倧éžãäºãã«ç¬ç«ããŠåœ¢æãããç°ãªã倧éžãæå®ãããŸãã
å°å³å°å
ãããã®1ã€ã®é åãæ§é äœãšããŠèª¬æããããšããå§ããŸãããã ããã«ãããããã€ãã®å°åã§ã®äœæ¥ãç°¡çŽ åãããŸãã ããã®ããã«
MapRegion
æ§é ãäœæããŠã¿ãŸããããããã«ã¯ããªãŒãžã§ã³ã®å¢çãã£ãŒã«ãã®ã¿ãå«ãŸããŠããŸãã
HexMapGenerator
å€éšã§ã¯ãã®æ§é ã䜿çšããªãããããã®ã¯ã©ã¹ã®å
éšã§ãã©ã€ããŒããªå
éšæ§é ãšããŠå®çŸ©ã§ããŸãã æ¬¡ã«ã4ã€ã®æŽæ°ãã£ãŒã«ãã1ã€ã®
MapRegion
ãã£ãŒã«ãã«çœ®ãæããããšãã§ããŸãã
ãã¹ãŠãæ©èœããããã«ã¯ã
GenerateMap
æå°å€ãšæå€§å€ã®ãã£ãŒã«ãã«
region.
ãã¬ãã£ãã¯ã¹ã远å ããå¿
èŠããã
region.
ã
region.xMin = mapBorderX; region.xMax = x - mapBorderX; region.zMin = mapBorderZ; region.zMax = z - mapBorderZ;
ãŸãã
GetRandomCell
ã
HexCell GetRandomCell () { return grid.GetCell( Random.Range(region.xMin, region.xMax), Random.Range(region.zMin, region.zMax) ); }
ããã€ãã®å°å
è€æ°ã®å°åããµããŒãããã«ã¯ã1ã€ã®
MapRegion
ãã£ãŒã«ã
MapRegion
å°åã®ãªã¹ãã«çœ®ãæããŸãã
ãã®æç¹ã§ããªãŒãžã§ã³ãäœæããããã®å¥ã®ã¡ãœããã远å ãããšããã§ãããã å¿
èŠãªãªã¹ããäœæããããæ¢ã«ååšããå Žåã¯ã¯ãªã¢ããå¿
èŠããããŸãã ãã®åŸã圌ã¯ä»¥åã«è¡ã£ãããã«1ã€ã®ãªãŒãžã§ã³ã決å®ããããããªã¹ãã«è¿œå ããŸãã
void CreateRegions () { if (regions == null) { regions = new List<MapRegion>(); } else { regions.Clear(); } MapRegion region; region.xMin = mapBorderX; region.xMax = grid.cellCountX - mapBorderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); }
GenerateMap
ã§ãã®ã¡ãœãããåŒã³åºããŸããããªãŒãžã§ã³ãçŽæ¥äœæããŸããã
GetRandomCell
ãä»»æã®é åã§
GetRandomCell
ã§ããããã«ã
MapRegion
ãã©ã¡ãŒã¿ãŒãæå®ããŸãã
HexCell GetRandomCell (MapRegion region) { return grid.GetCell( Random.Range(region.xMin, region.xMax), Random.Range(region.zMin, region.zMax) ); }
ããã§ã
RaiseTerraion
SinkTerrain
ãš
SinkTerrain
ã¯ã察å¿ããé åã
GetRandomCell
æž¡ãå¿
èŠããããŸãã ãããè¡ãã«ã¯ãããããã«ãªãŒãžã§ã³ãã©ã¡ãŒã¿ãŒãå¿
èŠã§ãã
int RaiseTerrain (int chunkSize, int budget, MapRegion region) { searchFrontierPhase += 1; HexCell firstCell = GetRandomCell(region); ⊠} int SinkTerrain (int chunkSize, int budget, MapRegion region) { searchFrontierPhase += 1; HexCell firstCell = GetRandomCell(region); ⊠}
CreateLand
ã¡ãœããã¯ãã»ã¯ã·ã§ã³ãäžäžãããåé åãæ±ºå®ããå¿
èŠããããŸãã ãªãŒãžã§ã³éã§åå°ã®ãã©ã³ã¹ããšãããã«ããµã€ã¯ã«å
ã®ãªãŒãžã§ã³ã®ãªã¹ããç¹°ãè¿ãç¹°ãè¿ããŸãã
void CreateLand () { int landBudget = Mathf.RoundToInt(cellCount * landPercentage * 0.01f); for (int guard = 0; landBudget > 0 && guard < 10000; guard++) { for (int i = 0; i < regions.Count; i++) { MapRegion region = regions[i]; int chunkSize = Random.Range(chunkSizeMin, chunkSizeMax - 1); if (Random.value < sinkProbability) { landBudget = SinkTerrain(chunkSize, landBudget, region); } else { landBudget = RaiseTerrain(chunkSize, landBudget, region); } } } if (landBudget > 0) { Debug.LogWarning("Failed to use up " + landBudget + " land budget."); } }
ãã ããããããã®äœäžãåçã«åæ£ãããå¿
èŠããããŸãã ããã¯ããã¹ãŠã®å°åã§ããããçç¥ãããã©ãããæ±ºå®ããªããè¡ãããšãã§ããŸãã
for (int guard = 0; landBudget > 0 && guard < 10000; guard++) { bool sink = Random.value < sinkProbability; for (int i = 0; i < regions.Count; i++) { MapRegion region = regions[i]; int chunkSize = Random.Range(chunkSizeMin, chunkSizeMax - 1);
æåŸã«ãåå°ã®å
šéãæ£ç¢ºã«äœ¿çšããããã«ã¯ãéããŒãã«ãªã£ããããã«ããã»ã¹ã忢ããå¿
èŠããããŸãã ããã¯ããªãŒãžã§ã³ã®ãµã€ã¯ã«ã®ã©ã®æ®µéã§ãçºçããå¯èœæ§ããããŸãã ãããã£ãŠããŒããµã ãã§ãã¯ãå
åŽã®ã«ãŒãã«ç§»åããŸãã å®éããã®ãã§ãã¯ã¯åå°ãäžããåŸã«ããå®è¡ã§ããŸããããªããªããéé¡ãäžãããšãã¯æ±ºããŠäœ¿ãããªãããã§ãã å®äºããããããã«
CreateLand
ã¡ãœãããçµäºã§ããŸãã
2ã€ã®å°å
çŸåšãããã€ãã®å°åã®ãµããŒãããããŸãããç§ãã¡ã¯ãŸã 1ã€ã ããæ±ããŠããŸãã
CreateRegions
倿ŽããŠãããããåçŽæ¹åã«ååã«åå²ããŸãã ãããè¡ãã«ã¯ã远å ãããé åã®
xMax
å€ãååã«ããŸãã æ¬¡ã«
xMin
åãå€ã䜿çšããåã³
xMin
ã®å
ã®å€ã䜿çšããŠãããã2çªç®ã®é åãšããŠäœ¿çšããŸãã
MapRegion region; region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = grid.cellCountX / 2; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region);
ãã®æ®µéã§ã«ãŒããçæããŠãéãã¯ãããŸããã 2ã€ã®é åãç¹å®ããŸãããããããã¯1ã€ã®å€ãé åãšåãé åãå ããŠããŸãã ããããåºããã«ã¯ããããã®éã«ç©ºãã¹ããŒã¹ãæ®ãå¿
èŠããããŸãã ããã¯ããããã®å¢çãšåãééãšããã©ã«ãå€ã䜿çšããŠããªãŒãžã§ã³ã®å¢çã«ã¹ã©ã€ããŒã远å ããããšã§å®è¡ã§ããŸãã
[Range(0, 10)] public int regionBorder = 5;
ãªãŒãžã§ã³å¢çã¹ã©ã€ããŒãåå°ã¯å°åéã®ã¹ããŒã¹ã®äž¡åŽã«åœ¢æã§ãããããå°å³ã®ç«¯ã«åå°ã®æ©ãäœãå¯èœæ§ãé«ããªããŸãã ãããé²ãããã«ãé åã®å¢çã䜿çšããŠãåå²ç·ãšãããããéå§ã§ããé åã®éã«åå°ãªããŸãŒã³ãèšå®ããŸãã ããã¯ã飿¥ããé åéã®è·é¢ãé åã®å¢çã®ãµã€ãºãã2倧ããããšãæå³ããŸãã
é åã®ãã®å¢çãé©çšããã«
xMax
æåã®é åã®
xMax
ãããããæžç®ã
xMin
2çªç®ã®é åã®
xMin
远å ããŸãã
MapRegion region; region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2 - regionBorder; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = grid.cellCountX / 2 + regionBorder; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region);
ãããã¯åçŽæ¹åã«2ã€ã®é åã«åå²ãããŸããããã©ã«ãèšå®ã§ã¯ã2ã€ã®é¡èã«åé¢ãããé åãäœæãããŸããã1ã€ã®é åãšå€§ããªå°å³ã®å¢çã®å Žåã®ããã«ãæ£ç¢ºã«2ã€ã®éžå°ãåãåãä¿èšŒã¯ãããŸããã ã»ãšãã©ã®å Žåã2ã€ã®å€§ããªå€§éžã§ãããããããã€ãã®å³¶ããããŸãã ãã ãã1ã€ã®å°åã«2ã€ä»¥äžã®å€§ããªå³¶ãäœæãããå ŽåããããŸãã ãŸãã2ã€ã®å€§éžãå°å³¡ã«ãã£ãŠæ¥ç¶ãããå ŽåããããŸãã
ãã¡ãããXãšZãæž¬å®ããæ¹æ³ã倿Žããããšã«ãããããããæ°Žå¹³æ¹åã«åå²ã§ããŸãã2ã€ã®å¯èœãªæ¹åã®ãããããã©ã³ãã ã«éžæããŸãããã
MapRegion region; if (Random.value < 0.5f) { region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2 - regionBorder; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = grid.cellCountX / 2 + regionBorder; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region); } else { region.xMin = mapBorderX; region.xMax = grid.cellCountX - mapBorderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ / 2 - regionBorder; regions.Add(region); region.zMin = grid.cellCountZ / 2 + regionBorder; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); }
æ°Žå¹³æ¹åã«2ã€ã®é åã«åå²ãããããããå¹
ã®åºããããã䜿çšããŠãããããå¹
ãåºããŠèãé åãæ°Žå¹³æ¹åã«åé¢ããŠäœæãããŸãã ãã®çµæããããã®å°åã¯ãããã€ãã®åå²ãããéžå°ã圢æããå¯èœæ§ãé«ããªããŸãã
4ã€ã®å°å
ãªãŒãžã§ã³ã®æ°ãã«ã¹ã¿ãã€ãºå¯èœã«ããŠã1ã4ã€ã®ãªãŒãžã§ã³ã®ãµããŒããäœæããŸãããã
[Range(1, 4)] public int regionCount = 1;
ãªãŒãžã§ã³æ°ã®ã¹ã©ã€ããŒãswitch
ã䜿çšããŠã察å¿ãããªãŒãžã§ã³ã³ãŒãã®å®è¡ãéžæã§ããŸãã ããã©ã«ãã§äœ¿çšããã1ã€ã®å°åã®ã³ãŒããç¹°ãè¿ãããšããå§ããã±ãŒã¹2ã®ããã«2ã€ã®å°åã®ã³ãŒããæ®ããŸãã
MapRegion region; switch (regionCount) { default: region.xMin = mapBorderX; region.xMax = grid.cellCountX - mapBorderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); break; case 2: if (Random.value < 0.5f) { region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2 - regionBorder; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = grid.cellCountX / 2 + regionBorder; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region); } else { region.xMin = mapBorderX; region.xMax = grid.cellCountX - mapBorderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ / 2 - regionBorder; regions.Add(region); region.zMin = grid.cellCountZ / 2 + regionBorder; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); } break; }
switchã¹ããŒãã¡ã³ããšã¯äœã§ããïŒããã¯ãif-else-if-elseã¹ããŒãã¡ã³ãã·ãŒã±ã³ã¹ãèšè¿°ãã代ããã«ãªããŸãã ã¹ã€ããã¯å€æ°ã«é©çšãããã©ã®ã³ãŒããå®è¡ããå¿
èŠããããã瀺ãããã«ã©ãã«ã䜿çšãããŸãã æåŸã®
else
ãããã¯ãšããŠäœ¿çšããã
default
ã©ãã«ããã
default
ã åãªãã·ã§ã³ã¯ã
break
ã¹ããŒãã¡ã³ããŸãã¯
return
çµäºããå¿
èŠããããŸãã
switch
ãããã¯ãèªã¿ãããç¶æ
ã«ä¿ã€ã«ã¯ãéåžžããã¹ãŠã®ã±ãŒã¹ãçããçæ³çã«ã¯åäžã®ã¹ããŒãã¡ã³ããŸãã¯ã¡ãœããåŒã³åºãã§ä¿æããã®ãæåã§ãã ãªãŒãžã§ã³ã³ãŒãã®äŸãšããŠããã¯è¡ããŸããããããè峿·±ããªãŒãžã§ã³ãäœæããå Žåã¯ãå¥ã®æ¹æ³ã䜿çšããããšããå§ãããŸãã äŸïŒ
switch (regionCount) { default: CreateOneRegion(); break; case 2: CreateTwoRegions(); break; case 3: CreateThreeRegions(); break; case 4: CreateFourRegions(); break; }
3ã€ã®é åã¯2ã€ã«äŒŒãŠããŸãããååã§ã¯ãªã3ã€ã ãã䜿çšãããŸãã ãã®å Žåãæ°Žå¹³æ¹åã®åé¢ã¯éåžžã«çãé åãäœæãããããåçŽæ¹åã®åé¢ã®ã¿ã®ãµããŒããäœæããŸããã ãã®çµæããªãŒãžã§ã³ã®å¢çé åã2åã«ãªã£ãŠãããããæ°ãããµã€ããäœæããããã®ã¹ããŒã¹ã¯ã2ã€ã®ãªãŒãžã§ã³ã®å Žåãããå°ãªãããšã«æ³šæããŠãã ããã
switch (regionCount) { default: ⊠break; case 2: ⊠break; case 3: region.xMin = mapBorderX; region.xMax = grid.cellCountX / 3 - regionBorder; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = grid.cellCountX / 3 + regionBorder; region.xMax = grid.cellCountX * 2 / 3 - regionBorder; regions.Add(region); region.xMin = grid.cellCountX * 2 / 3 + regionBorder; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region); break; }
3ã€ã®å°åãæ°Žå¹³æ¹åãšåçŽæ¹åã®åé¢ãçµã¿åãããŠããããã®åã³ãŒããŒã«1ã€ã®é åã远å ããããšã«ããã4ã€ã®é åãäœæã§ããŸãã
switch (regionCount) { ⊠case 4: region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2 - regionBorder; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ / 2 - regionBorder; regions.Add(region); region.xMin = grid.cellCountX / 2 + regionBorder; region.xMax = grid.cellCountX - mapBorderX; regions.Add(region); region.zMin = grid.cellCountZ / 2 + regionBorder; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); region.xMin = mapBorderX; region.xMax = grid.cellCountX / 2 - regionBorder; regions.Add(region); break; } }
4ã€ã®å°åãããã§äœ¿çšãããã¢ãããŒãã¯ãããããåå²ããæãç°¡åãªæ¹æ³ã§ãã åå°ã®è³ªéã«ãã£ãŠã»ãŒåãå°åãçæãããã®å€åæ§ã¯ãããçæã®ä»ã®ãã©ã¡ãŒã¿ãŒã«ãã£ãŠå¶åŸ¡ãããŸãã ãã ããããããçŽç·ã«åå²ãããŠããããšã¯åžžã«æããã§ãã ã³ã³ãããŒã«ãå¿
èŠãªã»ã©ãçµæã®å€èгã¯å°ãªããªããŸãã ãããã£ãŠãã²ãŒã ãã¬ã€ã«ã»ãŒçããé åãå¿
èŠãªå Žåãããã¯æ£åžžã§ãã ããããæã倿§ã§ç¡å¶éã®åå°ãå¿
èŠãªå Žåã¯ã1ã€ã®å°åã®å©ããåããŠé ããªããã°ãªããŸããã
ããã«ãããããåå²ããä»ã®æ¹æ³ããããŸãã çŽç·ã ãã«éå®ããããšã¯ã§ããŸããã åããµã€ãºã®ãªãŒãžã§ã³ã䜿çšããå¿
èŠã¯ãªãããããå
šäœãã«ããŒããå¿
èŠããããŸããã 穎ããããããšãã§ããŸãã å°åã®äº€å·®ãèš±å¯ããããå°åéã®åå°ã®ååžã倿Žãããããããšãã§ããŸãã ããã«ãåå°åã«ç¬èªã®ãžã§ãã¬ãŒã¿ãŒãã©ã¡ãŒã¿ãŒãèšå®ããããšãã§ããŸãïŒãã ããããè€éã§ããïŒãããšãã°ãå°å³äžã«å€§ããªå€§éžãšåå³¶ã眮ãããšãã§ããŸãã
ãŠããã£ããã±ãŒãžäŸµé£
ãããŸã§ã®ãšãããçæãããã¹ãŠã®ã«ãŒãã¯ããªã倱瀌ã§å£ããŠããŸããã æ¬åœã®ã¬ãªãŒãã¯ãã®ããã«èŠãããããããŸããããæéãçµã€ã«ã€ããŠãŸããŸãæ»ããã«ãªãããã®éãéšåã¯äŸµé£ã«ããéããªã£ãŠããŸããŸãã
ããããæ¹åããããã«ããã®äŸµé£ããã»ã¹ãé©çšã§ããŸããããã¯ãèãåå°ãäœæããåŸãå¥ã®æ¹æ³ã§è¡ããŸãã public void GenerateMap (int x, int z) { ⊠CreateRegions(); CreateLand(); ErodeLand(); SetTerrainType(); ⊠} ⊠void ErodeLand () {}
䟵é£ç
æéãçµéããã»ã©ã浞é£ãå€ããªããŸãããããã£ãŠã䟵é£ã¯æ°žç¶çã§ã¯ãªããã«ã¹ã¿ãã€ãºå¯èœã«ããå¿
èŠããããŸããå°ãªããšãã䟵é£ã¯ãŒãã§ãããããã¯ä»¥åã«äœæããããããã«å¯Ÿå¿ããŸããæå€§ã®äŸµé£ã¯å
æ¬çã§ããã€ãŸãã䟵é£åãããã«å ããŠãå°åœ¢ã¯å€åããŸãããã€ãŸãã䟵é£ãã©ã¡ãŒã¿ãŒã¯0ã100ã®å²åã§ããå¿
èŠããããããã©ã«ãã§ã¯50ã«ãªããŸãã [Range(0, 100)] public int erosionPercentage = 50;
䟵é£ã¹ã©ã€ããŒã䟵é£ç Žå£çްèã®æ€çŽ¢
䟵é£ã«ãããã¬ãªãŒããããæ»ããã«ãªããŸããç§ãã¡ã®å Žåãå¯äžã®éãéšåã¯åŽã§ãããããã£ãŠããããã¯äŸµé£ããã»ã¹ã®ã¿ãŒã²ããã«ãªããŸããåŽãååšããå Žåãæµžé£ã¯æçµçã«æé¢ã«å€ãããŸã§ãããæžããå¿
èŠããããŸããããã¯éå±ãªå°åœ¢ã«ã€ãªãããããæé¢ãæ»ããã«ããŸããããããè¡ãã«ã¯ãåŽã®äžã«ããã»ã«ãç¹å®ããé«ããäœãããå¿
èŠããããŸãããããã¯äŸµé£ããããã现èã§ããã»ã«ã䟵é£ããããããã©ããã倿ããã¡ãœãããäœæããŸãããã圌ã¯é«ãã®ååã«å€§ããªéããèŠã€ãããŸã§ã»ã«ã®é£äººããã§ãã¯ããããšã«ãã£ãŠãããæ±ºå®ããŸããåŽã¯å°ãªããšã1ã€ãŸãã¯2ã€ã®ã¬ãã«ã®é«ãã®å·®ãå¿
èŠãšããããã1ã€ãŸãã¯è€æ°ã®é£æ¥ã»ã«ãå°ãªããšã2ã¹ãããäžã«ããå Žåãã»ã«ã¯äŸµé£ã®åœ±é¿ãåããŸãããã®ãããªé£äººãããªãå Žåãã»ã«ã¯äŸµé£ãåããããšãã§ããŸããã bool IsErodible (HexCell cell) { int erodibleElevation = cell.Elevation - 2; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (neighbor && neighbor.Elevation <= erodibleElevation) { return true; } } return false; }
ãã®ã¡ãœããã䜿çšãErodeLand
ãŠããã¹ãŠã®ã»ã«ãã«ãŒããããã¹ãŠã®äŸµé£ããããã»ã«ãäžæãªã¹ãã«æžã蟌ãããšãã§ããŸãã void ErodeLand () { List<HexCell> erodibleCells = ListPool<HexCell>.Get(); for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); if (IsErodible(cell)) { erodibleCells.Add(cell); } } ListPool<HexCell>.Add(erodibleCells); }
䟵é£ãããã现èã®ç·æ°ãããã£ããã䟵é£ã®å²åã䜿çšããŠãæ®ãã®äŸµé£ãããã现èã®æ°ã決å®ã§ããŸããããšãã°ãããŒã»ã³ããŒãžã50ã®å Žåãå
ã®æ°éã®ååãæ®ããŸã§ã»ã«ã䟵é£ããå¿
èŠããããŸããããŒã»ã³ããŒãžã100ã®å Žåã䟵é£ãèµ·ããããã现èããã¹ãŠç Žå£ãããŸã§åæ¢ããŸããã void ErodeLand () { List<HexCell> erodibleCells = ListPool<HexCell>.Get(); for (int i = 0; i < cellCount; i++) { ⊠} int targetErodibleCount = (int)(erodibleCells.Count * (100 - erosionPercentage) * 0.01f); ListPool<HexCell>.Add(erodibleCells); }
䟵é£ãããããåå°ã®ã»ã«ã ããèæ
®ãã¹ãã§ã¯ãããŸãããïŒ. , , .
ã»ã«åæž
çŽ æŽãªã¢ãããŒãããå§ããŠã䟵é£ã«ãã£ãŠç Žå£ããã现èã®é«ããåçŽã«æžãããšããã¯ã䟵é£ããã«ãããªããšä»®å®ããŸãããããåœãŠã¯ãŸãå Žåããªã¹ãããã©ã³ãã ãªã»ã«ãåãåºããé«ããæžãããŠãããªã¹ãããåé€ããããšãã§ããŸãã䟵é£ãåããããå¿
èŠãªçŽ°èæ°ã«éãããŸã§ããã®æäœãç¹°ãè¿ããŸãã int targetErodibleCount = (int)(erodibleCells.Count * (100 - erosionPercentage) * 0.01f); while (erodibleCells.Count > targetErodibleCount) { int index = Random.Range(0, erodibleCells.Count); HexCell cell = erodibleCells[index]; cell.Elevation -= 1; erodibleCells.Remove(cell); } ListPool<HexCell>.Add(erodibleCells);
å¿
èŠãªæ€çŽ¢ãé²ãããerodibleCells.Remove
ã«ããªã¹ãã®æåŸã®çŸåšã®ã»ã«ãäžæžãããæåŸã®èŠçŽ ãåé€ããŸããç§ãã¡ã¯ãŸã 圌ãã®é åºãæ°ã«ããŸããã
䟵é£ãããã现èã®0ïŒ
ããã³100ïŒ
ã®çŽ æŽãªæžå°ãã·ãŒãããã1957632474ã䟵é£è¿œè·¡
åçŽãªã¢ãããŒãã«ããã䟵é£ãé©çšã§ããŸãããé©åãªçšåºŠã«ã¯é©çšã§ããŸãããããã¯ãé«ãã1ã€æžå°ããåŸãã»ã«ã䟵é£ãåãç¶ããå¯èœæ§ãããããã§ãããããã£ãŠã䟵é£ã®åŸåããªããªã£ããšãã«ã®ã¿ãªã¹ãããã»ã«ãåé€ããŸãã if (!IsErodible(cell)) { erodibleCells[index] = erodibleCells[erodibleCells.Count - 1]; erodibleCells.RemoveAt(erodibleCells.Count - 1); }
ãªã¹ãå
ã®äŸµé£ããããã»ã«ãç¶æããªããã100ïŒ
䟵é£ããããã£ãŠã䟵é£ã¯ã¯ããã«åŒ·ããªããŸããã100ïŒ
ã䜿çšããŠãããã¹ãŠã®åŽãåãé€ãããšã¯ã§ããŸããããã®çç±ã¯ãã»ã«ã®é«ããäœããããšããã®é£ã®ã»ã«ã®1ã€ã䟵é£ãåãããããªãå¯èœæ§ãããããã§ãããããã£ãŠãçµæãšããŠã䟵é£ãèµ·ããããã现èãå
ããå€ããªãå¯èœæ§ããããŸããã»ã«ãäžããåŸããã¹ãŠã®é£æ¥ã»ã«ã確èªããå¿
èŠããããŸãã䟵é£ã®åŸåããããããŸã ãªã¹ãã«ãªãå Žåã¯ãããã«è¿œå ããå¿
èŠããããŸãã if (!IsErodible(cell)) { erodibleCells[index] = erodibleCells[erodibleCells.Count - 1]; erodibleCells.RemoveAt(erodibleCells.Count - 1); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if ( neighbor && IsErodible(neighbor) && !erodibleCells.Contains(neighbor) ) { erodibleCells.Add(neighbor); } }
䟵é£ãããã»ã«ã¯ãã¹ãŠçç¥ãããŸããå€ãã®åå°ãç¯çŽããŸã
ããã§ããã¹ãŠã®åŽãæ¶ãããŸã§äŸµé£ããã»ã¹ãç¶ç¶ã§ããŸããããã¯åå°ã«å€§ãã圱é¿ããŸããåå°ã®å€§éšåã¯æ¶æ»
ããå¿
èŠãªåå°ã®å²åãããã¯ããã«å°ãªããªããŸãããããã¯ããããããåå°ãåé€ããŠããããã«çºçããŸãããçã®äŸµé£ã¯ç©è³ªãç Žå£ããŸããã圌女ã¯ããå Žæãããããåãåºããå¥ã®å Žæã«çœ®ããŸããåãããšãã§ããŸãã 1ã€ã®ã»ã«ãæžå°ãããšããã®é£ã®ã»ã«ã1ã€äžããå¿
èŠããããŸããå®éã1ã¬ãã«ã®é«ããäžã®ã»ã«ã«è»¢éãããŸããããã«ãããåçŽã«ã¹ã ãŒãžã³ã°ããªããããããã®å
šé«ãç¯çŽãããŸãããããå®çŸããã«ã¯ã䟵é£è£œåãã©ãã«ç§»åããããæ±ºå®ããå¿
èŠããããŸããããã䟵é£ã®ã¿ãŒã²ããã«ãªããŸãã䟵é£ãããã»ã«ã®ã¿ãŒã²ãããã€ã³ããæ±ºå®ããã¡ãœãããäœæããŸãããããã®ã»ã«ã«ã¯ãã¬ãŒã¯ãå«ãŸããŠããããããã®ãã¬ãŒã¯ã®äžã«ããã»ã«ãã¿ãŒã²ãããšããŠéžæããã®ãè«ççã§ãããããã䟵é£ãããããã»ã«ã«ã¯ããã€ãã®ãã¬ãŒã¯ãããå¯èœæ§ãããããããã¹ãŠã®é£æ¥ã»ã«ããã§ãã¯ãããã¹ãŠã®åè£ãäžæãªã¹ãã«å
¥ããŠãããã©ã³ãã ã«1ã€ãéžæããŸãã HexCell GetErosionTarget (HexCell cell) { List<HexCell> candidates = ListPool<HexCell>.Get(); int erodibleElevation = cell.Elevation - 2; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (neighbor && neighbor.Elevation <= erodibleElevation) { candidates.Add(neighbor); } } HexCell target = candidates[Random.Range(0, candidates.Count)]; ListPool<HexCell>.Add(candidates); return target; }
ErodeLand
æã
ã¯ããã«äŸµé£ãããã»ã«ãéžæããåŸãæšç现èãå®çŸ©ããŸããæ¬¡ã«ãã»ã«ã®é«ããæ¬¡ã
ã«å¢æžããŸãããã®å Žåãã¿ãŒã²ããã»ã«èªäœã䟵é£ãåãããããªãå¯èœæ§ããããŸãããæ°ãã䟵é£ãããã»ã«ã®é£æ¥ã»ã«ããã§ãã¯ãããšããã®ç¶æ³ã¯è§£æ±ºãããŸãã HexCell cell = erodibleCells[index]; HexCell targetCell = GetErosionTarget(cell); cell.Elevation -= 1; targetCell.Elevation += 1; if (!IsErodible(cell)) { erodibleCells[index] = erodibleCells[erodibleCells.Count - 1]; erodibleCells.RemoveAt(erodibleCells.Count - 1); }
ã¿ãŒã²ããã»ã«ãäžããã®ã§ããã®ã»ã«ã®é£æ¥éšåã®äžéšã䟵é£ãåããªããªãå¯èœæ§ããããŸããããããåã£ãŠã䟵é£ãåãããããã©ããã確èªããå¿
èŠããããŸããããã§ãªãå Žåã§ãããªã¹ãã«å«ãŸããŠããå Žåã¯ããªã¹ãããåé€ããå¿
èŠããããŸãã for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); ⊠} for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = targetCell.GetNeighbor(d); if ( neighbor && !IsErodible(neighbor) && erodibleCells.Contains(neighbor) ) { erodibleCells.Remove(neighbor); } }
åå°ã®è³ªéãç¶æããªãã100ïŒ
ã®äŸµé£ã䟵é£ã«ãããå°åœ¢ãããæ»ããã«ãªããäžéšã®ãšãªã¢ãäœããªããä»ã®ãšãªã¢ãé«ããªããŸãããã®çµæãåå°ã®è³ªéã¯å¢å ãããçããªã£ããããå¯èœæ§ããããŸããããã«ãããåå°ã®å²åãããããã®æ¹åã«æ°ããŒã»ã³ãå€åããå¯èœæ§ããããŸãããé倧ãªéžè±ã¯ã»ãšãã©çºçããŸãããã€ãŸããé©çšãã䟵é£ã倧ããã»ã©ãçµæãšããŠçããåå°ã®å²åã«å¯Ÿããå¶åŸ¡ãå°ãªããªããŸããå é䟵é£
䟵é£ã¢ã«ãŽãªãºã ã®æå¹æ§ãå®éã«æ°ã«ããå¿
èŠã¯ãããŸããããç°¡åãªæ¹åãè¡ãããšãã§ããŸããæåã«ã䟵é£ããã»ã«ã䟵é£å¯èœãã©ãããæç€ºçã«ãã§ãã¯ããŸããããã§ãªãå Žåã¯ãåºæ¬çã«ãªã¹ãããåé€ããŸãããããã£ãŠãã¿ãŒã²ããã»ã«ã®é£æ¥ã»ã«ãèµ°æ»ãããšãã«ãã®ã»ã«ã®ãã§ãã¯ãã¹ãããã§ããŸãã for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = targetCell.GetNeighbor(d); if ( neighbor && neighbor != cell && !IsErodible(neighbor) && erodibleCells.Contains(neighbor) ) { erodibleCells.Remove(neighbor); } }
第äºã«ãã¿ãŒã²ããã»ã«ã®éã«ãã¬ãŒã¯ãããå Žåã«ã®ã¿ãã¿ãŒã²ããã»ã«ã®ãã€ããŒããã§ãã¯ããå¿
èŠããããŸããããä»ã§ã¯å¿
èŠãããŸãããããã¯ã飿¥ã»ã«ãã¿ãŒã²ããã»ã«ãã1ã¹ãããé«ãå Žåã«ã®ã¿çºçããŸããããã§ããå Žåãé£äººã¯ãªã¹ãã«ããããšãä¿èšŒãããã®ã§ãããããã§ãã¯ããå¿
èŠã¯ãããŸãããã€ãŸããäžå¿
èŠãªæ€çŽ¢ãã¹ãããã§ããŸãã HexCell neighbor = targetCell.GetNeighbor(d); if ( neighbor && neighbor != cell && neighbor.Elevation == targetCell.Elevation + 1 && !IsErodible(neighbor)
第äžã«ã䟵é£ããããã»ã«ã®é£æ¥ããã§ãã¯ãããšãã«ãåæ§ã®ããªãã¯ã䜿çšã§ããŸãããããã®éã«åŽãããå Žåãé£äººã¯äŸµé£ãåããããã§ãã調ã¹ãããã«ããåŒã³åºãå¿
èŠã¯ãããŸããIsErodible
ã HexCell neighbor = cell.GetNeighbor(d); if ( neighbor && neighbor.Elevation == cell.Elevation + 2 &&
ãã ããã¿ãŒã²ããã»ã«ã䟵é£ã®åœ±é¿ãåãããããã©ããã確èªããå¿
èŠããããŸãããäžèšã®ãµã€ã¯ã«ã§ã¯ãããè¡ãããªããªããŸããããããã£ãŠãã¿ãŒã²ããã»ã«ã«å¯ŸããŠãããæç€ºçã«å®è¡ããŸãã if (!IsErodible(cell)) { erodibleCells[index] = erodibleCells[erodibleCells.Count - 1]; erodibleCells.RemoveAt(erodibleCells.Count - 1); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠} if (IsErodible(targetCell) && !erodibleCells.Contains(targetCell)) { erodibleCells.Add(targetCell); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠}
ããã§ãçæãããåŽã®æåã®æ°ã«å¯Ÿããå¿
èŠãªå²åã«ã浞é£ãååè¿
éã«é©çšã§ããŸããã¿ãŒã²ããã»ã«ã䟵é£åŸåãªã¹ãã«è¿œå ãããå Žæããããã«å€æŽãããšããäºå®ã«ãããçµæã¯æé©ååã®çµæãããããã«å€æŽãããŠããããšã«æ³šæããŠãã ããã25ïŒ
ã50ïŒ
ã75ïŒ
ãããã³100ïŒ
ã®äŸµé£ããŸããæµ·å²žã®åœ¢ç¶ã倿Žãããã«ãããããããããããžãæ ¹æ¬çã«å€æŽãããŠããªãããšã«ã泚æããŠãã ãããéžå°ã¯éåžžãæ¥ç¶ãŸãã¯åé¢ããããŸãŸã§ããå°ããªå³¶ã ããå®å
šã«drããããšãã§ããŸããã¬ãªãŒãã®è©³çްã¯å¹³æ»åãããŠããŸãããäžè¬çãªåœ¢åŒã¯åããŸãŸã§ããçãé¢ç¯ãæ¶ããããå°ãæé·ãããããå ŽåããããŸããå°ããªééããããã«åãããããæ¡å€§ãããããããšããããŸãããããã£ãŠã䟵é£ã¯åå²ãããé åã匷ãçµã³ä»ããŸããã4ã€ã®å®å
šã«äŸµé£ãããé åã¯ãŸã åé¢ããããŸãŸã§ãããŠããã£ããã±ãŒãžããŒã25ïŒæ°ŽåŸªç°
- çã®å°å³ããŒã¿ã衚瀺ããŸãã
- 现èã®æ°åã圢æããŸãã
- 氎埪ç°ã®éšåã·ãã¥ã¬ãŒã·ã§ã³ãäœæããŸãã
ãã®ããŒãã§ã¯ãåå°ã«æ¹¿åºŠã远å ããŸãããã®ãã¥ãŒããªã¢ã«ã¯Unity 2017.3.0ã§äœæãããŸãããæ°ŽåŸªç°ã䜿çšããŠãã€ãªãŒã ãæ±ºå®ããŸããé²
ãã®æç¹ãŸã§ããããçæã¢ã«ãŽãªãºã ã¯ã»ã«ã®é«ãã®ã¿ã倿ŽããŠããŸãããã»ã«éã®æå€§ã®éãã¯ãã»ã«ãæ°Žã®äžãäžãã§ãããããŸããŸãªçš®é¡ã®å°åœ¢ãå®çŸ©ã§ããŸãããããã¯é«ãã®åçŽãªèŠèŠåã§ããå°åã®æ°åãèæ
®ããŠãå°åœ¢ã®ã¿ã€ããæå®ããæ¹ãè¯ãã§ããããå°çã®æ°åã¯éåžžã«è€éãªã·ã¹ãã ã§ãã幞ããªããšã«ãçŸå®çãªæ°åã·ãã¥ã¬ãŒã·ã§ã³ãäœæããå¿
èŠã¯ãããŸãããååã«èªç¶ã«èŠãããã®ãå¿
èŠã§ããæ°åã®æãéèŠãªåŽé¢ã¯æ°ŽåŸªç°ã§ãããªããªãã忀ç©ã¯çãæ®ãããã«æ¶²äœã®æ°Žãå¿
èŠãšããããã§ããæž©åºŠãéåžžã«éèŠã§ãããä»ã®ãšãããç§ãã¡ã¯æ¬è³ªçã«å°çã®æž©åºŠãäžå®ã«ä¿ã¡ã湿床ã®ã¿ãå€åãããæ°Žã«çŠç¹ãåœãŠãŠããŸããæ°ŽåŸªç°ã¯ãç°å¢å
ã®æ°Žã®åãã衚ããŸããç°¡åã«èšãã°ãæ± ã¯èžçºããéšãé²ã«ãªããåã³éšãæ± ã«æµã蟌ã¿ãŸããã·ã¹ãã ã«ã¯ããã«å€ãã®åŽé¢ããããŸããããããã®æé ãã·ãã¥ã¬ãŒãããã ãã§ããããäžã«èªç¶ãªå€èŠ³ã®æ°Žã®ååžãäœæããã®ã«ååãªå ŽåããããŸããããŒã¿ã®å¯èŠå
ãã®ã·ãã¥ã¬ãŒã·ã§ã³ã«å
¥ãåã«ãé¢é£ããããŒã¿ãçŽæ¥ç¢ºèªãããšäŸ¿å©ã§ãããããè¡ãã«ã¯ããã¬ã€ã³ã·ã§ãŒããŒã倿ŽããŸããåãæ¿ãå¯èœãªããããã£ã远å ããŸããããã¯ãéåžžã®ã¬ãªãŒããã¯ã¹ãã£ã®ä»£ããã«çã®ãããããŒã¿ã衚瀺ããããŒã¿èŠèŠåã¢ãŒãã«åãæ¿ããããšãã§ããŸããããã¯ãããŒã¯ãŒããå®çŸ©ããåãæ¿ãå¯èœãªå±æ§ãæã€floatããããã£ã䜿çšããŠå®è£
ã§ããŸãããã®ããããããªã¢ã«ã€ã³ã¹ãã¯ã¿ãŒã«ããŒã¯ãŒãã®å®çŸ©ãå¶åŸ¡ãããã©ã°ãšããŠè¡šç€ºãããŸããããããã£èªäœã®ååã¯éèŠã§ã¯ãããŸãããããŒã¯ãŒãã«ã®ã¿èå³ããããŸããSHOW_MAP_DATAã䜿çšããŠããŸãã Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Terrain Texture Array", 2DArray) = "white" {} _GridTex ("Grid Texture", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Specular ("Specular", Color) = (0.2, 0.2, 0.2) _BackgroundColor ("Background Color", Color) = (0,0,0) [Toggle(SHOW_MAP_DATA)] _ShowMapData ("Show Map Data", Float) = 0 }
å°å³ããŒã¿ã®è¡šç€ºã«åãæ¿ããŸããããŒã¯ãŒããµããŒããæå¹ã«ããã·ã§ãŒããŒé¢æ°ã远å ããŸãã #pragma multi_compile _ GRID_ON #pragma multi_compile _ HEX_MAP_EDIT_MODE #pragma shader_feature SHOW_MAP_DATA
æ®ãã®ææžããŒã¿ã®å Žåãšåæ§ã«ãåäžã®ãããŒãã衚瀺ããŸãããããå®çŸããããã«ãããŒã¯ãŒããå®çŸ©ããããšãã«æ§é ã«Input
ãã£ãŒã«ãã远å ããŸãmapData
ã struct Input { float4 color : COLOR; float3 worldPos; float3 terrain; float4 visibility;
é ç¹ããã°ã©ã ã§ã¯ããããã®ã»ã«ã®Zãã£ãã«ã䜿çšããŠmapData
ãåžžã«ã»ã«éã§è£éãããããã«ãåããŸãã void vert (inout appdata_full v, out Input data) { ⊠#if defined(SHOW_MAP_DATA) data.mapData = cell0.z * v.color.x + cell1.z * v.color.y + cell2.z * v.color.z; #endif }
ã»ã«ããŒã¿ã衚瀺ããå¿
èŠãããå Žåã¯ãéåžžã®è²ã§ã¯ãªããã¢ã«ãããã©ã°ã¡ã³ããšããŠçŽæ¥äœ¿çšããŸããããŒã¿ãã¬ã³ããªã³ã°ãããšãã«ã°ãªããããŸã ãªã³ã«ãªãããã«ãã°ãªãããä¹ç®ããŸãã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { ⊠o.Albedo = c.rgb * grid * _Color * explored; #if defined(SHOW_MAP_DATA) o.Albedo = IN.mapData * grid; #endif ⊠}
å®éã«ããŒã¿ãã·ã§ãŒããŒã«è»¢éããŸããHexCellShaderData
ãã¯ã¹ãã£ããŒã¿ã®éããã£ãã«ã«äœããæžã蟌ãã¡ãœããã«è¿œå ããå¿
èŠããããŸããããŒã¿ã¯ã0ã1ã«å¶éãããåäžã®æµ®åå°æ°ç¹å€ã§ãã public void SetMapData (HexCell cell, float data) { cellTextureData[cell.Index].b = data < 0f ? (byte)0 : (data < 1f ? (byte)(data * 255f) : (byte)255); enabled = true; }
ãã ãããã®æ±ºå®ã¯ç ç©¶ã·ã¹ãã ã«åœ±é¿ããŸããéè²ã®ãã£ãã«ããŒã¿å€255ã¯ãã»ã«ã®å¯èŠæ§ãç§»è¡äžã§ããããšã瀺ãããã«äœ¿çšãããŸãããã®ã·ã¹ãã ãåŒãç¶ãæ©èœããããã«ã¯ãæå€§å€ãšããŠãã€ãå€254ã䜿çšããå¿
èŠããããŸãããã¿ããã¡ã³ãã®ç§»åã¯ãã¹ãŠã®ã«ãŒãããŒã¿ãæ¶å»ããããšã«æ³šæããŠãã ããã cellTextureData[cell.Index].b = data < 0f ? (byte)0 : (data < 1f ? (byte)(data * 254f) : (byte)254);
åãååã§ã«ã¡ãœããã远å ãHexCell
ãŸããèŠæ±ãã·ã§ãŒããŒããŒã¿ã«è»¢éããŸãã public void SetMapData (float data) { ShaderData.SetMapData(this, data); }
ã³ãŒãã®åäœã確èªããã«HexMapGenerator.SetTerrainType
ã¯ããããã®åã»ã«ã®ããŒã¿ãèšå®ããããã«å€æŽããŸãã0ã1ã®ééã§æŽæ°ããæµ®åå°æ°ç¹æ°ã«å€æãããé«ããèŠèŠåããŸããããã¯ãã»ã«ã®é«ãããæå°ã®é«ããåŒããŠãæå€§ã®é«ãããæå°ã®å€ãåŒããå€ã§é€ç®ããããšã«ããè¡ãããŸããé€ç®æµ®åå°æ°ç¹ãäœæããŸãããã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { ⊠cell.SetMapData( (cell.Elevation - elevationMinimum) / (float)(elevationMaximum - elevationMinimum) ); } }
ããã§ããã¬ã€ã³ãããªã¢ã«ã¢ã»ããã®[ ãããããŒã¿ã衚瀺]ãã§ãã¯ããã¯ã¹ã䜿çšããŠãéåžžã®å°åœ¢ãšããŒã¿ã®èŠèŠåãåãæ¿ããããšãã§ããŸããããã1208905299ãéåžžã®å°åœ¢ãé«ãã®èŠèŠåãæ°åã®åµé
æ°åãã·ãã¥ã¬ãŒãããã«ã¯ãæ°åããŒã¿ã远跡ããå¿
èŠããããŸãããããã¯åå¥ã®ã»ã«ã§æ§æãããŠãããããåã»ã«ã«ã¯åºæã®æ°åããããŸããClimateData
ãã¹ãŠã®é¢é£ããŒã¿ãä¿åããæ§é ãäœæããŸãããã¡ãããã»ã«èªäœã«ããŒã¿ã远å ã§ããŸãããããããçæããå Žåã«ã®ã¿äœ¿çšããŸãããããã£ãŠãããããåå¥ã«ä¿åããŸããããã¯HexMapGenerator
ãã®ããã«å
éšã§ãã®æ§é äœãå®çŸ©ã§ããããšãæå³ããŸãMapRegion
ãé²ã®è¿œè·¡ããå§ããŸããããã¯ãåäžã®ãããŒããã£ãŒã«ãã䜿çšããŠå®è£
ã§ããŸãã struct ClimateData { public float clouds; }
ãªã¹ãã远å ããŠããã¹ãŠã®ã»ã«ã®æ°åããŒã¿ã远跡ããŸãã List<ClimateData> climate = new List<ClimateData>();
次ã«ãæ°åããããäœæããæ¹æ³ãå¿
èŠã§ãããŸããæ°åãŸãŒã³ã®ãªã¹ããã¯ãªã¢ããŠãããåã»ã«ã«1ã€ã®èŠçŽ ã远å ããå¿
èŠããããŸããåæã®æ°åããŒã¿ã¯åçŽã«ãŒãã§ããããã¯æšæºã®ã³ã³ã¹ãã©ã¯ã¿ã䜿çšããŠå®çŸã§ããŸãClimateData
ã void CreateClimate () { climate.Clear(); ClimateData initialData = new ClimateData(); for (int i = 0; i < cellCount; i++) { climate.Add(initialData); } }
æ°åã¯ãå°åœ¢äŸµé£ã«ãããããåŸãææŽã®çš®é¡ãèšå®ããåã«äœæããå¿
èŠããããŸããå®éã«ã¯ã䟵é£ã¯äž»ã«æ°åã®äžéšã§ãã空æ°ãšæ°Žã®åãã«ãã£ãŠåŒãèµ·ããããŸããããããã·ãã¥ã¬ãŒãããŸããã public void GenerateMap (int x, int z) { ⊠CreateRegions(); CreateLand(); ErodeLand(); CreateClimate(); SetTerrainType(); ⊠}
SetTerrainType
ã»ã«ã®é«ãã®ä»£ããã«ã¯ã©ãŠãããŒã¿ã衚瀺ã§ããããã«å€æŽããŸããæåã¯ãé»ãã«ãŒãã®ããã«èŠããŸãã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { ⊠cell.SetMapData(climate[i].clouds); } }
æ°åå€å
æ°åã·ãã¥ã¬ãŒã·ã§ã³ã®æåã®ã¹ãããã¯èžçºã§ããã©ã®ãããã®æ°Žåãèžçºãããã¹ãã§ããïŒã¹ã©ã€ããŒã䜿çšããŠãã®å€ãå¶åŸ¡ããŸããããå€0ã¯èžçºãªãã1-æå€§èžçºãæå³ããŸããããã©ã«ãã§ã¯ã0.5ã䜿çšããŸãã [Range(0f, 1f)] public float evaporation = 0.5f;
èžçºã¹ã©ã€ããŒã1ã€ã®ã»ã«ã®æ°åã圢æããããã®å
·äœçãªæ¹æ³ããã1ã€äœæããŠã¿ãŸãããããã©ã¡ãŒã¿ãšããŠã»ã«ã€ã³ããã¯ã¹ãæå®ããããã䜿çšããŠã察å¿ããã»ã«ãšãã®æ°åããŒã¿ãååŸããŸããã»ã«ãæ°Žé¢äžã«ããå Žåãç§ãã¡ã¯èžçºããªããã°ãªããªãè²¯æ°Žæ± ãæ±ã£ãŠããŸããèžæ°ãããã«é²ã«å€ãïŒé²ç¹ãšçµé²ãç¡èŠïŒãã»ã«é²ã®å€ã«èžçºãçŽæ¥è¿œå ããŸãããããå®äºããããæ°åããŒã¿ããªã¹ãã«ã³ããŒããŸãã void EvolveClimate (int cellIndex) { HexCell cell = grid.GetCell(cellIndex); ClimateData cellClimate = climate[cellIndex]; if (cell.IsUnderwater) { cellClimate.clouds += evaporation; } climate[cellIndex] = cellClimate; }
ã®åã»ã«ã«å¯ŸããŠãã®ã¡ââãœãããåŒã³åºãCreateClimate
ãŸãã void CreateClimate () { ⊠for (int i = 0; i < cellCount; i++) { EvolveClimate(i); } }
ããããããã§ã¯ååã§ã¯ãããŸãããè€éãªã·ãã¥ã¬ãŒã·ã§ã³ãäœæããã«ã¯ã现èã®æ°åãæ°å圢æããå¿
èŠããããŸãããããé »ç¹ã«è¡ãã»ã©ãçµæã¯è¯ããªããŸãã宿°å€ãéžæããŠã¿ãŸãããã40ãµã€ã¯ã«äœ¿çšããŸãã for (int cycle = 0; cycle < 40; cycle++) { for (int i = 0; i < cellCount; i++) { EvolveClimate(i); } }
ãªããªããæ°Žã§æºãããã现èã®äžã®é²ã®å€ãå¢ããã ãã§ããã®ã§ããã®çµæãé»ãåå°ãšçœãè²¯æ°Žæ± ãæã«å
¥ããããã§ããæ°Žäžã§ã®èžçºãé²ã®æ£ä¹±
ç¹ã«ãŸããŸãå€ãã®æ°Žãèžçºãããšããé²ã¯åžžã«äžç®æã«ããããã§ã¯ãããŸãããå§åå·®ã¯ç©ºæ°ãåãããããã颚ã®åœ¢ã§çŸããé²ãåããŸããæ¯é
çãªé¢šåããªãå Žåãå¹³åããŠçްèã®é²ã¯ãã¹ãŠã®æ¹åã«åçã«åæ£ãã飿¥ãã现èã«çŸããŸããæ¬¡ã®ãµã€ã¯ã«ã§æ°ããé²ãçæãããšããã»ã«å
ã®ãã¹ãŠã®é²ããã®é£ã«åæ£ãããŸããããã€ãŸããåãã€ããŒã¯ã»ã«ã¯ã©ãŠããã6åã®1ãåä¿¡ãããã®åŸãŒããŸã§å±æçã«æžå°ããŸãã if (cell.IsUnderwater) { cellClimate.clouds += evaporation; } float cloudDispersal = cellClimate.clouds * (1f / 6f); cellClimate.clouds = 0f; climate[cellIndex] = cellClimate;
é£äººã«å®éã«é²ã远å ããã«ã¯ã茪ã«ãªã£ãŠåšããåããæ°åããŒã¿ãååŸããé²ã®å€ãå¢ãããŠããªã¹ãã«ã³ããŒãçŽãå¿
èŠããããŸãã float cloudDispersal = cellClimate.clouds * (1f / 6f); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } ClimateData neighborClimate = climate[neighbor.Index]; neighborClimate.clouds += cloudDispersal; climate[neighbor.Index] = neighborClimate; } cellClimate.clouds = 0f;
æ£ä¹±é²ãããã«ãããåãµã€ã¯ã«ã§æ°Žäžã®ã»ã«ããŸããŸãå€ãã®é²ãå°çèŠæš¡ã®æ°åã«è¿œå ãããããã»ãŒçœãããããäœæãããŸããæåã®ãµã€ã¯ã«ã®åŸãæ°Žã®è¿ãã®éžå°ã®ã»ã«ã«ã忣ããå¿
èŠãããé²ããããŸãããã®ããã»ã¹ã¯ããããã®å€§éšåãé²ã§èŠããããŸã§ç¶ããŸããããã©ã«ããã©ã¡ãŒã¿ã䜿çšããããã1208905299ã®å Žåãåæ±éšã®å€§èŠæš¡ãªåå°ã®å
éšã®ã¿ãå®å
šã«èŠããããŸãŸã§ãããæ± ã¯ç¡éã®æ°ã®é²ãçæã§ããããšã«æ³šæããŠãã ãããæ°Žäœã¯æ°åã·ãã¥ã¬ãŒã·ã§ã³ã®äžéšã§ã¯ãããŸãããå®éã«ã¯ãè²¯æ°Žæ± ã¯ãã»ãŒèžçºéåºŠã§æ°Žãéæµããããã«ã®ã¿ä¿åãããŸããã€ãŸããéšåçãªæ°ŽåŸªç°ã®ã¿ãã·ãã¥ã¬ãŒãããŸããããã¯æ£åžžã§ãããã·ãã¥ã¬ãŒã·ã§ã³ãé·ãè¡ãããã»ã©ãæ°åã«ããå€ãã®æ°Žã远å ãããããšãçè§£ããå¿
èŠããããŸãããããŸã§ã®ãšãããæ°Žã®æå€±ã¯ãããã®ç«¯ã§ã®ã¿çºçãã飿¥ãããšãªã¢ããªãããã«æ£åšããé²ã倱ãããŸããå°å³ã®äžéšãç¹ã«å³äžã®ã»ã«ã§æ°Žã®æå€±ã確èªã§ããŸããæåŸã®ã»ã«ã«ã¯é²ããŸã£ãããããŸããããªããªããé²ã¯æ°åã圢æãããæåŸã®ã»ã«ã ããã§ãã圌女ã¯ãŸã é£äººããé²ãåãåã£ãŠããŸããããã¹ãŠã®çްèã®æ°åã䞊è¡ããŠåœ¢æãããã¹ãã§ã¯ãªãã§ããããïŒ, . - , . 40 . - , .
éæ°Žé
æ°Žã¯æ°žé ã«å·ãããŸãŸã§ã¯ãããŸãããããæç¹ã§ã圌女ã¯åã³å°é¢ã«èœã¡ãã¯ãã§ããããã¯éåžžãéšã®åœ¢ã§èµ·ãããŸãããæã«ã¯éªãailãæ¹¿ã£ãéªã«ãªãããšããããŸããããã¯ãã¹ãŠãäžè¬ã«éæ°ŽéãšåŒã°ããŸããé²ã®æ¶å€±ã®å€§ãããšé床ã¯å€§ããç°ãªããŸãããã«ã¹ã¿ã ã®å
šçééšé床ã䜿çšããŸããå€0ã¯éæ°Žããªãããšãæå³ããå€1ã¯ãã¹ãŠã®é²ãå³åº§ã«æ¶ããããšãæå³ããŸããããã©ã«ãå€ã¯0.25ã§ããããã¯ãåãµã€ã¯ã«ã§é²ã®4åã®1ãæ¶ããããšãæå³ããŸãã [Range(0f, 1f)] public float precipitationFactor = 0.25f;
éæ°Žä¿æ°ã¹ã©ã€ããŒãèžçºåŸãé²ã®æ£ä¹±åã®éæ°Žéãã·ãã¥ã¬ãŒãããŸããããã¯ãè²¯æ°Žæ± ããèžçºããæ°Žã®äžéšãããã«æ²æ®¿ããããšãæå³ãããããæ£ä¹±é²ã®æ°ã¯æžå°ããŸããéžå°ã§ã¯ãéæ°Žã¯é²ã®æ¶å€±ã«ã€ãªãããŸãã if (cell.IsUnderwater) { cellClimate.clouds += evaporation; } float precipitation = cellClimate.clouds * precipitationFactor; cellClimate.clouds -= precipitation; float cloudDispersal = cellClimate.clouds * (1f / 6f);
æ¶ããé²ãä»ãåãµã€ã¯ã«ã§é²ã®25ïŒ
ãç Žå£ãããšãåå°ã¯åã³ã»ãŒé»ã«ãªããŸããé²ã¯ãããæ°ã¹ãããå
éžã«ç§»åãããã®åŸã¯èŠããªããªããŸãããŠããã£ããã±ãŒãžæ¹¿åºŠ
ééšã¯é²ãç Žå£ããŸãããæ°åããæ°Žãé€å»ãã¹ãã§ã¯ãããŸãããå°é¢ã«èœã¡ãåŸãæ°Žã¯å¥ã®ç¶æ
ã§ã®ã¿ä¿åãããŸããããã¯å€ãã®åœ¢ã§ååšããå¯èœæ§ãããããããããŸãšããŠæ¹¿åºŠãèæ
®ããŸããæ¹¿åºŠè¿œè·¡
é²ãšæ¹¿åºŠã®2ã€ã®æ°Žã®ç¶æ
ã远跡ããããšã«ãããæ°åã¢ãã«ãæ¹åããäºå®ã§ãããããå®è£
ããã«ã¯ãClimateData
ãã£ãŒã«ãã«è¿œå ããŸãmoisture
ã struct ClimateData { public float clouds, moisture; }
æãäžè¬åããã圢åŒã§ã¯ãèžçºã¯ãå°ãªããšãåçŽãªæ°åã¢ãã«ã§ã¯ãæ°Žåãé²ã«å€æããããã»ã¹ã§ããããã¯ãèžçºãäžå®ã®å€ã§ã¯ãªããå¥ã®èŠå ã§ããã¹ãã§ããããšãæå³ããŸãããããã£ãŠããªãã¡ã¯ã¿ãªã³ã°ãšåå倿Žãå®è¡evaporation
ãevaporationFactor
ãŸãã [Range(0f, 1f)] public float evaporationFactor = 0.5f;
ã»ã«ãæ°Žäžã«ããå Žåãæ¹¿åºŠã¬ãã«ã1ã§ããããšãéç¥ããŸããããã¯ãèžçºãèžçºä¿æ°ã«çããããšãæå³ããŸãããããä»ã§ã¯ã寿åžã®çްèããèžçºããããšãã§ããŸãããã®å Žåãèžçºãèšç®ããæ¹¿åºŠãããããå·®ãåŒããçµæãé²ã«è¿œå ããå¿
èŠããããŸãããã®åŸã湿床ã«éæ°Žéã远å ãããŸãã if (cell.IsUnderwater) { cellClimate.moisture = 1f; cellClimate.clouds += evaporationFactor; } else { float evaporation = cellClimate.moisture * evaporationFactor; cellClimate.moisture -= evaporation; cellClimate.clouds += evaporation; } float precipitation = cellClimate.clouds * precipitationFactor; cellClimate.clouds -= precipitation; cellClimate.moisture += precipitation;
é²ã¯éžå°ããã®èžçºã«ãã£ãŠæ¯ããããŠãããããé²ãããã«å
éžã«ç§»åã§ããŸããçŸåšã倧éšåã®åå°ã¯ç°è²ã«ãªã£ãŠããŸããæ¹¿åºŠãèžçºããé²ã é²ã®ä»£ããã«æ¹¿åºŠã衚瀺ããSetTerrainType
ããã«å€æŽããŠã¿ãŸããããããã¯ãã¬ãªãŒãã®ã¿ã€ããæ±ºå®ããããã«äœ¿çšããããã§ãã cell.SetMapData(climate[i].moisture);
湿床衚瀺ããã®æç¹ã§ã湿床ã¯é²ã«éåžžã«äŒŒãŠããŸãïŒãã ãããã¹ãŠã®æ°Žäžã®ã»ã«ãçœã§ããããšãé€ããŠïŒããããã«å€åããŸããééšæµåº
æ°Žåã现èããåºãå¯äžã®æ¹æ³ã¯èžçºã ãã§ã¯ãããŸãããæ°ŽåŸªç°ã¯ãåå°ã«è¿œå ãããæ°Žåã®å€§éšåãäœããã®åœ¢ã§æ°Žã«ãªã£ãŠããŸãããšã瀺ããŠããŸããæãé¡èãªããã»ã¹ã¯ãéåã®åœ±é¿äžã§ã®åå°äžã®æ°Žã®æµãã§ããå®éã®æ²³å·ãã·ãã¥ã¬ãŒãããã®ã§ã¯ãªããã«ã¹ã¿ã ééšæµåºä¿æ°ã䜿çšããŸããããã¯ãããäœããšãªã¢ã«ææ°Žããæ°Žã®å²åã瀺ããŸããããã©ã«ãã§ã¯25ïŒ
ã«ãªããŸãã [Range(0f, 1f)] public float runoffFactor = 0.25f;
ãã¬ã€ã³ã¹ã©ã€ããŒãå·ãçæããŸãããïŒ.
æ°Žã®æµåºã¯é²ã®æ£ä¹±ã®ããã«æ©èœããŸããã3ã€ã®éãããããŸãããŸãããã¹ãŠã®æ°Žåãã»ã«ããé€å»ãããããã§ã¯ãããŸããã第äºã«ãé²ã§ã¯ãªã湿æ°ãéã³ãŸãã第äžã«ãããã¯äžéããŸããã€ãŸãã身é·ãäœãé£äººã ãã«ãªããŸããææ°Žä¿æ°ã¯ã飿¥ãããã¹ãŠãäœãå Žåã«ã»ã«ããæµåºããæ°Žåã®éã衚ããŸãããå€ãã®å Žåãæ°Žåã¯å°ãªããªããŸããããã¯ãäžã«é£äººãèŠã€ãã£ãå Žåã«ã®ã¿ã»ã«ã®æ¹¿åºŠãäžããããšãæå³ããŸãã float cloudDispersal = cellClimate.clouds * (1f / 6f); float runoff = cellClimate.moisture * runoffFactor * (1f / 6f); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } ClimateData neighborClimate = climate[neighbor.Index]; neighborClimate.clouds += cloudDispersal; int elevationDelta = neighbor.Elevation - cell.Elevation; if (elevationDelta < 0) { cellClimate.moisture -= runoff; neighborClimate.moisture += runoff; } climate[neighbor.Index] = neighborClimate; }
ããäœãé«ããŸã§ææ°ŽãããçµæãšããŠãé«ãã»ã«ã¯æ°Žåãäœãæ¹ã«äŒéãããããæ¹¿åºŠã®ååžã¯ãã倿§ã«ãªããŸãããŸããæ²¿å²žã®ã»ã«ã¯æ°Žåãæ°Žäžã®ã»ã«ã«æåºãããããæ²¿å²žã®ã»ã«ã®æ°Žåã¯ã¯ããã«å°ãªããªããŸãããã®å¹æã匱ããã«ã¯ãã»ã«ãäœããã©ãããã€ãŸãèŠããã®é«ãã倿ãããšãã«æ°Žäœã䜿çšããå¿
èŠããããŸãã int elevationDelta = neighbor.ViewElevation - cell.ViewElevation;
ç®ã«èŠããé«ãã䜿çšããŸããæµžé
æ°Žã¯æµãèœã¡ãã ãã§ãªããåºãããå¹³ããªå°åœ¢ã浞éããæ°Žåã«é£æ¥ããåå°ã«åžåãããŸãããã®å¹æã¯ã»ãšãã©å¹æããªããããããŸããããæ¹¿åºŠã®ååžãæ»ããã«ããã®ã«åœ¹ç«ã¡ãŸãã®ã§ãã·ãã¥ã¬ãŒã·ã§ã³ã«è¿œå ããŸããããããã©ã«ãã§0.125ã«çããã«ã¹ã¿ã ä¿æ°ãäœæããŠã¿ãŸãããã [Range(0f, 1f)] public float seepageFactor = 0.125f;
æŒãã¹ã©ã€ããŒã浞éã¯ãã¬ã€ã³ã«äŒŒãŠããŸããã飿¥ã»ã«ã®é«ããã»ã«èªäœãšåãå Žåã«äœ¿çšãããŸãã float runoff = cellClimate.moisture * runoffFactor * (1f / 6f); float seepage = cellClimate.moisture * seepageFactor * (1f / 6f); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠int elevationDelta = neighbor.ViewElevation - cell.ViewElevation; if (elevationDelta < 0) { cellClimate.moisture -= runoff; neighborClimate.moisture += runoff; } else if (elevationDelta == 0) { cellClimate.moisture -= seepage; neighborClimate.moisture += seepage; } climate[neighbor.Index] = neighborClimate; }
å°ãæŒãã远å ããŸããããŠããã£ããã±ãŒãžéšã®åœ±
ç§ãã¡ã¯ãã§ã«æ°ŽåŸªç°ã®äŸ¡å€ããã·ãã¥ã¬ãŒã·ã§ã³ãäœæããŸããããæ°åã®éããæãæç¢ºã«ç€ºãéšã®é°ããªããããããŸãé¢çœããããŸãããéšã®åœ±ã¯ãè¿é£ã®å°åãšæ¯ã¹ãŠééšéãèããå°ãªãå°åã§ããå±±ãé²ããããã«å°éããã®ã劚ããããããã®ãããªé åãååšããŸãããããã®äœæã«ã¯ãé«ãå±±ãšæ¯é
çãªé¢šåãå¿
èŠã§ãã颚
æ¯é
çãªé¢šåãã·ãã¥ã¬ãŒã·ã§ã³ã«è¿œå ããããšããå§ããŸããããæ¯é
çãªé¢šã®æ¹åã¯å°çã®è¡šé¢ã§å€§ããç°ãªããŸãããã«ã¹ã¿ãã€ãºå¯èœãªã°ããŒãã«ãªé¢šã®æ¹åã§ç®¡çããŸããããã©ã«ãã§å西ã䜿çšããŸããããããã«ã颚åã1ã10ã®ç¯å²ã§ããã©ã«ãå€ã®4ã«èª¿æŽå¯èœã«ããŸãã public HexDirection windDirection = HexDirection.NW; [Range(1f, 10f)] public float windStrength = 4f;
é¢šã®æ¹åãšåŒ·ããæ¯é
çãªé¢šã®åŒ·ãã¯ãé²ã®å
šäœçãªåæ£ã«å¯ŸããŠè¡šãããŸãã颚åã1ã®å Žåãæ£ä¹±ã¯ãã¹ãŠã®æ¹åã§åãã§ãã2ã®å Žåãæ£ä¹±ã¯ä»ã®æ¹åãããé¢šã®æ¹åã§2é«ããªããŸãããããè¡ãã«ã¯ãã¯ã©ãŠãæ£åžåŒã®é€æ°ã倿ŽããŸãã6åã§ã¯ãªãã5åã«é¢šåãå ãããã®ã«ãªããŸãã float cloudDispersal = cellClimate.clouds * (1f / (5f + windStrength));
ããã«ãé¢šã®æ¹åã¯ã颚ãå¹ãæ¹åãæ±ºå®ããŸãããããã£ãŠãæ£ä¹±ã®äž»ãªæ¹åãšããŠå察æ¹åã䜿çšããå¿
èŠããããŸãã HexDirection mainDispersalDirection = windDirection.Opposite(); float cloudDispersal = cellClimate.clouds * (1f / (5f + windStrength));
ããã§ãè¿åãæ£ä¹±ã®äž»ãªæ¹åã«ãããã©ããã確èªã§ããŸãããããããªããé²ã®æ£ä¹±ã«é¢šã®åãæããªããã°ãªããŸããã ClimateData neighborClimate = climate[neighbor.Index]; if (d == mainDispersalDirection) { neighborClimate.clouds += cloudDispersal * windStrength; } else { neighborClimate.clouds += cloudDispersal; }
å西颚ããã©ãŒã¹4ãæ¯é
çãªé¢šã¯ãåå°å
šäœã«æ°Žåã®æ¹åååžã远å ããŸãã颚ã匷ãã»ã©ã广ã¯åŒ·ããªããŸãã絶察é«ã
éšã®åœ±ãååŸãã2çªç®ã®èŠçŽ ã¯å±±ã§ããç§ãã¡ã¯ãèªç¶ã«ãåæ§ã«å±±ããããšããå³å¯ãªåé¡ã¯ãããŸããã絶察çãªé«ãã®ã¿ãéèŠã§ããå®éã空æ°ãå±±ã®äžãç§»åãããšã空æ°ã¯å±±ã«åŒ·å¶çã«äžæããå·åŽãããæ°Žåãå°ãªããªãå¯èœæ§ãããã空æ°ãå±±ãééããåã«éæ°ŽãçºçããŸãããã®çµæãå察åŽã§ã¯ã也ç¥ãã空æ°ãã€ãŸãéšã®åœ±ãåŸãããŸããæãéèŠãªããšã¯ã空æ°ãäžæããã»ã©ã空æ°ãå°ãªããªãããšã§ããã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯ããããåã»ã«ã®æå€§ã¯ã©ãŠãå€ã®åŒ·å¶çãªå¶éãšããŠæ³åã§ããŸããå¯èŠã»ã«ã®é«ããé«ãã»ã©ããã®æå€§å€ã¯äœããªããŸãããããè¡ãæãç°¡åãªæ¹æ³ã¯ãæå€§å€ã1ãã€ãã¹èŠããã®é«ããæå€§é«ãã§å²ã£ãå€ã«èšå®ããããšã§ããããããå®éã«ã¯ãæå€§ã§ãã€ãã¹1ã§é€ç®ããŸããããããã«ãããé²ã®ããäžéšãæé«ã®ã»ã«ãééããããšãã§ããŸããéæ°Žéãèšç®ããåŸãæ£ä¹±ããåã«ãã®æå€§å€ãå²ãåœãŠãŸãã float precipitation = cellClimate.clouds * precipitationFactor; cellClimate.clouds -= precipitation; cellClimate.moisture += precipitation; float cloudMaximum = 1f - cell.ViewElevation / (elevationMaximum + 1f); HexDirection mainDispersalDirection = windDirection.Opposite();
ãã®çµæã蚱容ããããããå€ãã®é²ãåŸãããå Žåãäœåãªé²ãåã«æ¹¿åºŠã«å€æããŸããå®éãããã¯å®éã®å±±ã§èµ·ããããã«ã远å ã®éæ°Žéã远å ããæ¹æ³ã§ãã float cloudMaximum = 1f - cell.ViewElevation / (elevationMaximum + 1f); if (cellClimate.clouds > cloudMaximum) { cellClimate.moisture += cellClimate.clouds - cloudMaximum; cellClimate.clouds = cloudMaximum; }
é«å°ãåå ã®éšã®åœ±ããŠããã£ããã±ãŒãžã·ãã¥ã¬ãŒã·ã§ã³ãå®äºããŸã
ãã®æ®µéã§ã¯ããã§ã«æ°ŽåŸªç°ã®éåžžã«é«å質ãªéšåã·ãã¥ã¬ãŒã·ã§ã³ãè¡ãããŠããŸãããããå°ãæŽçããŠãã»ã«ã®ã¬ãªãŒãã®ã¿ã€ããæ±ºå®ããããã«é©çšããŠã¿ãŸãããã䞊åèšç®
ãã¿ãã¬ã§åè¿°ããããã«ãã»ã«ã圢æãããé åºã¯ã·ãã¥ã¬ãŒã·ã§ã³çµæã«åœ±é¿ããŸããçæ³çã«ã¯ãããã¯ãã¹ãã§ã¯ãªããå®éã«ãã¹ãŠã®ã»ã«ã䞊è¡ããŠåœ¢æããŸããããã¯ã圢æã®çŸåšã®æ®µéã®ãã¹ãŠã®å€åãæ°åã®2çªç®ã®ãªã¹ãã«é©çšããããšã«ãã£ãŠãããããšãã§ããŸãnextClimate
ã List<ClimateData> climate = new List<ClimateData>(); List<ClimateData> nextClimate = new List<ClimateData>();
ä»ã®ãã¹ãŠã®äººãšåæ§ã«ããã®ãªã¹ããã¯ãªã¢ããŠåæåããŸãããã®åŸãåãµã€ã¯ã«ã§ãªã¹ãã亀æããŸãããã®å Žåãã·ãã¥ã¬ãŒã·ã§ã³ã¯2ã€ã®ãªã¹ãã亀äºã«äœ¿çšããçŸåšãšæ¬¡ã®æ°åããŒã¿ãé©çšããŸãã void CreateClimate () { climate.Clear(); nextClimate.Clear(); ClimateData initialData = new ClimateData(); for (int i = 0; i < cellCount; i++) { climate.Add(initialData); nextClimate.Add(initialData); } for (int cycle = 0; cycle < 40; cycle++) { for (int i = 0; i < cellCount; i++) { EvolveClimate(i); } List<ClimateData> swap = climate; climate = nextClimate; nextClimate = swap; } }
ã»ã«ãé£ã®æ°åã«åœ±é¿ãäžããå ŽåãçŸåšã®ããŒã¿ã§ã¯ãªããæ¬¡ã®æ°åããŒã¿ã倿Žããå¿
èŠããããŸãã for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } ClimateData neighborClimate = nextClimate[neighbor.Index]; ⊠nextClimate[neighbor.Index] = neighborClimate; }
ãããŠãæ¬¡ã®æ°åããŒã¿ãçŸåšã®æ°åãªã¹ãã«ã³ããŒãã代ããã«ãæ¬¡ã®æ°åããŒã¿ãååŸãããããã«çŸåšã®æ¹¿åºŠã远å ããŠããã¹ãŠã次ã®ãªã¹ãã«ã³ããŒããŸãããã®åŸãçŸåšã®ãªã¹ãã®ããŒã¿ããªã»ããããŠã次ã®ãµã€ã¯ã«ã§æŽæ°ãããããã«ããŸãã
ãããè¡ã£ãŠããéãæ¹¿åºŠã¬ãã«ãæå€§1ã«èšå®ããŠãéžäžã®çްèãæ°Žäžãããæ¿¡ããªãããã«ããŸãã nextCellClimate.moisture += cellClimate.moisture; if (nextCellClimate.moisture > 1f) { nextCellClimate.moisture = 1f; } nextClimate[cellIndex] = nextCellClimate;
䞊åã³ã³ãã¥ãŒãã£ã³ã°ããœãŒã¹æ¹¿åºŠ
ã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯ãç¹ã«åå°ã®å²åãé«ããšã也ç¥ããåå°ãå€ããªããããå¯èœæ§ããããŸããç»åãæ¹åããããã«ãããã©ã«ãã®0.1ã®ã«ã¹ã¿ã åææ¹¿åºŠã¬ãã«ã远å ã§ããŸãã [Range(0f, 1f)] public float startingMoisture = 0.1f;
äžã¯å
ã®æ¹¿åºŠã®ã¹ã©ã€ããŒã§ãããã®å€ã¯åææ°åãªã¹ãã®æ¹¿åºŠã«äœ¿çšããŸããã以äžã«ã¯äœ¿çšããŸããã ClimateData initialData = new ClimateData(); initialData.moisture = startingMoisture; ClimateData clearData = new ClimateData(); for (int i = 0; i < cellCount; i++) { climate.Add(initialData); nextClimate.Add(clearData); }
å
ã®æ¹¿åºŠã§ããã€ãªãŒã ã®å®çŸ©
æåŸã«ãã»ã«ãªãªãŒãã®ã¿ã€ããèšå®ããããã«ãé«ãã®ä»£ããã«æ¹¿åºŠã䜿çšããŸããå®å
šã«ä¹Ÿç¥ããåå°ã«ã¯éªã䜿çšãã也ç¥ããå°åã«ã¯éªã䜿çšããŸããæ¬¡ã«ãç³ãååã«æ¹¿æ°ã®ããèãæ°Žã飜åããæ°Žé¢äžã®çްèã«åå°ã䜿çšããŸãã0.2ã®å¢åã§5ã€ã®ééã䜿çšããæãç°¡åãªæ¹æ³ã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); float moisture = climate[i].moisture; if (!cell.IsUnderwater) { if (moisture < 0.2f) { cell.TerrainTypeIndex = 4; } else if (moisture < 0.4f) { cell.TerrainTypeIndex = 0; } else if (moisture < 0.6f) { cell.TerrainTypeIndex = 3; } else if (moisture < 0.8f) { cell.TerrainTypeIndex = 1; } else { cell.TerrainTypeIndex = 2; } } else { cell.TerrainTypeIndex = 2; } cell.SetMapData(moisture); } }
ãã€ãªãŒã ãåäžãªååžã䜿çšããå Žåãçµæã¯ããŸãè¯ããªããäžèªç¶ã«èŠããŸãã0.05ã0.12ã0.28ã0.85ãªã©ãä»ã®ãããå€ã䜿çšããããšããå§ãããŸãã if (moisture < 0.05f) { cell.TerrainTypeIndex = 4; } else if (moisture < 0.12f) { cell.TerrainTypeIndex = 0; } else if (moisture < 0.28f) { cell.TerrainTypeIndex = 3; } else if (moisture < 0.85f) { cell.TerrainTypeIndex = 1; }
倿Žããããã€ãªãŒã ããŠããã£ããã±ãŒãžããŒã26ïŒãã€ãªãŒã ãšå·
- 湿床ã®é«ã现èããçããå·ãäœãåºããŸãã
- åçŽãªæž©åºŠã¢ãã«ãäœæããŸãã
- 现èã«ãã€ãªãŒã ãããªãã¯ã¹ã䜿çšããããã倿ŽããŸãã
ãã®ããŒãã§ã¯ã氎埪ç°ãæ²³å·ãšæ°æž©ã§è£å®ããããã«è峿·±ããã€ãªãŒã ã现èã«å²ãåœãŠãŸãããã¥ãŒããªã¢ã«ã¯Unity 2017.3.0p3ã䜿çšããŠäœæãããŸãããç±ãšæ°Žãå°å³ã掻æ°ã¥ããŸããå·ã®äžä»£
å·ã¯æ°ŽåŸªç°ã®çµæã§ããå®éããããã¯ããã£ãã«äŸµé£ã®å©ããåããŠåŒãè£ãããææ°Žã«ãã£ãŠåœ¢æãããŸããããã¯ãã»ã«ã®ã·ã³ã¯ã®å€ã«åºã¥ããŠå·ã远å ã§ããããšãæå³ããŸãããã ããããã¯å®éã®å·ã«äŒŒããã®ãåŸãããããšãä¿èšŒãããã®ã§ã¯ãããŸãããå·ãå§ãããšããããã¯å¯èœãªéãå€ãã®çްèãéã£ãŠæµããªããã°ãªããŸãããããã¯ã现èã䞊è¡ããŠåŠçããæ°ŽåŸªç°ã®ã·ãã¥ã¬ãŒã·ã§ã³ãšã¯äžèŽããŸãããããã«ãéåžžããããäžã®æ²³å·ã®æ°ã®å¶åŸ¡ãå¿
èŠã§ããå·ã¯éåžžã«ç°ãªããããåå¥ã«çæããŸããæ°ŽåŸªç°ã·ãã¥ã¬ãŒã·ã§ã³ã®çµæã䜿çšããŠå·ã®äœçœ®ãç¹å®ããŸãããå·ã¯ã·ãã¥ã¬ãŒã·ã§ã³ã«åœ±é¿ããŸããããªãå·ã®æµããæã
ééã£ãŠããã®ã§ããïŒTriangulateWaterShore
, . , . , , . , . , , . («»).
void TriangulateWaterShore ( HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center ) { ⊠if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary( e1, e2, cell.HasIncomingRiver && cell.IncomingRiver == direction, indices ); } ⊠}
髿¹¿åºŠã»ã«
ãããã§ã¯ãã»ã«ã«å·ãããå Žåãšãªãå ŽåããããŸããããã«ãåå²ãŸãã¯æ¥ç¶ã§ããŸããçŸå®ã«ã¯ãå·ã¯ã¯ããã«æè»æ§ããããŸããã倧ããªå·ã ããäœæãããã®è¿äŒŒå€ã§å¯ŸåŠããå¿
èŠããããŸããæãéèŠãªããšã¯ãã©ã³ãã ã«éžæããã倧ããªå·ã®å§ãŸãã®äœçœ®ã決å®ããå¿
èŠãããããšã§ããå·ã¯æ°Žãå¿
èŠãšãããããå·ã®æ°Žæºã¯æ¹¿åºŠã®é«ãã»ã«å
ã«ãªããã°ãªããŸãããããããããã§ã¯ååã§ã¯ãããŸãããå·ã¯æé¢ãæµãèœã¡ãã®ã§ãçæ³çã«ã¯æºã®é«ãã倧ããããå¿
èŠããããŸããæ°Žäœããäžã®ã»ã«ãé«ããã°é«ãã»ã©ãå·ã®æ°Žæºã®åœ¹å²ã®ããè¯ãåè£ã«ãªããŸããã»ã«ã®é«ããæå€§ã®é«ãã§å²ãããšã«ãããããããããããŒã¿ãšããŠèŠèŠåã§ããŸããçµæãæ°Žäœã«å¯ŸããŠåŸãããããã«ãåå²ããåã«äž¡æ¹ã®é«ããããããå·®ãåŒããŸãã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { ⊠float data = (float)(cell.Elevation - waterLevel) / (elevationMaximum - waterLevel); cell.SetMapData(data); } }
湿床ãšé«åºŠãããã©ã«ãèšå®ã®å€§ããªã«ãŒãçªå·1208905299ãæé©ãªåè£ã¯ã髿¹¿åºŠãšé«ãã®äž¡æ¹ãæã€ã»ã«ã§ãããããã®åºæºãä¹ç®ããããšã«ããããããã®åºæºãçµã¿åãããããšãã§ããŸããçµæã¯ãæ²³å·ã®æ°Žæºã®é©å床ãŸãã¯ééã®å€ã«ãªããŸãã float data = moisture * (cell.Elevation - waterLevel) / (elevationMaximum - waterLevel); cell.SetMapData(data);
æ²³å·ã®æ°Žæºã®éã¿ãçæ³çã«ã¯ããããã®éã¿ã䜿çšããŠããœãŒã¹ã»ã«ã®ã©ã³ãã éžæãæåŠããŸããæ£ããéã¿ã§ãªã¹ããäœæããŠéžæããããšã¯ã§ããŸãããããã¯éèŠãªã¢ãããŒãã§ãããçæããã»ã¹ã®é床ãäœäžããŸãã 4ã€ã®ã¬ãã«ã«åããããéèŠåºŠã®ããåçŽãªåé¡ã§ååã§ããæåã®åè£ã¯ãå€ã0.75ãè¶
ããéã¿ã«ãªããŸããè¯ãåè£è
ã®éã¿ã¯0.5ããã§ãã驿 Œãªåè£è
ã¯0.25ãè¶
ããŠããŸããä»ã®ãã¹ãŠã®ã»ã«ã¯ç Žæ£ãããŸãããããã°ã©ãã£ã«ã«ã«ã©ã®ããã«èŠããããèŠãŠã¿ãŸãããã float data = moisture * (cell.Elevation - waterLevel) / (elevationMaximum - waterLevel); if (data > 0.75f) { cell.SetMapData(1f); } else if (data > 0.5f) { cell.SetMapData(0.5f); } else if (data > 0.25f) { cell.SetMapData(0.25f); }
æ²³å·æºã®éã¿ã®ã«ããŽãªããã®åé¡ã¹ããŒã ã䜿çšãããšããããã®æãæ¹¿æ°ã®å€ãå°åã«æ°Žæºãæã€æ²³å·ãåŸãããå¯èœæ§ããããŸããããã§ããæ¯èŒç也ç¥ããå°åãäœãå°åã§æ²³å·ãé ãå¯èœæ§ã¯æ®ã£ãŠãããå€åæ§ãé«ãŸããŸãããããã®åºæºã«åºã¥ããŠã»ã«ã®ãªã¹ããåããã¡ãœããCreateRivers
ã远å ããŸãã驿 Œãªã»ã«ã¯ãã®ãªã¹ãã«1åãè¯å¥œãªã»ã«ã¯2åãäž»èŠãªåè£ã¯4å远å ãããŸããæ°Žäžã®ã»ã«ã¯åžžã«ç Žæ£ãããããã確èªããããšã¯ã§ããŸããã void CreateRivers () { List<HexCell> riverOrigins = ListPool<HexCell>.Get(); for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); if (cell.IsUnderwater) { continue; } ClimateData data = climate[i]; float weight = data.moisture * (cell.Elevation - waterLevel) / (elevationMaximum - waterLevel); if (weight > 0.75f) { riverOrigins.Add(cell); riverOrigins.Add(cell); } if (weight > 0.5f) { riverOrigins.Add(cell); } if (weight > 0.25f) { riverOrigins.Add(cell); } } ListPool<HexCell>.Add(riverOrigins); }
ãã®ã¡ãœããã¯CreateClimate
ãæ¹¿åºŠããŒã¿ãå©çšã§ããããã«ããããã«åŸã§åŒã³åºãå¿
èŠããããŸãã public void GenerateMap (int x, int z) { ⊠CreateRegions(); CreateLand(); ErodeLand(); CreateClimate(); CreateRivers(); SetTerrainType(); ⊠}
åé¡ãå®äºãããšãå°å³äžã®ããŒã¿ã®èŠèŠåãåãé€ãããšãã§ããŸãã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { âŠ
ãªããŒãã€ã³ã
ããã€ã®å·ãå¿
èŠã§ããïŒãã®ãã©ã¡ãŒã¿ãŒã¯ã«ã¹ã¿ãã€ãºå¯èœã§ãªããã°ãªããŸãããæ²³å·ã®é·ãã¯ããŸããŸã§ãããããæ²³å·ãå容ããéžå°ã»ã«ã®æ°ã決å®ããæ²³å·ãã€ã³ãã䜿çšããŠæ²³å·ãå¶åŸ¡ããæ¹ãè«ççã§ããæå€§20ïŒ
ãããã©ã«ãå€10ïŒ
ã®ããŒã»ã³ããŒãžã§ãããã衚çŸããŸãããã寿åžã®å²åãšåæ§ã«ãããã¯ç®æšå€ã§ãããä¿èšŒå€ã§ã¯ãããŸããããã®çµæãé©åãªåå°ãã«ããŒããã«ã¯çãããåè£è
ãå·ãå°ãªãããå¯èœæ§ããããŸãããã®ãããæå€§ããŒã»ã³ããŒãžã¯å€§ããããŠã¯ãããŸããã [Range(0, 20)] public int riverPercentage = 10;
ã¹ã©ã€ããŒããŒã»ã³ãã®å·ãã»ã«ã®æ°ãšããŠè¡šãããæ²³å·ãã€ã³ããæ±ºå®ããã«ã¯ãã§çæãããéžäžã»ã«ã®æ°ãèŠããŠããå¿
èŠããããŸãCreateLand
ã int cellCount, landCells; ⊠void CreateLand () { int landBudget = Mathf.RoundToInt(cellCount * landPercentage * 0.01f); landCells = landBudget; for (int guard = 0; guard < 10000; guard++) { ⊠} if (landBudget > 0) { Debug.LogWarning("Failed to use up " + landBudget + " land budget."); landCells -= landBudget; } }
å
éšã§ã¯ãCreateRivers
ã§è¡ãã®ãšåãæ¹æ³ã§æ²³å·ãã€ã³ãã®æ°ãèšç®ã§ããŸãCreateLand
ã void CreateRivers () { List<HexCell> riverOrigins = ListPool<HexCell>.Get(); for (int i = 0; i < cellCount; i++) { ⊠} int riverBudget = Mathf.RoundToInt(landCells * riverPercentage * 0.01f); ListPool<HexCell>.Add(riverOrigins); }
ããã«ããã€ã³ããšãœãŒã¹ã»ã«ããŸã ããéãå
ã®ãªã¹ãããã©ã³ãã ãªã»ã«ãååŸããã³åé€ãç¶ããŸãããã€ã³ãã®æ°ãå®äºãããšãã³ã³ãœãŒã«ã«èŠåã衚瀺ãããŸãã int riverBudget = Mathf.RoundToInt(landCells * riverPercentage * 0.01f); while (riverBudget > 0 && riverOrigins.Count > 0) { int index = Random.Range(0, riverOrigins.Count); int lastIndex = riverOrigins.Count - 1; HexCell origin = riverOrigins[index]; riverOrigins[index] = riverOrigins[lastIndex]; riverOrigins.RemoveAt(lastIndex); } if (riverBudget > 0) { Debug.LogWarning("Failed to use up river budget."); }
ããã«ãå·ãçŽæ¥äœæããæ¹æ³ã远å ããŸãããã©ã¡ãŒã¿ãŒãšããŠã圌ã¯åæã»ã«ãå¿
èŠã§ãããå®äºåŸãå·ã®é·ããè¿ãå¿
èŠããããŸããé·ããŒããè¿ãã¡ãœãããä¿åããããšããå§ããŸãã int CreateRiver (HexCell origin) { int length = 0; return length; }
ã§è¿œå ãããµã€ã¯ã«ã®æåŸã«ãã®ã¡ãœãããåŒã³åºãCreateRivers
ãæ®ãã®ãã€ã³ãã®æ°ãæžãããŸããéžæããã»ã«ã«å·ãæµããŠããªãå Žåã«ã®ã¿ãæ°ããå·ãäœæãããããã«ããŸãã while (riverBudget > 0 && riverOrigins.Count > 0) { ⊠if (!origin.HasRiver) { riverBudget -= CreateRiver(origin); } }
çŸåšã®å·
æµ·ãŸãã¯ä»ã®æ°Žåã«æµããå·ãäœæããããšã¯è«ççã§ãããœãŒã¹ããéå§ãããšãããã«é·ã1ãååŸãããŸãããã®åŸãã©ã³ãã ãªè¿åãéžæããŠé·ããå¢ãããŸããæ°Žäžã»ã«ã«å°éãããŸã§ç§»åãç¶ããŸãã int CreateRiver (HexCell origin) { int length = 1; HexCell cell = origin; while (!cell.IsUnderwater) { HexDirection direction = (HexDirection)Random.Range(0, 6); cell.SetOutgoingRiver(direction); length += 1; cell = cell.GetNeighbor(direction); } return length; }
ã©ã³ãã ãªå·ããã®ãããªçŽ æŽãªã¢ãããŒãã®çµæãšããŠãäž»ã«ä»¥åã«çæãããå·ã®çœ®ãæãã«ãããã©ã³ãã ã«æ£ãã°ã£ãå·ã®ç ŽçãåŸãããŸããé£äººãå®éã«ååšãããã©ããã確èªããªããããããã¯ãšã©ãŒã«ã€ãªããããšãããããŸãããµã€ã¯ã«ã®ãã¹ãŠã®æ¹åããã§ãã¯ããããã«é£äººãããããšã確èªããå¿
èŠããããŸããããã§ããå Žåããã®æ¹åãæœåšçãªãããŒæ¹åã®ãªã¹ãã«è¿œå ããŸãããããã¯å·ããã®é£ããŸã æµããŠããªãå Žåã®ã¿ã§ããæ¬¡ã«ããã®ãªã¹ãããã©ã³ãã ãªå€ãéžæããŸãã List<HexDirection> flowDirections = new List<HexDirection>(); ⊠int CreateRiver (HexCell origin) { int length = 1; HexCell cell = origin; while (!cell.IsUnderwater) { flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor || neighbor.HasRiver) { continue; } flowDirections.Add(d); } HexDirection direction =
ãã®æ°ããã¢ãããŒãã§ã¯ãå©çšå¯èœãªãããŒæ¹åããŒãã«ãªãå ŽåããããŸãããããçºçãããšãå·ã¯ããä»¥äžæµããããšãã§ããªããªããçµäºããå¿
èŠããããŸãããã®æç¹ã§é·ãã1ã®å Žåãããã¯å
ã®ã»ã«ããæŒããããšãã§ããªãã£ãããšãæå³ããŸããã€ãŸããå·ããŸã£ãããªãå¯èœæ§ããããŸãããã®å Žåãå·ã®é·ãã¯ãŒãã§ãã flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠} if (flowDirections.Count == 0) { return length > 1 ? length : 0; }
ä¿åãããå·ãèµ°ãå»ã
ããã§ãäœææžã¿ã®å·ãä¿åã§ããŸãããå·ã®å€ç«ããæçãååŸã§ããŸããããã¯ãé«ããç¡èŠããŠããããã«çºçããŸããå·ãããé«ãé«ããŸã§åŒ·å¶çã«æµããã³ã«ãHexCell.SetOutgoingRiver
ãã®è©Šã¿ãäžæããå·ã®æè£ã«è³ããŸããããããã£ãŠãå·ãäžã«æµãæ¹åãã¹ãããããå¿
èŠããããŸãã if (!neighbor || neighbor.HasRiver) { continue; } int delta = neighbor.Elevation - cell.Elevation; if (delta > 0) { continue; } flowDirections.Add(d);
æµããå·ããã®ãããå·ã®å€ãã®æçãåãé€ããŸãããããã€ãã¯ãŸã æ®ã£ãŠããŸãããã®ç¬éãããæãmostãå·ãåãé€ãããšã¯æŽç·Žã®åé¡ã«ãªããŸãããããããå·ã¯ã§ããã ãæ©ãæµããããšã奜ã¿ãŸãã圌ãã¯å¿
ãããæçã«ãŒããéžæãããšã¯éããŸãããããã®å¯èœæ§ã¯é«ããªããŸãããããã·ãã¥ã¬ãŒãããããã«ããªã¹ãã«äžæ¹åã3å远å ããŸãã if (delta > 0) { continue; } if (delta < 0) { flowDirections.Add(d); flowDirections.Add(d); flowDirections.Add(d); } flowDirections.Add(d);
æ¥ã«ãŒããé¿ãã
æµäžã«å ããŠãæ°Žã«ãæ
£æ§ããããŸããå·ã¯ãæ¥ã«æ¥ã«æ²ãããããããŸã£ããã«æµãããããããã«æ²ããåŸåããããŸããå·ã®æåŸã®æ¹åã远跡ããããšã§ããã®æªã¿ã远å ã§ããŸãã黿µã®æœåšçãªæ¹åããã®æ¹åãã倧ããéžè±ããŠããªãå Žåã¯ããªã¹ãã«å床远å ããŸããããã¯ãœãŒã¹ã«ãšã£ãŠåé¡ã§ã¯ãªããããåžžã«è¿œå ãçŽããŸãã int CreateRiver (HexCell origin) { int length = 1; HexCell cell = origin; HexDirection direction = HexDirection.NE; while (!cell.IsUnderwater) { flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠if (delta < 0) { flowDirections.Add(d); flowDirections.Add(d); flowDirections.Add(d); } if ( length == 1 || (d != direction.Next2() && d != direction.Previous2()) ) { flowDirections.Add(d); } flowDirections.Add(d); } if (flowDirections.Count == 0) { return length > 1 ? length : 0; }
ããã«ãããå·ããžã°ã¶ã°ã«èŠããå¯èœæ§ã倧å¹
ã«äœäžããŸããæ¥æåãå°ãªããæ²³å·åæµç¹
å·ã¯ã以åã«äœæãããå·ã®æ°Žæºã®ããé£ãæµããããšããããŸãããã®å·ã®æ°Žæºãããé«ãé«åºŠã«ãªãå Žåãæ°ããå·ãå€ãå·ã«æµã蟌ããšå€æã§ããŸãããã®çµæã2ã€ã®é£æ¥ããå·ã§ã¯ãªãã1ã€ã®é·ãå·ãåŸãããŸãããããè¡ãã«ã¯ãå
¥ã£ãŠããå·ãããå ŽåããŸãã¯çŸåšã®å·ã®æ°Žæºã§ããå Žåã«ã®ã¿ãé£äººãééãããŸãããã®æ¹åãäžåããŠããªããšå€æãããããå€åãã®å·ããããã©ããã確èªããŸããããããã°ãåã³å€ãå·ãèŠã€ããŸãããããã¯ãã£ãã«èµ·ãããªãã®ã§ãä»ã®è¿é£ã®æ°Žââæºããã§ãã¯ããããšã¯ãããããã«å·ãåæµãããŸãã HexCell neighbor = cell.GetNeighbor(d);
ããŒã«ã®ååŸã®å·ãè·é¢ãä¿ã€
ãœãŒã¹ããŒã«ã®é©åãªåè£è
ã¯éåžžäžç·ã«ã°ã«ãŒãåããããããå·ã®ã¯ã©ã¹ã¿ãŒãååŸããŸããããã«ãè²¯æ°Žæ± ã®ããè¿ãã§æ°Žæºããšãå·ããããé·ã1ã®å·ãã§ããŸããæ°Žæºãåé
ããŠãå·ãŸãã¯è²¯æ°Žæ± ã«é£æ¥ããæ°ŽãæšãŠãããšãã§ããŸããç§ãã¡ã¯ãããå
éšã®ã«ãŒãã§éžæããããœãŒã¹ã®é£äººããã€ãã¹ããŸãCreateRivers
ãã«ãŒã«ã«éåããŠããé£äººãèŠã€ããå ŽåããœãŒã¹ã¯ç§ãã¡ã«åãããã¹ãããããå¿
èŠããããŸãã while (riverBudget > 0 && riverOrigins.Count > 0) { int index = Random.Range(0, riverOrigins.Count); int lastIndex = riverOrigins.Count - 1; HexCell origin = riverOrigins[index]; riverOrigins[index] = riverOrigins[lastIndex]; riverOrigins.RemoveAt(lastIndex); if (!origin.HasRiver) { bool isValidOrigin = true; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = origin.GetNeighbor(d); if (neighbor && (neighbor.HasRiver || neighbor.IsUnderwater)) { isValidOrigin = false; break; } } if (isValidOrigin) { riverBudget -= CreateRiver(origin); } }
ãŸããå·ã¯çžæ¬¡ãã§æµããããããåºãå°åãã«ããŒããåŸåããããè·é¢ãªãã§ãããšãå·ãæ¹ã§çµãããã
ãã¹ãŠã®å·ãè²¯æ°Žæ± ã«å°éããããã§ã¯ãªããæžè°·ã§åããªããªã£ãããä»ã®å·ã«é»ãŸãããããŸããå€ãã®å Žåãå®éã®å·ãæ¶ããŠããããã«èŠãããããããã¯ç¹ã«åé¡ã§ã¯ãããŸãããããã¯ãããšãã°ãå°äžã«æµããããæ¹¿å°ã«åæ£ãããã也ç¥ãããããå Žåã«çºçããå¯èœæ§ããããŸããç§ãã¡ã®å·ã¯ãããèŠèŠåã§ããªããããåçŽã«çµãããŸãããã ãããã®ãããªã±ãŒã¹ã®æ°ãæå°éã«æããããšã詊ã¿ãããšãã§ããŸããå·ãåæµãããããå·ãäžã«æµãããããããšã¯ã§ããŸããããå®éã«ã¯ããèŠãããæ¹ã§çµããããã«ããããšã¯ã§ããŸãããã®ããã«CreateRiver
åããªããªã£ãå Žåãã»ã«å
ã®æ°Žäœãäžããå¿
èŠããããŸãããã®å¯èœæ§ã¯ããã®ã»ã«ã®è¿é£ã®æå°é«ãã«äŸåããŸãããããã£ãŠãè¿é£ã調æ»ãããšãã«ããã远跡ããã«ã¯ãã³ãŒããå°ã倿Žããå¿
èŠããããŸãã while (!cell.IsUnderwater) { int minNeighborElevation = int.MaxValue; flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d);
ç«ã¡åŸçããŠããå Žåã¯ããŸãããŸã ãœãŒã¹ã«ãããã©ããã確èªããå¿
èŠããããŸããã¯ãã®å ŽåããªããŒããã£ã³ã»ã«ããŸãããã以å€ã®å Žåããã¹ãŠã®é£æ¥ã»ã«ãå°ãªããšãçŸåšã®ã»ã«ãšåããã©ããã確èªããŸãããããããªãããã®ã¬ãã«ãŸã§æ°Žãäžããããšãã§ããŸããããã«ãããã»ã«ã®é«ããåãã¬ãã«ã®ãŸãŸã§ãªãéãã1ã€ã®ã»ã«ããæ¹ãäœæãããŸãããã®å ŽåãåçŽã«æ°Žäœãã1ã¬ãã«äžã®é«ããå²ãåœãŠãŸãã if (flowDirections.Count == 0) {
æ¹ã®ãªãå·ãšæ¹ã®ããå·ã®ç«¯ããã®å Žåãå·ã®å²åã¯20ã§ããããããçæããããã«äœ¿çšãããæ°Žäœãè¶
ããæ°Žäžã»ã«ãããå Žåãããããšã«æ³šæããŠãã ããã圌ãã¯æµ·æã®æ¹ã瀺ããŸãã远å ã®æ¹
ç«ã¡åŸçããŠããªãå Žåã§ããæ¹ãäœæããããšãã§ããŸããããã«ãããå·ãæ¹ã«åºå
¥ãããå¯èœæ§ããããŸããç«ã¡åŸçããŠããªãå Žåãæ¹ãäœæããã«ã¯ãæ°ŽäœãäžããŠããçŸåšã®ã»ã«ã®é«ããäžããã»ã«ã®é«ããäžããŸããããã¯ãè¿é£ã®æå°é«ããå°ãªããšãçŸåšã®ã»ã«ã®é«ãã«çããå Žåã«ã®ã¿é©çšãããŸããããã¯ãå·ã®ãµã€ã¯ã«ã®çµããã«ã次ã®ã»ã«ã«é²ãåã«è¡ããŸãã while (!cell.IsUnderwater) { ⊠if (minNeighborElevation >= cell.Elevation) { cell.WaterLevel = cell.Elevation; cell.Elevation -= 1; } cell = cell.GetNeighbor(direction); }
远å ã®æ¹ãªãã§ãããããšå
±ã«ãããã€ãã®æ¹ã¯çŸããã§ãããç¡å¶éã«å€ãã®æ¹ãäœæã§ããŸãããããã£ãŠã远å ã®æ¹ã®ã«ã¹ã¿ã 確çã远å ããããã©ã«ãå€ã0.25ã«ããŸãã [Range(0f, 1f)] public float extraLakeProbability = 0.25f;
å¯èœã§ããã°ã圌女ã¯è¿œå ã®æ¹ãçæããå¯èœæ§ãå¶åŸ¡ããŸãã if ( minNeighborElevation >= cell.Elevation && Random.value < extraLakeProbability ) { cell.WaterLevel = cell.Elevation; cell.Elevation -= 1; }
远å ã®æ¹ãè€æ°ã®ã»ã«ãæã€æ¹ãäœæããã®ã¯ã©ãã§ããïŒ, , , . . : . , . , , , .
ãŠããã£ããã±ãŒãžæž©åºŠ
æ°Žã¯çްèã®ãã€ãªãŒã ãæ±ºå®ã§ããèŠå ã®1ã€ã«ãããŸããããã1ã€ã®éèŠãªèŠçŽ ã¯æž©åºŠã§ããæ°Žã®ã·ãã¥ã¬ãŒã·ã§ã³ã®ããã«æž©åºŠã®æµããšæ¡æ£ãã·ãã¥ã¬ãŒãã§ããŸãããè峿·±ãæ°åãäœæããã«ã¯ã1ã€ã®è€éãªèŠçŽ ã®ã¿ãå¿
èŠã§ãããããã£ãŠã枩床ãåçŽã«ä¿ã¡ãåã»ã«ã«èšå®ããŠã¿ãŸããããæž©åºŠãšç·¯åºŠ
枩床ã«å¯Ÿããæå€§ã®åœ±é¿ã¯ç·¯åºŠã§ããèµ€éã§ã¯æããæ¥µã§ã¯å¯ãã䞡極ã®éã¯ã¹ã ãŒãºã«ç§»è¡ããŸããDetermineTemperature
ç¹å®ã®ã»ã«ã®æž©åºŠãè¿ãã¡ãœãããäœæããŸããããéå§ããã«ã¯ãã»ã«ã®Z座æšã次å
Zã§é€ç®ããŠç·¯åºŠãšããŠäœ¿çšãããã®å€ã枩床ãšããŠäœ¿çšããŸãã float DetermineTemperature (HexCell cell) { float latitude = (float)cell.coordinates.Z / grid.cellCountZ; return latitude; }
枩床ãå®çŸ©ããSetTerrainType
ãããããŒã¿ãšããŠäœ¿çšããŸãã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); float temperature = DetermineTemperature(cell); cell.SetMapData(temperature); float moisture = climate[i].moisture; ⊠} }
枩床ãšããŠã®ç·¯åºŠãååçãäžããäžã«åãã£ãŠç·åœ¢ã®æž©åºŠåŸé
ãå¢å ããŸããããã䜿çšããŠãååçãã·ãã¥ã¬ãŒãããäžéšã«æ¥µããäžéšã«èµ€éãé
眮ã§ããŸããããããåçå
šäœãèšè¿°ããå¿
èŠã¯ãããŸãããæž©åºŠå·®ãå°ãããããŸã£ããå·®ããªãå Žåãé¢ç©ãå°ããããããšãã§ããŸãããããè¡ãããã«ãäœæž©ãšé«æž©ãã«ã¹ã¿ãã€ãºå¯èœã«ããŸãããããã®æž©åºŠã0ã1ã®ç¯å²ã§èšå®ããæ¥µå€ãããã©ã«ãå€ãšããŠäœ¿çšããŸãã [Range(0f, 1f)] public float lowTemperature = 0f; [Range(0f, 1f)] public float highTemperature = 1f;
枩床ã¹ã©ã€ããŒãè£éåšãšããŠç·¯åºŠã䜿çšããŠãç·åœ¢è£éã䜿çšããŠæž©åºŠç¯å²ãé©çšããŸãã緯床ã¯0ãã1ãŸã§ã®å€ãšããŠè¡šããããããã䜿çšã§ããŸãMathf.LerpUnclamped
ã float DetermineTemperature (HexCell cell) { float latitude = (float)cell.coordinates.Z / grid.cellCountZ; float temperature = Mathf.LerpUnclamped(lowTemperature, highTemperature, latitude); return temperature; }
äœæž©ã¯å¿
ããã髿ž©ããäœãããã§ã¯ãªãããšã«æ³šæããŠãã ãããå¿
èŠã«å¿ããŠãããããè£è¿ãããšãã§ããŸããåç
ããã§ã枩床ãåããšååçãããããååçãã·ãã¥ã¬ãŒãã§ããŸãããã ããåçéãåãæ¿ããã«ã¯å¥ã®èšå®ãªãã·ã§ã³ã䜿çšããæ¹ãã¯ããã«äŸ¿å©ã§ããåæãšãã®ãã£ãŒã«ããäœæããŸãããããããã£ãŠãäž¡æ¹ã®åçãäœæãããªãã·ã§ã³ã远å ããŸããããã¯ããã©ã«ãã§é©çšå¯èœã§ãã public enum HemisphereMode { Both, North, South } public HemisphereMode hemisphere;
åçã®éžæãååçãå¿
èŠãªå Žåã¯ã1ããæžç®ããããšã§ç·¯åºŠãåçŽã«å転ã§ããŸããäž¡æ¹ã®åçãã·ãã¥ã¬ãŒãããã«ã¯ã極ãå°å³ã®äžäžã«ãèµ€éãäžå€®ã«é
眮ããå¿
èŠããããŸãããããè¡ãã«ã¯ã緯床ã2åã«ããŸããäžåçã¯æ£ããåŠçãããäžã®åçã¯1ã2ã®ç·¯åºŠã«ãªããŸãããããä¿®æ£ããã«ã¯ã1ãè¶
ãããš2ãã緯床ãåŒããŸãã float DetermineTemperature (HexCell cell) { float latitude = (float)cell.coordinates.Z / grid.cellCountZ; if (hemisphere == HemisphereMode.Both) { latitude *= 2f; if (latitude > 1f) { latitude = 2f - latitude; } } else if (hemisphere == HemisphereMode.North) { latitude = 1f - latitude; } float temperature = Mathf.LerpUnclamped(lowTemperature, highTemperature, latitude); return temperature; }
äž¡æ¹ã®åçãããã«ãããèµ€éãå¯ããæ¥µãæããããšããŸããã¯ãªããããäœæã§ããå¯èœæ§ãçãŸããŸããå¯ãã»ã©é«ã
緯床ã«å ããŠã枩床ãé«åºŠã«ãã£ãŠå€§ãã圱é¿ãããŸããå¹³åããŠãç»ãã»ã©å¯ããªããŸããæ²³å·åè£ã§è¡ã£ãããã«ããããèŠå ã«å€ããããšãã§ããŸãããã®å Žåãã»ã«ã®é«ãã䜿çšããŸããããã«ããã®ã€ã³ãžã±ãŒã¿ã¯é«ããšãšãã«æžå°ããŸããã€ãŸãã1ããé«ããæ°Žäœã«å¯Ÿããæå€§å€ã§å²ã£ãå€ã«çãããªããŸããæé«ã¬ãã«ã®ã€ã³ãžã±ãŒã¿ãŒããŒãã«ãªããªãããã«ã逿°ã«è¿œå ããŸããæ¬¡ã«ããã®ã€ã³ãžã±ãŒã¿ã䜿çšããŠæž©åºŠãã¹ã±ãŒãªã³ã°ããŸãã float temperature = Mathf.LerpUnclamped(lowTemperature, highTemperature, latitude); temperature *= 1f - (cell.ViewElevation - waterLevel) / (elevationMaximum - waterLevel + 1f); return temperature;
é«ãã¯æž©åºŠã«åœ±é¿ããŸããæž©åºŠå€å
ã©ã³ãã ãªæž©åºŠå€åã远å ããããšã§ã枩床åŸé
ã®åçŽããç®ç«ããªãããããšãã§ããŸããããçŸå®çã«ããããã®å°ããªãã£ã³ã¹ã§ãããå€åã倧ãããããšã圌ãã¯arbitraryæçã«èŠããŸããæž©åºŠå€åã®åãã«ã¹ã¿ãã€ãºå¯èœã«ããŠãããã©ã«ãå€0.1ã§æå€§æž©åºŠåå·®ãšããŠè¡šçŸããŠã¿ãŸãããã [Range(0f, 1f)] public float temperatureJitter = 0.1f;
枩床å€åã¹ã©ã€ããŒããã®ãããªå€åã¯ã屿çãªå€åãã»ãšãã©ãªããæ»ããã§ãªããã°ãªããŸãããããã«ã¯ãã€ãºãã¯ã¹ãã£ã䜿çšã§ããŸããHexMetrics.SampleNoise
0.1ã§ã¹ã±ãŒãªã³ã°ãããã»ã«äœçœ®ãåŒã³åºããŠäœ¿çšããŸãããã£ã³ãã«Wãåããäžå€®ã«é
眮ããæ¯åä¿æ°ã§ã¹ã±ãŒãªã³ã°ããŸããæ¬¡ã«ããã®å€ã以åã«èšç®ãããæž©åºŠã«è¿œå ããŸãã temperature *= 1f - (cell.ViewElevation - waterLevel) / (elevationMaximum - waterLevel + 1f); temperature += (HexMetrics.SampleNoise(cell.Position * 0.1f).w * 2f - 1f) * temperatureJitter; return temperature;
0.1ãš1ã®å€ã®æž©åºŠå€åã4ã€ã®ãã€ãºãã£ãã«ããã©ã³ãã ã«éžæããŠãåãããã®å€åã«ããããªå€åæ§ã远å ã§ããŸãããã£ã³ãã«ãäžåºŠã«èšå®ããŠããSetTerrainType
ãã«ã©ãŒãã£ã³ãã«ã®ã€ã³ããã¯ã¹ãäœæããŸãDetermineTemperature
ã int temperatureJitterChannel; ⊠void SetTerrainType () { temperatureJitterChannel = Random.Range(0, 4); for (int i = 0; i < cellCount; i++) { ⊠} } float DetermineTemperature (HexCell cell) { ⊠float jitter = HexMetrics.SampleNoise(cell.Position * 0.1f)[temperatureJitterChannel]; temperature += (jitter * 2f - 1f) * temperatureJitter; return temperature; }
æå€§ã®åã§ç°ãªã枩床å€åããŠããã£ããã±ãŒãžãã€ãªãŒã
æ¹¿åºŠãšæž©åºŠã«é¢ããããŒã¿ãåŸãããã®ã§ããã€ãªãŒã ãããªãã¯ã¹ãäœæã§ããŸãããã®ãããªãã¯ã¹ã«ã€ã³ããã¯ã¹ãä»ããããšã«ããããã€ãªãŒã ããã¹ãŠã®ã»ã«ã«å²ãåœãŠã1ã€ã®ããŒã¿ãã£ã¡ã³ã·ã§ã³ã®ã¿ã䜿çšãããããè€éãªã©ã³ãã¹ã±ãŒããäœæã§ããŸãããã€ãªãŒã ãããªãã¯ã¹
æ°åã¢ãã«ã¯å€æ°ãããŸããããããã䜿çšããŸãããç§ãã¡ã¯ãããéåžžã«åçŽã«ããŸããç§ãã¡ã¯ããžãã¯ã«ã®ã¿èå³ããããŸãã也ç¥ãšã¯ç æŒ ïŒå¯ããŸãã¯æãïŒãæå³ããç ã䜿çšããŸããå¯ããŠæ¿¡ããŠãããšã¯éªãæå³ããŸãã髿ž©å€æ¹¿ãšã¯ãå€ãã®æ€ç©ãã€ãŸãèãæå³ããŸãããããã®éã«ãã¿ã€ã¬ãŸãã¯ãã³ãã©ããããŸããããã¯ãå°çã®ç°è²ããã£ããã¯ã¹ãã£ãšããŠæå®ããŸãããããã®ãã€ãªãŒã éã®ç§»è¡ãäœæããã«ã¯ã4x4ãããªãã¯ã¹ã§ååã§ãã以åã¯ã5ã€ã®æ°Žåééã«åºã¥ããŠã¬ãªãŒãã¿ã€ããå²ãåœãŠãŸãããæã也ç¥ããã¹ããªããã0.05ãŸã§äžããæ®ããä¿åããŸããæž©åºŠåž¯åã«ã¯ã0.1ã0.3ã0.6以äžã䜿çšããŸãã䟿å®äžããããã®å€ãéçé
åã«èšå®ããŸãã static float[] temperatureBands = { 0.1f, 0.3f, 0.6f }; static float[] moistureBands = { 0.12f, 0.28f, 0.85f };
ãã€ãªãŒã ã«åºã¥ããŠã¬ãªãŒãã¿ã€ãã®ã¿ãæå®ããŸãããããã䜿çšããŠä»ã®ãã©ã¡ãŒã¿ãŒã決å®ã§ããŸãããããã£ãŠãåã
ã®ãã€ãªãŒã ã®æ§æãèšè¿°ããHexMapGenerator
æ§é Biome
ã§å®çŸ©ããŸãããããããŸã§ã®ãšããããã³ãã€ã³ããã¯ã¹ãšå¯Ÿå¿ããã³ã³ã¹ãã©ã¯ã¿ãŒã¡ãœããã®ã¿ãå«ãŸããŠããŸãã struct Biome { public int terrain; public Biome (int terrain) { this.terrain = terrain; } }
ãã®æ§é ã䜿çšããŠãè¡åããŒã¿ãå«ãéçé
åãäœæããŸããX座æšãšããŠæ¹¿åºŠã䜿çšããYãšããŠæž©åºŠã䜿çšããŸããæãäœã枩床ã®ã©ã€ã³ãéªã§ã2çªç®ã®ã©ã€ã³ããã³ãã©ã§ãä»ã®2ã€ãèã§åããŸããæ¬¡ã«ãæã也ç¥ããæ±ãç æŒ ã«çœ®ãæããŠã枩床ã®éžæãåå®çŸ©ããŸãã static Biome[] biomes = { new Biome(0), new Biome(4), new Biome(4), new Biome(4), new Biome(0), new Biome(2), new Biome(2), new Biome(2), new Biome(0), new Biome(1), new Biome(1), new Biome(1), new Biome(0), new Biome(1), new Biome(1), new Biome(1) };
1次å
é
åã®ã€ã³ããã¯ã¹ãæã€ãã€ãªãŒã ã®ãããªãã¯ã¹ããã€ãªãŒã ã®å®çŸ©
SetTerrainType
ãã€ãªãŒã å
ã®çްèãæ±ºå®ããã«ã¯ããµã€ã¯ã«å
ã®æž©åºŠãšæ¹¿åºŠã®ç¯å²ã調ã¹ãŠãå¿
èŠãªãããªãã¯ã¹ã€ã³ããã¯ã¹ã決å®ããŸãããããã䜿çšããŠãç®çã®ãã€ãªãŒã ãååŸãã现èããã°ã©ãã£ãŒã®ã¿ã€ããæå®ããŸãã void SetTerrainType () { temperatureJitterChannel = Random.Range(0, 4); for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); float temperature = DetermineTemperature(cell);
ãã€ãªãŒã ãããªãã¯ã¹ã«åºã¥ãææžããã€ãªãŒã ã®ã»ããã¢ãã
ãããªãã¯ã¹ã§å®çŸ©ããããã€ãªãŒã ãè¶
ããããšãã§ããŸããããšãã°ããããªãã¯ã¹ã§ã¯ããã¹ãŠã®ä¹Ÿç¥ãã€ãªãŒã ã¯ç ç æŒ ãšããŠå®çŸ©ãããŠããŸããããã¹ãŠã®ä¹Ÿç¥ç æŒ ãç ã§æºããããŠããããã§ã¯ãããŸãããéåžžã«ç°ãªã£ãŠèŠããå€ãã®å²©ãå€ãç æŒ ããããŸããããã§ã¯ãç æŒ ã®ã»ã«ã®äžéšãç³ã§çœ®ãæããŸããããããã¯åã«é«ãã«åºã¥ããŠè¡ããŸããç ã¯æšé«ãäœããéåžžã¯è£žã®å²©ãäžã«ãããŸããã»ã«ã®é«ããæ°Žäœãããæå€§ã®é«ãã«è¿ããšãã«ãç ãç³ã«å€ãããšä»®å®ããŸããããã¯æåã«èšç®ã§ãã岩ã®å€ãç æŒ ã®é«ãã®ç·ã§ãSetTerrainType
ãã»ã«ãç ã§æºãããããã®é«ããååã«å€§ããå Žåããã€ãªãŒã ã®ã¬ãªãŒããç³ã«å€æŽããŸãã void SetTerrainType () { temperatureJitterChannel = Random.Range(0, 4); int rockDesertElevation = elevationMaximum - (elevationMaximum - waterLevel) / 2; for (int i = 0; i < cellCount; i++) { ⊠if (!cell.IsUnderwater) { ⊠Biome cellBiome = biomes[t * 4 + m]; if (cellBiome.terrain == 0) { if (cell.Elevation >= rockDesertElevation) { cellBiome.terrain = 3; } } cell.TerrainTypeIndex = cellBiome.terrain; } else { cell.TerrainTypeIndex = 2; } } }
ç ãšå²©ã®ç æŒ ãé«ãã«åºã¥ãå¥ã®å€æŽã¯ã枩床ã«é¢ä¿ãªãã也ç¥ããããŠããªãå Žåã«ã®ã¿ãæå€§ã®é«ãã®ã»ã«ã匷å¶çã«éªã®ããŒã¯ã«å€ããããšã§ããããã«ããã髿ž©å€æ¹¿ã®èµ€éä»è¿ã§éªãããŒã¯ã«ãªãå¯èœæ§ãé«ããªããŸãã if (cellBiome.terrain == 0) { if (cell.Elevation >= rockDesertElevation) { cellBiome.terrain = 3; } } else if (cell.Elevation == elevationMaximum) { cellBiome.terrain = 4; }
æå€§é«ãã®éªã®ãã£ãããæ€ç©
ããã§ã¯ããã€ãªãŒã ã«æ€ç©çްèã®ã¬ãã«ã決å®ãããŸãããããããè¡ãã«ã¯Biome
ãæ€ç©ã®ãã£ãŒã«ãã«è¿œå ããã³ã³ã¹ãã©ã¯ã¿ãŒã«å«ããŸãã struct Biome { public int terrain, plant; public Biome (int terrain, int plant) { this.terrain = terrain; this.plant = plant; } }
æãå¯ããŠä¹Ÿç¥ãããã€ãªãŒã ã§ã¯ãæ€ç©ã¯ãŸã£ãããããŸãããä»ã®ãã¹ãŠã®ç¹ã§ã¯ãæ°åãæããæ¹¿ã£ãŠããã»ã©ãæ€ç©ãå¢ããŸããæ¹¿åºŠã®2çªç®ã®åã¯ãæãç±ãè¡ã®æ€ç©ã®æåã®ã¬ãã«ã®ã¿ãåãåãããã[0ã0ã0ã1]ã§ãã3åç®ã¯ãéªãé€ããŠã¬ãã«ã1ã€å¢ãããŸããã€ãŸãã[0ã1ã1ã2]ã§ãããããŠãæãæ¿¡ããåãåã³ããããå¢ãããŸããã€ãŸãã[0ã2ã2ã3]ã«ãªããŸããbiomes
ãã©ã³ãæ§æã远å ããŠã¢ã¬ã€ã倿ŽããŸãã static Biome[] biomes = { new Biome(0, 0), new Biome(4, 0), new Biome(4, 0), new Biome(4, 0), new Biome(0, 0), new Biome(2, 0), new Biome(2, 1), new Biome(2, 2), new Biome(0, 0), new Biome(1, 0), new Biome(1, 1), new Biome(1, 2), new Biome(0, 0), new Biome(1, 1), new Biome(1, 2), new Biome(1, 3) };
æ€ç©ã¬ãã«ã®ãã€ãªãŒã ã®ãããªãã¯ã¹ãããã§ãã»ã«ã®æ€ç©ã®ã¬ãã«ãèšå®ã§ããŸãã cell.TerrainTypeIndex = cellBiome.terrain; cell.PlantLevel = cellBiome.plant;
æ€ç©ã®ãããã€ãªãŒã ãæ€ç©ã¯ä»ã§ã¯ç°ãªã£ãŠèŠããŸããïŒ, . (1, 2, 1) (0.75, 1, 0.75). (1.5, 3, 1.5) (2, 1.5, 2). â (2, 4.5, 2) (2.5, 3, 2.5).
, : (13, 114, 0).
ãã€ãªãŒã ã®æ€ç©ã®ã¬ãã«ã倿Žã§ããŸãããŸããéªã®å°åœ¢ã«ãããã衚瀺ãããªãããã«ããå¿
èŠããããŸããããã¯æ¢ã«èšå®ã§ããŸãã第äºã«ããŸã æå€§å€ã«ãªã£ãŠããªãå Žåã¯ãå·æ²¿ãã®æ€ç©ã®ã¬ãã«ãäžããŸãããã if (cellBiome.terrain == 4) { cellBiome.plant = 0; } else if (cellBiome.plant < 3 && cell.HasRiver) { cellBiome.plant += 1; } cell.TerrainTypeIndex = cellBiome.terrain; cell.PlantLevel = cellBiome.plant;
倿Žãããæ€ç©ãæ°Žäžãã€ãªãŒã
ãã®ç¬éãŸã§ãç§ãã¡ã¯æ°Žäžã®çްèãå®å
šã«ç¡èŠããŸããããããã«å°ãã®ããªãšãŒã·ã§ã³ã远å ããŸããããããããã¹ãŠã«å°çã®ãã¯ã¹ãã£ã䜿çšããããã§ã¯ãããŸãããé«ããåºã«ããåçŽãªãœãªã¥ãŒã·ã§ã³ã¯ãããè峿·±ãç»åãäœæããã®ã«ååã§ããããšãã°ãæ°Žäœã®1ã€äžã®ã»ã«ã«èã䜿çšããŠã¿ãŸãããããŸããæ°Žäœããäžã®ã»ã«ãã€ãŸãå·ã«ãã£ãŠäœãããæ¹ã«ãèã䜿çšããŸããããè² ã®é«ãã®ã»ã«ã¯æ·±æµ·åã§ãããããç³ã䜿çšããŸããä»ã®ãã¹ãŠã®ã»ã«ã¯æ¥å°ããããŸãŸã§ãã void SetTerrainType () { ⊠if (!cell.IsUnderwater) { ⊠} else { int terrain; if (cell.Elevation == waterLevel - 1) { terrain = 1; } else if (cell.Elevation >= waterLevel) { terrain = 1; } else if (cell.Elevation < 0) { terrain = 3; } else { terrain = 2; } cell.TerrainTypeIndex = terrain; } } }
æ°Žäžå€åãæµ·å²žæ²¿ãã®æ°Žäžã»ã«ã®è©³çްã远å ããŸãããããããã¯ãæ°Žäžã«å°ãªããšã1ã€ã®é£æ¥ã»ã«ãæã€ã»ã«ã§ãããã®ãããªã»ã«ãæµ
ãå Žåã¯ãããŒããäœæããŸããåŽã®é£ã«ããå Žåã¯ãèŠèŠçãªãã£ããŒã«ãæ¯é
çã«ãªããç³ã䜿çšããŸããããã倿ããããã«ãæ°Žäœã®1ã€äžã®ã»ã«ã«é£æ¥ããã»ã«ããã§ãã¯ããŸãã飿¥ããéžã®ã»ã«ãšã®åŽãæé¢ã«ããæ¥ç¶ã®æ°ãæ°ããŸãããã if (cell.Elevation == waterLevel - 1) { int cliffs = 0, slopes = 0; for ( HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++ ) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } int delta = neighbor.Elevation - cell.WaterLevel; if (delta == 0) { slopes += 1; } else if (delta > 0) { cliffs += 1; } } terrain = 1; }
ããã§ããã®æ
å ±ã䜿çšããŠã»ã«ãåé¡ã§ããŸãããŸããé£äººã®åå以äžãåå°ã§ããå Žåãæ¹ãŸãã¯æ¹Ÿãæ±ã£ãŠããŸãããããã®ã»ã«ã«ã¯ãèã®ãã¯ã¹ãã£ã䜿çšããŸãããã以å€ã®å ŽåãåŽãããå Žåã¯ãç³ã䜿çšããŸãããã以å€ã®å Žåãæé¢ãããå Žåã¯ãç ã䜿çšããŠããŒããäœæããŸããæ®ã£ãŠããå¯äžã®ãªãã·ã§ã³ã¯ã海岞ããé¢ããæµ
ããšãªã¢ã§ãããã«ã¯ãŸã èã䜿çšããŠããŸãã if (cell.Elevation == waterLevel - 1) { int cliffs = 0, slopes = 0; for ( HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++ ) { ⊠} if (cliffs + slopes > 3) { terrain = 1; } else if (cliffs > 0) { terrain = 3; } else if (slopes > 0) { terrain = 0; } else { terrain = 1; } }
海岞ã®å€åãæåŸã«ãæãå¯ã枩床ç¯å²ã«ç·è²ã®æ°Žäžã»ã«ããªãããšã確èªããŸãããããã®ãããªçްèã«ã¯ãå°çã䜿çšããŸãã if (terrain == 1 && temperature < temperatureBands[0]) { terrain = 2; } cell.TerrainTypeIndex = terrain;
å€ãã®èšå®ãªãã·ã§ã³ãåãããéåžžã«è峿·±ãèªç¶ã«èŠããã©ã³ãã ã«ãŒããçæããæ©äŒãåŸãŸããããŠããã£ããã±ãŒãžããŒã27ïŒã«ãŒãã®æãããã¿
- ã«ãŒããç§»åå¯èœãªåã«åå²ããŸãã
- ã«ãŒããã«ã¡ã©ã®äžå€®ã«çœ®ããŸãã
- ç§ãã¡ã¯ãã¹ãŠã厩å£ãããŸãã
ãã®æåŸã®éšåã§ã¯ãå°å³ãæå°åããæ±ç«¯ãšè¥¿ç«¯ãæ¥ç¶ããããã®ãµããŒãã远å ããŸãããã¥ãŒããªã¢ã«ã¯Unity 2017.3.0p3ã䜿çšããŠäœæãããŸãããæãç³ãããšã§ãäžçãäžåšã§ããŸããæãããã¿ã«ãŒã
ãããã䜿çšããŠãããŸããŸãªãµã€ãºã®ãšãªã¢ãã¢ãã«åã§ããŸããããããã¯åžžã«é·æ¹åœ¢ã«å¶éãããŸããææå
šäœã§ã¯ãªãã1ã€ã®å³¶ãŸãã¯å€§éžå
šäœã®å°å³ãäœæã§ããŸããææã¯ç圢ã§ã衚é¢ã®åââãã劚ããåäœã®å¢çã¯ãããŸãããäžæ¹åã«ç§»åãç¶ãããšãé
ããæ©ããéå§ç¹ã«æ»ããŸããçã®åšãã«å
è§åœ¢ã®ã°ãªãããã©ããããããšã¯ã§ããŸãã;ãã®ãããªãªãŒããŒã©ããã¯äžå¯èœã§ããæè¯ã®è¿äŒŒã§ã¯ã12åã®ã»ã«ãäºè§åœ¢ã§ãªããã°ãªããªãæ£äºåé¢äœããããžãŒã䜿çšãããŸãããã ããæªã¿ãäŸå€ãªãã§ãã¡ãã·ã¥ãåæ±ã«å·»ãä»ããããšãã§ããŸãããããè¡ãã«ã¯ããããã®æ±ç«¯ãšè¥¿ç«¯ãæ¥ç¶ããã ãã§ããã©ããã³ã°ããžãã¯ãé€ããä»ã®ãã¹ãŠã¯åããŸãŸã§ããåæ±ã¯çã®è²§åŒ±ãªè¿äŒŒã§ããæ¥µãã¢ãã«åã§ããªãããã§ããããããããã¯å€ãã®ã²ãŒã ã®éçºè
ãæ±ãã西ãžã®æãããã¿ã䜿çšããŠææå°å³ãã¢ãã«åããããšãæ¢ããŸããã§ãããæ¥µå°ã¯åã«ã²ãŒã ãŸãŒã³ã®äžéšã§ã¯ãããŸãããåãšåã«æ²ãã£ãŠã¿ãŠã¯ãããã§ããïŒ, . , , . -, -. .
åçåœ¢ã®æãããã¿ãå®è£
ããã«ã¯ã2ã€ã®æ¹æ³ããããŸããæåã®æ¹æ³ã¯ãå®éã«ãã®è¡šé¢ãšãã®äžã®ãã¹ãŠãæ²ããŠå°å³ãåç圢ã«ããæ±ãšè¥¿ã®ãšããžãæ¥è§Šããããã«ããããšã§ããä»ãããªãã¯å¹³ããªè¡šé¢ã§ã¯ãªããå®éã®ã·ãªã³ããŒã§ãã¬ãŒããŸãã2çªç®ã®ã¢ãããŒãã¯ããã©ããããããä¿åãããã¬ããŒããŒã·ã§ã³ãŸãã¯è€è£œã䜿çšããŠæããããããšã§ããã»ãšãã©ã®ã²ãŒã ã¯2çªç®ã®ã¢ãããŒãã䜿çšããããããããæ¡çšããŸãããªãã·ã§ã³ã®æãããã¿
ããããæããããå¿
èŠããããã©ããã¯ããã®ã¹ã±ãŒã«ïŒããŒã«ã«ãŸãã¯ææïŒã«ãã£ãŠç°ãªããŸããæãããã¿ããªãã·ã§ã³ã«ããããšã§ãäž¡æ¹ã®ãµããŒãã䜿çšã§ããŸãããããè¡ãã«ã¯ãããã©ã«ãã§æãããã¿ããªã³ã«ãªã£ãç¶æ
ã§[ æ°ãããããã®äœæ ]ã¡ãã¥ãŒã«æ°ããã¹ã€ããã远å ããŸããæãããã¿ãªãã·ã§ã³ãåããæ°ãããããã®ã¡ãã¥ãŒã éžæã远跡ããããã®NewMapMenu
ãã£ãŒã«ããšã倿޿¹æ³ã远å ããŸããã¹ã€ããã®ç¶æ
ãå€åãããšãã«ãã®ã¡ãœãããåŒã³åºãããããã«ããŸãã bool wrapping = true; ⊠public void ToggleWrapping (bool toggle) { wrapping = toggle; }
æ°ããããããèŠæ±ããããšãæå°åãªãã·ã§ã³ã®å€ãæž¡ããŸãã void CreateMap (int x, int z) { if (generateMaps) { mapGenerator.GenerateMap(x, z, wrapping); } else { hexGrid.CreateMap(x, z, wrapping); } HexMapCamera.ValidatePosition(); Close(); }
倿ŽãHexMapGenerator.GenerateMap
ã圌ã¯ãã®æ°ããåŒæ°ãåãããã®åŸã«ããã転éãããããšã®éãHexGrid.CreateMap
ã public void GenerateMap (int x, int z, bool wrapping) { ⊠grid.CreateMap(x, z, wrapping); ⊠}
code> HexGridã¯æããããŸããŠãããã©ãããç¥ãå¿
èŠãããããããã£ãŒã«ãã远å ããŠCreateMap
èšå®ããŸããä»ã®ã¯ã©ã¹ã¯ãã°ãªãããæå°åãããŠãããã©ããã«å¿ããŠããžãã¯ã倿Žããå¿
èŠãããããããã£ãŒã«ããäžè¬åããŸããããã«ãã€ã³ã¹ãã¯ã¿ãŒã䜿çšããŠããã©ã«ãå€ãèšå®ã§ããŸãã public int cellCountX = 20, cellCountZ = 15; public bool wrapping; ⊠public bool CreateMap (int x, int z, bool wrapping) { ⊠cellCountX = x; cellCountZ = z; this.wrapping = wrapping; ⊠}
HexGrid
CreateMap
2ã€ã®å Žæã§èªåèªèº«ãåŒã³åºããŸããcollapseåŒæ°ã«ç¬èªã®ãã£ãŒã«ãã䜿çšããã ãã§ãã void Awake () { ⊠CreateMap(cellCountX, cellCountZ, wrapping); } ⊠public void Load (BinaryReader reader, int header) { ⊠if (x != cellCountX || z != cellCountZ) { if (!CreateMap(x, z, wrapping)) { return; } } ⊠}
ã°ãªããæãããã¿ã¹ã€ããã¯ããã©ã«ãã§ãªã³ã«ãªã£ãŠããŸããä¿åãšèªã¿èŸŒã¿
æãããã¿ã¯ã«ãŒãããšã«èšå®ããããããä¿åããŠããŒãããå¿
èŠããããŸããããã¯ããã¡ã€ã«ã®ä¿å圢åŒã倿Žããå¿
èŠããããããã®ããŒãžã§ã³å®æ°ã倧ããããããšãæå³ããŸãSaveLoadMenu
ã const int mapFileVersion = 5;
ä¿åãããšãHexGrid
ã¯ãããããµã€ãºã®åŸã«ããŒã«å€ã®æãããã¿å€ãæžã蟌ãã ãã«ããŸãã public void Save (BinaryWriter writer) { writer.Write(cellCountX); writer.Write(cellCountZ); writer.Write(wrapping); ⊠}
ããŠã³ããŒããããšãã¯ãæ£ããããŒãžã§ã³ã®ãã¡ã€ã«ã§ã®ã¿èªã¿åããŸããç°ãªãå Žåãããã¯å€ãã«ãŒãã§ãããæå°åããªãã§ãã ããããã®æ
å ±ãããŒã«ã«å€æ°ã«ä¿åããçŸåšã®æãããã¿ç¶æ
ãšæ¯èŒããŸããç°ãªãå Žåãä»ã®ãµã€ãºã®ããããããŒãããå Žåãšåãæ¹æ³ã§æ¢åã®ãããããããžãåå©çšããããšã¯ã§ããŸããã public void Load (BinaryReader reader, int header) { ClearPath(); ClearUnits(); int x = 20, z = 15; if (header >= 1) { x = reader.ReadInt32(); z = reader.ReadInt32(); } bool wrapping = header >= 5 ? reader.ReadBoolean() : false; if (x != cellCountX || z != cellCountZ || this.wrapping != wrapping) { if (!CreateMap(x, z, wrapping)) { return; } } ⊠}
æãããã¿ã¡ããªãã¯
ããããæããããã«ã¯ãããšãã°è·é¢ãèšç®ãããšããªã©ãããžãã¯ã倧å¹
ã«å€æŽããå¿
èŠããããŸãããããã£ãŠãã°ãªãããžã®çŽæ¥ãªã³ã¯ãæããªãã³ãŒãã«è§Šããããšãã§ããŸãããã®æ
å ±ãåŒæ°ãšããŠæž¡ã代ããã«ãã«è¿œå ããŸãããHexMetrics
ããããã®å¹
ã«äžèŽããæãããã¿ãµã€ãºãå«ãéçæŽæ°ã远å ããŸãããŒããã倧ããå Žåãæãããã¿å¯èœãªã«ãŒããæ±ã£ãŠããŸããããã確èªããã«ã¯ãããããã£ã远å ããŸãã public static int wrapSize; public static bool Wrapping { get { return wrapSize > 0; } }
ååŒã³åºãã®æãããã¿ãµã€ãºãèšå®ããå¿
èŠããããŸãHexGrid.CreateMap
ã public bool CreateMap (int x, int z, bool wrapping) { ⊠this.wrapping = wrapping; HexMetrics.wrapSize = wrapping ? cellCountX : 0; ⊠}
ãã®ããŒã¿ã¯Playã¢ãŒãã§ã®åã³ã³ãã€ã«ã«ã¯èããããªããããã«èšå®ããŠã¿ãŸãããOnEnable
ã void OnEnable () { if (!HexMetrics.noiseSource) { HexMetrics.noiseSource = noiseSource; HexMetrics.InitializeHashGrid(seed); HexUnit.unitPrefab = unitPrefab; HexMetrics.wrapSize = wrapping ? cellCountX : 0; ResetVisibility(); } }
ã»ã«å¹
æãããã¿å¯èœãªã«ãŒãã䜿çšããå Žåãã»ã«ã®å¹
ã§æž¬å®ãããXè»žã«æ²¿ã£ãäœçœ®ãåŠçããå¿
èŠããããŸãããã®ããã«äœ¿çšã§ããŸããHexMetrics.innerRadius * 2f
ãæ¯åä¹ç®ã远å ããªãæ¹ã䟿å©ã§ãã宿°ã远å ããŸãããHexMetrics.innerDiameter
ã public const float innerRadius = outerRadius * outerToInner; public const float innerDiameter = innerRadius * 2f;
ãã§ã«3ç®æã§çŽåŸã䜿çšã§ããŸãããŸããHexGrid.CreateCell
æ°ããã»ã«ãé
眮ãããšãã void CreateCell (int x, int z, int i) { Vector3 position; position.x = (x + z * 0.5f - z / 2) * HexMetrics.innerDiameter; ⊠}
第äºHexMapCamera
ã«ãã«ã¡ã©ã®äœçœ®ãå¶éããŸãã Vector3 ClampPosition (Vector3 position) { float xMax = (grid.cellCountX - 0.5f) * HexMetrics.innerDiameter; position.x = Mathf.Clamp(position.x, 0f, xMax); ⊠}
ãŸãHexCoordinates
ãäœçœ®ãã座æšãžã®å€æã§ãã public static HexCoordinates FromPosition (Vector3 position) { float x = position.x / HexMetrics.innerDiameter; ⊠}
ãŠããã£ããã±ãŒãžã«ãŒãã®ã»ã³ã¿ãªã³ã°
ããããæããããŸããŠããªãå Žåãæ±ç«¯ãšè¥¿ç«¯ãæç¢ºã«å®çŸ©ãããŠãããããæ°Žå¹³æ¹åã®äžå¿ãæç¢ºã«ãªããŸããããããæãããã¿å¯èœãªã«ãŒãã®å Žåããã¹ãŠãç°ãªããŸããæ±ç«¯ã西端ãäžå€®ããããŸããããŸãã¯ãäžå¿ãã«ã¡ã©ã®ããå Žæã§ãããšæ³å®ã§ããŸããããã¯ãããããåžžã«èŠç¹ã®äžå¿ã«é
眮ããå¿
èŠããããã䟿å©ã§ãããã®åŸãã©ãã«ããŠãããããã®æ±ç«¯ãŸãã¯è¥¿ç«¯ãèŠããªããªããŸãããã©ã°ã¡ã³ãåã®ããã
ãããã®èŠèŠåãã«ã¡ã©ã«å¯ŸããŠäžå€®ã«é
眮ãããããã«ãã«ã¡ã©ã®åãã«å¿ããŠèŠçŽ ã®é
眮ã倿Žããå¿
èŠããããŸãã西ã«ç§»åããå Žåã¯ãçŸåšæ±éšã®ç«¯ã«ãããã®ãååŸãã西éšã®ç«¯ã«ç§»åããå¿
èŠããããŸããåãããšãå察æ¹åã«ãåœãŠã¯ãŸããŸããçæ³çã«ã¯ãã«ã¡ã©ã飿¥ããã»ã«ã®åã«ç§»åãããããã«ãã»ã«ã®æãé ãåãããã«å察åŽã«ç§»åããå¿
èŠããããŸãããã ããããã»ã©æ£ç¢ºã§ããå¿
èŠã¯ãããŸããã代ããã«ãããããã©ã°ã¡ã³ãå
šäœã転éã§ããŸããããã«ãããã¡ãã·ã¥ã倿Žããã«ãããã®äžéšãç§»åã§ããŸãããã©ã°ã¡ã³ãã®åå
šäœãåæã«ç§»åãããããåã°ã«ãŒãã®èŠªåãªããžã§ã¯ããäœæããŠãããããã°ã«ãŒãåããŸãããããã®ãªããžã§ã¯ãã®é
åãã«è¿œå ããã§HexGrid
åæåãCreateChunks
ãŸããã³ã³ãããšããŠã®ã¿äœ¿çšãããããã³ã³ããŒãã³ããžã®ãªã³ã¯ã远跡ããã ãã§ãTransform
ããã©ã°ã¡ã³ãã®å Žåãšåæ§ã«ããããã®åæäœçœ®ã¯ã°ãªãã座æšã®ããŒã«ã«åç¹ã«ãããŸãã Transform[] columns; ⊠void CreateChunks () { columns = new Transform[chunkCountX]; for (int x = 0; x < chunkCountX; x++) { columns[x] = new GameObject("Column").transform; columns[x].SetParent(transform, false); } ⊠}
ããã§ããã©ã°ã¡ã³ãã¯ã°ãªããã§ã¯ãªãã察å¿ããåã®åã«ãªããŸãã void CreateChunks () { ⊠chunks = new HexGridChunk[chunkCountX * chunkCountZ]; for (int z = 0, i = 0; z < chunkCountZ; z++) { for (int x = 0; x < chunkCountX; x++) { HexGridChunk chunk = chunks[i++] = Instantiate(chunkPrefab); chunk.transform.SetParent(columns[x], false); } } }
åã«ã°ã«ãŒãåããããã©ã°ã¡ã³ãããã¹ãŠã®ãã©ã°ã¡ã³ããåã®åã«ãªã£ãããããã©ã°ã¡ã³ãã§ã¯CreateMap
ãªãããã¹ãŠã®åãçŽæ¥ç Žæ£ããã ãã§ååã§ãããããã£ãŠãåšã®æçãåãé€ããŸãã public bool CreateMap (int x, int z, bool wrapping) { ⊠if (columns != null) { for (int i = 0; i < columns.Length; i++) { Destroy(columns[i].gameObject); } } ⊠}
ãã¬ããŒãå
äœçœ®Xããã©ã¡ãŒã¿ãŒãšããŠHexGrid
æ°ããã¡ãœããã«è¿œå ãCenterMap
ãŸããäœçœ®ãåã€ã³ããã¯ã¹ã«å€æããUnityåäœã®ãã©ã°ã¡ã³ãå¹
ã§é€ç®ããŸããããã¯ãã«ã¡ã©ãçŸåšé
眮ãããŠããåã®ã€ã³ããã¯ã¹ã«ãªããŸããã€ãŸãããããã®äžå€®ã®åã«ãªããŸãã public void CenterMap (float xPosition) { int centerColumnIndex = (int) (xPosition / (HexMetrics.innerDiameter * HexMetrics.chunkSizeX)); }
äžå€®ã®åã®ã€ã³ããã¯ã¹ã倿Žãããå Žåã«ã®ã¿ããããã®èŠèŠåã倿Žããã ãã§ååã§ããããã§ããã£ãŒã«ãã§ããã远跡ããŸããããããããäœæãããšãã«ããã©ã«ãå€-1ã䜿çšããŠãæ°ããããããåžžã«äžå€®ã«é
眮ãããããã«ããŸãã int currentCenterColumnIndex = -1; ⊠public bool CreateMap (int x, int z, bool wrapping) { ⊠this.wrapping = wrapping; currentCenterColumnIndex = -1; ⊠} ⊠public void CenterMap (float xPosition) { int centerColumnIndex = (int) (xPosition / (HexMetrics.innerDiameter * HexMetrics.chunkSizeX)); if (centerColumnIndex == currentCenterColumnIndex) { return; } currentCenterColumnIndex = centerColumnIndex; }
äžå€®ã®åã®ã€ã³ããã¯ã¹ãããã£ãã®ã§ãåã®ååã®æ°ãåçŽã«æžç®ããŠå ç®ããããšã«ãããæå°ããã³æå€§ã®ã€ã³ããã¯ã¹ã決å®ã§ããŸãã奿°åã®æŽæ°å€ã䜿çšãããããããã¯å®å
šã«æ©èœããŸããå¶æ°ã®å Žåãåãå®å
šã«äžå€®ã«é
眮ããããšã¯ã§ããªããããã€ã³ããã¯ã¹ã®1ã€ã¯å¿
èŠä»¥äžã«1ã¹ãããé²ã¿ãŸããããã«ããããããã®æãé ããšããžã®æ¹åã«1åã®ãªãã»ãããäœæãããŸãããããã¯åé¡ã§ã¯ãããŸããã currentCenterColumnIndex = centerColumnIndex; int minColumnIndex = centerColumnIndex - chunkCountX / 2; int maxColumnIndex = centerColumnIndex + chunkCountX / 2;
ãããã®ã€ã³ããã¯ã¹ã¯ãè² ãŸãã¯èªç¶æå€§åã€ã³ããã¯ã¹ãã倧ããå ŽåããããŸããã«ã¡ã©ããããã®èªç¶äžå¿ã«è¿ãå Žåã«ã®ã¿ãæå°å€ã¯ãŒãã§ããç§ãã¡ã®ã¿ã¹ã¯ã¯ããããã®çžå¯Ÿã€ã³ããã¯ã¹ã«å¯Ÿå¿ããããã«åãç§»åããããšã§ããããã¯ãã«ãŒãå
ã®ååã®ããŒã«ã«X座æšã倿Žããããšã§å®è¡ã§ããŸãã int minColumnIndex = centerColumnIndex - chunkCountX / 2; int maxColumnIndex = centerColumnIndex + chunkCountX / 2; Vector3 position; position.y = position.z = 0f; for (int i = 0; i < columns.Length; i++) { position.x = 0f; columns[i].localPosition = position; }
ååã«ã€ããŠãã€ã³ããã¯ã¹ãæå°ã€ã³ããã¯ã¹ãããäœããã©ããã確èªããŸãããããããªããããã¯äžå¿ã®å·Šã«é ãããŸãã圌ã¯ãããã®å察åŽã«ãã¬ããŒãããªããã°ãªããŸãããããã¯ãX座æšããããã®å¹
ã«çããããããšã§å®è¡ã§ããŸããåæ§ã«ãåã®ã€ã³ããã¯ã¹ãæå€§ã®ã€ã³ããã¯ã¹ããã倧ããå Žåã¯ãäžå¿ããå³ã«é¢ããããŠãããããå察åŽã«ãã¬ããŒãããå¿
èŠããããŸãã for (int i = 0; i < columns.Length; i++) { if (i < minColumnIndex) { position.x = chunkCountX * (HexMetrics.innerDiameter * HexMetrics.chunkSizeX); } else if (i > maxColumnIndex) { position.x = chunkCountX * -(HexMetrics.innerDiameter * HexMetrics.chunkSizeX); } else { position.x = 0f; } columns[i].localPosition = position; }
ç§»åã«ã¡ã©
ããã倿ŽãHexMapCamera.AdjustPosition
ãŠãæãããã¿å¯èœãªã«ãŒããæäœãããšãã«ã代ããã«ãClampPosition
åŒã³åºãããã«ããŸãWrapPosition
ãæåã«ãæ°ããã¡ãœãããWrapPosition
è€è£œClampPosition
ã«ããŸãããå¯äžã®éãããããŸãCenterMap
ãæçµçã«ããåŒã³åºããŸãã void AdjustPosition (float xDelta, float zDelta) { ⊠transform.localPosition = grid.wrapping ? WrapPosition(position) : ClampPosition(position); } ⊠Vector3 WrapPosition (Vector3 position) { float xMax = (grid.cellCountX - 0.5f) * HexMetrics.innerDiameter; position.x = Mathf.Clamp(position.x, 0f, xMax); float zMax = (grid.cellCountZ - 1) * (1.5f * HexMetrics.outerRadius); position.z = Mathf.Clamp(position.z, 0f, zMax); grid.CenterMap(position.x); return position; }
ã«ãŒããããã«äžå€®ã«ããããã«ãOnEnable
ã¡ãœãããåŒã³åºããŸãValidatePosition
ã void OnEnable () { instance = this; ValidatePosition(); }
ã«ã¡ã©ã®äžå¿ã«ãããšãã«å·Šå³ã«ç§»åããŸããã«ã¡ã©ã®ç§»åã¯åŒãç¶ãå¶éãããŸããããããã¯ã«ã¡ã©ã«å¯ŸããŠäžå¿ã«é
眮ãããå¿
èŠã«å¿ããŠããããã©ã°ã¡ã³ãã®åããã¬ããŒãããŸããå°ããªå°å³ãšãªã¢ãŒãã«ã¡ã©ã§ã¯ããããã¯ã£ãããšèŠããŸããã倧ããªå°å³ã§ã¯ããã¬ããŒããããæçãã«ã¡ã©ã®è¡šç€ºç¯å²å€ã«ãããŸããæããã«ããããã®éã«ãŸã äžè§åœ¢åå²ããªãããããããã®æåã®æ±ãšè¥¿ã®ãšããžã®ã¿ãç®ç«ã¡ãŸããã«ã¡ã©ãæããããã«ã¯ããã®X座æšã®å¶éãåé€ãWrapPosition
ãŸãã代ããã«ãX座æšã¯ãŒããããå°ããéã¯ãããã®å¹
ã ãå¢å ãç¶ãããããã®å¹
ããã倧ããå Žåã¯æžå°ããŸãã Vector3 WrapPosition (Vector3 position) {
ããŒã«ã¢ããã«ã¡ã©ã¯ãããã«æ²¿ã£ãŠç§»åããŸããæãããã¿å¯èœãªã·ã§ãŒããŒãã¯ã¹ãã£
äžè§æž¬é空éãé€ããã²ãŒã ã¢ãŒãã§ã«ã¡ã©ãæå°åããããšã¯æç¥ã§ããªãã¯ãã§ãããã ãããããçºçãããšãå°åœ¢ãšæ°Žã®ååãèŠèŠçã«å€åããŸããããã¯ãäžçã®äœçœ®ã䜿çšããŠãããã®ãã¯ã¹ãã£ããµã³ããªã³ã°ããããã«çºçããŸãããã©ã°ã¡ã³ãã®éããã¬ããŒããŒã·ã§ã³ã¯ããã¯ã¹ãã£ã®äœçœ®ã倿ŽããŸãããã®åé¡ã解決ããã«ã¯ããã©ã°ã¡ã³ããµã€ãºã®åæ°ã®ã¿ã€ã«ã«ãã¯ã¹ãã£ã衚瀺ããŸãããã©ã°ã¡ã³ããµã€ãºã¯ã®å®æ°ããèšç®ãããHexMetrics
ãããHexMetrics.cgincã·ã§ãŒããŒã€ã³ã¯ã«ãŒããã¡ã€ã«ãäœæããããã«å¯Ÿå¿ããå®çŸ©ã貌ãä»ããŸããããåºæ¬çãªã¿ã€ã«ã¹ã±ãŒã«ã¯ããã©ã°ã¡ã³ããµã€ãºãšã»ã«ã®å€ååŸããèšç®ãããŸããä»ã®ã¡ããªãã¯ã䜿çšããå Žåãããã«å¿ããŠãã¡ã€ã«ã倿Žããå¿
èŠããããŸãã #define OUTER_TO_INNER 0.866025404 #define OUTER_RADIUS 10 #define CHUNK_SIZE_X 5 #define TILING_SCALE (1 / (CHUNK_SIZE_X * 2 * OUTER_RADIUS / OUTER_TO_INNER))
ããã«ãããã¿ã€ã«ã¹ã±ãŒã«ã0.00866025404ã«ãªããŸãããã®å€ã®æŽæ°åã䜿çšããå Žåããã¯ã¹ãã£ãªã³ã°ã¯ãã©ã°ã¡ã³ãã®ãã¬ããŒããŒã·ã§ã³ã®åœ±é¿ãåããŸãããããã«ããããã®æ±ãšè¥¿ã®ãšããžã®ãã¯ã¹ãã£ã¯ãæ¥ç¶ãæ£ããäžè§åœ¢åå²ããåŸãã·ãŒã ã¬ã¹ã«çµåããŸãããã¬ã€ã³ã·ã§ãŒããŒã®UVã¹ã±ãŒã«ãšããŠ0.02ã䜿çšããŸããã代ããã«ã0.01732050808ã®2åã®ã¿ã€ã«ã¹ã±ãŒã«ã䜿çšã§ããŸããã¹ã±ãŒã«ã¯ä»¥åãããå°ãå°ãããªãããã¯ã¹ãã£ã®ã¹ã±ãŒã«ã¯ãããã«å¢å ããŸããããèŠèŠçã«ã¯èŠããŸããã #include "../HexMetrics.cginc" #include "../HexCellData.cginc" ⊠float4 GetTerrainColor (Input IN, int index) { float3 uvw = float3( IN.worldPos.xz * (2 * TILING_SCALE), IN.terrain[index] ); ⊠}
UVãã€ãºã®Roadsã·ã§ãŒããŒã§ã¯ã0.025ã®ã¹ã±ãŒã«ã䜿çšããŸããã代ããã«ãããªãã«ã¿ã€ã«ã¹ã±ãŒã«ã䜿çšã§ããŸããããã«ãã0.02598076212ãåŸãããŸãããããã¯ããªãè¿ãå€ã§ãã #include "HexMetrics.cginc" #include "HexCellData.cginc" ⊠void surf (Input IN, inout SurfaceOutputStandardSpecular o) { float4 noise = tex2D(_MainTex, IN.worldPos.xz * (3 * TILING_SCALE)); ⊠}
æåŸã«ãWater.cgincã§ã¯ã泡ã«0.015ãæ³¢ã«0.025ã䜿çšããŸãããããã§ãããããã®å€ã2åããã³3åã®ã¿ã€ã«ã¹ã±ãŒã«ã«çœ®ãæããããšãã§ããŸãã #include "HexMetrics.cginc" float Foam (float shore, float2 worldXZ, sampler2D noiseTex) { shore = sqrt(shore) * 0.9; float2 noiseUV = worldXZ + _Time.y * 0.25; float4 noise = tex2D(noiseTex, noiseUV * (2 * TILING_SCALE)); ⊠} ⊠float Waves (float2 worldXZ, sampler2D noiseTex) { float2 uv1 = worldXZ; uv1.y += _Time.y; float4 noise1 = tex2D(noiseTex, uv1 * (3 * TILING_SCALE)); float2 uv2 = worldXZ; uv2.x += _Time.y; float4 noise2 = tex2D(noiseTex, uv2 * (3 * TILING_SCALE)); ⊠}
ãŠããã£ããã±ãŒãžæ±ãšè¥¿ã®é£å
ãã®æ®µéã§ã¯ãããããæãç³ãããšã®å¯äžã®èŠèŠç蚌æ ã¯ãææ±åãšæè¥¿åã®éã®å°ããªã®ã£ããã§ãããã®ã®ã£ããã¯ãæããããããšãªããããã®å察åŽã®ã»ã«éã®ãšããžãšè§åºŠã®æ¥ç¶ããŸã äžè§åœ¢åå²ããŠããªãããã«çºçããŸãã端ã®ã¹ããŒã¹ããŒãæãããã¿é£äºº
æ±è¥¿æ¥ç¶ãäžè§æž¬éããããã«ãå察åŽã®ã»ã«ãäºãã«é£æ¥ãããå¿
èŠããããŸãããããŸã§ã¯HexGrid.CreateCell
ãXã®ã€ã³ããã¯ã¹ããŒããã倧ããå Žåã«ã®ã¿ãåã®ã»ã«ãšã®E-Wæ¥ç¶ã確ç«ãããããããããè¡ã£ãŠããŸããããã®æ¥ç¶ãæããããã«ã¯ããããã®æãç³ã¿ããªã³ã«ãªã£ãŠãããšãã«ãè¡ã®æåŸã®ã»ã«ãåãè¡ã®æåã®ã»ã«ã«æ¥ç¶ããå¿
èŠããããŸãã void CreateCell (int x, int z, int i) { ⊠if (x > 0) { cell.SetNeighbor(HexDirection.W, cells[i - 1]); if (wrapping && x == cellCountX - 1) { cell.SetNeighbor(HexDirection.E, cells[i - x]); } } ⊠}
é£äººE â Wã®æ¥ç¶ã確ç«ããããã®ã£ããã®éšåçãªäžè§åœ¢åå²ãååŸããŸããæªã¿ã誀ã£ãŠé ãããŠããããããšããžã®æ¥ç¶ã¯çæ³çã§ã¯ãããŸãããããã«ã€ããŠã¯åŸã§å¯ŸåŠããŸããååç©E â WNE-SWãªã³ã¯ãæããããå¿
èŠããããŸããããã¯ãåå¶æ°è¡ã®æåã®ã»ã«ãåã®è¡ã®æåŸã®ã»ã«ã«æ¥ç¶ããããšã§å®è¡ã§ããŸããåã®ã»ã«ã«ãªããŸãã if (z > 0) { if ((z & 1) == 0) { cell.SetNeighbor(HexDirection.SE, cells[i - cellCountX]); if (x > 0) { cell.SetNeighbor(HexDirection.SW, cells[i - cellCountX - 1]); } else if (wrapping) { cell.SetNeighbor(HexDirection.SW, cells[i - 1]); } } else { ⊠} }
NE â SWæ¥ç¶ãæåŸã«ãSE â NWæ¥ç¶ã¯ãæåã®äžã®å奿°è¡ã®çµããã«ç¢ºç«ãããŸãããããã®ã»ã«ã¯ãåã®è¡ã®æåã®ã»ã«ã«æ¥ç¶ããå¿
èŠããããŸãã if (z > 0) { if ((z & 1) == 0) { ⊠} else { cell.SetNeighbor(HexDirection.SW, cells[i - cellCountX]); if (x < cellCountX - 1) { cell.SetNeighbor(HexDirection.SE, cells[i - cellCountX + 1]); } else if (wrapping) { cell.SetNeighbor( HexDirection.SE, cells[i - cellCountX * 2 + 1] ); } } }
ã³ã³ããŠã³ãSE â NWããã€ãºãã©ãŒã«ãã£ã³ã°
ã®ã£ãããå®å
šã«é ãã«ã¯ãé ç¹ã®äœçœ®ãæªããããã«äœ¿çšããããã€ãºãããããã®æ±ç«¯ãšè¥¿ç«¯ã§å®å
šã«æãããã«ããå¿
èŠããããŸããã·ã§ãŒããŒã«äœ¿çšããã®ãšåãããªãã¯ã䜿çšã§ããŸããããã€ãºã¹ã±ãŒã«ã¯æªã¿ã«å¯ŸããŠ0.003ã§ãããã¿ã€ã«ã確å®ã«äœæããã«ã¯ãã¹ã±ãŒã«ã倧å¹
ã«å€§ããããå¿
èŠããããŸããããã«ãããé ç¹ãããæ··distortionãšããæªã¿ã«ãªããŸããå¥ã®è§£æ±ºçã¯ããã€ãºãããŒãªã³ã°ããããšã§ã¯ãªãããããã®ç«¯ã§ãã€ãºãæ»ããã«æžè¡°ãããããšã§ãã1ã€ã®ã»ã«ã®å¹
ã«æ²¿ã£ãŠæ»ãããªæžè¡°ãå®è¡ãããšãæªã¿ã«ããã®ã£ããã®ãªãæ»ãããªé·ç§»ãäœæãããŸãããã®é åã®ãã€ãºã¯ãããã«æ»ããã«ãªããé·è·é¢ããã¯å€åãã·ã£ãŒãã«èŠããŸãããé ç¹ã®ããããªæªã¿ã䜿çšããå Žåãããã¯ããã»ã©æçœã§ã¯ãããŸãããæž©åºŠå€åã¯ã©ãã§ããïŒ. , . , . , .
ã«ãŒããæããããŸãªãå Žåã¯ãHexMetrics.SampleNoise
1ã€ã®ãµã³ãã«ã§å¯Ÿå¿ã§ããŸããããããæãç³ããšãã¯æžè¡°ã远å ããå¿
èŠããããŸãããããã£ãŠããµã³ãã«ãè¿ãåã«ã倿°ã«ä¿åããŠãã ããã public static Vector4 SampleNoise (Vector3 position) { Vector4 sample = noiseSource.GetPixelBilinear( position.x * noiseScale, position.z * noiseScale ); return sample; }
æå°åããå Žåã2çªç®ã®ãµã³ãã«ãšæ··åããå¿
èŠããããŸãããããã®æ±éšã§ãã©ã³ãžã·ã§ã³ãå®è¡ããããã2çªç®ã®ãµã³ãã«ã西ã«ç§»åããå¿
èŠããããŸãã Vector4 sample = noiseSource.GetPixelBilinear( position.x * noiseScale, position.z * noiseScale ); if (Wrapping && position.x < innerDiameter) { Vector4 sample2 = noiseSource.GetPixelBilinear( (position.x + wrapSize * innerDiameter) * noiseScale, position.z * noiseScale ); }
æžè¡°ã¯ã1ã€ã®ã»ã«ã®å¹
ã«ããã£ãŠã西éšããæ±éšãžã®åçŽãªç·åœ¢è£éã䜿çšããŠå®è¡ãããŸãã if (Wrapping && position.x < innerDiameter) { Vector4 sample2 = noiseSource.GetPixelBilinear( (position.x + wrapSize * innerDiameter) * noiseScale, position.z * noiseScale ); sample = Vector4.Lerp( sample2, sample, position.x * (1f / innerDiameter) ); }
ãã€ãºããã·ã³ã°ãäžå®å
šãªãœãªã¥ãŒã·ã§ã³ããã®çµæãæ±åŽã®ã»ã«ã®äžéšãè² ã®X座æšãæã€ãããå®å
šã«äžèŽããŸããããã®é åã«è¿ã¥ããªãããã«ãé·ç§»é åãã»ã«å¹
ã®è¥¿ååã«ç§»åããŸãããã if (Wrapping && position.x < innerDiameter * 1.5f) { Vector4 sample2 = noiseSource.GetPixelBilinear( (position.x + wrapSize * innerDiameter) * noiseScale, position.z * noiseScale ); sample = Vector4.Lerp( sample2, sample, position.x * (1f / innerDiameter) - 0.5f ); }
æ£ããæžè¡°ãã»ã«ç·šé
äžè§åœ¢åå²ãæ£ããããã«ãªã£ãã®ã§ãå°å³ãšæãç³ã¿ã®ç¶ãç®ã§ãã¹ãŠãç·šéã§ããããšã確èªããŸããããçµå±ã®ãšããããã¬ããŒãããããã©ã°ã¡ã³ãã§ã¯ã座æšã誀ã£ãŠããã倧ããªãã©ã·ãçž«ãç®ã§åããŠããŸãããã©ã·ãããªãã³ã°ãããŸãããããä¿®æ£ããã«ã¯ãHexCoordinates
æãããã¿ãå ±åããå¿
èŠããããŸãããããè¡ãã«ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã¡ãœããã§X座æšãäžèŽãããŸãã軞座æšXã¯ããªãã»ããã®X座æšããZ座æšã®ååãæžç®ããããšã§ååŸãããããšãããã£ãŠããããããã®æ
å ±ã䜿çšããŠé倿ãå®è¡ãããŒã座æšãå°ãããã©ããã確èªã§ããŸãããã®å Žåãå±éããããããã®æ±åŽãè¶
ãã座æšããããŸããåæ¹åã§ãããã®åå以äžããã¬ããŒããããããæãç³ã¿ãµã€ãºãXã«1å远å ããã ãã§ååã§ãããããŠããªãã»ãã座æšãæãããã¿ãµã€ãºããã倧ããå Žåãæžç®ãå®è¡ããå¿
èŠããããŸãã public HexCoordinates (int x, int z) { if (HexMetrics.Wrapping) { int oX = x + z / 2; if (oX < 0) { x += HexMetrics.wrapSize; } else if (oX >= HexMetrics.wrapSize) { x -= HexMetrics.wrapSize; } } this.x = x; this.z = z; }
ãããã®äžéšãŸãã¯äžéšãç·šéãããšãã«ãšã©ãŒãçºçããããšããããŸããããã¯ãé ç¹ã®ããã¿ã«ããããããã®å€åŽã®ã»ã«ã®è¡ã«ã«ãŒãœã«ã衚瀺ãããå Žåã«çºçããŸããããã¯HexGrid.GetCell
ããã¯ãã«ãã©ã¡ãŒã¿ãšåº§æšãäžèŽãããªãããã«çºçãããã°ã§ãããããä¿®æ£GetCell
ããã«ã¯ãå¿
èŠãªãã§ãã¯ãå®è¡ãããã©ã¡ãŒã¿ãŒãšããŠåº§æšãæã€ã¡ãœãããé©çšããŸãã public HexCell GetCell (Vector3 position) { position = transform.InverseTransformPoint(position); HexCoordinates coordinates = HexCoordinates.FromPosition(position);
沿岞æãããã¿
äžè§æž¬éã¯å°åœ¢ã«é©ããŠããŸãããæ±è¥¿ã®ç¶ãç®ã«æ²¿ã£ãŠãæ°Žã®æµ·å²žã®ç«¯ã¯ãããŸãããå®éã圌ãã¯ãã ã厩å£ããŸããããããã¯å転ããããããã®å察åŽã«åŒã䌞ã°ãããŸããæ°Žã®ç«¯ããããŸãããããã¯ãæµ·å²žã®æ°Žãäžè§æž¬éãããšãã«ãé£äººã®äœçœ®ã䜿çšããããã§ãããããä¿®æ£ããã«ã¯ãã«ãŒãã®å察åŽãæ±ã£ãŠãããšå€æããå¿
èŠããããŸããã¿ã¹ã¯ãç°¡çŽ åããHexCell
ããã«ãã€ã³ããã¯ã¹ã®ããããã£ã«ã»ã«åã远å ããŸãã public int ColumnIndex { get; set; }
ãã®ã€ã³ããã¯ã¹ãã«å²ãåœãŠãŸãHexGrid.CreateCell
ãããã¯ããªãã»ãã座æšXããã©ã°ã¡ã³ããµã€ãºã§å²ã£ããã®ã«åçŽã«çãããªããŸãã void CreateCell (int x, int z, int i) { ⊠cell.Index = i; cell.ColumnIndex = x / HexMetrics.chunkSizeX; ⊠}
HexGridChunk.TriangulateWaterShore
çŸåšã®ã»ã«ãšãã®é£ã®ã»ã«ã®åã€ã³ããã¯ã¹ãæ¯èŒããããšã§ãæå°åãããŠãããã®ã倿ã§ããŸããé£äººã®åã®ã€ã³ããã¯ã¹ã1段éäžã®å Žåã西åŽã«ããŸããé£äººã¯æ±åŽã«ããŸãããããã£ãŠãé£äººã西ã«åããå¿
èŠããããŸããåæ§ã«ãå察æ¹åã«ã Vector3 center2 = neighbor.Position; if (neighbor.ColumnIndex < cell.ColumnIndex - 1) { center2.x += HexMetrics.wrapSize * HexMetrics.innerDiameter; } else if (neighbor.ColumnIndex > cell.ColumnIndex + 1) { center2.x -= HexMetrics.wrapSize * HexMetrics.innerDiameter; }
海岞ã®Ri骚ããããè§ã¯ãããŸããããã®ãããç§ãã¡ã¯æµ·å²žã®rib骚ã®äžè©±ãããŸãããããããŸã§ã®ãšããã³ãŒããŒãæ±ã£ãŠããŸããã§ãããæ¬¡ã®é£äººã«ãåãããšãããå¿
èŠããããŸãã if (nextNeighbor != null) { Vector3 center3 = nextNeighbor.Position; if (nextNeighbor.ColumnIndex < cell.ColumnIndex - 1) { center3.x += HexMetrics.wrapSize * HexMetrics.innerDiameter; } else if (nextNeighbor.ColumnIndex > cell.ColumnIndex + 1) { center3.x -= HexMetrics.wrapSize * HexMetrics.innerDiameter; } Vector3 v3 = center3 + (nextNeighbor.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); ⊠}
é©åã«çž®å°ãããæµ·å²žãã«ãŒãçæ
æ±ãšè¥¿ãæ¥ç¶ãããªãã·ã§ã³ã¯ããããã®çæã«åœ±é¿ããŸããããããæå°åããå Žåãçæã¢ã«ãŽãªãºã ãæå°åããå¿
èŠããããŸããããã«ãããå¥ã®ããããäœæãããŸããããŒã以å€ã®ãããããŒããŒXã䜿çšããå Žåãæãç³ã¿ã¯æããã§ã¯ãããŸãããããã©ã«ãèšå®ã®å€§ããªããã1208905299ãæãç³ã¿ãããšãªããæå°åã䜿çšããŠãæå³ããããŸããå Žåã¯å°å³ããŒããŒã«Xããããããåæã«ãªãŒãžã§ã³ãããŒãžããããããåã«ãããåãé€ãããšã¯ã§ããŸããã代ããã«æããããå Žåã¯ãåã«RegionBorderã䜿çšã§ããŸãããã¹ãŠã®å Žåã§å€æŽããŠãã ããããã®æ°ãã倿°ã¯ãcollapseãªãã·ã§ã³ã®å€ã«å¿ããŠããŸãã¯ããŸãã¯ã«çãããªããŸãã以äžã«ãæåã®ã±ãŒã¹ã®ã¿ã®å€æŽã瀺ããŸãããHexMapGenerator.CreateRegions
mapBorderX
borderX
regionBorder
mapBorderX
int borderX = grid.wrapping ? regionBorder : mapBorderX; MapRegion region; switch (regionCount) { default: region.xMin = borderX; region.xMax = grid.cellCountX - borderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); break; ⊠}
åæã«ãå°åã¯åé¢ããããŸãŸã§ãããããã¯ãããã®æ±åŽãšè¥¿åŽã«ç°ãªãå°åãããå Žåã«ã®ã¿å¿
èŠã§ãããããå°éãããªãå Žåã2ã€ãããŸãã1ã€ã¯ããªãŒãžã§ã³ã1ã€ãããªãå Žåã§ãã2ã€ç®ã¯ãããããæ°Žå¹³ã«åå²ãã2ã€ã®é åãããå Žåã§ãããããã®å ŽåãborderX
ãŒãã®å€ãå²ãåœãŠãããšãã§ããŸããããã«ãããéžå°ãæ±è¥¿ã®ç¶ãç®ã暪åãããšãã§ããŸãã switch (regionCount) { default: if (grid.wrapping) { borderX = 0; } region.xMin = borderX; region.xMax = grid.cellCountX - borderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); break; case 2: if (Random.value < 0.5f) { ⊠} else { if (grid.wrapping) { borderX = 0; } region.xMin = borderX; region.xMax = grid.cellCountX - borderX; region.zMin = mapBorderZ; region.zMax = grid.cellCountZ / 2 - regionBorder; regions.Add(region); region.zMin = grid.cellCountZ / 2 + regionBorder; region.zMax = grid.cellCountZ - mapBorderZ; regions.Add(region); } break; ⊠}
1ã€ã®å°åã厩å£ããŠããŸããäžèŠããã¹ãŠãæ£ããæ©èœããŠããããã«èŠããŸãããå®éã«ã¯ç¶ãç®ã«æ²¿ã£ãŠã®ã£ããããããŸããããã¯ã䟵é£çããŒãã«èšå®ãããšãããé¡èã«ãªããŸãã䟵é£ãç¡å¹ã«ãªããšãã¬ãªãŒãã®ç¶ãç®ãç®ç«ã€ããã«ãªããŸããç¶ãç®ãã¬ãªãŒãç Žçã®æé·ã劚ãããããã®ã£ãããçºçããŸããæåã«è¿œå ããããã®ã決å®ããããã«ãã»ã«ãããã©ã°ã¡ã³ãã®äžå¿ãŸã§ã®è·é¢ã䜿çšããããããã®å察åŽã®ã»ã«ã¯éåžžã«é ããªãå¯èœæ§ããããããã»ãšãã©ç¹ç¯ããŸããããã¡ãããããã¯ééã£ãŠããŸããHexCoordinates.DistanceTo
æå°åããããããã«ã€ããŠç¥ã£ãŠããããšã確èªããå¿
èŠããããŸããéã®è·é¢ãèšç®ãHexCoordinates
ã3ã€ã®è»žã®ããããã«æ²¿ã£ã絶察è·é¢ãåèšããçµæãååã«ããŸãã Zã«æ²¿ã£ãè·é¢ã¯åžžã«çã§ãããããã«æ²¿ã£ãŠæãããããšXãšYã®è·é¢ã«åœ±é¿ããå ŽåããããŸããããã§ã¯ãX + Yã®åå¥ã®èšç®ããå§ããŸãããã public int DistanceTo (HexCoordinates other) {
æãç³ãããšã§ä»»æã®ã»ã«ã®è·é¢ãçããªããã©ããã倿ããã®ã¯ç°¡åãªäœæ¥ã§ã¯ãªããããå¥ã®åº§æšã西åŽã«æãç³ãå Žåã®X + Yãèšç®ããŠã¿ãŸããããå€ãå
ã®X + Yããå°ããå Žåã¯ãããã䜿çšããŸãã int xy = (x < other.x ? other.x - x : x - other.x) + (Y < other.Y ? other.Y - Y : Y - other.Y); if (HexMetrics.Wrapping) { other.x += HexMetrics.wrapSize; int xyWrapped = (x < other.x ? other.x - x : x - other.x) + (Y < other.Y ? other.Y - Y : Y - other.Y); if (xyWrapped < xy) { xy = xyWrapped; } }
ããã«ããè·é¢ãçããªããªãå Žåã¯ãä»ã®æ¹åã«çãåãããšãã§ããããã確èªããŸãã if (HexMetrics.Wrapping) { other.x += HexMetrics.wrapSize; int xyWrapped = (x < other.x ? other.x - x : x - other.x) + (Y < other.Y ? other.Y - Y : Y - other.Y); if (xyWrapped < xy) { xy = xyWrapped; } else { other.x -= 2 * HexMetrics.wrapSize; xyWrapped = (x < other.x ? other.x - x : x - other.x) + (Y < other.Y ? other.Y - Y : Y - other.Y); if (xyWrapped < xy) { xy = xyWrapped; } } }
ããã§ãæãããã¿å¯èœãªãããã§åžžã«æçè·é¢ãååŸã§ããŸããå°åœ¢ã®ç Žçã¯ç¶ãç®ã«ãã£ãŠãããã¯ãããªããªããéžå°ãäžžãŸãããšãã§ããŸãã䟵é£ãšäŸµé£ã®ãªãã¬ãªãŒããæ£ããæãããã¿ãŸãããŠããã£ããã±ãŒãžäžçãæ
ãã
ãããã®çæãšäžè§æž¬éãæ€èšããã®ã§ã次ã«åéã調æ»ãããã³å¯èŠæ§ã®ãã§ãã¯ã«ç§»ããŸãããããã¹ãã·ãŒã
ããŒã ãäžçäžã«ç§»åãããšãã«æåã«ééããé害ã¯ãæ¢çŽ¢ã§ããªããããã®ç«¯ã§ããã«ãŒãã®ç¶ãç®ã調ã¹ãããšã¯ã§ããŸããããããã®ç«¯ã«æ²¿ã£ãã»ã«ã¯ããããã®çªç¶ã®å®äºãé ãããã«æªæ¢çŽ¢ã«ãããŸãããã ããããããæå°åãããšãåãšåã®ã»ã«ã®ã¿ãããŒã¯ãããæ±ãšè¥¿ã®ã»ã«ã¯ããŒã¯ãããŸãããHexGrid.CreateCell
ãããèæ
®ããŠå€æŽããŠãã ããã if (wrapping) { cell.Explorable = z > 0 && z < cellCountZ - 1; } else { cell.Explorable = x > 0 && z > 0 && x < cellCountX - 1 && z < cellCountZ - 1; }
ã¬ãªãŒãæ©èœã®å¯èŠæ§
次ã«ãç¶ãç®ã«æ²¿ã£ãŠå¯èŠæ§ãæ©èœãããã©ããã確èªããŸããããå°åœ¢ã«å¯ŸããŠã¯æ©èœããŸãããå°åœ¢æ©èœã«å¯ŸããŠã¯æ©èœããŸãããæããããŸããŠãããªããžã§ã¯ãã¯ãæããããŸããŠããªãæåŸã®ã»ã«ã®å¯èŠæ§ãååŸããŠããããã«èŠããŸãããªããžã§ã¯ãã®äžæ£ç¢ºãªå¯èŠæ§ãããã¯ã䜿çšãããã¯ã¹ãã£ãã©ãŒã«ãã£ã³ã°ã¢ãŒãã«HexCellShaderData
ã¯ã©ã³ãã¢ãŒããèšå®ãããŠããããã«çºçããŸãããã®åé¡ã解決ããã«ã¯ãã¯ã©ã³ãã¢ãŒãã倿ŽããŠç¹°ãè¿ããŸãããã ããããInitialize
ã¯Uã®åº§æšã«å¯ŸããŠã®ã¿è¡ãå¿
èŠããããããåå¥ã«èšå®wrapModeU
ãwrapModeV
ãŸãã public void Initialize (int x, int z) { if (cellTexture) { cellTexture.Resize(x, z); } else { cellTexture = new Texture2D( x, z, TextureFormat.RGBA32, false, true ); cellTexture.filterMode = FilterMode.Point;
åéãšå
å¥ã®åé¡ã¯ããŠãããããŸã æãç³ãŸããŠããªãããšã§ãããŠããããé
眮ãããŠããåãç§»åããåŸããŠãããã¯åãå Žæã«æ®ããŸãããŠãããã¯è»¢éããããå察åŽã«ãããŸãããã®åé¡ã¯ããã©ã°ã¡ã³ãã§è¡ã£ãããã«ãåéã®åèŠçŽ ãåã«ããããšã§è§£æ±ºã§ããŸãããŸããããããã°ãªããã®çŽæ¥ã®åã«ããŸããHexGrid.AddUnit
ã public void AddUnit (HexUnit unit, HexCell location, float orientation) { units.Add(unit); unit.Grid = this;
ãŠããããç§»åãããšãå¥ã®åã«è¡šç€ºãããå ŽåããããŸããã€ãŸãã芪ã倿Žããå¿
èŠããããŸãããããå¯èœã«ããããã«ãHexGrid
äžè¬ã¡ãœããã«è¿œå ããMakeChildOfColumn
ãã©ã¡ãŒã¿ãŒãšããŠTransform
åèŠçŽ ã®ã³ã³ããŒãã³ããšåã€ã³ããã¯ã¹ãæž¡ããŸãã public void MakeChildOfColumn (Transform child, int columnIndex) { child.SetParent(columns[columnIndex], false); }
ããããã£ãèšå®ããããšãã«ãã®ã¡ãœãããåŒã³åºããŸãHexUnit.Location
ã public HexCell Location { ⊠set { ⊠Grid.MakeChildOfColumn(transform, value.ColumnIndex); } }
ããã«ããããŠãããäœæã®åé¡ã解決ãããŸãããã ããç§»åãããšãã«ç®çã®åã«ç§»åããå¿
èŠããããŸãããããè¡ãã«ã¯ãHexUnit.TravelPath
ã€ã³ããã¯ã¹ã®çŸåšã®åã远跡ããå¿
èŠããããŸãããã®ã¡ãœããã®æåã§ã¯ãããã¯ãã¹ã®æåã®ã»ã«åã®ã€ã³ããã¯ã¹ããŸãã¯åã³ã³ãã€ã«ã«ãã£ãŠç§»åãäžæãããå Žåã¯çŸåšã®ã€ã³ããã¯ã¹ã§ãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position; yield return LookAt(pathToTravel[1].Position);
ç§»åã®åå埩äžã«ã次ã®åã®ã€ã³ããã¯ã¹ãç°ãªããã©ããã確èªããããã§ããã°ãé åºã®èŠªã倿ŽããŸãã int currentColumn = currentTravelLocation.ColumnIndex; float t = Time.deltaTime * travelSpeed; for (int i = 1; i < pathToTravel.Count; i++) { ⊠Grid.IncreaseVisibility(pathToTravel[i], VisionRange); int nextColumn = currentTravelLocation.ColumnIndex; if (currentColumn != nextColumn) { Grid.MakeChildOfColumn(transform, nextColumn); currentColumn = nextColumn; } ⊠}
ããã«ããããŠãããã¯ãã©ã°ã¡ã³ããšåæ§ã«ç§»åã§ããŸãããã ããã«ãŒãã®ç¶ãç®ãç§»åãããšãããŠãããã¯ãŸã 厩å£ããŠããŸããã代ããã«ã圌ãã¯çªç¶ééã£ãæ¹åã«åãå§ããŸããããã¯ãç¶ãç®ã®äœçœ®ã«é¢ä¿ãªãçºçããŸãããæãé¡èãªã®ã¯ããããå
šäœãé£ã³è¶ãããšãã§ãããããå
šäœã§ç«¶éЬãããã§ã¯ã海岞ã§äœ¿çšãããã®ãšåãã¢ãããŒãã䜿çšã§ããŸãããä»åã¯ããã¿ããã¡ã³ããç§»åããã«ãŒãããªãã«ããŸããæ¬¡ã®åãæ±ã«åããŠããå Žåãä»ã®æ¹åã«ã€ããŠãåæ§ã«ãæ²ç·ãæ±ã«ãã¬ããŒãããŸããæ²ç·ã®å¶åŸ¡ç¹ã倿Žããå¿
èŠãããa
ãšb
ãããã¯ãŸããã³ã³ãããŒã«ãã€ã³ãã«åœ±é¿ãäžããŸãc
ã for (int i = 1; i < pathToTravel.Count; i++) { currentTravelLocation = pathToTravel[i]; a = c; b = pathToTravel[i - 1].Position;
æãããã¿åŒã®åããæåŸã«è¡ãããšã¯ãããŒã ãç§»åããæåã®ã»ã«ãèŠããšãã«ããŒã ã®æåã®ã¿ãŒã³ã倿Žããããšã§ãããã®ã»ã«ãæ±è¥¿ã®ç¶ãç®ã®å察åŽã«ããå ŽåããŠãããã¯ééã£ãæ¹åãåããŠããŸããå°å³ãæå°åãããšããæ£ç¢ºã«åãŸãã¯åã«ãªããã€ã³ããèŠãã«ã¯2ã€ã®æ¹æ³ããããŸããããªãã¯æ±ãŸãã¯è¥¿ãèŠãããšãã§ããŸããããã¯ç§»åã®æ¹åã§ãããããããã€ã³ãã«æãè¿ãè·é¢ã«å¯Ÿå¿ããæ¹åãèŠãã®ãè«ççã§ãã®ã§ãã§äœ¿çšããŸãããLookAt
ãæå°åãããšããXè»žã«æ²¿ã£ãçžå¯Ÿè·é¢ããã§ãã¯ããŸãããããã®å¹
ã®è² ã®ååãããå°ããå Žåã¯ã西ã«ç®ãåããå¿
èŠããããŸãããã以å€ã®å Žåãè·é¢ããããã®å¹
ã®ååããã倧ããå Žåã¯ãæ±ã«æããããå¿
èŠããããŸãã IEnumerator LookAt (Vector3 point) { if (HexMetrics.Wrapping) { float xDistance = point.x - transform.localPosition.x; if (xDistance < -HexMetrics.innerRadius * HexMetrics.wrapSize) { point.x += HexMetrics.innerDiameter * HexMetrics.wrapSize; } else if (xDistance > HexMetrics.innerRadius * HexMetrics.wrapSize) { point.x -= HexMetrics.innerDiameter * HexMetrics.wrapSize; } } ⊠}
ãããã£ãŠãæãããã¿æ©èœãåããå®å
šã«æ©èœãããããããããŸããããã§ãå
è§åœ¢ãããã«é¢ããäžé£ã®ãã¥ãŒããªã¢ã«ãçµäºããŸãããåã®ã»ã¯ã·ã§ã³ã§è¿°ã¹ãããã«ãä»ã®ãããã¯ãæ€èšã§ããŸãããå
è§åœ¢ãããã«åºæã®ãã®ã§ã¯ãããŸããããããããä»åŸã®äžé£ã®ãã¥ãŒããªã¢ã«ã§ããããæ€èšããŸããæåŸã®ããã±ãŒãžãããŠã³ããŒããããã¬ã€ã¢ãŒãã§ã¿ãŒã³ãšã©ãŒãååŸããŸãã, Rotation . . . 5.
æåŸã®ããã±ãŒãžãããŠã³ããŒãããŸããããã¹ã¯ãªãŒã³ã·ã§ããã®ããã«ã°ã©ãã£ãã¯ãçŸãããããŸãã. - .
æåŸã®ããã±ãŒãžãããŠã³ããŒãããŸããããåãã«ãŒããåžžã«çæãããŸãseed (1208905299), . , Use Fixed Seed .
ãŠããã£ããã±ãŒãž