ãã£ãŒã«ã
- ã¿ã€ã«ãã£ãŒã«ããäœæããŸãã
- å¹
åªå
æ€çŽ¢ã䜿çšããæ€çŽ¢ãã¹ã
- 空ã®ã¿ã€ã«ãšãªãŒãã¿ã€ã«ãããã³å£ã¿ã€ã«ã®ãµããŒããå®è£
ããŸãã
- ã²ãŒã ã¢ãŒãã§ã®ã³ã³ãã³ãã®ç·šéã
- ã°ãªãããã£ãŒã«ããšãã¹ã®ãªãã·ã§ã³è¡šç€ºã
ããã¯ãåçŽãª
ã¿ã¯ãŒãã£ãã§ã³ã¹ã²ãŒã ã®äœæã«é¢ããäžé£ã®ãã¥ãŒããªã¢ã«ã®æåã®éšåã§ãã ãã®ããŒãã§ã¯ã競æå Žã®äœæããã¹ã®æ€çŽ¢ãæçµçãªã¿ã€ã«ãšå£ã®é
眮ãæ€èšããŸãã
ãã¥ãŒããªã¢ã«ã¯Unity 2018.3.0f2ã§äœæãããŸããã
ã¿ã¯ãŒãã£ãã§ã³ã¹ã®ãžã£ã³ã«ã¿ã€ã«ã²ãŒã ã§äœ¿çšã§ãããã£ãŒã«ããã¿ã¯ãŒãã£ãã§ã³ã¹ã²ãŒã
ã¿ã¯ãŒãã£ãã§ã³ã¹ã¯ããã¬ã€ã€ãŒã®ç®æšãæµã®çŸ€éãæçµå°ç¹ã«å°éãããŸã§ç Žå£ããããšã§ãããžã£ã³ã«ã§ãã ãã¬ã€ã€ãŒã¯æµãæ»æããå¡ã建èšããããšã§ç®æšãéæããŸãã ãã®ãžã£ã³ã«ã«ã¯å€ãã®ããªãšãŒã·ã§ã³ããããŸãã ã¿ã€ã«ãã£ãŒã«ãã䜿çšããŠã²ãŒã ãäœæããŸãã æµã¯ãã£ãŒã«ãã暪åã£ãŠçµç¹ã«åãã£ãŠç§»åãããã¬ã€ã€ãŒã¯é害ç©ãäœæããŸãã
ãªããžã§ã¯ãã®ç®¡çã«é¢ããäžé£ã®ãã¥ãŒããªã¢ã«ãæ¢ã«åŠç¿ãããšä»®å®ããŸãã
ãã£ãŒã«ã
競æå Žã¯ã²ãŒã ã®æãéèŠãªéšåã§ãããããæåã«äœæããŸãã ããã¯ã
GameBoard
ãšããç¬èªã®ã³ã³ããŒãã³ããæã€ã²ãŒã ãªããžã§ã¯ãã«ãªããŸããããã¯ã2次å
ã§ãµã€ãºãèšå®ããããšã§åæåã§ãã
Vector2Int
ã®å€ã䜿çšã§ããŸãã ãã£ãŒã«ãã¯ä»»æã®ãµã€ãºã§æ©èœããã¯ãã§ãããã©ããã§ãµã€ãºãéžæããããããã®ããã®å
±éã®
Initialize
ã¡ãœãããäœæããŸãã
ããã«ãå°çã瀺ã1ã€ã®åè§åœ¢ã§ãã£ãŒã«ããèŠèŠåããŸãã ãã£ãŒã«ããªããžã§ã¯ãèªäœãå蟺圢ã«ããã®ã§ã¯ãªããåã¯ã¯ãããªããžã§ã¯ããè¿œå ããŸãã åæåæã«ãå°çã®XYã¹ã±ãŒã«ããã£ãŒã«ãã®ãµã€ãºã«çããããŸãã ã€ãŸããåã¿ã€ã«ã®ãµã€ãºã¯ããšã³ãžã³ã®1å¹³æ¹åäœã§ãã
using UnityEngine; public class GameBoard : MonoBehaviour { [SerializeField] Transform ground = default; Vector2Int size; public void Initialize (Vector2Int size) { this.size = size; ground.localScale = new Vector3(size.x, size.y, 1f); } }
ã°ã©ãŠã³ããããã©ã«ãå€ã«æ瀺çã«èšå®ããã®ã¯ãªãã§ããïŒã¢ã€ãã¢ã¯ãUnityãšãã£ã¿ãŒã§ã«ã¹ã¿ãã€ãºå¯èœãªãã¹ãŠã®ãã®ã«ãã·ãªã¢ã«åãããé衚瀺ãã£ãŒã«ãããã¢ã¯ã»ã¹ã§ãããšããããšã§ãã ãããã®ãã£ãŒã«ãã¯ãã€ã³ã¹ãã¯ã¿ãŒã§ã®ã¿å€æŽã§ããå¿
èŠããããŸãã æ®å¿µãªãããUnityãšãã£ã¿ãŒã¯ãå€ãå²ãåœãŠãããªããšããã³ã³ãã€ã©ãŒã®èŠåãåžžã«è¡šç€ºããŸãã ãã£ãŒã«ãã®ããã©ã«ãå€ãæ瀺çã«èšå®ããããšã«ããããã®èŠåãæå¶ããããšãã§ããŸãã null
å²ãåœãŠãããšãã§ããŸãããããã©ã«ãå€ã䜿çšããããšãæ瀺çã«ç€ºãããã«äœæããŸãããããã¯ãã°ã©ãŠã³ããžã®çã®åç
§ã§ã¯ãªãããã default
ã䜿çšãdefault
ã
æ°ããã·ãŒã³ã§ãã£ãŒã«ããªããžã§ã¯ããäœæããå°çã®ããã«èŠãããããªã¢ã«ã§åã¯ã¯ãããè¿œå ããŸãã åçŽãªãããã¿ã€ãã²ãŒã ãäœæããŠãããããåäžãªã°ãªãŒã³ãããªã¢ã«ã§ååã§ãã X軞ã«æ²¿ã£ãŠ90床å転ããŠãXZå¹³é¢äžã«é
眮ããŸãã
競æå Žãã²ãŒã ãXYå¹³é¢ã«é
眮ããŠã¿ãŸãããïŒã²ãŒã ã¯2D空éã§è¡ãããŸããã3Dã®æµãšç¹å®ã®ãã€ã³ãã«å¯ŸããŠç§»åå¯èœãªã«ã¡ã©ã䜿çšããŠã3Dã§ã¬ã³ããªã³ã°ããŸãã XZãã¬ãŒã³ã¯ããã«äŸ¿å©ã§ãã¢ã³ããšã³ãç
§æã«äœ¿çšãããæšæºã®ã¹ã«ã€ããã¯ã¹ã®åãã«å¯Ÿå¿ããŠããŸãã
ã²ãŒã
次ã«ã
Game
å
šäœãæ
åœãã
Game
ã³ã³ããŒãã³ããäœæããŸãã ãã®æ®µéã§ã¯ãããã¯ãã£ãŒã«ããåæåããããšãæå³ããŸãã ã€ã³ã¹ãã¯ã¿ãŒã䜿çšããŠãµã€ãºãã«ã¹ã¿ãã€ãºããèµ·åæã«ã³ã³ããŒãã³ãã«ãã£ãŒã«ããåæåãããã ãã§ãã ããã©ã«ãã®ãµã€ãºã§ãã11Ã11ã䜿çšããŸãããã
using UnityEngine; public class Game : MonoBehaviour { [SerializeField] Vector2Int boardSize = new Vector2Int(11, 11); [SerializeField] GameBoard board = default; void Awake () { board.Initialize(boardSize); } }
ãã£ãŒã«ããµã€ãºã¯æ£ã®å€ã®ã¿ã§ãããåäžã®ã¿ã€ã«ã§ãã£ãŒã«ããäœæããããšã¯ã»ãšãã©æå³ããããŸããã æå°å€ã2Ã2ã«å¶éããŸãããã ãããè¡ãã«ã¯ã
OnValidate
ã¡ãœãããè¿œå ããŠãæå°å€ã匷å¶çã«å¶éããŸãã
void OnValidate () { if (boardSize.x < 2) { boardSize.x = 2; } if (boardSize.y < 2) { boardSize.y = 2; } }
Onvalidateã¯ãã€åŒã³åºãããŸããïŒååšããå ŽåãUnityãšãã£ã¿ãŒã¯ãã³ã³ããŒãã³ããå€æŽããåŸããããåŒã³åºããŸãã ã²ãŒã ãªããžã§ã¯ããžã®è¿œå æãã·ãŒã³ã®ããŒãåŸãåã³ã³ãã€ã«åŸããšãã£ã¿ãŒã§ã®å€æŽåŸããã£ã³ã»ã«/åè©Šè¡åŸãããã³ã³ã³ããŒãã³ãã®ãªã»ããåŸãå«ã¿ãŸãã
OnValidate
ã¯ãã³ã³ããŒãã³ãæ§æãã£ãŒã«ãã«å€ãå²ãåœãŠãããšãã§ããã³ãŒãå
ã®å¯äžã®å Žæã§ãã
ã²ãŒã ãªããžã§ã¯ããããã§ãã²ãŒã ã¢ãŒããéå§ãããšãæ£ãããµã€ãºã®ãã£ãŒã«ããååŸãããŸãã ã²ãŒã äžãããŒãå
šäœãèŠããããã«ã«ã¡ã©ãé
眮ãããã®å€æã³ã³ããŒãã³ããã³ããŒãããã¬ã€ã¢ãŒããçµäºããŠãã³ã³ããŒãã³ãã®å€ã貌ãä»ããŸãã åç¹ã«11Ã11ãã£ãŒã«ããããå ŽåãäžããèŠãããããããã«ãã«ã¡ã©ãäœçœ®ïŒ0.10.0ïŒã«é
眮ããX軞ã«æ²¿ã£ãŠ90°å転ã§ããŸããã«ã¡ã©ã¯ãã®åºå®äœçœ®ã®ãŸãŸã«ããŸãããå¯èœã§ããå°æ¥å€æŽããŸãã
ãã£ãŒã«ãäžã®ã«ã¡ã©ãã³ã³ããŒãã³ãå€ãã³ããŒããŠè²Œãä»ããæ¹æ³ã¯ïŒã³ã³ããŒãã³ãã®å³äžé
ã«ããæ¯è»ãã¿ã³ãã¯ãªãã¯ãããšè¡šç€ºãããããããããŠã³ã¡ãã¥ãŒããã
ãã¬ããã¿ã€ã«
ãã£ãŒã«ãã¯æ£æ¹åœ¢ã®ã¿ã€ã«ã§æ§æãããŠããŸãã æµã¯ã¿ã€ã«ããã¿ã€ã«ãžãšç§»åã§ããŸããããšããžã暪åãããšã¯ã§ããŸãããæãã«ã¯ã§ããŸããã 移åã¯åžžã«æãè¿ããšã³ããã€ã³ãã«åãã£ãŠè¡ãããŸãã ç¢å°ã«æ²¿ã£ãŠã¿ã€ã«ã«æ²¿ã£ã移åæ¹åãã°ã©ãã£ã«ã«ã«ç€ºããŸãããã
ãã¡ãããç¢å°ãã¯ã¹ãã£ãããŠã³ããŒãã§ããŸãã
é»ã®èæ¯ã®ç¢å°ããããžã§ã¯ãã«ç¢å°ãã¯ã¹ãã£ãé
眮ãã
Alpha As Transparencyãªãã·ã§ã³ãæå¹ã«ããŸãã 次ã«ãã«ããã¢ãŠãã¢ãŒããéžæãããŠããããã©ã«ãã®ãããªã¢ã«ã«ããããšãã§ããç¢å°ã®ãããªã¢ã«ãäœæããã¡ã€ã³ãã¯ã¹ãã£ãšããŠç¢å°ãéžæããŸãã
ç¢å°çŽ æãã«ããã¢ãŠãã¬ã³ããªã³ã°ã¢ãŒãã䜿çšããçç±ããã«ãããæšæºã®Unityã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã䜿çšãããšãã«ç¢å°ãäžæçã«ããããšãã§ããŸãã
ã²ãŒã å
ã®åã¿ã€ã«ã瀺ãããã«ãã²ãŒã ãªããžã§ã¯ãã䜿çšããŸãã ãã£ãŒã«ããå°çã®ã¯ã¯ãããæã£ãŠããã®ãšåãããã«ããããã®ããããã¯ãç¢å°ãããªã¢ã«ãæã€ç¬èªã®ã¯ã¯ãããæã£ãŠããŸãã ãŸããç¢å°ãžã®ãªã³ã¯ãå«ãGameTileã³ã³ããŒãã³ãã«ã¿ã€ã«ãè¿œå ããŸãã
using UnityEngine; public class GameTile : MonoBehaviour { [SerializeField] Transform arrow = default; }
ã¿ã€ã«ãªããžã§ã¯ããäœæãããã¬ããã«å€æããŸãã ã¿ã€ã«ã¯å°é¢ãšåãé«ãã«ãªãã®ã§ãç¢å°ãå°ãäžããŠãã¬ã³ããªã³ã°æã®å¥¥è¡ãã®åé¡ãåé¿ããŸãã ãŸããé£æ¥ããç¢å°ã®éã«ã¹ããŒã¹ãã»ãšãã©ãªãããã«ãå°ããºãŒã ã¢ãŠãããŸãã Yã®0.001ã®ã·ãããš0.8ã®ã¹ã±ãŒã«ã¯ããã¹ãŠã®è»žã§åãã§ãã
ãã¬ããã¿ã€ã«ããã¬ããã¿ã€ã«éå±€ã¯ã©ãã«ãããŸããïŒãã¬ããã¢ã»ãããããã«ã¯ãªãã¯ãããããã¬ãããéžæããŠã€ã³ã¹ãã¯ã¿ãŒã®[ãã¬ãããéã ]ãã¿ã³ãã¯ãªãã¯ãããšããã¬ããç·šéã¢ãŒããéãããšãã§ããŸãã éå±€ããããŒã®å·Šäžé
ã«ããç¢å°ã®ä»ãããã¿ã³ãã¯ãªãã¯ãããšããã¬ããç·šéã¢ãŒããçµäºã§ããŸãã
ã¿ã€ã«èªäœã¯ã²ãŒã ãªããžã§ã¯ãã§ããå¿
èŠã¯ãããŸããã ãã£ãŒã«ãã®ç¶æ
ã远跡ããããã«ã®ã¿å¿
èŠã§ãã
ãªããžã§ã¯ã管çã·ãªãŒãºã®ãã¥ãŒããªã¢ã«ã®åäœãšåãã¢ãããŒãã䜿çšã§ããŸãã ããããåçŽãªã²ãŒã ãã²ãŒã ãªããžã§ã¯ãã®ãããã¿ã€ãã®åæ段éã§ã¯ãéåžžã«æºè¶³ããŠããŸãã ããã¯å°æ¥å€æŽãããå¯èœæ§ããããŸãã
ã¿ã€ã«ããããŸã
ã¿ã€ã«ãäœæããã«ã¯ã
GameBoard
ã«ã¿ã€ã«ãã¬ãããžã®ãªã³ã¯ãå¿
èŠã§ãã
[SerializeField] GameTile tilePrefab = default;
ãã¬ããã¿ã€ã«ãžã®ãªã³ã¯ããã®åŸã2ã€ã®ã°ãªãã次å
ã§ããã«ãµã€ã¯ã«ã䜿çšããŠã€ã³ã¹ã¿ã³ã¹ãäœæã§ããŸãã ãµã€ãºã¯XãšYã§è¡šãããŸãããXZå¹³é¢ãšãã£ãŒã«ãèªäœã«ã¿ã€ã«ãé
眮ããŸãã ãã£ãŒã«ãã¯åç¹ãåºæºã«äžå€®ã«é
眮ãããããã察å¿ãããµã€ãºãã1ã2ã§å²ã£ãå€ãã¿ã€ã«äœçœ®ã®ã³ã³ããŒãã³ãããæžç®ããå¿
èŠããããŸãã ããã¯æµ®åå°æ°ç¹é€ç®ã§ãªããã°ãªããªãããšã«æ³šæããŠãã ãããããããªããšãå¶æ°ãµã€ãºã§ã¯æ©èœããŸããã
public void Initialize (Vector2Int size) { this.size = size; ground.localScale = new Vector3(size.x, size.y, 1f); Vector2 offset = new Vector2( (size.x - 1) * 0.5f, (size.y - 1) * 0.5f ); for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { GameTile tile = Instantiate(tilePrefab); tile.transform.SetParent(transform, false); tile.transform.localPosition = new Vector3( x - offset.x, 0f, y - offset.y ); } } }
ã¿ã€ã«ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãããåŸã§ãããã®ã¿ã€ã«ã«ã¢ã¯ã»ã¹ããå¿
èŠããããããã¿ã€ã«ãé
åã§è¿œè·¡ããŸãã åæååŸããã£ãŒã«ãã®ãµã€ãºã¯å€ãããªãããããªã¹ãã¯å¿
èŠãããŸããã
GameTile[] tiles; public void Initialize (Vector2Int size) { ⊠tiles = new GameTile[size.x * size.y]; for (int i = 0, y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++, i++) { GameTile tile = tiles[i] = Instantiate(tilePrefab); ⊠} } }
ãã®å²ãåœãŠã¯ã©ã®ããã«æ©èœããŸããïŒããã¯ãªã³ã¯ãããå²ãåœãŠã§ãã ãã®å Žåãããã¯ãã¿ã€ã«ã€ã³ã¹ã¿ã³ã¹ãžã®ãªã³ã¯ãé
åèŠçŽ ãšããŒã«ã«å€æ°ã®äž¡æ¹ã«å²ãåœãŠãããšãæå³ããŸãã ãããã®æäœã¯ã以äžã«ç€ºãã³ãŒããšåãããã«å®è¡ãããŸãã
GameTile t = Instantiate(tilePrefab); tiles[i] = t; GameTile tile = t;
éãæ¢ã
ãã®æ®µéã§ã¯ãåã¿ã€ã«ã«ã¯ç¢å°ããããŸããããããã¯ãã¹ãŠZ軞ã®æ£ã®æ¹åãæãããããåãšè§£éããŸãã 次ã®ã¹ãããã¯ãã¿ã€ã«ã®æ£ããæ¹åã決å®ããããšã§ãã ãããè¡ãã«ã¯ãæµãçµç¹ã«å°éããªããã°ãªããªãçµè·¯ãèŠã€ããŸãã
ã¿ã€ã«ã®é£äºº
ãã¹ã¯ãã¿ã€ã«ããã¿ã€ã«ãžãåãæ±ãåããŸãã¯è¥¿ã®æ¹åã«é²ã¿ãŸãã æ€çŽ¢ãç°¡çŽ åããããã«ã
GameTile
4ã€ã®é£äººãžã®ãªã³ã¯ã远跡ãããŸãã
GameTile north, east, south, west;
é£å士ã®é¢ä¿ã¯å¯Ÿç§°çã§ãã ã¿ã€ã«ã2çªç®ã®ã¿ã€ã«ã®æ±é£ã§ããå Žåã2çªç®ã¯æåã®ã¿ã€ã«ã®è¥¿é£ã§ãã äžè¬çãªéçã¡ãœããã
GameTile
ã«è¿œå ããŠã2ã€ã®ã¿ã€ã«éã®ãã®é¢ä¿ãå®çŸ©ããŸãã
public static void MakeEastWestNeighbors (GameTile east, GameTile west) { west.east = east; east.west = west; }
éçã¡ãœããã䜿çšããçç±åäžã®ãã©ã¡ãŒã¿ãŒãæã€ã€ã³ã¹ã¿ã³ã¹ã¡ãœããã«ããããšãã§ããŸãããã®å Žåã eastTile.MakeEastWestNeighbors(westTile)
ãŸãã¯ãã®ãããªãã®ãšããŠåŒã³åºããŸãã ãã ããã©ã®ã¿ã€ã«ã§ã¡ãœãããåŒã³åºãå¿
èŠãããããæ確ã§ãªãå Žåã¯ãéçã¡ãœããã䜿çšããããšããå§ãããŸãã äŸã¯ã Vector3
ã¯ã©ã¹ã®Distance
ããã³Dot
ã¡ãœããã§ãã
æ¥ç¶ãããšãå€æŽãããããšã¯ãããŸããã ãããçºçããå Žåãã³ãŒããééããŸããã ããã確èªããã«ã¯ãå€ã
null
ã«å²ãåœãŠãåã«äž¡æ¹ã®ãªã³ã¯ãæ¯èŒããæ£ãããªãå Žåã¯ãšã©ãŒã衚瀺ããŸãã
Debug.Assert
ã¯
Debug.Assert
ã¡ãœããã䜿çšã§ããŸãã
public static void MakeEastWestNeighbors (GameTile east, GameTile west) { Debug.Assert( west.east == null && east.west == null, "Redefined neighbors!" ); west.east = east; east.west = west; }
Debug.Assertã¯äœãããŸããïŒæåã®åŒæ°ãfalse
å Žåã2çªç®ã®åŒæ°ãæå®ãããŠããå Žåã¯ããã䜿çšããŠãæ¡ä»¶ãšã©ãŒã衚瀺ããŸãã ãã®ãããªåŒã³åºãã¯ãã¹ããã«ãã«ã®ã¿å«ãŸãããªãªãŒã¹ãã«ãã«ã¯å«ãŸããŸããã ãããã£ãŠãããã¯éçºããã»ã¹äžã«æçµãªãªãŒã¹ã«åœ±é¿ããªããã§ãã¯ãè¿œå ããã®ã«é©ããæ¹æ³ã§ãã
åæ§ã®æ¹æ³ãè¿œå ããŠãåãšåã®é£äººã®éã®é¢ä¿ãäœæããŸãã
public static void MakeNorthSouthNeighbors (GameTile north, GameTile south) { Debug.Assert( south.north == null && north.south == null, "Redefined neighbors!" ); south.north = north; north.south = south; }
GameBoard.Initialize
ã¿ã€ã«ãäœæãããšãã«ãã®é¢ä¿ã確ç«ã§ããŸãã X座æšããŒããã倧ããå ŽåãçŸåšã®ã¿ã€ã«ãšåã®ã¿ã€ã«ã®éã«æ±è¥¿ã®é¢ä¿ãäœæã§ããŸãã Y座æšããŒããã倧ããå ŽåãçŸåšã®ã¿ã€ã«ãšåã®è¡ã®ã¿ã€ã«ã®éã«ååé¢ä¿ãäœæã§ããŸãã
for (int i = 0, y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++, i++) { ⊠if (x > 0) { GameTile.MakeEastWestNeighbors(tile, tiles[i - 1]); } if (y > 0) { GameTile.MakeNorthSouthNeighbors(tile, tiles[i - size.x]); } } }
ãã£ãŒã«ãã®ç«¯ã«ããã¿ã€ã«ã«ã¯4ã€ã®é£æ¥ããªãããšã«æ³šæããŠãã ããã 1ã€ãŸãã¯2ã€ã®é£æ¥åç
§ã¯
null
ãŸãŸã§ãã
è·é¢ãšæ¹å
ãã¹ãŠã®æµã«çµ¶ããéãæ¢ãããããšã¯ãããŸããã ããã¯ãã¿ã€ã«ããšã«1åã ãå®è¡ããå¿
èŠããããŸãã ãã®åŸãæµã¯ç§»åå
ã®ã¿ã€ã«ãããªã¯ãšã¹ãã§ããããã«ãªããŸãã ãã¹ã®æ¬¡ã®ã¿ã€ã«ãžã®ãªã³ã¯ãè¿œå ããŠããã®æ
å ±ã
GameTile
ããŸãã ããã«ããšã³ããã€ã³ããŸã§ã®è·é¢ãä¿åããŸããããã¯ãæµããšã³ããã€ã³ãã«å°éããåã«èšªåããå¿
èŠãããã¿ã€ã«ã®æ°ãšããŠè¡šãããŸãã æµã«ãšã£ãŠããã®æ
å ±ã¯åœ¹ã«ç«ããªãããæççµè·¯ãèŠã€ããããã«äœ¿çšããã
GameTile north, east, south, west, nextOnPath; int distance;
ãã¹ãæ¢ãå¿
èŠããããšå€æãããã³ã«ããã¹ããŒã¿ãåæåããå¿
èŠããããŸãã ãã¹ãèŠã€ãããŸã§ã次ã®ã¿ã€ã«ã¯ãªããè·é¢ã¯ç¡éãšèŠãªãããšãã§ããŸãã ããã¯
int.MaxValue
å¯èœãªæ倧æŽæ°å€ãšããŠæ³åã§ããŸãã æ±çš
ClearPath
ã¡ãœãããè¿œå ããŠã
GameTile
ããã®ç¶æ
ã«ãªã»ããããŸãã
public void ClearPath () { distance = int.MaxValue; nextOnPath = null; }
ãã¹ã¯ããšã³ããã€ã³ããããå Žåã«ã®ã¿æ€çŽ¢ã§ããŸãã ããã¯ãã¿ã€ã«ããšã³ããã€ã³ãã«ãªãå¿
èŠãããããšãæå³ããŸãã ãã®ãããªã¿ã€ã«ã®è·é¢ã¯0ã«çããããã¹ã¯ãã®äžã§çµäºãããããæåŸã®ã¿ã€ã«ã¯ãããŸããã ã¿ã€ã«ããšã³ããã€ã³ãã«å€æããæ±çšã¡ãœãããè¿œå ããŸãã
public void BecomeDestination () { distance = 0; nextOnPath = null; }
æçµçã«ã¯ããã¹ãŠã®ã¿ã€ã«ããã¹ã«å€ããããããããã®è·é¢ã¯
int.MaxValue
ãšçãããªããŸããã ã¿ã€ã«ã«çŸåšãã¹ããããã©ããã確èªãã䟿å©ãªã²ãã¿ãŒããããã£ãè¿œå ããŸãã
public bool HasPath => distance != int.MaxValue;
ãã®ããããã£ã¯ã©ã®ããã«æ©èœããŸããïŒããã¯ã1ã€ã®åŒã®ã¿ãå«ãã²ãã¿ãŒããããã£ã®ççž®ãšã³ããªã§ãã 以äžã«ç€ºãã³ãŒããšåãã§ãã
public bool HasPath { get { return distance != int.MaxValue; } }
ç¢å°æŒç®å
=>
ã¯ãããããã£ã®ã²ãã¿ãŒãšã»ãã¿ãŒãã¡ãœããã®æ¬äœãã³ã³ã¹ãã©ã¯ã¿ãŒãããã³ãã®ä»ã®å Žæã§åå¥ã«äœ¿çšããããšãã§ããŸãã
éãè²ãŠã
ãã¹ã®ããã¿ã€ã«ãããå Žåã¯ãã¿ã€ã«ããã®é£ã®ã¿ã€ã«ã«åãã£ãŠãã¹ãæé·ãããããšãã§ããŸãã æåã¯ããã¹ãæã€å¯äžã®ã¿ã€ã«ã¯çµç¹ã§ããããããŒãè·é¢ããéå§ããŠããããå¢å ãããæµã®åããšã¯å察æ¹åã«ç§»åããŸãã ã€ãŸãããšã³ããã€ã³ãã®ããé£ã®ãã¹ãŠã®è·é¢ã¯1ã«ãªãããããã®ã¿ã€ã«ã®ãã¹ãŠã®é£ã®è·é¢ã¯2ã«ãªããŸãã
GameTile
é ãã¡ãœãããè¿œå ããŠããã©ã¡ãŒã¿ãŒã§æå®ãããè¿é£ã®1
GameTile
ãã¹ãæ¡å€§ããŸãã é£äººãŸã§ã®è·é¢ã¯çŸåšã®ã¿ã€ã«ããã1ã€å€§ãããé£äººã®ãã¹ã¯çŸåšã®ã¿ã€ã«ã瀺ããŸãã ãã®ã¡ãœããã¯ããã§ã«ãã¹ãããã¿ã€ã«ã«å¯ŸããŠã®ã¿åŒã³åºãå¿
èŠããããããã¢ãµãŒãã§ããã確èªããŸãããã
void GrowPathTo (GameTile neighbor) { Debug.Assert(HasPath, "No path!"); neighbor.distance = distance + 1; neighbor.nextOnPath = this; }
ã¢ã€ãã¢ã¯ãã¿ã€ã«ã®4ã€ã®é£æ¥ã®ããããã«å¯ŸããŠãã®ã¡ââãœããã1ååŒã³åºããšããããšã§ãã ãããã®ãªã³ã¯ã®äžéšã¯
null
ã«ãªããããããããã§ãã¯ããããã§ããã°å®è¡ãåæ¢ããŸãã ããã«ãé£äººããã§ã«ãã¹ãæã£ãŠããå Žåãäœãããã«ããããã¹ãã§ãã
void GrowPathTo (GameTile neighbor) { Debug.Assert(HasPath, "No path!"); if (neighbor == null || neighbor.HasPath) { return; } neighbor.distance = distance + 1; neighbor.nextOnPath = this; }
GameTile
ãè¿é£ã远跡ããæ¹æ³ã¯ãæ®ãã®ã³ãŒãã§ã¯äžæã§ãã ãããã£ãŠã
GrowPathTo
ã¯é衚瀺ã«ãªããŸãã
GrowPathTo
éæ¥çã«åŒã³åºããŠãç¹å®ã®æ¹åã«ãã¹ãæ¡å€§ããããã¿ã€ã«ã«æ瀺ããäžè¬çãªã¡ãœãããè¿œå ããŸãã ãã ãããã£ãŒã«ãå
šäœãæ€çŽ¢ããã³ãŒãã¯ã蚪åãããã¿ã€ã«ã远跡ããå¿
èŠããããŸãã ãããã£ãŠãå®è¡ãçµäºããå Žåããã€ããŒãŸãã¯
null
è¿ããŸãã
GameTile GrowPathTo (GameTile neighbor) { if (!HasPath || neighbor == null || neighbor.HasPath) { return null; } neighbor.distance = distance + 1; neighbor.nextOnPath = this; return neighbor; }
次ã«ãç¹å®ã®æ¹åã«ãã¹ãæ¡å€§ããã¡ãœãããè¿œå ããŸãã
public GameTile GrowPathNorth () => GrowPathTo(north); public GameTile GrowPathEast () => GrowPathTo(east); public GameTile GrowPathSouth () => GrowPathTo(south); public GameTile GrowPathWest () => GrowPathTo(west);
åºãæ€çŽ¢
GameBoard
ã¯ããã¹ãŠã®ã¿ã€ã«ã«æ£ãããã¹ããŒã¿ãå«ãŸããŠãã
GameBoard
ã
GameBoard
å¿
èŠããããŸãã ãããè¡ãã«ã¯ãå¹
åªå
æ€çŽ¢ãå®è¡ããŸãã ãšã³ããã€ã³ãã¿ã€ã«ããå§ããŠããã®é£ã®ã¿ã€ã«ãžã®ãã¹ãæ¡å€§ãã次ã«ãããã®ã¿ã€ã«ã®é£ãžã®ãã¹ãæ¡å€§ããŸãã åã¹ãããã§ãè·é¢ã¯1ãã€å¢å ãããã¹ãæ¢ã«ãã¹ãæã£ãŠããã¿ã€ã«ã®æ¹åã«æé·ããããšã¯ãããŸããã ããã«ãããçµæãšããŠãã¹ãŠã®ã¿ã€ã«ããšã³ããã€ã³ããžã®æçãã¹ã«æ²¿ã£ãŠãã€ã³ããããããã«ãªããŸãã
A *ã䜿çšããŠãã¹ãèŠã€ããã®ã¯ã©ãã§ããïŒA
*ã¢ã«ãŽãªãºã ã¯ãå¹
åªå
æ¢çŽ¢ã®é²åçéçºã§ãã å¯äžã®æççµè·¯ãæ¢ããŠãããšãã«äŸ¿å©ã§ãã ãã ãããã¹ãŠã®æçãã¹ãå¿
èŠãªã®ã§ãA
*ã«ã¯å©ç¹ããããŸããã å¹
åªå
æ€çŽ¢ããã³ã¢ãã¡ãŒã·ã§ã³ä»ãã®å
è§åœ¢ã®ã°ãªããã§ã®A
*ã®äŸã«ã€ããŠ
ã¯ãå
è§åœ¢ã®ãããã«é¢ããäžé£ã®ãã¥ãŒããªã¢ã«ãåç
§ããŠãã ããã
æ€çŽ¢ãå®è¡ããã«ã¯ããã¹ã«è¿œå ãããããŸã ãã¹ãæ¡å€§ããŠããªãã¿ã€ã«ã远跡ããå¿
èŠããããŸãã ãã®ã¿ã€ã«ã®ã³ã¬ã¯ã·ã§ã³ã¯ãå€ãã®å Žåãæ€çŽ¢ããã³ãã£ã¢ãšåŒã°ããŸãã ã¿ã€ã«ã¯ãå¢çç·ã«è¿œå ãããã®ãšåãé åºã§åŠçãããããšãéèŠã§ãããããã£ãŠã
Queue
䜿çšããŸãããã åŸã§æ€çŽ¢ãæ°åå®è¡ããå¿
èŠãããããã
GameBoard
ãã£ãŒã«ããšããŠèšå®ããŸãããã
using UnityEngine; using System.Collections.Generic; public class GameBoard : MonoBehaviour { ⊠Queue<GameTile> searchFrontier = new Queue<GameTile>(); ⊠}
競æå Žã®ç¶æ
ãåžžã«trueã§ããããã«ã¯ã
Initialize
ã®æåŸã«ãã¹ãèŠã€ããå¿
èŠããããŸãããå¥ã®
FindPaths
ã¡ãœããã«ã³ãŒããé
眮ããå¿
èŠããããŸãã ãŸãããã¹ãŠã®ã¿ã€ã«ã®ãã¹ãã¯ãªã¢ããŠããã1ã€ã®ã¿ã€ã«ããšã³ããã€ã³ãã«ããŠå¢çç·ã«è¿œå ããå¿
èŠããããŸãã æåã«æåã®ã¿ã€ã«ãéžæããŸãããã
tiles
ã¯é
åã§ãããããã¡ã¢ãªæ±æãæããããšãªã
foreach
ã䜿çšã§ããŸãã åŸã§é
åãããªã¹ãã«ç§»åããå Žåã
foreach
ã«ãŒãã
for
ã«ãŒãã«çœ®ãæããå¿
èŠããããŸãã
public void Initialize (Vector2Int size) { ⊠FindPaths(); } void FindPaths () { foreach (GameTile tile in tiles) { tile.ClearPath(); } tiles[0].BecomeDestination(); searchFrontier.Enqueue(tiles[0]); }
次ã«ãå¢çç·ãã1ã€ã®ã¿ã€ã«ãååŸãããã¹ãŠã®é£æ¥ã¿ã€ã«ãžã®ãã¹ãæé·ãããŠãããããã¹ãŠãå¢çç·ã«è¿œå ããå¿
èŠããããŸãã æåã«åã次ã«æ±ãåãæåŸã«è¥¿ã«ç§»åããŸãã
public void FindPaths () { foreach (GameTile tile in tiles) { tile.ClearPath(); } tiles[0].BecomeDestination(); searchFrontier.Enqueue(tiles[0]); GameTile tile = searchFrontier.Dequeue(); searchFrontier.Enqueue(tile.GrowPathNorth()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathWest()); }
ãã®æ®µéãç¹°ãè¿ããŸãããå¢çç·ã«ã¯ã¿ã€ã«ããããŸãã
while (searchFrontier.Count > 0) { GameTile tile = searchFrontier.Dequeue(); searchFrontier.Enqueue(tile.GrowPathNorth()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathWest()); }
ãã¹ãéæããŠããå¿
ãããæ°ããã¿ã€ã«ã«å°éãããšã¯éããŸããã ãã¥ãŒã«è¿œå ããåã«ã
null
ã®å€ããã§ãã¯ããå¿
èŠããããŸããããã¥ãŒããã®åºåã®åŸãŸã§
null
ã®ãã§ãã¯ã延æã§ããŸãã
GameTile tile = searchFrontier.Dequeue(); if (tile != null) { searchFrontier.Enqueue(tile.GrowPathNorth()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathWest()); }
衚瀺ãã¹
ããã§æ£ãããã¹ãå«ããã£ãŒã«ããã§ããŸããããä»ã®ãšããããã¯è¡šç€ºãããŸããã ã¿ã€ã«ãéããã¹ã«æ²¿ã£ãŠç¢å°ãåãããã«ç¢å°ãæ§æããå¿
èŠããããŸãã ããã¯ãããããåãããšã§å®è¡ã§ããŸãã ãããã®ã¿ãŒã³ã¯åžžã«åããªã®ã§ãæ¹åããšã«éçãª
Quaternion
ãã£ãŒã«ãã
GameTile
1ã€è¿œå ããŸãã
static Quaternion northRotation = Quaternion.Euler(90f, 0f, 0f), eastRotation = Quaternion.Euler(90f, 90f, 0f), southRotation = Quaternion.Euler(90f, 180f, 0f), westRotation = Quaternion.Euler(90f, 270f, 0f);
ãŸããäžè¬çãª
ShowPath
ã¡ãœãããè¿œå ããŸãã è·é¢ããŒãã®å Žåãã¿ã€ã«ã¯çµç¹ã§ãããæããã®ã¯äœããªãã®ã§ããã®ç¢å°ãéã¢ã¯ãã£ãã«ããŸãã ãã以å€ã®å Žåã¯ãç¢å°ãã¢ã¯ãã£ãã«ããŠãã®å転ãèšå®ããŸãã ç®çã®æ¹åã¯ã
nextOnPath
ããã®è¿é£ãšæ¯èŒããããšã§æ±ºå®ã§ããŸãã
public void ShowPath () { if (distance == 0) { arrow.gameObject.SetActive(false); return; } arrow.gameObject.SetActive(true); arrow.localRotation = nextOnPath == north ? northRotation : nextOnPath == east ? eastRotation : nextOnPath == south ? southRotation : westRotation; }
æåŸã«ãã¹ãŠã®ã¿ã€ã«ã«å¯ŸããŠãã®ã¡ââãœãããåŒã³åºãGameBoard.FindPaths
ãŸãã public void FindPaths () { ⊠foreach (GameTile tile in tiles) { tile.ShowPath(); } }
èŠã€ããæ¹æ³ãç¢å°ãçŽæ¥GrowPathToã«å€ããŠã¿ãŸãããïŒæ€çŽ¢ã®ããžãã¯ãšèŠèŠåãåé¢ãããããåŸã§ãèŠèŠåãç¡å¹ã«ããŸããç¢å°ã衚瀺ãããªãå ŽåããåŒã³åºããã³ã«ç¢å°ãå転ãããå¿
èŠã¯ãããŸããFindPaths
ã
æ€çŽ¢ã®åªå
床ãå€æŽãã
çµç¹ãå西ã®è§ã§ããå Žåããã¹ãŠã®ãã¹ã¯ãã£ãŒã«ãã®ç«¯ã«å°éãããŸã§æ£ç¢ºã«è¥¿ã«é²ã¿ããã®åŸåã«æ²ããããšãããããŸããããã§ã¯ãã¹ãŠãçå®ã§ãããªããªããæãã®åãã¯äžå¯èœã ããã§ããããããä»ã«ããããã«èŠããå¯èœæ§ã®ããæççµè·¯ã¯ä»ã«ããããããããŸãããã®ãããªãã¹ãèŠã€ããçç±ãããããç解ããã«ã¯ãçµç¹ããããã®äžå¿ã«ç§»åããŸããå¥æ°ã®ãã£ãŒã«ããµã€ãºã§ã¯ãé
åã®äžå€®ã«ããåãªãã¿ã€ã«ã§ãã tiles[tiles.Length / 2].BecomeDestination(); searchFrontier.Enqueue(tiles[tiles.Length / 2]);
äžå€®ã®çµç¹ãæ€çŽ¢ã®ä»çµã¿ãèŠããŠããã°ãçµæã¯è«ççã«èŠããŸããé£äººãåæ±åæ±ã®é åºã§è¿œå ãããããåã®åªå
床ãæãé«ããªããŸããéé ã§æ€çŽ¢ããŠããã®ã§ãããã¯æåŸã«ç§»åããæ¹åãåã§ããããšãæå³ããŸãããã®ãããåãæãç¢å°ã¯ãããã§ãæ±ãæãç¢å°ã¯å€ããªã£ãŠããŸããã«ãŒãã®åªå
é äœãèšå®ããŠãçµæãå€æŽã§ããŸããæ±ãšåã亀æããŸãããããããã£ãŠãååããã³æ±è¥¿ã®å¯Ÿç§°æ§ãååŸããå¿
èŠããããŸãã searchFrontier.Enqueue(tile.GrowPathNorth()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathWest())
æ€çŽ¢é åºã¯ãååæ±è¥¿ã§ããèŠãç®ã¯ãããã§ããããã¹ãæ¹åãå€ããèªç¶ã«èŠããåãã«æãã«è¿ã¥ãæ¹ãè¯ãã§ãããããè¡ãã«ã¯ãåžæŸæš¡æ§ã®é£æ¥ã¿ã€ã«ã®æ€çŽ¢åªå
é äœãéã«ããŸããæ€çŽ¢äžã«åŠçããŠããã¿ã€ã«ã®ã¿ã€ããææ¡ãã代ããã«GameTile
ãçŸåšã®ã¿ã€ã«ã代æ¿ã§ãããã©ããã瀺ãäžè¬ããããã£ã«è¿œå ããŸãã public bool IsAlternative { get; set; }
ãã®ããããã£ã¯ã§èšå®ããŸãGameBoard.Initialize
ãæåã«ãX座æšãå¶æ°ã®å Žåãã¿ã€ã«ã代æ¿ãšããŠããŒã¯ããŸãã for (int i = 0, y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++, i++) { ⊠tile.IsAlternative = (x & 1) == 0; } }
æäœïŒxïŒ1ïŒ== 0ã¯äœãããŸããïŒâ (AND). . 1, 1. 10101010 00001111 00001010.
. 0 1. 1, 2, 3, 4 1, 10, 11, 100. , .
AND , , . , .
次ã«ãY座æšãå¶æ°ã®å Žåãçµæã®ç¬Šå·ãå€æŽããŸããããã§ããã§ã¹ãã¿ãŒã³ãäœæããŸãã tile.IsAlternative = (x & 1) == 0; if ((y & 1) == 0) { tile.IsAlternative = !tile.IsAlternative; }
FindPaths
æã
ã¯ä»£æ¿ã¿ã€ã«ã®æ€çŽ¢ãšåãé åºãç¶æããããä»ã®ãã¹ãŠã®ã¿ã€ã«ã«æ»ã£ãŠãããäœãããã«ãããã«ããããã¹ãæãã«ç§»åãããžã°ã¶ã°ã«ãªããŸãã if (tile != null) { if (tile.IsAlternative) { searchFrontier.Enqueue(tile.GrowPathNorth()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathWest()); } else { searchFrontier.Enqueue(tile.GrowPathWest()); searchFrontier.Enqueue(tile.GrowPathEast()); searchFrontier.Enqueue(tile.GrowPathSouth()); searchFrontier.Enqueue(tile.GrowPathNorth()); } }
å¯å€æ€çŽ¢é åºãã¿ã€ã«ã®å€æŽ
ãã®æç¹ã§ããã¹ãŠã®ã¿ã€ã«ã¯ç©ºã§ãã1ã€ã®ã¿ã€ã«ããšã³ããã€ã³ããšããŠäœ¿çšãããŸãããç®ã«èŠããç¢å°ããªãããšã«å ããŠãä»ã®ãã¹ãŠã®ã¿ã€ã«ãšåãããã«èŠããŸãããªããžã§ã¯ããé
眮ããŠã¿ã€ã«ãå€æŽããæ©èœãè¿œå ããŸããã¿ã€ã«ã³ã³ãã³ã
ã¿ã€ã«ãªããžã§ã¯ãèªäœã¯ãã¿ã€ã«æ
å ±ã远跡ããæ¹æ³ã«ãããŸããããããã®ãªããžã§ã¯ããçŽæ¥å€æŽããããšã¯ãããŸããã代ããã«ãåå¥ã®ã³ã³ãã³ããè¿œå ããŠãã£ãŒã«ãã«é
眮ããŸããä»ã®ãšããã空ã®ã¿ã€ã«ãšãšã³ããã€ã³ãã¿ã€ã«ãåºå¥ã§ããŸãããããã®ã±ãŒã¹ã瀺ãã«ã¯ãåæãäœæããŸãGameTileContentType
ã public enum GameTileContentType { Empty, Destination }
次ã«ãGameTileContent
ã€ã³ã¹ãã¯ã¿ãŒã䜿çšããŠãã®ã³ã³ãã³ãã®ã¿ã€ããèšå®ã§ããã³ã³ããŒãã³ãã¿ã€ããäœæããŸããã³ã³ããŒãã³ãã¿ã€ããžã®ã¢ã¯ã»ã¹ã¯ãå
±éã®getterããããã£ãä»ããŠè¡ãããŸãã using UnityEngine; public class GameTileContent : MonoBehaviour { [SerializeField] GameTileContentType type = default; public GameTileContentType Type => type; }
次ã«ã2ã€ã®ã¿ã€ãã®ã³ã³ãã³ãçšã®ãã¬ãããäœæããŸããåã³ã³ãã³ãã«GameTileContent
ã¯ã察å¿ããæå®ãããã¿ã€ãã®ã³ã³ããŒãã³ãããããŸããéãå¹³ããªç«æ¹äœã䜿çšããŠããšã³ããã€ã³ãã¿ã€ã«ãæå®ããŸããããã»ãšãã©å¹³ããªã®ã§ãã³ã©ã€ããŒã¯å¿
èŠãããŸããã空ã®ã³ã³ãã³ãããã¬ããããã«ã¯ã空ã®ã²ãŒã ãªããžã§ã¯ãã䜿çšããŸãããšã³ããã€ã³ãã®ãã¬ãããšç©ºã®ã³ã³ãã³ããã³ã³ãã³ããªããžã§ã¯ãã空ã®ã¿ã€ã«ã«æž¡ããŸããããã¯ããã¹ãŠã®ã¿ã€ã«ã«åžžã«ã³ã³ãã³ããå«ãŸãããããã³ã³ãã³ããžã®ãªã³ã¯ãçãããã©ããããã§ãã¯ããå¿
èŠããªãããnull
ã§ããã³ã³ãã³ããã¡ã¯ããªãŒ
ã³ã³ãã³ããç·šéå¯èœã«ããããã«ããªããžã§ã¯ã管çãã¥ãŒããªã¢ã«ãšåãã¢ãããŒãã䜿çšããŠããã®ããã®ãã¡ã¯ããªãäœæããŸããããã¯GameTileContent
ãå
ã®ãã¡ã¯ããªã远跡ããäžåºŠã ãèšå®ããå¿
èŠãããããšãæå³ããã¡ãœããã§ãã¡ã¯ããªã«æ»ããŸãRecycle
ã GameTileContentFactory originFactory; ⊠public GameTileContentFactory OriginFactory { get => originFactory; set { Debug.Assert(originFactory == null, "Redefined origin factory!"); originFactory = value; } } public void Recycle () { originFactory.Reclaim(this); }
ããã¯ååšãåæãšããŠããGameTileContentFactory
ãããå¿
èŠãªæ¹æ³ã§ããã®ã¹ã¯ãªããå¯èœãªããžã§ã¯ãã¿ã€ããäœæããŸãRecycle
ããã®æ®µéã§ã¯ãã³ã³ãã³ããå©çšããå®å
šã«æ©èœãããã¡ã¯ããªãŒã®äœæã«ç
©ããããããšã¯ãªãã®ã§ãã³ã³ãã³ããç Žå£ããã ãã§ããåŸã§ãæ®ãã®ã³ãŒããå€æŽããã«ãªããžã§ã¯ãã®åå©çšããã¡ã¯ããªã«è¿œå ããããšãå¯èœã«ãªããŸãã using UnityEngine; using UnityEngine.SceneManagement; [CreateAssetMenu] public class GameTileContentFactory : ScriptableObject { public void Reclaim (GameTileContent content) { Debug.Assert(content.OriginFactory == this, "Wrong factory reclaimed!"); Destroy(content.gameObject); } }
Get
ãã¬ããããã©ã¡ãŒã¿ãŒãšããŠäœ¿çšããŠãé衚瀺ã¡ãœããããã¡ã¯ããªãŒã«è¿œå ããŸããããã§ãããªããžã§ã¯ãã®åå©çšãã¹ãããããŸãã圌ã¯ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ãäœæããå
ã®ãã¡ã¯ããªãèšå®ããããããã¡ã¯ããªã·ãŒã³ã«ç§»åããŠè¿ããŸãã GameTileContent Get (GameTileContent prefab) { GameTileContent instance = Instantiate(prefab); instance.OriginFactory = this; MoveToFactoryScene(instance.gameObject); return instance; }
ã€ã³ã¹ã¿ã³ã¹ã¯å·¥å Žã®ã³ã³ãã³ãã·ãŒã³ã«ç§»åãããå¿
èŠã«å¿ããŠäœæã§ããŸãããšãã£ã¿ã䜿çšããŠããå Žåãã·ãŒã³ãäœæããåã«ãããããªã¹ã¿ãŒãäžã«èŠããªããªã£ãå Žåã«åããŠãã·ãŒã³ãååšãããã©ããã確èªããå¿
èŠããããŸãã Scene contentScene; ⊠void MoveToFactoryScene (GameObject o) { if (!contentScene.isLoaded) { if (Application.isEditor) { contentScene = SceneManager.GetSceneByName(name); if (!contentScene.isLoaded) { contentScene = SceneManager.CreateScene(name); } } else { contentScene = SceneManager.CreateScene(name); } } SceneManager.MoveGameObjectToScene(o, contentScene); }
ã³ã³ãã³ãã¯2çš®é¡ãããªãããã2ã€ã®ãã¬ããæ§æãã£ãŒã«ããè¿œå ããã ãã§ãã [SerializeField] GameTileContent destinationPrefab = default; [SerializeField] GameTileContent emptyPrefab = default;
ãã¡ã¯ããªãæ©èœããããã«æåŸã«è¡ãå¿
èŠãããã®ã¯ã察å¿ãããã¬ããã®ã€ã³ã¹ã¿ã³ã¹ãåãåãGet
ãã©ã¡ãŒã¿ãŒGameTileContentType
ãæã€å
±éã¡ãœãããäœæããããšã§ãã public GameTileContent Get (GameTileContentType type) { switch (type) { case GameTileContentType.Destination: return Get(destinationPrefab); case GameTileContentType.Empty: return Get(emptyPrefab); } Debug.Assert(false, "Unsupported type: " + type); return null; }
空ã®ã³ã³ãã³ãã®åå¥ã®ã€ã³ã¹ã¿ã³ã¹ãåã¿ã€ã«ã«è¿œå ããããšã¯å¿
é ã§ããïŒ, . . , - , , , , . , . , , .
ãã¡ã¯ããªã¢ã»ãããäœæãããã¬ãããžã®ãªã³ã¯ãèšå®ããŸããããã³ã³ãã³ããã¡ã¯ããªããããŠãGame
ãªã³ã¯ãå·¥å Žã«æž¡ããŸãã [SerializeField] GameTileContentFactory tileContentFactory = default;
å·¥å Žãšã®ã²ãŒã ãã¿ã€ã«ã¿ãã
ãã£ãŒã«ããå€æŽããã«ã¯ãã¿ã€ã«ãéžæã§ããå¿
èŠããããŸããã²ãŒã ã¢ãŒãã§å¯èœã«ããŸãããã¬ã€ã€ãŒãã²ãŒã ãŠã£ã³ããŠãã¯ãªãã¯ããå Žæã®ã·ãŒã³ã«å
ç·ãæŸåºããŸããããŒã ãã¿ã€ã«ãšäº€å·®ããå Žåããã¬ã€ã€ãŒã¯ã¿ã€ã«ã«è§ŠããŸãããã€ãŸããå€æŽããå¿
èŠããããŸããGame
ãã¬ãŒã€ãŒã®å
¥åãåŠçããŸããããã¬ãŒã€ãŒãã¿ããããã¿ã€ã«ã決å®ãã責任ãããGameBoard
ãŸãããã¹ãŠã®å
ç·ãã¿ã€ã«ãšäº€å·®ããããã§ã¯ãªããããäœãåãåããªãå ŽåããããŸãããããã£ãŠãåžžã«æåã«åžžã«è¿ãããGameBoard
ã¡ãœããã«ã¡ãœãããè¿œå ãGetTile
ãŸãnull
ïŒããã¯ãã¿ã€ã«ãèŠã€ãããªãã£ãããšãæå³ããŸãïŒã public GameTile GetTile (Ray ray) { return null; }
å
ç·ãã¿ã€ã«ãééãããã©ãããå€æPhysics.Raycast
ããã«ã¯ãå
ç·ãåŒæ°ãšããŠæå®ããŠåŒã³åºãå¿
èŠããããŸãã亀差ç¹ããã£ããã©ããã«é¢ããæ
å ±ãè¿ããŸãããã®å Žåã¯ãã¿ã€ã«ãè¿ãããšãã§ããŸããããŸã ã©ã®ã¿ã€ã«ãããããªãã®ã§ãä»ã®ãšããã¯è¿ããŸãnull
ã public GameTile TryGetTile (Ray ray) { if (Physics.Raycast(ray) { return null; } return null; }
ã¿ã€ã«ãšã®äº€å·®ç¹ããããã©ããã確èªããã«ã¯ã亀差ç¹ã«é¢ãã詳现æ
å ±ãå¿
èŠã§ããPhysics.Raycast
2çªç®ã®ãã©ã¡ãŒã¿ã䜿çšããŠãã®æ
å ±ãæäŸã§ããŸãRaycastHit
ãããã¯åºåãã©ã¡ãŒã¿ãŒã§ããããã®out
åã®åèªã§ç€ºãããŸããããã¯ãã¡ãœããåŒã³åºãããæž¡ããå€æ°ã«å€ãå²ãåœãŠãããšãã§ããããšãæå³ããŸãã RaycastHit hit; if (Physics.Raycast(ray, out hit) { return null; }
åºåãã©ã¡ãŒã¿ãŒã«äœ¿çšãããå€æ°ã®å®£èšãåã蟌ãããšãã§ããŸãã®ã§ãããããã£ãŠã¿ãŸãããã if (Physics.Raycast(ray, out RaycastHit hit) { return null; }
亀差ç¹ãã©ã®ã³ã©ã€ããŒã§çºçãããã¯é¢ä¿ãããŸãããXZ亀差ç¹ã®äœçœ®ã䜿çšããŠã¿ã€ã«ã決å®ããŸãã亀差ç¹ã®åº§æšã«ãã£ãŒã«ãã®ãµã€ãºã®ååãè¿œå ããçµæãæŽæ°å€ã«å€æããããšã«ãããã¿ã€ã«ã®åº§æšãååŸããŸããçµæãšããŠã®æçµçãªã¿ã€ã«ã€ã³ããã¯ã¹ã¯ãX座æšãšY座æšã«ãã£ãŒã«ãå¹
ãæãããã®ã«ãªããŸãã if (Physics.Raycast(ray, out RaycastHit hit)) { int x = (int)(hit.point.x + size.x * 0.5f); int y = (int)(hit.point.z + size.y * 0.5f); return tiles[x + y * size.x]; }
ãã ããããã¯ã¿ã€ã«ã®åº§æšããã£ãŒã«ãå
ã«ããå Žåã«ã®ã¿å¯èœã§ãããããããã確èªããŸããããã§ãªãå Žåãã¿ã€ã«ã¯è¿ãããŸããã int x = (int)(hit.point.x + size.x * 0.5f); int y = (int)(hit.point.z + size.y * 0.5f); if (x >= 0 && x < size.x && y >= 0 && y < size.y) { return tiles[x + y * size.x]; }
ã³ã³ãã³ãã®å€æŽ
ã¿ã€ã«ã®ã³ã³ãã³ããå€æŽã§ããããã«ãGameTile
äžè¬ããããã£ã«è¿œå ããŸãContent
ããã®ã²ãã¿ãŒã¯åã«ã³ã³ãã³ããè¿ããã»ãã¿ãŒã¯åã®ã³ã³ãã³ããããã°ãããç Žæ£ããæ°ããã³ã³ãã³ããé
眮ããŸãã GameTileContent content; public GameTileContent Content { get => content; set { if (content != null) { content.Recycle(); } content = value; content.transform.localPosition = transform.localPosition; } }
null
æåã¯ã³ã³ãã³ãããªããããããã§ã³ã³ãã³ãã確èªããå¿
èŠãããå¯äžã®å Žæã§ããä¿èšŒããããã«ãsetterãã§åŒã³åºãããªãããã«assertãå®è¡ãnull
ãŸãã set { Debug.Assert(value != null, "Null assigned to content!"); ⊠}
ãããŠæåŸã«ããã¬ã€ã€ãŒã®å
¥åãå¿
èŠã§ããããŠã¹ã®ã¯ãªãã¯ãå
ç·ã«å€æããã«ã¯ãåŒæ°ãšããŠScreenPointToRay
with Input.mousePosition
ãåŒã³åºããŸãããä»ããŠã¢ã¯ã»ã¹ã§ããã¡ã€ã³ã«ã¡ã©ã«å¯ŸããŠåŒã³åºããè¡ãå¿
èŠããããŸãCamera.main
ãããã«ããããã£cãè¿œå ããŸãGame
ã Ray TouchRay => Camera.main.ScreenPointToRay(Input.mousePosition);
次ã«Update
ãæŽæ°äžã«ã¡ã€ã³ã®ããŠã¹ãã¿ã³ãæŒããããã©ããã確èªããã¡ãœãããè¿œå ããŸãããããè¡ãã«ã¯Input.GetMouseButtonDown
ãåŒæ°ãšããŠãŒãã§åŒã³åºããŸããããŒãæŒãããå Žåããã¬ãŒã€ãŒã®ã¿ãããåŠçããŸããã€ãŸãããã£ãŒã«ãããã¿ã€ã«ãååŸãããšã³ããã€ã³ãããã®ã³ã³ãã³ããšããŠèšå®ããå·¥å ŽããååŸããŸãã void Update () { if (Input.GetMouseButtonDown(0)) { HandleTouch(); } } void HandleTouch () { GameTile tile = GetTile(TouchRay); if (tile != null) { tile.Content = tileContentFactory.Get(GameTileContentType.Destination); } }
ããã§ãã«ãŒãœã«ãæŒããŠä»»æã®ã¿ã€ã«ããšã³ããã€ã³ãã«å€ããããšãã§ããŸããããã€ãã®ãšã³ããã€ã³ãããã£ãŒã«ããæ£ãããã
ã¿ã€ã«ããšã³ããã€ã³ãã«å€ããããšã¯ã§ããŸãããããã¯ãããŸã§ã®ãã¹ã«ã¯åœ±é¿ããŸãããããã«ãã¿ã€ã«ã«ç©ºã®ã³ã³ãã³ãããŸã èšå®ããŠããŸããããã£ãŒã«ãã®æ£ç¢ºããšæŽåæ§ãç¶æããããšã¯ã¿ã¹ã¯ãªGameBoard
ã®ã§ãã¿ã€ã«ã®ã³ã³ãã³ããèšå®ãã責任ã圌ã«äžããŸãããããããå®è£
ããã«ã¯ãmethodãä»ããŠã³ã³ãã³ããã¡ã¯ããªãžã®ãªã³ã¯ãæäŸããIntialize
ããã䜿çšããŠãã¹ãŠã®ã¿ã€ã«ã«ç©ºã®ã³ã³ãã³ãã®ã€ã³ã¹ã¿ã³ã¹ãæäŸããŸãã GameTileContentFactory contentFactory; public void Initialize ( Vector2Int size, GameTileContentFactory contentFactory ) { this.size = size; this.contentFactory = contentFactory; ground.localScale = new Vector3(size.x, size.y, 1f); tiles = new GameTile[size.x * size.y]; for (int i = 0, y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++, i++) { ⊠tile.Content = contentFactory.Get(GameTileContentType.Empty); } } FindPaths(); }
ä»Game
ãå·¥å ŽãçŸå Žã«ç§»ããªããã°ãªããŸããã void Awake () { board.Initialize(boardSize, tileContentFactory); }
ãã¡ã¯ããªãŒæ§æãã£ãŒã«ããGameBoardã«è¿œå ããŠã¿ãŸãããïŒ, , . , .
ããã§ããã€ãã®ãšã³ããã€ã³ããã§ããGameBoard.FindPaths
ã®ã§ãBecomeDestination
ãããããåŒã³åºããŠãããããã¹ãŠå¢çç·ã«è¿œå ããããã«å€æŽããŸãããããŠãè€æ°ã®ãšã³ããã€ã³ãããµããŒãããã®ã«å¿
èŠãªããšã¯ããã ãã§ããä»ã®ãã¹ãŠã®ã¿ã€ã«ã¯éåžžã©ããã¯ãªã¢ãããŸãã次ã«ãäžå€®ã®ããŒãã»ãããšã³ããã€ã³ããåé€ããŸãã void FindPaths () { foreach (GameTile tile in tiles) { if (tile.Content.Type == GameTileContentType.Destination) { tile.BecomeDestination(); searchFrontier.Enqueue(tile); } else { tile.ClearPath(); } }
ãã ããã¿ã€ã«ããšã³ããã€ã³ãã«å€æã§ããå Žåã¯ãéã®æäœãå®è¡ããŠããšã³ããã€ã³ãã空ã®ã¿ã€ã«ã«å€æã§ããå¿
èŠããããŸãããããããã®åŸããšã³ããã€ã³ãããŸã£ãããªããã£ãŒã«ããååŸã§ããŸãããã®å ŽåãFindPaths
ã¿ã¹ã¯ãå®è¡ã§ããŸãããããã¯ããã¹ãŠã®ã»ã«ã®ãã¹ã®åæååŸã«å¢çã空ã®å Žåã«çºçããŸããããã¯ããã£ãŒã«ãã®ç¡å¹ãªç¶æ
ãšããŠç€ºãããfalse
å®è¡ãè¿ããå®äºããŸããããã§ãªãå Žåã¯ãæåŸã«æ»ãtrue
ãŸãã bool FindPaths () { foreach (GameTile tile in tiles) { ⊠} if (searchFrontier.Count == 0) { return false; } ⊠return true; }
ãšã³ããã€ã³ãã®åé€ã®ãµããŒããå®è£
ããŠã¹ã€ããæäœã«ããæãç°¡åãªæ¹æ³ã空ã®ã¿ã€ã«ãã¯ãªãã¯ããŠããããããšã³ããã€ã³ãã«å€ãããšã³ããã€ã³ããã¯ãªãã¯ããŠãããããåé€ããŸããããããä»ã§ã¯ã³ã³ãã³ãã®å€æŽã«åãçµãã§ããGameBoard
ã®ã§ToggleDestination
ãã¿ã€ã«ããã©ã¡ãŒã¿ãŒãšããäžè¬çãªã¡ãœãããæäŸããŸããããã¿ã€ã«ããšã³ããã€ã³ãã®å Žåã空ã«ããŠã¿ã€ã«ãåŒã³åºããŸãFindPaths
ããã以å€ã®å Žåã¯ãããããšã³ããã€ã³ãã«ããŠåŒã³åºããŸãFindPaths
ã public void ToggleDestination (GameTile tile) { if (tile.Content.Type == GameTileContentType.Destination) { tile.Content = contentFactory.Get(GameTileContentType.Empty); FindPaths(); } else { tile.Content = contentFactory.Get(GameTileContentType.Destination); FindPaths(); } }
ãšã³ããã€ã³ããè¿œå ããŠãç¡å¹ãªãã£ãŒã«ãç¶æ
ãäœæãããããšã¯ãªãããšã³ããã€ã³ããåé€ããããšãã§ããŸãããããã£ãŠãFindPaths
ã¿ã€ã«ã空ã«ããåŸãæ£åžžã«å®è¡ããããã©ããã確èªããŸããããã§ãªãå Žåã¯ãå€æŽããã£ã³ã»ã«ããã¿ã€ã«ãåã³ãšã³ããã€ã³ãFindPaths
ã«æ»ããããäžåºŠåŒã³åºããŠåã®æ£ããç¶æ
ã«æ»ããŸãã if (tile.Content.Type == GameTileContentType.Destination) { tile.Content = contentFactory.Get(GameTileContentType.Empty); if (!FindPaths()) { tile.Content = contentFactory.Get(GameTileContentType.Destination); FindPaths(); } }
æ€èšŒãããå¹ççã«ã§ããŸããïŒ, . , . , . FindPaths
, .
æåŸã«ãæ瀺çã«ãåŒã³åºã代ããã«ãäžå€®ã®ã¿ã€ã«ãåŒæ°ãšããŠInitialize
åŒã³åºãããšãã§ããŸããããã¯ç¡å¹ãªãã£ãŒã«ãç¶æ
ã§éå§ããå¯äžã®æéã§ãããæ£ããç¶æ
ã§çµäºããããšãä¿èšŒãããŠããŸããToggleDestination
FindPaths
public void Initialize ( Vector2Int size, GameTileContentFactory contentFactory ) { âŠ
æåŸã«ãã¿ã€ã«èªäœã®ã³ã³ãã³ããèšå®ãã代ããã«ã匷å¶çã«Game
åŒã³åºãToggleDestination
ãŸãã void HandleTouch () { GameTile tile = board.GetTile(TouchRay); if (tile != null) {
æ£ãããã¹ãæã€è€æ°ã®ãšã³ããã€ã³ããGameãã¿ã€ã«ã®ã³ã³ãã³ããçŽæ¥èšå®ããããšãçŠæ¢ãã¹ãã§ã¯ãªãã§ããããïŒ. . , Game
. , .
å£
ã¿ã¯ãŒãã£ãã§ã³ã¹ã®ç®æšã¯ãæµãæçµå°ç¹ã«å°éããã®ãé²ãããšã§ãããã®ç®æšã¯2ã€ã®æ¹æ³ã§éæãããŸãã第äžã«ã圌ãã殺ãã第äºã«ã圌ãã殺ãããå€ãã®æéãããããã«ã圌ããé
ãããŸããã¿ã€ã«ãã£ãŒã«ãã§ã¯ãæµã移åããå¿
èŠãããè·é¢ãé·ãããããšã§æéã䌞ã°ãããšãã§ããŸããããã¯ãé害ç©ã®ãã£ãŒã«ãã«é
眮ããããšã§å®çŸã§ããŸããéåžžããããã¯æµã殺ãå¡ã§ããããã®ãã¥ãŒããªã¢ã«ã§ã¯å£ã®ã¿ã«å¶éããŸããå
容
å£ã¯å¥ã®ã¿ã€ãã®ã³ã³ãã³ããªã®ã§GameTileContentType
ãèŠçŽ ãè¿œå ããŠã¿ãŸãããã public enum GameTileContentType { Empty, Destination, Wall }
次ã«ãå£ã®ãã¬ãããäœæããŸããä»åã¯ãã¿ã€ã«ã®ã³ã³ãã³ãã®ã²ãŒã ãªããžã§ã¯ããäœæãããã£ãŒã«ãã«åãã¥ãŒããè¿œå ããŸããããã¯ããã£ãŒã«ãã®äžéšã«ãããã¿ã€ã«å
šäœãåããŸããå£ãèåŸã®ã¿ã€ã«ã®äžéšãšèŠèŠçã«éãªãããšããããããé«ããååã«ããŠã³ã©ã€ããŒãç¯çŽããŸãããããã£ãŠããã¬ãŒã€ãŒãå£ã«è§Šãããšã察å¿ããã¿ã€ã«ã«åœ±é¿ãäžããŸãããã¬ããå£ãã³ãŒããšã€ã³ã¹ãã¯ã¿ãŒã®äž¡æ¹ã§ãå·¥å Žã«å£ã®ãã¬ãããè¿œå ããŸãã [SerializeField] GameTileContent wallPrefab = default; ⊠public GameTileContent Get (GameTileContentType type) { switch (type) { case GameTileContentType.Destination: return Get(destinationPrefab); case GameTileContentType.Empty: return Get(emptyPrefab); case GameTileContentType.Wall: return Get(wallPrefab); } Debug.Assert(false, "Unsupported type: " + type); return null; }
ãã¬ããå£ã®å·¥å Žãå£ã®ãªã³ãšãªããåãæ¿ãã
GameBoard
ãšã³ããã€ã³ãã§è¡ã£ãããã«ãå£ããªã³ãŸãã¯ãªãã«ããæ¹æ³ãè¿œå ããŸããæåã¯ããã£ãŒã«ãã®èª€ã£ãç¶æ
ããã§ãã¯ããŸããã public void ToggleWall (GameTile tile) { if (tile.Content.Type == GameTileContentType.Wall) { tile.Content = contentFactory.Get(GameTileContentType.Empty); FindPaths(); } else { tile.Content = contentFactory.Get(GameTileContentType.Wall); FindPaths(); } }
空ã®ã¿ã€ã«ãšå£ã®ã¿ã€ã«ã®ã¿ãåââãæ¿ããããã®ãµããŒããæäŸããå£ããšã³ããã€ã³ããçŽæ¥çœ®ãæããããšãèš±å¯ããŸããããããã£ãŠãã¿ã€ã«ã空ã®å Žåã«ã®ã¿å£ãäœæããŸããããã«ãå£ã¯ãã¹ã®æ€çŽ¢ããããã¯ããå¿
èŠããããŸãããã ããåã¿ã€ã«ã«ã¯ãšã³ããã€ã³ããžã®ãã¹ãå¿
èŠã§ããããããªããšãæµã¯ã¹ã¿ãã¯ããŸãããããè¡ãã«ã¯ãå床validationã䜿çšãFindPaths
ãäžæ£ç¢ºãªãã£ãŒã«ãç¶æ
ãäœæããå Žåãå€æŽãç Žæ£ããå¿
èŠããããŸãã else if (tile.Content.Type == GameTileContentType.Empty) { tile.Content = contentFactory.Get(GameTileContentType.Wall); if (!FindPaths()) { tile.Content = contentFactory.Get(GameTileContentType.Empty); FindPaths(); } }
å£ã®ãªã³/ãªãã®åãæ¿ãã¯ããšã³ããã€ã³ãã®ãªã³/ãªãã®åãæ¿ããããé »ç¹ã«äœ¿çšããããããGame
ã¡ã€ã³ã®ã¿ããã§å£ãåãæ¿ããŸãããšã³ããã€ã³ãã¯ãè¿œå ã®ã¿ããïŒéåžžã¯ããŠã¹ã®å³ãã¿ã³ïŒã§åãæ¿ããããšãã§ããInput.GetMouseButtonDown
å€1 ãæž¡ãããšã§èªèã§ããŸãã void Update () { if (Input.GetMouseButtonDown(0)) { HandleTouch(); } else if (Input.GetMouseButtonDown(1)) { HandleAlternativeTouch(); } } void HandleAlternativeTouch () { GameTile tile = board.GetTile(TouchRay); if (tile != null) { board.ToggleDestination(tile); } } void HandleTouch () { GameTile tile = board.GetTile(TouchRay); if (tile != null) { board.ToggleWall(tile); } }
ããã§å£ãã§ããŸãããæãã«é£æ¥ããå£ã®åœ±ã®éã«å€§ããªééãçããã®ã¯ãªãã§ããïŒ, , , . , , far clipping plane . , far plane 20 . , MSAA, .
ãŸãããšã³ããã€ã³ããå£ãçŽæ¥çœ®ãæããããšãã§ããªãããšã確èªããŸãããã public void ToggleDestination (GameTile tile) { if (tile.Content.Type == GameTileContentType.Destination) { ⊠} else if (tile.Content.Type == GameTileContentType.Empty) { tile.Content = contentFactory.Get(GameTileContentType.Destination); FindPaths(); } }
ãã¹æ€çŽ¢ããã¯
å£ããã¹ã®æ€çŽ¢ããããã¯ããããã«ããã«ã¯ãå£ã®ããã¿ã€ã«ãæ€çŽ¢å¢çã«è¿œå ããªããŠãååã§ããããã¯GameTile.GrowPathTo
ãå£ã®ããã¿ã€ã«ãè¿ããªãããã«åŒ·å¶ããããšã§å®è¡ã§ããŸãããã ãããã£ãŒã«ãäžã®ãã¹ãŠã®ã¿ã€ã«ã«ãã¹ãããããã«ããã¹ã¯ãŸã å£ã®æ¹åã«æé·ããå¿
èŠããããŸããæµã®ããã¿ã€ã«ãçªç¶å£ã«å€ããå¯èœæ§ãããããããããå¿
èŠã§ãã GameTile GrowPathTo (GameTile neighbor) { if (!HasPath || neighbor == null || neighbor.HasPath) { return null; } neighbor.distance = distance + 1; neighbor.nextOnPath = this; return neighbor.Content.Type != GameTileContentType.Wall ? neighbor : null; }
ãã¹ãŠã®ã¿ã€ã«ã«ãã¹ãããããšGameBoard.FindPaths
ã確èªããã«ã¯ãæ€çŽ¢ã®å®äºåŸã«ããã確èªããå¿
èŠããããŸããããã§ãªãå Žåããã£ãŒã«ãã®ç¶æ
ã¯ç¡å¹ã§ãããè¿ãããå¿
èŠããããŸãfalse
ããã£ãŒã«ãã以åã®ç¶æ
ã«æ»ããããç¡å¹ãªç¶æ
ã®ãã¹ã®èŠèŠåãæŽæ°ããå¿
èŠã¯ãããŸããã bool FindPaths () { ⊠foreach (GameTile tile in tiles) { if (!tile.HasPath) { return false; } } foreach (GameTile tile in tiles) { tile.ShowPath(); } return true; }
å£ãéã«åœ±é¿ããŸããå®éã«å£ã«æ£ãããã¹ãããããšã確èªããã«ã¯ããã¥ãŒããåéæã«ããå¿
èŠããããŸããéæãªå£ããã¹ãŠã®ãã¹ã®æ£ç¢ºãã®èŠä»¶ã«ãããå£ãçµç¹ã®ãªããã£ãŒã«ãã®äžéšããã§ã³ã¹ã§ããªãããšã«æ³šæããŠãã ãããããããåå²ã§ããŸãããåããŒãã«å°ãªããšã1ã€ã®ãšã³ããã€ã³ããããå Žåã®ã¿ã§ãããŸããåå£ã¯ç©ºã®ã¿ã€ã«ãŸãã¯ãšã³ããã€ã³ãã«é£æ¥ããŠããå¿
èŠããããŸããããã§ãªãå Žåããã¹ãæã€ããšãã§ããŸãããããšãã°ã3Ã3ã®å£ã®åºäœãããã¯ãäœæããããšã¯äžå¯èœã§ããéãé ã
ãã¹ã®èŠèŠåã«ããããã¹æ€çŽ¢ãã©ã®ããã«æ©èœãããã確èªããå®éã«æ£ããããšã確èªã§ããŸãããã ãããã¬ãŒã€ãŒã«è¡šç€ºããå¿
èŠã¯ãããŸãããå°ãªããšããå¿
ããã衚瀺ããå¿
èŠã¯ãããŸããããããã£ãŠãç¢å°ããªãã«ããæ©èœãæäŸããŸããããããã¯ãç¢å°ãç¡å¹ã«ããã ãã®GameTile
äžè¬çãªã¡ãœããã«è¿œå ããããšã§å®è¡ã§ããŸãHidePath
ã public void HidePath () { arrow.gameObject.SetActive(false); }
ãã¹ãããã³ã°ç¶æ
ã¯ããã£ãŒã«ãç¶æ
ã®äžéšã§ããGameBoard
ããŒã«ãã£ãŒã«ããããã©ã«ãã®ã€ã³ãŒã«false
ã«è¿œå ããŠããã®ç¶æ
ã远跡ããã²ãã¿ãŒããã³ã»ãã¿ãŒãšããŠã®å
±éããããã£ã远跡ããŸããã»ãã¿ãŒã¯ããã¹ãŠã®ã¿ã€ã«ã®ãã¹ã衚瀺ãŸãã¯é衚瀺ã«ããå¿
èŠããããŸãã bool showPaths; public bool ShowPaths { get => showPaths; set { showPaths = value; if (showPaths) { foreach (GameTile tile in tiles) { tile.ShowPath(); } } else { foreach (GameTile tile in tiles) { tile.HidePath(); } } } }
ããã§ãFindPaths
ã¬ã³ããªã³ã°ãæå¹ãªå Žåã«ã®ã¿ãã¡ãœããã¯æŽæ°ããããã¹ã衚瀺ããã¯ãã§ãã bool FindPaths () { ⊠if (showPaths) { foreach (GameTile tile in tiles) { tile.ShowPath(); } } return true; }
ããã©ã«ãã§ã¯ããã¹ã®èŠèŠåã¯ç¡å¹ã«ãªã£ãŠããŸããã¿ã€ã«ãã¬ããã®ç¢å°ããªãã«ããŸãããã¬ããç¢å°ã¯ããã©ã«ãã§ã¯ç¡å¹ã§ãã ããŒãæŒããããšãã«èŠèŠåã®ç¶æ
ãåãæ¿ããããã«ãGame
ãŸããPããŒã䜿çšããã®ã¯è«ççã§ãããUnityãšãã£ã¿ãŒã§ã²ãŒã ã¢ãŒããæå¹/ç¡å¹ã«ãããããããŒã§ããããŸãããã®çµæãã²ãŒã ã¢ãŒããçµäºããããã®ãããããŒã䜿çšãããšãèŠèŠåãåãæ¿ãããŸãããèŠãç®ã¯ããŸããããããŸãããVããŒïŒèŠèŠåã®ç¥ïŒã䜿çšããŠã¿ãŸããããç¢å°ãªããã°ãªãã衚瀺
ç¢å°ãé衚瀺ã«ãªããšãåã¿ã€ã«ã®å ŽæãèŠåããã®ãé£ãããªããŸããã°ãªããç·ãè¿œå ããŸããããããããæ£æ¹åœ¢ã®å¢çã¡ãã·ã¥ãã¯ã¹ãã£ãããŠã³ããŒãããŸããããã¯ãåäžã®ã¿ã€ã«ã®ã¢ãŠãã©ã€ã³ãšããŠäœ¿çšã§ããŸããã¡ãã·ã¥ãã¯ã¹ãã£ããã®ãã¯ã¹ãã£ãåã¿ã€ã«ã«åå¥ã«è¿œå ããã®ã§ã¯ãªããå°é¢ã«é©çšããŸãããã ãããã®ã°ãªããããªãã·ã§ã³ã«ãããã¹ãèŠèŠåããŸãããããã£ãŠãGameBoard
æ§æãã£ãŒã«ãã«è¿œå ãããã®ããã®Texture2D
ã¡ãã·ã¥ãã¯ã¹ãã£ãéžæããŸãã [SerializeField] Texture2D gridTexture = default;
ã¡ãã·ã¥ãã¯ã¹ãã£ãæã€ãã£ãŒã«ããå¥ã®ããŒã«ãã£ãŒã«ããšããããã£ãè¿œå ããŠãã°ãªããã®èŠèŠåã®ç¶æ
ãå¶åŸ¡ããŸãããã®å Žåãã»ãã¿ãŒã¯å°çã®ãããªã¢ã«ãå€æŽããå¿
èŠããããŸããããã¯ãGetComponent<MeshRenderer>
å°çãåŒã³åºããŠmaterial
çµæããããã£ã«ã¢ã¯ã»ã¹ããããšã§å®è£
ã§ããŸããã¡ãã·ã¥ã衚瀺ããå¿
èŠãããå Žåãã¡ãã·ã¥mainTexture
ãã¯ã¹ãã£ããããªã¢ã«ããããã£ã«å²ãåœãŠãŸãããã以å€ã®å Žåã¯ã圌ã«å²ãåœãŠnull
ãŸãããããªã¢ã«ã®ãã¯ã¹ãã£ãå€æŽãããšããããªã¢ã«ã€ã³ã¹ã¿ã³ã¹ã®è€è£œãäœæãããããããããªã¢ã«ã¢ã»ããããç¬ç«ããããšã«æ³šæããŠãã ããã bool showGrid, showPaths; public bool ShowGrid { get => showGrid; set { showGrid = value; Material m = ground.GetComponent<MeshRenderer>().material; if (showGrid) { m.mainTexture = gridTexture; } else { m.mainTexture = null; } } }
Game
GããŒã§ã°ãªããã®èŠèŠåãåãæ¿ããŸãããã void Update () { ⊠if (Input.GetKeyDown(KeyCode.G)) { board.ShowGrid = !board.ShowGrid; } }
ãŸããããã©ã«ãã®ã¡ãã·ã¥èŠèŠåãã«è¿œå ããŸãAwake
ã void Awake () { board.Initialize(boardSize, tileContentFactory); board.ShowGrid = true; }
ã¹ã±ãŒã«ãªãã®ã°ãªããããããŸã§ã®ãšããããã£ãŒã«ãå
šäœã«å¢çç·ããããŸãããã¯ã¹ãã£ãšäžèŽããŸãããããã¯å¿
èŠãªãã®ã§ã¯ãããŸãããã°ãªããã®ãµã€ãºã«äžèŽããããã«ããããªã¢ã«ã®ã¡ã€ã³ãã¯ã¹ãã£ãã¹ã±ãŒãªã³ã°ããå¿
èŠããããŸãããããè¡ãã«SetTextureScale
ã¯ããã¯ã¹ãã£ããããã£ã®ååïŒ_MainTexïŒãš2次å
ãµã€ãºã§material ã¡ãœãããåŒã³åºããŸããéæ¥çã«valueã«å€æããããã£ãŒã«ãã®ãµã€ãºãçŽæ¥äœ¿çšã§ããŸãVector2
ã if (showGrid) { m.mainTexture = gridTexture; m.SetTextureScale("_MainTex", size); }
ãã¹ã®èŠèŠåããªã³/ãªãã«ããã¹ã±ãŒãªã³ã°ãããã°ãªããããã®ããããã®æ®µéã§ãã¿ã¯ãŒãã£ãã§ã³ã¹ã®ãžã£ã³ã«ã®ã¿ã€ã«ã²ãŒã ã®æ©èœãã£ãŒã«ããååŸããŸããã次ã®ãã¥ãŒããªã¢ã«ã§ã¯ãæµãè¿œå ããŸãããªããžããªPDF