ããŒã1ã3ïŒã°ãªãããè²ãã»ã«ã®é«ãããŒã4ã7ïŒç²ããå·ãããã³éè·¯ããŒã8-11ïŒæ°Žãå°åœ¢ãåå£ããŒã12ã15ïŒä¿åãšèªã¿èŸŒã¿ããã¯ã¹ãã£ãè·é¢ããŒã16ã19ïŒéãèŠã€ããããã¬ã€ã€ãŒããŒã ãã¢ãã¡ãŒã·ã§ã³ããŒã20-23ïŒæŠäºã®é§ãå°å³èª¿æ»ãæç¶ãçæããŒã24ã27ïŒæ°ŽåŸªç°ã䟵é£ããã€ãªãŒã ãåæ±å°å³ããŒã16ïŒéãèŠã€ãã
- ã»ã«ã匷調衚瀺ãã
- æ€çŽ¢å¯Ÿè±¡ãéžæããŠãã ãã
- æççµè·¯ãèŠã€ãã
- åªå
ãã¥ãŒãäœæãã
ã»ã«éã®è·é¢ãèšç®ãããããããã®éã®ãã¹ãèŠã€ããããšã«é²ã¿ãŸããã
ãã®ããŒãããå§ããŠãå
è§åœ¢ã®ããããã¥ãŒããªã¢ã«ãUnity 5.6.0ã§äœæãããŸãã 5.6ã«ã¯ãããã€ãã®ãã©ãããã©ãŒã ã®ã¢ã»ã³ããªã§ãã¯ã¹ãã£ã®é
åãç Žå£ãããã°ãããããšã«æ³šæããŠãã ããã ãã¯ã¹ãã£é
åã€ã³ã¹ãã¯ã¿ãŒã«
Is Readableãå«ããããšã§åé¿ã§ããŸãã
æ
è¡ã®èšç»ãã€ã©ã€ããããã»ã«
2ã€ã®ã»ã«éã®ãã¹ãæ€çŽ¢ããã«ã¯ããŸããããã®ã»ã«ãéžæããå¿
èŠããããŸãã 1ã€ã®ã»ã«ãéžæããŠå°å³äžã®æ€çŽ¢ãç£èŠããã ãã§ã¯ãããŸããã ããšãã°ãæåã®ã»ã«ãéžæããŠãããæåŸã®ã»ã«ãéžæããŸãã ãã®å Žåã匷調衚瀺ããããšäŸ¿å©ã§ãã ãããã£ãŠããã®ãããªæ©èœãè¿œå ããŸãããã 匷調衚瀺ã®è€éãŸãã¯å¹æçãªæ¹æ³ãäœæãããŸã§ãéçºã«åœ¹ç«ã€ãã®ãäœæããã ãã§ãã
ã¢ãŠãã©ã€ã³ãã¯ã¹ãã£
ã»ã«ãéžæããç°¡åãªæ¹æ³ã®1ã€ã¯ãã»ã«ã«ãã¹ãè¿œå ããããšã§ãã ãããè¡ãæãç°¡åãªæ¹æ³ã¯ãå
è§åœ¢ã®èŒªéãå«ããã¯ã¹ãã£ã䜿çšããããšã§ãã
ããã§ã¯ããã®ãããªãã¯ã¹ãã£ãããŠã³ããŒãã§ããŸãã å
è§åœ¢ã®çœã茪éãé€ããŠéæã§ãã çœè²ã«ããã®ã§ãå°æ¥ã¯å¿
èŠã«å¿ããŠè²ä»ãã§ããããã«ãªããŸãã
é»ã®èæ¯ã«ã»ã«ã®æŠèŠãã¯ã¹ãã£ãã€ã³ããŒããããã®
Texture Typeã
Spriteã«èšå®ããŸãã ãã®
ã¹ãã©ã€ãã¢ãŒãã¯ãããã©ã«ãèšå®ã§
ã·ã³ã°ã«ã«èšå®ãããŸãã ããã¯éåžžã«çœããã¯ã¹ãã£ãªã®ã§ã
sRGBã«å€æããå¿
èŠã¯ãããŸããã ã¢ã«ãã¡ãã£ãã«ã¯éæ床ãè¡šããŠããããã
Alpha is Transparencyãæå¹ã«ããŸãã ãŸãã
ãã£ã«ã¿ãŒã¢ãŒããã¯ã¹ãã£ã
Trilinearã«èšå®ã
ãŸããããããªããšããã¹ã®ããããã©ã³ãžã·ã§ã³ãç®ç«ã¡ããããªãå¯èœæ§ããããŸãã
ãã¯ã¹ãã£ã€ã³ããŒããªãã·ã§ã³ã»ã«ããšã«1ã€ã®ã¹ãã©ã€ã
æéã®æ¹æ³ã¯ãå¯èœãªèŒªéãã»ã«ã«è¿œå ããããããç¬èªã®ã¹ãã©ã€ããè¿œå ããããšã§ãã æ°ããã²ãŒã ãªããžã§ã¯ããäœæããImageã³ã³ããŒãã³ãïŒ
Component / UI / Image ïŒãè¿œå ããŠãã¢ãŠãã©ã€ã³ã¹ãã©ã€ããå²ãåœãŠãŸãã 次ã«ã
Hex Cell Labelãã¬ããã€ã³ã¹ã¿ã³ã¹ãã·ãŒã³ã«æ¿å
¥ããã¹ãã©ã€ããªããžã§ã¯ãããã®åã«ããå€æŽããã¬ããã«é©çšããŠããããã¬ãããåãé€ããŸãã
ãã¬ããã®åéžæèŠçŽ åã»ã«ã«ã¯ã¹ãã©ã€ãããããŸããã倧ããããŸãã 茪éãã»ã«ã®äžå¿ã«äžèŽãããã«ã¯ãã¹ãã©ã€ãã®å€æã³ã³ããŒãã³ãã®
å¹
ãš
é«ãã17ã«å€æŽããŸãã
ã¬ãªãŒãã«ãã£ãŠéšåçã«é ãããéžæã¹ãã©ã€ããã¹ãŠã®äžã«æã
茪éã¯ã»ã«ã®ç«¯ã®é åã«éãããããããã¬ãªãŒãã®ãžãªã¡ããªã®äžã«è¡šç€ºãããããšããããããŸãã ãã®ãããåè·¯ã®äžéšãæ¶ããŸãã ããã¯ã¹ãã©ã€ããåçŽæ¹åã«ãããã«äžããããšã§åé¿ã§ããŸããããã¬ãŒã¯ã®å Žåã¯ã§ããŸããã 代ããã«ã次ã®ããšãã§ããŸããåžžã«ä»ã®ãã¹ãŠã®äžã«ã¹ãã©ã€ããæç»ããŸãã ãããè¡ãã«ã¯ãç¬èªã®ã¹ãã©ã€ãã·ã§ãŒããŒãäœæããŸãã æšæºã®Unityã¹ãã©ã€ãã·ã§ãŒããŒãã³ããŒããŠãããã«ããã€ãã®å€æŽãå ããã ãã§ååã§ãã
Shader { Properties { [PerRendererData] _MainTex (, 2D) = {} _Color (, Color) = (1,1,1,1) [MaterialToggle] PixelSnap (, Float) = 0 [HideInInspector] _RendererColor (, Color) = (1,1,1,1) [HideInInspector] _Flip (, Vector) = (1,1,1,1) [PerRendererData] _AlphaTex (, 2D) = {} [PerRendererData] _EnableExternalAlpha (, Float) = 0 } SubShader { Tags { = = = = = } Cull Off ZWrite Off Blend One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex SpriteVert #pragma fragment SpriteFrag #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include ENDCG } } }
æåã®å€æŽã¯ã深床ãããã¡ãç¡èŠããZãã¹ããåžžã«æåããããã«ããããšã§ãã
ZWrite Off ZTest Always
2çªç®ã®å€æŽç¹ã¯ãæ®ãã®ãã¹ãŠã®éæãžãªã¡ããªã®åŸã«ã¬ã³ããªã³ã°ããããšã§ãã ééæ§ãã¥ãŒã«10ãè¿œå ããã®ã«ååã§ãã
"Queue"="Transparent+10"
ãã®ã·ã§ãŒããŒã䜿çšããæ°ãããããªã¢ã«ãäœæããŸãã ããã©ã«ãå€ã«åŸã£ãŠããã®ãã¹ãŠã®ããããã£ãç¡èŠã§ããŸãã 次ã«ãã¹ãââã©ã€ããã¬ããã«ãã®ãããªã¢ã«ã䜿çšãããŸãã
ç¬èªã®ã¹ãã©ã€ããããªã¢ã«ã䜿çšããŸãããã§ãéžæç¯å²ã®èŒªéãåžžã«è¡šç€ºãããŸãã ã»ã«ãããé«ãæµ®ã圫ãã®äžã«é ããŠããŠãããã®èŒªéã¯ä»ã®ãã¹ãŠã®äžã«æç»ãããŸãã èŠãç®ã¯çŸãããªããããããŸããããéžæããã»ã«ã¯åžžã«è¡šç€ºãããŠããã®ã§äŸ¿å©ã§ãã
深床ãããã¡ãç¡èŠããéžæå¶åŸ¡
ãã¹ãŠã®ã»ã«ãåæã«åŒ·èª¿è¡šç€ºããããšã¯æãŸãããããŸããã å®éãæåã¯ãã¹ãŠéžæã解é€ããå¿
èŠããããŸãã
Highlightãã¬ãããªããžã§ã¯ãã®Imageã³ã³ããŒãã³ããç¡å¹ã«ããããšã§ãããå®è£
ã§ããŸãã
ç¡å¹ãªç»åã³ã³ããŒãã³ãã»ã«ã®éžæãæå¹ã«ããã«ã¯ã
HexCell
ã¡ãœããã
EnableHighlight
è¿œå ã
EnableHighlight
ã
uiRect
å¯äžã®åãåããImageã³ã³ããŒãã³ããå«ããå¿
èŠããããŸãã
DisableHighlight
ã¡ãœãããäœæããŸãã
public void DisableHighlight () { Image highlight = uiRect.GetChild(0).GetComponent<Image>(); highlight.enabled = false; } public void EnableHighlight () { Image highlight = uiRect.GetChild(0).GetComponent<Image>(); highlight.enabled = true; }
æåŸã«ããªã³ã«ãããšãã«ããã¯ã©ã€ãã«è²çžãäžããããã«è²ãæå®ã§ããŸãã
public void EnableHighlight (Color color) { Image highlight = uiRect.GetChild(0).GetComponent<Image>(); highlight.color = color; highlight.enabled = true; }
ãŠããã£ããã±ãŒãžéãèŠã€ãã
ã»ã«ãéžæã§ããããã«ãªã£ãã®ã§ã次ã«é²ãã§2ã€ã®ã»ã«ãéžæãããããã®éã®ãã¹ãèŠã€ããå¿
èŠããããŸãã æåã«ã»ã«ãéžæãã次ã«æ€çŽ¢ãã»ã«éã®ãã¹ã«å¶éããæåŸã«ãã®ãã¹ã衚瀺ããå¿
èŠããããŸãã
æ€çŽ¢éå§
æ€çŽ¢ã®éå§ç¹ãšçµäºç¹ã®2ã€ã®ç°ãªãã»ã«ãéžæããå¿
èŠããããŸãã æåã®æ€çŽ¢ã»ã«ãéžæããã«ã¯ãå·Šã®ShiftããŒãæŒããªããããŠã¹ãã¯ãªãã¯ãããšããŸãã ãã®å Žåãã»ã«ã¯éã§åŒ·èª¿è¡šç€ºãããŸãã ããã«æ€çŽ¢ããã«ã¯ããã®ã»ã«ãžã®ãªã³ã¯ãä¿åããå¿
èŠããããŸãã ããã«ãæ°ããéå§ã»ã«ãéžæããå Žåãå€ãã»ã«ã®éžæãç¡å¹ã«ããå¿
èŠããããŸãã ãããã£ãŠã
HexMapEditor
ãã£ãŒã«ãã
searchFromCell
è¿œå ã
searchFromCell
ã
HexCell previousCell, searchFromCell;
HandleInput
å
HandleInput
ã¯
HandleInput
Input.GetKey(KeyCode.LeftShift)
ã䜿çšããŠãShiftããŒãæŒããªãããã¹ãã§ããŸãã
if (editMode) { EditCells(currentCell); } else if (Input.GetKey(KeyCode.LeftShift)) { if (searchFromCell) { searchFromCell.DisableHighlight(); } searchFromCell = currentCell; searchFromCell.EnableHighlight(Color.blue); } else { hexGrid.FindDistancesTo(currentCell); }
èŠã©ããæ€çŽ¢ãšã³ããã€ã³ã
ã»ã«ãŸã§ã®ãã¹ãŠã®è·é¢ãæ¢ã代ããã«ã2ã€ã®ç¹å®ã®ã»ã«éã®ãã¹ãæ¢ããŠããŸãã ãããã£ãŠã
HexGrid.FindDistancesTo
ååã
HexGrid.FindDistancesTo
ã«å€æŽãã2çªç®ã®
HexCell
ãã©ã¡ãŒã¿ãŒãæå®ãã
Search
ã¡ãœãããå€æŽããŸãã
public void FindPath (HexCell fromCell, HexCell toCell) { StopAllCoroutines(); StartCoroutine(Search(fromCell, toCell)); } IEnumerator Search (HexCell fromCell, HexCell toCell) { for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; } WaitForSeconds delay = new WaitForSeconds(1 / 60f); List<HexCell> frontier = new List<HexCell>(); fromCell.Distance = 0; frontier.Add(fromCell); ⊠}
ããã§ã
HexMapEditor.HandleInput
ã¯ã
searchFromCell
ããã³
searchFromCell
ãåŒæ°ãšããŠäœ¿çšããŠãå€æŽãããã¡ãœãããåŒã³åºãå¿
èŠããããŸãã ãŸããã©ã®ã»ã«ããæ€çŽ¢ããããããã£ãŠããå Žåã«ã®ã¿æ€çŽ¢ã§ããŸãã ãŸããéå§ç¹ãšçµäºç¹ãäžèŽããå Žåãããããæ€çŽ¢ããå¿
èŠã¯ãããŸããã
if (editMode) { EditCells(currentCell); } else if (Input.GetKey(KeyCode.LeftShift)) { ⊠} else if (searchFromCell && searchFromCell != currentCell) { hexGrid.FindPath(searchFromCell, currentCell); }
æ€çŽ¢ã«æ»ããšãæåã«ä»¥åã®éžæããã¹ãŠåãé€ãå¿
èŠããããŸãã ãããã£ãŠãè·é¢ããªã»ãããããšãã«
HexGrid.Search
ãéžæããªãã«ããŸãã ããã«ããåæã»ã«ã®ç
§æããªãã«ãªããããå床ãªã³ã«ããŸãã ãã®æ®µéã§ããšã³ããã€ã³ãã匷調衚瀺ããããšãã§ããŸãã 圌女ãèµ€ã«ããŸãããã
IEnumerator Search (HexCell fromCell, HexCell toCell) { for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; cells[i].DisableHighlight(); } fromCell.EnableHighlight(Color.blue); toCell.EnableHighlight(Color.red); ⊠}
æœåšçãªãã¹ã®ãšã³ããã€ã³ãæ€çŽ¢ãå¶éãã
ãã®æç¹ã§ãæ€çŽ¢ã¢ã«ãŽãªãºã ã¯ãéå§ã»ã«ããå°éå¯èœãªãã¹ãŠã®ã»ã«ãŸã§ã®è·é¢ãèšç®ããŸãã ããããããå¿
èŠãããŸããã æçµã»ã«ãŸã§ã®æçµè·é¢ãèŠã€ãã£ããããã«åæ¢ã§ããŸãã ã€ãŸããçŸåšã®ã»ã«ãæéã®å Žåãã¢ã«ãŽãªãºã ã«ãŒããçµäºã§ããŸãã
while (frontier.Count > 0) { yield return delay; HexCell current = frontier[0]; frontier.RemoveAt(0); if (current == toCell) { break; } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠} }
çµç¹ã§åæ¢ãšã³ããã€ã³ãã«å°éã§ããªãå Žåã¯ã©ããªããŸããïŒãã®åŸãã¢ã«ãŽãªãºã ã¯ãå°éå¯èœãªãã¹ãŠã®ã»ã«ãèŠã€ãããŸã§æ©èœãç¶ããŸãã æ©æçµäºã®å¯èœæ§ããªããã°ãå€ãFindDistancesTo
ã¡ãœãããšããŠFindDistancesTo
ãŸãã
ãã¹è¡šç€º
ãã¹ã®å§ç¹ãšçµç¹ã®éã®è·é¢ãèŠã€ããããšã¯ã§ããŸãããå®éã®ãã¹ãã©ããªããã¯ãŸã ããããŸããã ãããèŠã€ããã«ã¯ãåã»ã«ã«å°éããæ¹æ³ã远跡ããå¿
èŠããããŸãã ãããããããè¡ãæ¹æ³ã¯ïŒ
ã»ã«ãå¢çç·ã«è¿œå ãããšããçŸåšã®ã»ã«ã®é£ã«ããããããããè¡ããŸãã 1ã€ã®äŸå€ã¯éå§ã»ã«ã§ãã ä»ã®ãã¹ãŠã®ã»ã«ã¯ãçŸåšã®ã»ã«ãä»ããŠå°éããŠããŸãã åã»ã«ã«å°éããã»ã«ã远跡ãããšãçµæãšããŠã»ã«ã®ãããã¯ãŒã¯ãååŸãããŸãã ããæ£ç¢ºã«ã¯ãã«ãŒããéå§ç¹ã§ããããªãŒã®ãããªãããã¯ãŒã¯ã ãšã³ããã€ã³ãã«å°éããåŸãããã䜿çšããŠãã¹ãæ§ç¯ã§ããŸãã
ã»ã³ã¿ãŒãžã®ãã¹ãèšè¿°ããããªãŒãããã¯ãŒã¯HexCell
å¥ã®ã»ã«ãžã®ãªã³ã¯ãè¿œå ããããšã«ããããã®æ
å ±ãä¿åã§ããŸãã ãã®ããŒã¿ãã·ãªã¢ã«åããå¿
èŠã¯ãªããããããã«ã¯æšæºããããã£ã䜿çšããŸãã
public HexCell PathFrom { get; set; }
HexGrid.Search
ãå¢çç·ã«è¿œå ãããšãã«ãé£æ¥ã»ã«ã®
PathFrom
å€ãçŸåšã®ã»ã«ã«èšå®ããŸãã ããã«ãè¿é£ãžã®ããçãæ¹æ³ãèŠã€ããå Žåããã®ãªã³ã¯ãå€æŽããå¿
èŠããããŸãã
if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; frontier.Add(neighbor); } else if (distance < neighbor.Distance) { neighbor.Distance = distance; neighbor.PathFrom = current; }
çµç¹ã«å°éãããããããã®ãªã³ã¯ããã©ã£ãŠéå§ã»ã«ã«æ»ããéžæããããšã§ãã¹ãèŠèŠåã§ããŸãã
if (current == toCell) { current = current.PathFrom; while (current != fromCell) { current.EnableHighlight(Color.white); current = current.PathFrom; } break; }
ãã¹ãèŠã€ãããŸããå€ãã®å Žåãããã€ãã®æççµè·¯ãååšããããšãèæ
®ãã䟡å€ããããŸãã èŠã€ãã£ããã®ã¯ãã»ã«ã®åŠçé åºã«ãã£ãŠç°ãªããŸãã äžéšã®ãã¹ã¯è¯ãèŠãããããããŸããããä»ã®ãã¹ã¯æªããããããŸãããã決ããŠçããã¹ã¯ãããŸããã ããã«ã€ããŠã¯åŸã§èª¬æããŸãã
æ€çŽ¢ã®éå§ãå€æŽ
éå§ç¹ãéžæããåŸãçµäºç¹ãå€æŽãããšãæ°ããæ€çŽ¢ãããªã¬ãŒãããŸãã æ°ããéå§ã»ã«ãéžæãããšãã«ãåãããšãèµ·ããã¯ãã§ãã ãããå¯èœã«ããã«ã¯ã
HexMapEditor
ããšã³ããã€ã³ããèšæ¶ããå¿
èŠããããŸãã
HexCell previousCell, searchFromCell, searchToCell;
ãã®ãã£ãŒã«ãã䜿çšããŠãæ°ããå§ãŸããéžæãããšãã«æ°ããæ€çŽ¢ãéå§ããããšãã§ããŸãã
else if (Input.GetKey(KeyCode.LeftShift)) { if (searchFromCell) { searchFromCell.DisableHighlight(); } searchFromCell = currentCell; searchFromCell.EnableHighlight(Color.blue); if (searchToCell) { hexGrid.FindPath(searchFromCell, searchToCell); } } else if (searchFromCell && searchFromCell != currentCell) { searchToCell = currentCell; hexGrid.FindPath(searchFromCell, searchToCell); }
ããã«ãéå§ç¹ãšçµäºç¹ãçãããªããªãããã«ããå¿
èŠããããŸãã
if (editMode) { EditCells(currentCell); } else if ( Input.GetKey(KeyCode.LeftShift) && searchToCell != currentCell ) { ⊠}
ãŠããã£ããã±ãŒãžããã¹ããŒããªæ€çŽ¢
ã¢ã«ãŽãªãºã ã¯æççµè·¯ãèŠã€ããŸãããæããã«ãã®çµè·¯ã®äžéšã«ãªããªãç¹ãæ¢ãã®ã«å€ãã®æéãè²»ãããŸãã å°ãªããšãããã¯æããã§ãã ã¢ã«ãŽãªãºã ã¯å°å³ãèŠäžããããšã¯ã§ããŸãã;ããæ¹åã®æ€çŽ¢ãç¡æå³ã«ãªãããšãèŠãããšãã§ããŸããã 圌ã¯çµç¹ããå察æ¹åã«åãã£ãŠãããšããäºå®ã«ãããããããéè·¯ã移åããããšã奜ã¿ãŸãã æ€çŽ¢ãããã¹ããŒãã«ããããšã¯å¯èœã§ããïŒ
çŸæç¹ã§ã¯ã次ã«åŠçããå¿
èŠãããã»ã«ãéžæãããšããã»ã«ããå
é ãŸã§ã®è·é¢ã®ã¿ãèæ
®ããŸãã ãã£ãšè³¢ããããå Žåã¯ãçµç¹ãŸã§ã®è·é¢ãèæ
®ããå¿
èŠããããŸãã æ®å¿µãªãããç§ãã¡ã¯åœŒããŸã ç¥ããŸããã ãã ããæ®ãã®è·é¢ã®æšå®å€ãäœæã§ããŸãã ãã®æšå®å€ãã»ã«ãŸã§ã®è·é¢ã«è¿œå ãããšããã®ã»ã«ãééãããã¹ã®å
šé·ãããããŸãã 次ã«ãããã䜿çšããŠã»ã«æ€çŽ¢ã®åªå
é äœãèšå®ã§ããŸãã
æ€çŽ¢ãã¥ãŒãªã¹ãã£ãã¯
æ£ç¢ºã«æ¢ç¥ã®ããŒã¿ã®ä»£ããã«æšå®ãŸãã¯æšæž¬ã䜿çšããå Žåãããã¯æ€çŽ¢ãã¥ãŒãªã¹ãã£ãã¯ã䜿çšããŠåŒã³åºãããŸãã ãã®ãã¥ãŒãªã¹ãã£ãã¯ã¯ãæ®ãã®è·é¢ã®æè¯ã®æšæž¬ãè¡šããŸãã æ€çŽ¢ããåã»ã«ã«å¯ŸããŠãã®å€ã決å®ããå¿
èŠãããããã
HexCell
æŽæ°ããããã£ãè¿œå ããŸãã ã·ãªã¢ã«åããå¿
èŠã¯ãªãã®ã§ãå¥ã®æšæºããããã£ã§ååã§ãã
public int SearchHeuristic { get; set; }
æ®ãã®è·é¢ã«ã€ããŠã©ã®ããã«ä»®å®ããŸããïŒ æãçæ³çãªã±ãŒã¹ã§ã¯ãçµç¹ãŸã§ãŸã£ããã«ç¶ãéè·¯ããããŸãã ãã®å Žåãè·é¢ã¯ããã®ã»ã«ãšæçµã»ã«ã®åº§æšéã®å€æŽãããŠããªãè·é¢ã«çãããªããŸãã ãã¥ãŒãªã¹ãã£ãã¯ã§ããã掻çšããŸãããã
ãã¥ãŒãªã¹ãã£ãã¯ã¯ä»¥åã«ç§»åãããã¹ã«äŸåããªããããæ€çŽ¢ããã»ã¹ã§ã¯äžå®ã§ãã ãããã£ãŠã
HexGrid.Search
ãå¢çã«ã»ã«ãè¿œå ãããšãã«äžåºŠã ãèšç®ããå¿
èŠããããŸãã
if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); frontier.Add(neighbor); }
æ€çŽ¢ã®åªå
床
ãããããã»ã«ãŸã§ã®è·é¢ãšãã®ãã¥ãŒãªã¹ãã£ãã¯ã«åºã¥ããŠãæ€çŽ¢ã®åªå
é äœã決å®ããŸãã ãã®å€ã®ããããã£ã
HexCell
è¿œå ããŸãããã
public int SearchPriority { get { return distance + SearchHeuristic; } }
ãããæ©èœ
HexGrid.Search
ã«ã¯ããã®ããããã£ã䜿çšããŠå¢çç·ã䞊ã¹æ¿ãã
HexGrid.Search
ããŸãã
frontier.Sort( (x, y) => x.SearchPriority.CompareTo(y.SearchPriority) );
ãã¥ãŒãªã¹ãã£ãã¯ãªãã§ããã€ãã¥ãŒãªã¹ãã£ãã¯ã§æ€çŽ¢æå¹ãªãã¥ãŒãªã¹ãã£ãã¯
æ°ããæ€çŽ¢åªå
é äœã®ãããã§ãçµæãšããŠå®éã«ã¢ã¯ã»ã¹ããã»ã«ãå°ãªããªããŸãã ãã ããåäžãªãããã§ã¯ãã¢ã«ãŽãªãºã ã¯ééã£ãæ¹åã®ã»ã«ãåŠçããŸãã ããã¯ãããã©ã«ãã§ã¯ãå移åã¹ãããã®ã³ã¹ãã5ã§ãããã¹ãããããšã®ãã¥ãŒãªã¹ãã£ãã¯ã1ã ãå ç®ããããã§ããã€ãŸãããã¥ãŒãªã¹ãã£ãã¯ã®åœ±é¿ã¯ããŸã匷ããããŸããã
ãã¹ãŠã®ã«ãŒãã移åããã³ã¹ããåãå Žåããã¥ãŒãªã¹ãã£ãã¯ã決å®ãããšãã«åãã³ã¹ãã䜿çšã§ããŸãã ãã®å Žåãããã¯çŸåšã®ãã¥ãŒãªã¹ãã£ãã¯ã«5ãæãããã®ã«ãªããŸããããã«ãããåŠçãããã»ã«ã®æ°ã倧å¹
ã«åæžãããŸãã
ãã¥ãŒãªã¹ãã£ãã¯ã®äœ¿çšÃ5ãã ããå°å³äžã«éè·¯ãããå Žåãæ®ãã®è·é¢ãé倧è©äŸ¡ããããšãã§ããŸãã ãã®çµæãã¢ã«ãŽãªãºã ã¯ééããç¯ããå®éã«ã¯æçã§ã¯ãªããã¹ãäœæããå¯èœæ§ããããŸãã
é倧è©äŸ¡ãããæå¹ãªãã¥ãŒãªã¹ãã£ãã¯æççµè·¯ã確å®ã«èŠã€ããããã«ããã«ã¯ãæ®ãã®è·é¢ãé倧è©äŸ¡ããªãããã«ããå¿
èŠããããŸãã ãã®ã¢ãããŒãã¯æå¹ãªãã¥ãŒãªã¹ãã£ãã¯ãšåŒã°ããŸãã 移åã®æå°ã³ã¹ãã¯1ãªã®ã§ããã¥ãŒãªã¹ãã£ãã¯ã®æ±ºå®ã«åãã³ã¹ãã䜿çšãã以å€ã«éžæè¢ã¯ãããŸããã
å³å¯ã«èšãã°ãããã«äœãã³ã¹ãã䜿çšããããšã¯éåžžã«æ®éã§ãããããã¯ãã¥ãŒãªã¹ãã£ãã¯ããã匱ãããã ãã§ãã å¯èœãªæå°ã®ãã¥ãŒãªã¹ãã£ãã¯ã¯ãŒãã§ããããã«ããããã€ã¯ã¹ãã©ã®ã¢ã«ãŽãªãºã ã®ã¿ãåŸãããŸãã ãŒã以å€ã®ãã¥ãŒãªã¹ãã£ãã¯ã§ã¯ãã¢ã«ãŽãªãºã ã¯A
* ïŒãAã¹ã¿ãŒããšçºé³ïŒãšåŒã°ããŸãã
ãªãA *ãšåŒã°ããã®ã§ããïŒDijkstraã®ã¢ã«ãŽãªãºã ã«ãã¥ãŒãªã¹ãã£ãã¯ãè¿œå ãããšããã¢ã€ãã¢ã¯ãæåã«Niels Nilssonã«ãã£ãŠææ¡ãããŸããã 圌ã¯èªåã®ããŒãžã§ã³ãA1ãšåä»ããŸããã ããŒãã©ã ã»ã©ãã¡ãšã«ã¯åŸã«åœŒãA2ãšåŒãã æé«ã®ããŒãžã§ã³ãæãã€ããã ãã®åŸãPeter Hartã¯ãåªãããã¥ãŒãªã¹ãã£ãã¯ã䜿çšããŠãA2ãæé©ã§ããããšãã€ãŸããããè¯ãããŒãžã§ã³ã¯ååšã§ããªãããšã蚌æããŸããã ããã«ããã圌ã¯ã¢ã«ãŽãªãºã A *ãåŒã³åºããŠãæ¹åã§ããªãããšãã€ãŸãA3ãŸãã¯A4ã衚瀺ãããªãããšã瀺ããŸããã ãã®ãããA *ã¢ã«ãŽãªãºã ã䜿çšããã®ãæåã§ããããã¥ãŒãªã¹ãã£ãã¯ãšåããããåªããŠããŸãã
ãŠããã£ããã±ãŒãžåªå
ãã¥ãŒ
A
*ã¯è¯ãã¢ã«ãŽãªãºã ã§ãããå¢çãæ ŒçŽããããã«ãªã¹ãã䜿çšãããããå®è£
ã¯ããã»ã©å¹æçã§ã¯ãããŸãããããã¯åå埩ã§ãœãŒãããå¿
èŠããããŸãã åã®éšåã§è¿°ã¹ãããã«ãåªå
床ãã¥ãŒãå¿
èŠã§ããããã®æšæºå®è£
ã¯ååšããŸããã ãããã£ãŠãèªåã§äœæããŸãããã
é çªã¯ãåªå
床ã«åºã¥ããŠãã¥ãŒããèšå®ããã³é€å€ããæäœããµããŒãããå¿
èŠããããŸãã ãŸãããã§ã«ãã¥ãŒã«ããã»ã«ã®åªå
床ã®å€æŽããµããŒãããå¿
èŠããããŸãã çæ³çã«ã¯ããããå®è£
ããŠããœãŒãããã³å²ãåœãŠãããã¡ã¢ãªã®æ€çŽ¢ãæå°éã«æããŸãã ããã«ãã·ã³ãã«ãªãŸãŸã«ããå¿
èŠããããŸãã
ç¬èªã®ãã¥ãŒãäœæãã
å¿
èŠãªå
±éã¡ãœããã§æ°ãã
HexCellPriorityQueue
ã¯ã©ã¹ãäœæããŸãã åçŽãªãªã¹ãã䜿çšããŠããã¥ãŒã®å
容ã远跡ããŸãã ããã«ããã¥ãŒãã¯ãªã¢ããŠåå©çšã§ããããã«ã
Clear
ã¡ãœãããè¿œå ããŸãã
using System.Collections.Generic; public class HexCellPriorityQueue { List<HexCell> list = new List<HexCell>(); public void Enqueue (HexCell cell) { } public HexCell Dequeue () { return null; } public void Change (HexCell cell) { } public void Clear () { list.Clear(); } }
ã»ã«èªäœã«ã»ã«ã®åªå
é äœãä¿åããŸãã ã€ãŸãããã¥ãŒã«ã»ã«ãè¿œå ããåã«ããã®åªå
床ãèšå®ããå¿
èŠããããŸãã ããããåªå
é äœãå€æŽãããå Žåãå€ãåªå
é äœãäœã§ãã£ãããç¥ãããšã¯ãããã圹ç«ã€ã§ãããã ããããã©ã¡ãŒã¿ãŒãšããŠ
Change
è¿œå ããŸãããã
public void Change (HexCell cell, int oldPriority) { }
ãŸãããã¥ãŒã«ããã»ã«ã®æ°ãç¥ãããšã圹ç«ã€ã®ã§ããã®ããã«
Count
ããããã£ãè¿œå ããŸãããã 察å¿ããã€ã³ã¯ãªã¡ã³ããšãã¯ãªã¡ã³ããå®è¡ãããã£ãŒã«ãã䜿çšããŠãã ããã
int count = 0; public int Count { get { return count; } } public void Enqueue (HexCell cell) { count += 1; } public HexCell Dequeue () { count -= 1; return null; } ⊠public void Clear () { list.Clear(); count = 0; }
ãã¥ãŒã«è¿œå
ã»ã«ããã¥ãŒã«è¿œå ããããããŸããã®åªå
床ãã€ã³ããã¯ã¹ãšããŠäœ¿çšããŠããªã¹ããåçŽãªé
åãšããŠæ±ããŸãããã
public void Enqueue (HexCell cell) { count += 1; int priority = cell.SearchPriority; list[priority] = cell; }
ãã ããããã¯ãªã¹ããååã«é·ãå Žåã«ã®ã¿æ©èœããŸãããã以å€ã®å Žåã¯å¢çãè¶ããŸãã å¿
èŠãªé·ãã«éãããŸã§ç©ºã®ã¢ã€ãã ããªã¹ãã«è¿œå ããããšã«ããããããåé¿ã§ããŸãã ãããã®ç©ºã®èŠçŽ ã¯ã»ã«ãåç
§ããªãããããªã¹ãã«
null
ãè¿œå ããŠäœæã§ããŸãã
int priority = cell.SearchPriority; while (priority >= list.Count) { list.Add(null); } list[priority] = cell;
ç©Žã®ãããªã¹ãããããããã¯åªå
床ããšã«1ã€ã®ã»ã«ã®ã¿ãæ ŒçŽããæ¹æ³ã§ãããå€ãã®å Žåãè€æ°ã®ã»ã«ãæ ŒçŽãããŸãã åãåªå
床ã®ãã¹ãŠã®ã»ã«ã远跡ããã«ã¯ãå¥ã®ãªã¹ãã䜿çšããå¿
èŠããããŸãã åªå
床ããšã«å®éã®ãªã¹ãã䜿çšã§ããŸããã
HexCell
ã«ããããã£ãè¿œå ããŠããããçµåããããšãã§ããŸãã ããã«ããããªã³ã¯ãªã¹ããšåŒã°ããäžé£ã®ã»ã«ãäœæã§ããŸãã
public HexCell NextWithSamePriority { get; set; }
ãã§ãŒã³ãäœæããã«ã¯ã
HexCellPriorityQueue.Enqueue
ã䜿çšããŠãæ°ããè¿œå ãããã»ã«ã«ãåé€ããåã«åãåªå
床ã§çŸåšã®å€ã匷å¶çã«åç
§ãããŸãã
cell.NextWithSamePriority = list[priority]; list[priority] = cell;
ãªã³ã¯ãªã¹ãã®ãªã¹ããã¥ãŒããåé€
åªå
床ãã¥ãŒããã»ã«ãååŸããã«ã¯ã空ã§ãªãæå°ã®ã€ã³ããã¯ã¹ã§ãªã³ã¯ãªã¹ãã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸãã ãããã£ãŠããªã¹ããèŠã€ãããŸã§ã«ãŒãå
ãå·¡åããŸãã èŠã€ãããªãå Žåããã¥ãŒã¯ç©ºã§ããã
null
ãè¿ã
null
ã
èŠã€ãã£ããã§ãŒã³ããããã¹ãŠã®ã»ã«ã®åªå
é äœãåããªã®ã§ãä»»æã®ã»ã«ãè¿ãããšãã§ããŸãã æãç°¡åãªæ¹æ³ã¯ããã§ãŒã³ã®å
é ããã»ã«ãè¿ãããšã§ãã
public HexCell Dequeue () { count -= 1; for (int i = 0; i < list.Count; i++) { HexCell cell = list[i]; if (cell != null) { return cell; } } return null; }
æ®ãã®ãã§ãŒã³ãžã®ãªã³ã¯ãç¶æããã«ã¯ãæ°ããéå§ãšåãåªå
床ãæã€æ¬¡ã®ã»ã«ã䜿çšããŸãã ãã®åªå
床ã¬ãã«ã«ã»ã«ã1ã€ãããªãã£ãå ŽåãèŠçŽ ã¯
null
ãªããå°æ¥ã¹ããããããŸãã
if (cell != null) { list[i] = cell.NextWithSamePriority; return cell; }
æå°è¿œè·¡
ãã®ã¢ãããŒãã¯æ©èœããŸãããã»ã«ãåä¿¡ããããã³ã«ãªã¹ããå埩åŠçããŸãã æå°ã®ç©ºã§ãªãã€ã³ããã¯ã¹ãèŠã€ããããšã¯é¿ããããŸããããæ¯åãŒãããå§ããå¿
èŠã¯ãããŸããã 代ããã«ãæäœåªå
é äœã远跡ããããã§æ€çŽ¢ãéå§ã§ããŸãã æåã¯ãæå°å€ã¯æ¬è³ªçã«ç¡é倧ã§ãã
int minimum = int.MaxValue; ⊠public void Clear () { list.Clear(); count = 0; minimum = int.MaxValue; }
ã»ã«ããã¥ãŒã«è¿œå ãããšããå¿
èŠã«å¿ããŠæå°å€ãå€æŽããŸãã
public void Enqueue (HexCell cell) { count += 1; int priority = cell.SearchPriority; if (priority < minimum) { minimum = priority; } ⊠}
ãããŠããã¥ãŒããæ€åãããšãããŒãããå§ããã®ã§ã¯ãªããå°ãªããšãå埩ã®ããã«ãªã¹ãã䜿çšããŸãã
public HexCell Dequeue () { count -= 1; for (; minimum < list.Count; minimum++) { HexCell cell = list[minimum]; if (cell != null) { list[minimum] = cell.NextWithSamePriority; return cell; } } return null; }
ããã«ãããåªå
é äœãªã¹ãã«ãŒãã§ã®ãã€ãã¹ã«ãããæéã倧å¹
ã«ççž®ãããŸãã
åªå
é äœã®å€æŽ
ã»ã«ã®åªå
床ãå€æŽãããšãã¯ãã»ã«ãå±ãããªã³ã¯ãªã¹ãããåé€ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãèŠã€ãããŸã§ãã§ãŒã³ããã©ãå¿
èŠããããŸãã
å€ãåªå
é äœãªã¹ãã®å
é ãçŸåšã®ã»ã«ã«ãªãããšã宣èšããããšããå§ããŸãããããŸãã次ã®ã»ã«ã远跡ããŸãã ãã®ã€ã³ããã¯ã¹ã«ãã£ãŠå°ãªããšã1ã€ã®ã»ã«ãããããšãããã£ãŠãããããããã«æ¬¡ã®ã»ã«ãååŸã§ããŸãã
public void Change (HexCell cell, int oldPriority) { HexCell current = list[oldPriority]; HexCell next = current.NextWithSamePriority; }
çŸåšã®ã»ã«ãå€æŽãããã»ã«ã§ããå Žåãããã¯å
é ã®ã»ã«ã§ããããã¥ãŒããåŒãåºããããã«åãåãããšãã§ããŸãã
HexCell current = list[oldPriority]; HexCell next = current.NextWithSamePriority; if (current == cell) { list[oldPriority] = next; }
ããã§ãªãå Žåã¯ãå€æŽãããã»ã«ã®åã®ã»ã«ã«å
¥ããŸã§ãã§ãŒã³ããã©ãå¿
èŠããããŸãã å€æŽãããã»ã«ãžã®ãªã³ã¯ãå«ãŸããŠããŸãã
if (current == cell) { list[oldPriority] = next; } else { while (next != cell) { current = next; next = current.NextWithSamePriority; } }
ãã®æç¹ã§ããªã³ã¯ããããªã¹ãããå€æŽãããã»ã«ãåé€ããŠãã¹ãããã§ããŸãã
while (next != cell) { current = next; next = current.NextWithSamePriority; } current.NextWithSamePriority = cell.NextWithSamePriority;
ã»ã«ãåé€ããåŸãæ°ããåªå
床ã®ãªã¹ãã«è¡šç€ºãããããã«ã»ã«ãå床远å ããå¿
èŠããããŸãã
public void Change (HexCell cell, int oldPriority) { ⊠Enqueue(cell); }
Enqueue
ã¡ãœããã¯ã«ãŠã³ã¿ãŒãã€ã³ã¯ãªã¡ã³ãããŸãããå®éã«ã¯æ°ããã»ã«ãè¿œå ããããã§ã¯ãããŸããã ãããã£ãŠããããè£ãããã«ãã«ãŠã³ã¿ãŒãæžããå¿
èŠããããŸãã
Enqueue(cell); count -= 1;
ãã¥ãŒã®äœ¿çš
ããã§ã
HexGrid
åªå
ãã¥ãŒãå©çšã§ããŸãã ããã¯ããã¹ãŠã®æ€çŽ¢æäœã§åå©çšå¯èœãªåäžã®ã€ã³ã¹ã¿ã³ã¹ã§å®è¡ã§ããŸãã
HexCellPriorityQueue searchFrontier; ⊠IEnumerator Search (HexCell fromCell, HexCell toCell) { if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } ⊠}
ã«ãŒããéå§ããåã«ãã¡ãœããSearch
ãæåã«ãã¥ãŒfromCell
ã«è¿œå ããå¿
èŠããããåå埩ã¯ãã¥ãŒããã®ã»ã«ã®åºåããå§ãŸããŸããããã«ãããå€ãå¢çã³ãŒãã眮ãæããããŸãã WaitForSeconds delay = new WaitForSeconds(1 / 60f);
ã³ãŒããå€æŽããŠãè¿é£ãè¿œå ããã³å€æŽããŸããå€æŽã®åã«ãå€ãåªå
é äœãèŠããŠããŸãã if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates);
ããã«ãå¢çç·ã䞊ã¹æ¿ããå¿
èŠããªããªããŸããã
åªå
ãã¥ãŒã䜿çšããæ€çŽ¢åè¿°ã®ããã«ãæ€åºãããæçãã¹ã¯ã»ã«ã®åŠçé åºã«ãã£ãŠç°ãªããŸããç§ãã¡ã®é çªã¯ããœãŒãããããªã¹ãã®é åºãšã¯ç°ãªãé åºãäœæããã®ã§ãä»ã®æ¹æ³ãåŸãããšãã§ããŸããååªå
床ã®ãªã³ã¯ãªã¹ãã®å
é ã«è¿œå ããã³åé€ããããããã¥ãŒãããã¹ã¿ãã¯ã«äŒŒãŠããŸããæåŸã«è¿œå ãããã»ã«ãæåã«åŠçãããŸãããã®ã¢ãããŒãã®å¯äœçšã¯ãã¢ã«ãŽãªãºã ããžã°ã¶ã°ã«ãªããããããšã§ãããããã£ãŠããžã°ã¶ã°ãã¹ã®å¯èœæ§ãé«ããªããŸãã幞ããªããšã«ããããã®ãã¹ã¯éåžžè¯ãèŠããã®ã§ããã®å¯äœçšã¯ç§ãã¡ã«ãšã£ãŠè¯ãããšã§ããunitypackage åªå
床ã®ãœãŒãããããªã¹ããšãã¥ãŒããŒã17ïŒéãããåã
- 段éçãªç§»åã®æ¹æ³ãèŠã€ããŸãã
- ããã«ãã¹ã衚瀺ããŸãã
- ããå¹æçãªæ€çŽ¢ãäœæããŸãã
- ãã¹ã®ã¿ãèŠèŠåããŸãã
ãã®ããŒãã§ã¯ãåããåãã«åå²ããå¯èœãªéãæ€çŽ¢ãé«éåããŸããããã€ãã®åãããã®æ
è¡å¢å移å
å
è§åœ¢ãããã䜿çšããæŠç¥ã²ãŒã ã¯ãã»ãšãã©åžžã«ã¿ãŒã³ããŒã¹ã§ãããããäžã移åãããŠãããã®é床ã¯å¶éãããŠããã1ã¿ãŒã³ã®ç§»åè·é¢ãå¶éãããŸããã¹ããŒã
éãããåããã¢ããªã³ãžã®ãµããŒããæäŸããHexGrid.FindPath
ãšHexGrid.Search
æŽæ°ãã©ã¡ãŒã¿speed
ã1åã®åãã®å¯åç¯å²ã決å®ããŸãã public void FindPath (HexCell fromCell, HexCell toCell, int speed) { StopAllCoroutines(); StartCoroutine(Search(fromCell, toCell, speed)); } IEnumerator Search (HexCell fromCell, HexCell toCell, int speed) { ⊠}
ã²ãŒã å
ã®ç°ãªãã¿ã€ãã®ãŠãããã¯ç°ãªãé床ã䜿çšããŸããéšå
µéã¯éããæ©å
µéã¯é
ããªã©ã§ãããŸã ãŠãããããããŸããã®ã§ãä»ã®ãšããã¯äžå®ã®é床ã䜿çšããŸãã24ã®å€ãåããŸããããããã¯ããªã倧ããå€ã§ããã5ïŒç§»åã®ããã©ã«ãã³ã¹ãïŒã§å²ãåããŸãããåŒæ°ãšããŠäžå®é床FindPath
ã§è¿œå ããŸãHexMapEditor.HandleInput
ã if (editMode) { EditCells(currentCell); } else if ( Input.GetKey(KeyCode.LeftShift) && searchToCell != currentCell ) { if (searchFromCell) { searchFromCell.DisableHighlight(); } searchFromCell = currentCell; searchFromCell.EnableHighlight(Color.blue); if (searchToCell) { hexGrid.FindPath(searchFromCell, searchToCell, 24); } } else if (searchFromCell && searchFromCell != currentCell) { searchToCell = currentCell; hexGrid.FindPath(searchFromCell, searchToCell, 24); }
åã
ãã¹ã«æ²¿ã£ãŠç§»åããç·ã³ã¹ãã远跡ããããšã«å ããŠããã¹ã«æ²¿ã£ãŠç§»åããã®ã«å¿
èŠãªç§»åæ°ãç¥ãå¿
èŠããããŸãããã ãããã®æ
å ±ãåã»ã«ã«ä¿åããå¿
èŠã¯ãããŸããã移åè·é¢ãé床ã§é€ç®ããããšã§ååŸã§ããŸãããããã¯æŽæ°ã§ãããããæŽæ°é€ç®ã䜿çšããŸããã€ãŸãã24ãè¶
ããªãåèšè·é¢ã¯ã³ãŒã¹0ã«å¯Ÿå¿ããŸããããã¯ãçŸåšã®ã³ãŒã¹ã§ãã¹å
šäœãå®äºã§ããããšãæå³ããŸããçµç¹ã30ã®è·é¢ã«ããå Žåãããã¯ã¿ãŒã³1ã§ãªããã°ãªããŸãããçµç¹ã«å°éããã«ã¯ããŠãããã¯çŸåšã®ã¿ãŒã³ãšæ¬¡ã®ã¿ãŒã³ã®äžéšã§ãã¹ãŠã®åããè²»ããå¿
èŠããããŸããçŸåšã®ã»ã«ãšãã®å
éšã®ãã¹ãŠã®é£æ¥ã»ã«ã®ã³ãŒã¹ã決å®ããŸãããHexGrid.Search
ãçŸåšã®ã»ã«ã®ã³ãŒã¹ã¯ãé£æ¥ãµã€ã¯ã«ãå·¡åããçŽåã«äžåºŠã ãèšç®ã§ããŸããé£äººã®è·é¢ã¯ãè·é¢ãããããšããã«å€æã§ããŸãã int currentTurn = current.Distance / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠int distance = current.Distance; if (current.HasRoadThroughEdge(d)) { distance += 1; } else if (current.Walled != neighbor.Walled) { continue; } else { distance += edgeType == HexEdgeType.Flat ? 5 : 10; distance += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } int turn = distance / speed; ⊠}
倱ãããåã
é£äººã®åããçŸåšã®åãããã倧ããå Žåã¯ãåãã®å¢çãè¶ããŸãããé£äººã«å°éããããã«å¿
èŠãªåãã1ã ã£ãå Žåããã¹ãŠãæ£åžžã§ãããããã次ã®ã»ã«ãžã®ç§»åãããé«äŸ¡ãªå Žåããã¹ãŠãããè€éã«ãªããŸããå質ãªãããã«æ²¿ã£ãŠç§»åãããšããŸããã€ãŸããåã»ã«ã«å
¥ãããã«5åäœã®ç§»åãå¿
èŠã ãšããŸãã4ã€ã®ã¹ãããã®åŸã移åã¹ããã¯ãã20ãŠããããè²»ãããæ®ãã®4ã€ãæ®ã£ãŠããŸãããã®æ®µéã§äœãããå¿
èŠããããŸããïŒãã®ç¶æ³ã«ã¯2ã€ã®ã¢ãããŒãããããŸãã 1ã€ç®ã¯ãååãªåãããªãå Žåã§ãããŠããããçŸåšã®ã¿ãŒã³ã§5çªç®ã®ã»ã«ã«å
¥ãããšãèš±å¯ããããšã§ãã 2ã€ç®ã¯ãçŸåšã®ç§»åäžã®ç§»åãçŠæ¢ããããšã§ããã€ãŸããæ®ãã®ç§»åãã€ã³ãã¯äœ¿çšã§ããã倱ãããŸãããªãã·ã§ã³ã®éžæã¯ã²ãŒã ã«ãã£ãŠç°ãªããŸããäžè¬çãªå Žåãæåã®ã¢ãããŒãã¯ãããšãã°ææã·ãªãŒãºã®ã²ãŒã ã®ããã«ããŠãããã1ã¿ãŒã³ãããæ°ã¹ããããã移åã§ããªãã²ãŒã ãšããæŽåæ§ããããŸããããã«ããããŠãããã¯åžžã«1ã¿ãŒã³ãããå°ãªããšã1ã€ã®ã»ã«ã移åã§ããŸãã Age of WondersãBattle for Wesnothã®ããã«ããŠãããã1ã¿ãŒã³ãããå€ãã®ã»ã«ã移åã§ããå Žåã2çªç®ã®ãªãã·ã§ã³ã®æ¹ãåªããŠããŸããé床24ã䜿çšããããã2çªç®ã®ã¢ãããŒããéžæããŸããããäœæ¥ãéå§ããã«ã¯ãçŸåšã®è·é¢ã«è¿œå ããåã«ã次ã®ã»ã«ã«å
¥ãã³ã¹ããåé¢ããå¿
èŠããããŸãã
ãã®çµæã移åã®å¢çãè¶ããå ŽåããŸãçŸåšã®ç§»åã®ãã¹ãŠã®ç§»åãã€ã³ãã䜿çšããŸãããããè¡ãã«ã¯ãåçŽã«åãã«é床ãæããŸãããã®åŸã移åã®ã³ã¹ããè¿œå ããŸãã int distance = current.Distance + moveCost; int turn = distance / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; }
ãã®çµæã4ã€ã®æªäœ¿çšã®ç§»åãã€ã³ãã§4çªç®ã®ã»ã«ã®æåã®ç§»åãå®äºããŸãããããã®å€±ããããã€ã³ãã¯ã5çªç®ã®ã»ã«ã®ã³ã¹ãã«è¿œå ãããããããã®è·é¢ã¯25ã§ã¯ãªã29ã«ãªããŸãããã®çµæãè·é¢ã¯ä»¥åããã倧ãããªããŸããããšãã°ã10çªç®ã®ã»ã«ã®è·é¢ã¯50ã§ãããããããããã«å
¥ãã«ã¯ã2ã€ã®åãã®å¢çãè¶ããŠã8ã€ã®ç§»åãã€ã³ãã倱ãå¿
èŠããããŸããã€ãŸããè·é¢ã¯58ã«ãªããŸããäºæ³ããé·ãæªäœ¿çšã®ç§»åãã€ã³ãã¯ã»ã«ãŸã§ã®è·é¢ã«è¿œå ããããããæççµè·¯ã決å®ããéã«èæ
®ãããŸããæãå¹æçãªæ¹æ³ã¯ãã§ããã ãå°ãªããã€ã³ããç¡é§ã«ããããšã§ãããããã£ãŠãç°ãªãé床ã§ãç°ãªããã¹ãååŸã§ããŸããè·é¢ã§ã¯ãªãåãã衚瀺ãã
ã²ãŒã ããã¬ã€ãããšããæçãã¹ãèŠã€ããããã«äœ¿çšãããè·é¢å€ã«ã¯ããŸãé¢å¿ããããŸããããšã³ããã€ã³ãã«å°éããããã«å¿
èŠãªåãã®æ°ã«èå³ããããŸãããããã£ãŠãè·é¢ã®ä»£ããã«ãåãã衚瀺ããŸãããããŸããã§UpdateDistanceLabel
圌ã®åŒã³åºããåãé€ãHexCell
ãŸãã public int Distance { get { return distance; } set { distance = value;
代ããã«ãä»»æã®æååãåãåãHexCell
äžè¬çãªã¡ãœããã«è¿œå ãSetLabel
ãŸãã public void SetLabel (string text) { UnityEngine.UI.Text label = uiRect.GetComponent<Text>(); label.text = text; }
HexGrid.Search
ã»ã«ã®ã¯ãªãŒãã³ã°ã«ãã®æ°ããæ¹æ³ã䜿çšããŸããã»ã«ãé衚瀺ã«ããã«ã¯ãåã«ããããå²ãåœãŠãŸãnull
ã for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; cells[i].SetLabel(null); cells[i].DisableHighlight(); }
次ã«ãé£äººã®ããŒã¯ã«åœŒã®ç§»åã®å€ãå²ãåœãŠãŸãããã®åŸãæåŸãŸã§ç§»åããããã«å¿
èŠãªè¿œå ã®ç§»åæ°ã確èªã§ããŸãã if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance; neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); }
unitypackage ãã¹ã«æ²¿ã£ãŠç§»åããããã«å¿
èŠãªç§»åã®æ°ã€ã³ã¹ã¿ã³ããã¹
ãŸããã²ãŒã ããã¬ã€ãããšãããã¹æ€çŽ¢ã¢ã«ãŽãªãºã ãã©ã®ããã«éãèŠã€ãããã¯æ°ã«ããŸãããèŠæ±ããããã¹ãããã«èŠããã§ããçŸæç¹ã§ã¯ãã¢ã«ãŽãªãºã ãæ©èœããŠããããšã確èªã§ããŸãã®ã§ãæ€çŽ¢ã®èŠèŠåãåé€ããŸããããã³ã«ãã³ãªã
ã¢ã«ãŽãªãºã ããã£ãããšééãããããã«ãã³ã«ãã³ã䜿çšããŸããããããè¡ãå¿
èŠã¯ãããªãã®ã§ãåŒã³åºãStartCoroutine
ãšStopAllCoroutines
c ãåãé€ããŸãHexGrid
ã代ããã«ãåçŽã«Search
éåžžã®ã¡ãœãããšããŠåŒã³åºããŸãã public void Load (BinaryReader reader, int header) {
Search
ã³ã«ãŒãã³ãšããŠäœ¿çšããªããªã£ããããyieldãå¿
èŠãšããªãããããã®æŒç®åãåãé€ããŸããããã¯ã宣èšãåé€ãWaitForSeconds
ãã¡ãœããã®æ»ãå€ã®åãã«å€æŽããããšãæå³ãvoid
ãŸãã void Search (HexCell fromCell, HexCell toCell, int speed) { âŠ
ã€ã³ã¹ã¿ã³ãçµææ€çŽ¢æéã®å®çŸ©
ããã§ããã«ãã¹ãååŸã§ããŸãããã©ã®ãããã®éãã§èšç®ãããŸããïŒçããã¹ã¯ã»ãšãã©ããã«è¡šç€ºãããŸããã倧ããªãããã§é·ããã¹ã¯å°ãé
ãèŠãããããããŸããããã¹ãèŠã€ããŠè¡šç€ºããã®ã«ãããæéã枬å®ããŸãããããããã¡ã€ã©ãŒã䜿çšããŠæ€çŽ¢æéã決å®ã§ããŸãããããã¯å°ãå€ãããŠè¿œå ã³ã¹ããçºçããŸãã代ããStopwatch
ã«ãnamespaceã«ããã䜿çšããŸãããSystem.Diagnostics
ãäžæçã«ã®ã¿äœ¿çšããããusing
ãã¹ã¯ãªããã®å
é ã«æ§é ãè¿œå ããŸãããæ€çŽ¢ã®çŽåã«ãæ°ããã¹ããããŠã©ãããäœæããŠéå§ããŸããæ€çŽ¢ãå®äºããããã¹ããããŠã©ãããåæ¢ããã³ã³ãœãŒã«ã«çµéæéã衚瀺ããŸãã public void FindPath (HexCell fromCell, HexCell toCell, int speed) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); Search(fromCell, toCell, speed); sw.Stop(); Debug.Log(sw.ElapsedMilliseconds); }
ã¢ã«ãŽãªãºã ã®ææªã®ã±ãŒã¹ãéžæããŸããã-倧ããªå°å³ã®å·Šäžããå³äžé
ãžã®æ€çŽ¢ãã¢ã«ãŽãªãºã ã¯4,800åã®ãããã»ã«ãã¹ãŠãåŠçããå¿
èŠããããããææªã®å Žåã¯åäžãªãããã§ããææªã®å Žåã®æ€çŽ¢Unityãšãã£ã¿ãŒããã·ã³ã§å®è¡ãããŠããå¯äžã®ããã»ã¹ã§ã¯ãªããããæ€çŽ¢ã«ãããæéã¯ç°ãªãå ŽåããããŸãããããã£ãŠããããæ°åãã¹ãããŠãå¹³åæéãç解ããŠãã ãããç§ã®å Žåãæ€çŽ¢ã«ã¯çŽ45ããªç§ããããŸããããã¯ããã»ã©å€ãã¯ãªãã1ç§ããã22.22ãã¹ã«çžåœããŸããããã22 ppsïŒãã¹/ç§ïŒãšããŠç€ºããŸããã€ãŸãããã®ãã¹ãèšç®ãããšãã²ãŒã ã®ãã¬ãŒã ã¬ãŒãããã®ãã¬ãŒã ã§æ倧22 fpsäœäžããŸãããããŠãããã¯ããã¬ãŒã èªäœã®ã¬ã³ããªã³ã°ãªã©ãä»ã®ãã¹ãŠã®äœæ¥ãèæ
®ã«å
¥ããŠããŸãããã€ãŸãããã¬ãŒã ã¬ãŒããããªã倧ããäœäžãã20 fpsã«äœäžããŸãããã®ãããªããã©ãŒãã³ã¹ãã¹ããå®è¡ããå ŽåãUnityãšãã£ã¿ãŒã®ããã©ãŒãã³ã¹ã¯ãå®æããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã»ã©é«ããªãããšãèæ
®ããå¿
èŠããããŸããã¢ã»ã³ããªã§åããã¹ããå®è¡ãããšãå¹³åã§ããã15ããªç§ããããŸããããã¯66 ppsã§ãã¯ããã«åªããŠããŸããããã§ããããã¯ãã¬ãŒã ããšã«å²ãåœãŠããããªãœãŒã¹ã®å€§éšåã§ããããããã¬ãŒã ã¬ãŒãã¯60 fpsæªæºã«ãªããŸããã¢ã»ã³ããªã®ãããã°ãã°ã¯ã©ãã§ç¢ºèªã§ããŸããïŒUnityã¢ããªã±ãŒã·ã§ã³ã¯ãã·ã¹ãã ã«ä¿åãããŠãããã°ãã¡ã€ã«ã«æžã蟌ã¿ãŸãããã®å Žæã¯ãã©ãããã©ãŒã ã«ãã£ãŠç°ãªããŸããã·ã¹ãã ã§ãã°ãã¡ã€ã«ãèŠã€ããæ¹æ³ã«ã€ããŠã¯ãUnity ãã°ãã¡ã€ã«ã®ããã¥ã¡ã³ããåç
§ããŠãã ããã å¿
èŠãªå Žåã«ã®ã¿æ€çŽ¢
åçŽãªæé©åãè¡ãããšãã§ããŸã-å¿
èŠãªãšãã«ã®ã¿æ€çŽ¢ãå®è¡ããŸããããŠã¹ãã¿ã³ãæŒãããŠããåãã¬ãŒã ã§æ°ããæ€çŽ¢ãéå§ããŸãããããã£ãŠããã¬ãŒã ã¬ãŒãã¯ããã©ãã°ã¢ã³ãããããæã«åžžã«éå°è©äŸ¡ãããŸããHexMapEditor.HandleInput
æ°ãããšã³ããã€ã³ããå®éã«åŠçããŠããå Žåã«ã®ã¿ãæ°ããæ€çŽ¢ãéå§ããããšã§ãããåé¿ã§ããŸããããã§ãªãå ŽåãçŸåšã®è¡šç€ºãã¹ã¯ãŸã æå¹ã§ãã if (editMode) { EditCells(currentCell); } else if ( Input.GetKey(KeyCode.LeftShift) && searchToCell != currentCell ) { if (searchFromCell != currentCell) { if (searchFromCell) { searchFromCell.DisableHighlight(); } searchFromCell = currentCell; searchFromCell.EnableHighlight(Color.blue); if (searchToCell) { hexGrid.FindPath(searchFromCell, searchToCell, 24); } } } else if (searchFromCell && searchFromCell != currentCell) { if (searchToCell != currentCell) { searchToCell = currentCell; hexGrid.FindPath(searchFromCell, searchToCell, 24); } }
ãã¹ã®ã©ãã«ã®ã¿ã衚瀺
æ
è¡ããŒã¯ã®è¡šç€ºã¯ãç¹ã«æé©åãããŠããªãã¢ãããŒãã䜿çšããŠãããããããªãè²»çšã®ãããæäœã§ãããã¹ãŠã®ã»ã«ã«å¯ŸããŠãã®æäœãå®è¡ãããšãééããªãå®è¡é床ãäœäžããŸããã®ã©ãã«ä»ããã¹ãããããŸãããHexGrid.Search
ã if (neighbor.Distance == int.MaxValue) { neighbor.Distance = distance;
ãã®æ
å ±ã¯ãèŠã€ãã£ããã¹ã«ã€ããŠã®ã¿è¡šç€ºããå¿
èŠããããŸãããããã£ãŠãçµç¹ã«å°éããåŸãã³ãŒã¹ãèšç®ããéäžã®ã»ã«ã«ã®ã¿ã©ãã«ãèšå®ããŸãã if (current == toCell) { current = current.PathFrom; while (current != fromCell) { int turn = current.Distance / speed; current.SetLabel(turn.ToString()); current.EnableHighlight(Color.white); current = current.PathFrom; } break; }
ãã¹ã»ã«ã®ã¿ã®ã©ãã«ã®è¡šç€ºããã§ãéå§ãšçµäºã®éã«ã»ã«ã®ã©ãã«ã®ã¿ãå«ããŸããããããçµç¹ã¯æãéèŠãªãã®ã§ãããããã«ã©ãã«ãèšå®ããå¿
èŠããããŸãããããè¡ãã«ã¯ãå®å
ã»ã«ã®ãã¹ãµã€ã¯ã«ãéå§ãããã®åã®ã»ã«ããã§ã¯ãããŸããããã®å Žåããšã³ããã€ã³ãã®èµ€ããçœãžã®ç
§æãå€åããããããµã€ã¯ã«ã®äžã§ããã¯ã©ã€ããåé€ããŸãã fromCell.EnableHighlight(Color.blue);
æãéèŠãªãšã³ããã€ã³ãã«é¢ããæ
å ±ãããã®å€æŽåŸãææªã®å Žåã®æéã¯ããšãã£ã¿ã§ãå®æããã¢ã»ã³ããªã§6ããªç§ãŸã§ã®23ããªç§ã«æžå°ããŸããããããã¯43 ppsãš166 ppsã§ãããŠããã£ããã±ãŒãžæãè³¢ãæ€çŽ¢
åã®ããŒãã§ã¯ãA *ã¢ã«ãŽãªãºã ãå®è£
ããããšã«ãããæ€çŽ¢æé ãããã¹ããŒãã«ããŸããããã ããå®éã«ã¯ãŸã æé©ãªæ¹æ³ã§æ€çŽ¢ãå®è¡ããŠããŸãããåå埩ã§ãçŸåšã®ã»ã«ãããã®ãã¹ãŠã®é£æ¥ã»ã«ãŸã§ã®è·é¢ãèšç®ããŸããããã¯ããŸã æ€çŽ¢æ ã«å«ãŸããŠããªãããçŸåšæ€çŽ¢æ ã®äžéšã«ãªã£ãŠããã»ã«ã«åœãŠã¯ãŸããŸãããããããã§ã«å¢çããåé€ãããã»ã«ã¯ããããã®ã»ã«ãžã®æççµè·¯ããã§ã«èŠã€ããŠãããããèæ
®ããå¿
èŠã¯ãããŸãããA *ã®æ£ããå®è£
ã¯ãããã®ã»ã«ãã¹ãããããã®ã§ãåãããšãã§ããŸããã»ã«æ€çŽ¢ãã§ãŒãº
ã»ã«ããã§ã«å¢çç·ãé¢ããŠãããã©ãããã©ã®ããã«ããŠç¥ãã®ã§ããããïŒãããå€æããããšã¯ã§ããŸãããããã®ãããã»ã«ãæ€çŽ¢ã®ã©ã®æ®µéã«ãããã远跡ããå¿
èŠããããŸãã圌女ã¯ãŸã åœå¢ã«ããªãã£ãããä»åœå¢ã«ããŠããããæµ·å€ã«ããŸããããã远跡ããã«ã¯ãHexCell
åçŽãªæŽæ°ããããã£ã«è¿œå ããŸãã public int SearchPhase { get; set; }
ããšãã°ã0ã¯ã»ã«ããŸã å°éããŠããªãããšã1-ã»ã«ã¯çŸåšå¢çå
ã«ããããšã2-æ¢ã«å¢çããåé€ãããŠããããšãæå³ããŸããããŒããŒãæã€
ããã§HexGrid.Search
ã¯ããã¹ãŠã®ã»ã«ã0ã«ãªã»ããããå¢çã«åžžã«1ã䜿çšã§ããŸãããŸãã¯ãæ°ããæ€çŽ¢ããšã«å¢çç·ã®æ°ãå¢ããããšãã§ããŸãããã®ãããã§ãå¢çç·ã®æ°ãæ¯å2ãã€å¢ãããŠããã»ã«ã®ãã³ããåŠçããå¿
èŠã¯ãããŸããã int searchFrontierPhase; ⊠void Search (HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; ⊠}
次ã«ãå¢çã«ã»ã«ãè¿œå ãããšãã«ã»ã«æ€çŽ¢ã®ãã§ãŒãºãèšå®ããå¿
èŠããããŸããããã»ã¹ã¯ãå¢çã«è¿œå ãããåæã»ã«ããå§ãŸããŸãã fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell);
ãŸããåœå¢ã«é£äººãè¿œå ãããã³ã«ã if (neighbor.Distance == int.MaxValue) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); }
ããŒããŒãã§ãã¯
ãããŸã§ãã»ã«ããŸã å¢çç·ã«è¿œå ãããŠããªãããšã確èªããããã«ãã«çããè·é¢ã䜿çšããŸããint.MaxValue
ãããã§ãã»ã«æ€çŽ¢ã®ãã§ãŒãºãšçŸåšã®å¢çç·ãæ¯èŒã§ããŸãã
ããã¯ãæ€çŽ¢ããåã«ã»ã«ã®è·é¢ããªã»ããããå¿
èŠããªããªã£ãããšãæå³ããŸããã€ãŸããäœæ¥ãå°ãªããŠãã¿ãŸããããã¯è¯ãããšã§ãã for (int i = 0; i < cells.Length; i++) {
åœå¢ãé¢ãã
å¢çããã»ã«ãåé€ããããšãæ€çŽ¢ãã§ãŒãºã®å¢å ã«ãã£ãŠããã瀺ããŸããããã«ããã圌女ã¯çŸåšã®å¢çãè¶ããŠæ¬¡ã®å¢çã®åã«é
眮ãããŸãã while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; ⊠}
ããã§ãå¢çããåé€ãããã»ã«ãã¹ãããããŠãç¡æå³ãªèšç®ãšè·é¢ã®æ¯èŒãåé¿ã§ããŸãã for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } ⊠}
ãã®æç¹ã§ãã¢ã«ãŽãªãºã ã¯åãçµæãçæããŸãããããå¹ççã§ããç§ã®ãã·ã³ã§ã¯ãææªã®å Žåã®æ€çŽ¢ã«ã¯ãšãã£ã¿ãŒã§20ããªç§ãã¢ã»ã³ããªã§5ããªç§ããããŸããã¢ã«ãŽãªãºã ã«ãã£ãŠã»ã«ãåŠçãããåæ°ãèšç®ããããšãã§ããŸããããã«ãããã»ã«ãŸã§ã®è·é¢ãèšç®ãããšãã«ã«ãŠã³ã¿ãŒãå¢ããŸãã以åã¯ãææªã®å Žåã®ã¢ã«ãŽãªãºã ã¯28,239ã®è·é¢ãèšç®ããŠããŸãããæ¢è£œã®A *ã¢ã«ãŽãªãºã ã§ã¯ã14,120ã®è·é¢ãèšç®ããŸããéã¯50ïŒ
æžå°ããŸããããããã®ææšãçç£æ§ã«äžãã圱é¿ã®çšåºŠã¯ã移åã³ã¹ããèšç®ããã³ã¹ãã«äŸåããŸããç§ãã¡ã®å Žåãããã§ã®äœæ¥ã¯ããŸããªãã®ã§ãã¢ã»ã³ããªã®æ¹åã¯ããã»ã©å€§ãããããŸãããããšãã£ã¿ãŒã§ã¯éåžžã«é¡èã§ãããŠããã£ããã±ãŒãžéãéã
æ°ããæ€çŽ¢ãéå§ãããšããæåã«ä»¥åã®ãã¹ã®èŠèŠåãã¯ãªã¢ããå¿
èŠããããŸãããã®éãéžæããªãã«ããŠãåã°ãªããã»ã«ããã©ãã«ãåé€ããŸããããã¯éåžžã«é£ããã¢ãããŒãã§ããçæ³çã«ã¯ãåã®ãã¹ã®äžéšã§ãã£ãã»ã«ã®ã¿ããªã»ããããå¿
èŠããããŸããæ€çŽ¢ã®ã¿
ããèŠèŠåã³ãŒããå®å
šã«åé€ããããšããå§ããŸãããSearch
ã圌ã¯ãã¹æ€çŽ¢ãå®è¡ããã ãã§ããããã®æ
å ±ã§äœãããããç¥ãå¿
èŠã¯ãããŸããã void Search (HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); }
Search
æ¹æ³ãèŠã€ãã£ãããšãå ±åããã«ã¯ãããŒã«å€ãè¿ããŸãã bool Search (HexCell fromCell, HexCell toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return true; } ⊠} return false; }
æ¹æ³ãèŠããŠãã
ãã¹ãèŠã€ãã£ããããããèŠããŠããå¿
èŠããããŸããããã«ãããå°æ¥çã«ã¯ã¯ãªãŒãã³ã°ã§ããããã«ãªããŸãããããã£ãŠããšã³ããã€ã³ããšããããã®éã«ãã¹ããããã©ããã远跡ããŸãã HexCell currentPathFrom, currentPathTo; bool currentPathExists; ⊠public void FindPath (HexCell fromCell, HexCell toCell, int speed) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); currentPathFrom = fromCell; currentPathTo = toCell; currentPathExists = Search(fromCell, toCell, speed); sw.Stop(); Debug.Log(sw.ElapsedMilliseconds); }
ãã¹ãããäžåºŠè¡šç€ºãã
èšé²ããæ€çŽ¢ããŒã¿ã䜿çšããŠããã¹ãå床èŠèŠåã§ããŸãããã®ããã®æ°ããã¡ãœãããäœæããŸãããShowPath
ããã¹ã®çµããããå§ãŸããŸã§ã®ãµã€ã¯ã«ã§è¡ãããã»ã«ã匷調衚瀺ããã©ãã«ã«ã¹ãããŒã¯å€ãå²ãåœãŠãŸãããããè¡ãã«ã¯ãé床ãç¥ãå¿
èŠããããããé床ããã©ã¡ãŒã¿ã«ããŸãããã¹ããªãå Žåãã¡ãœããã¯åã«ãšã³ããã€ã³ããéžæããŸãã void ShowPath (int speed) { if (currentPathExists) { HexCell current = currentPathTo; while (current != currentPathFrom) { int turn = current.Distance / speed; current.SetLabel(turn.ToString()); current.EnableHighlight(Color.white); current = current.PathFrom; } } currentPathFrom.EnableHighlight(Color.blue); currentPathTo.EnableHighlight(Color.red); }
FindPath
æ€çŽ¢åŸã«ãã®ã¡ãœãããåŒã³åºããŸãã currentPathExists = Search(fromCell, toCell, speed); ShowPath(speed);
ã¹ã€ãŒã
ç§ãã¡ã¯åã³éãèŠãããä»ã§ã¯ããã¯é¢ããŠããªããã¯ãªã¢ããã«ã¯ãã¡ãœãããäœæããŸãClearPath
ãå®éãããã¯ã³ããŒã§ãShowPath
ããã ããéžæãšã©ãã«ã¯ç¡å¹ã«ãªããŸããããããã¯å«ãŸããŸããããããè¡ã£ãåŸã圌ã¯ç¡å¹ã«ãªã£ãèšé²ããããã¹ããŒã¿ãæ¶å»ããå¿
èŠããããŸãã void ClearPath () { if (currentPathExists) { HexCell current = currentPathTo; while (current != currentPathFrom) { current.SetLabel(null); current.DisableHighlight(); current = current.PathFrom; } current.DisableHighlight(); currentPathExists = false; } currentPathFrom = currentPathTo = null; }
ãã®æ¹æ³ã䜿çšãããšãå¿
èŠãªã»ã«ã®ã¿ã«ã¢ã¯ã»ã¹ããããšã§å€ããã¹ã®èŠèŠåãã¯ãªã¢ã§ããŸãããããã®ãµã€ãºã¯éèŠã§ã¯ãªããªããŸãããFindPath
æ°ããæ€çŽ¢ãéå§ããåã«åŒã³åºããŠãã ããã sw.Start(); ClearPath(); currentPathFrom = fromCell; currentPathTo = toCell; currentPathExists = Search(fromCell, toCell, speed); if (currentPathExists) { ShowPath(speed); } sw.Stop();
ããã«ãæ°ããããããäœæãããšãã«ãã¹ãã¯ãªã¢ããŸãã public bool CreateMap (int x, int z) { ⊠ClearPath(); if (chunks != null) { for (int i = 0; i < chunks.Length; i++) { Destroy(chunks[i].gameObject); } } ⊠}
ãŸããå¥ã®ã«ãŒããããŒãããåã«ã public void Load (BinaryReader reader, int header) { ClearPath(); ⊠}
ãã®å€æŽåãšåæ§ã«ããã¹ã®èŠèŠåã¯åã³ã¯ãªã¢ãããŸããããããä»ã§ã¯ããå¹ççãªã¢ãããŒãã䜿çšããŠãããææªã®æ€çŽ¢ã®å Žåãæéã¯14ããªç§ã«ççž®ãããŠããŸããããã€ã³ããªãžã§ã³ããªã¯ãªãŒãã³ã°ã®ã¿ã«ããååãªæ·±å»ãªæ¹åãã¢ã»ã³ããªæéã¯3ããªç§ã«æžå°ããŸãããããã¯333 ppsã§ããããã«ããããã¹ã®æ€çŽ¢ã¯ãªã¢ã«ã¿ã€ã ã§æ£ç¢ºã«é©çšã§ããŸãããã¹ããã°ããæ€çŽ¢ããã®ã§ãäžæçãªãããã°ã³ãŒããåé€ã§ããŸãã public void FindPath (HexCell fromCell, HexCell toCell, int speed) {
ãŠããã£ããã±ãŒãžããŒã18ïŒãŠããã
- ãããã«ããŒã ãé
眮ããŸãã
- ããŒã ãä¿åããŠããŒãããŸãã
- è»éã®ããã®æ¹æ³ãèŠã€ããŸãã
- ãŠãããã移åããŸãã
ãã¹ãæ€çŽ¢ããæ¹æ³ãããã£ãã®ã§ããããã«ããŒã ãé
眮ããŸããããå¢æŽãå°çããŸããããŒã ãäœæãã
ãããŸã§ã¯ãã»ã«ãšãã®åºå®ãªããžã§ã¯ãã®ã¿ãæ±ã£ãŠããŸããããŠãããã¯ã¢ãã€ã«ã§ãããšããç¹ã§ããããšç°ãªããŸããåé¢ãšã¯ã1人ã®äººéãè»äž¡ããè»å
šäœã«è³ããŸã§ãããããèŠæš¡ã®ãããããã®ãæå³ããŸãããã®ãã¥ãŒããªã¢ã«ã§ã¯ãåçŽãªæ±çšã¿ã€ãã®ãŠãããã«éå®ããŸãããã®åŸãããã€ãã®ã¿ã€ãã®ãŠãããã®çµã¿åããã®ãµããŒãã«é²ã¿ãŸãããã¬ããåé
åéã§äœæ¥ããã«ã¯ãæ°ããã¿ã€ãã®ã³ã³ããŒãã³ããäœæããŸãHexUnit
ããšããããã空ã®ãã®ããå§ããŠãMonoBehaviour
åŸã§æ©èœãè¿œå ããŸãããã using UnityEngine; public class HexUnit : MonoBehaviour { }
ãã®ã³ã³ããŒãã³ãã§ç©ºã®ã²ãŒã ãªããžã§ã¯ããäœæããŸããããã¯ãã¬ããã«ãªããŸãããããããŒã ã®ã«ãŒããªããžã§ã¯ãã«ãªããŸãããã¬ããéšéãåé¢ã象城ãã3Dã¢ãã«ãåãªããžã§ã¯ããšããŠè¿œå ããŸããéè²ã®ãããªã¢ã«ãäœæããã·ã³ãã«ãªã¹ã±ãŒã«ãã¥ãŒãã䜿çšããŸãããã«ãŒããªããžã§ã¯ãããã¿ããã¡ã³ãã®ã°ã©ãŠã³ãã¬ãã«ã決å®ãããããããã«å¿ããŠåèŠçŽ ã移åããŸããåèŠçŽ ãã¥ãŒãå°æ¥çã«éžæããããããããã«ãããŒã ã«ã³ã©ã€ããŒãè¿œå ããŸããæšæºãã¥ãŒãã®ã³ã©ã€ããŒã¯ç§ãã¡ã«éåžžã«é©ããŠããŸããã³ã©ã€ããŒã1ã€ã®ã»ã«ã«åããã ãã§ããåéã€ã³ã¹ã¿ã³ã¹ã®äœæ
ãŸã ã²ãŒã ãã¬ã€ããªãããããŠãããã®äœæã¯ç·šéã¢ãŒãã§è¡ãããŸãããããã£ãŠãããã«å¯ŸåŠããå¿
èŠããããŸãHexMapEditor
ããããè¡ãã«ã¯ããã¬ãããå¿
èŠãªã®ã§ããã£ãŒã«ãHexUnit unitPrefab
ãè¿œå ããŠæ¥ç¶ããŸãã public HexUnit unitPrefab;
ãã¬ããã®æ¥ç¶ãŠããããäœæãããšããããããã«ãŒãœã«ã®äžã®ã»ã«ã«é
眮ããŸããHandleInput
å°åœ¢ãç·šéãããšãã«ãã®ã»ã«ãèŠã€ããããã®ã³ãŒãããããŸããä»åºŠã¯ããŒã ã«ãå¿
èŠãªã®ã§ã察å¿ããã³ãŒããå¥ã®ã¡ãœããã«ç§»åããŸãã HexCell GetCellUnderCursor () { Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(inputRay, out hit)) { return hexGrid.GetCell(hit.point); } return null; }
ããã§ããã®ã¡ãœããã䜿çšããŠHandleInput
åçŽåã§ããŸãã void HandleInput () {
次ã«ãã䜿çšããæ°ããã¡ãœããCreateUnit
ãè¿œå ããŸãGetCellUnderCursor
ãã»ã«ãããã°ãæ°ããããŒã ãäœæããŸãã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell) { Instantiate(unitPrefab); } }
éå±€ããããã«ä¿ã€ããã«ãã°ãªãããããŒã ã®ãã¹ãŠã®ã²ãŒã ãªããžã§ã¯ãã®èŠªãšããŠäœ¿çšããŠã¿ãŸãããã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell) { HexUnit unit = Instantiate(unitPrefab); unit.transform.SetParent(hexGrid.transform, false); } }
HexMapEditor
ãŠãããäœæã®ãµããŒããè¿œå ããæãç°¡åãªæ¹æ³ã¯ãããŒãæŒãããšã§ããUããŒãæŒããããšãUpdate
ã«åŒã³åºãCreateUnit
ããããã«ã¡ãœãããå€æŽããŸãc HandleInput
ãšåæ§ã«ãããã¯ã«ãŒãœã«ãGUIèŠçŽ ã®äžã«ãªãå Žåã«çºçããŸããæåã«ãããããç·šéããå¿
èŠããããã©ããã確èªããç·šéããªãå Žåã¯ãããŒã ãè¿œå ããå¿
èŠããããã©ããã確èªããŸãããã®å Žåã¯ããåŒã³åºããŸãCreateUnit
ã void Update () {
åéã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸããéšéé
眮
ããã§ãŠããããäœæã§ããŸããããããã¯ãããã®åç¹ã«è¡šç€ºãããŸããé©åãªå Žæã«é
眮ããå¿
èŠããããŸãããã®ããã«ã¯ãè»éãèªåã®ç«å Žãèªèããå¿
èŠããããŸãããããã£ãŠãããããå ããã»ã«ã瀺ãHexUnit
ããããã£ã«è¿œå ããŸãLocation
ãããããã£ãèšå®ãããšããã»ã«ã®äœçœ®ã«äžèŽããããã«åéã®äœçœ®ãå€æŽããŸãã public HexCell Location { get { return location; } set { location = value; transform.localPosition = value.Position; } } HexCell location;
次ã«HexMapEditor.CreateUnit
ãã«ãŒãœã«ã®äžã®åéã»ã«ã®äœçœ®ãå²ãåœãŠãå¿
èŠããããŸãããã®åŸããŠãããã¯å¿
èŠãªå Žæã«é
眮ãããŸãã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell) { HexUnit unit = Instantiate(unitPrefab); unit.transform.SetParent(hexGrid.transform, false); unit.Location = cell; } }
ãããäžã®åéãŠãããã®åã
ãããŸã§ã®ãšããããã¹ãŠã®ãŠãããã®åãã¯åãã§ãããªãäžèªç¶ã«èŠããŸãããããã埩掻ãããã«ã¯ãHexUnit
ããããã£ã«è¿œå ããŸãOrientation
ãããã¯ãY軞ã«æ²¿ã£ãåéã®å転ã床åäœã§ç€ºããããŒãå€ã§ãããããèšå®ãããšããããã«å¿ããŠã²ãŒã ãªããžã§ã¯ãèªäœã®å転ãå€æŽããŸãã public float Orientation { get { return orientation; } set { orientation = value; transform.localRotation = Quaternion.Euler(0f, value, 0f); } } float orientation;
HexMapEditor.CreateUnit
0ã360床ããå²ãåœãŠã©ã³ãã å転ã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell) { HexUnit unit = Instantiate(unitPrefab); unit.transform.SetParent(hexGrid.transform, false); unit.Location = cell; unit.Orientation = Random.Range(0f, 360f); } }
ç°ãªããŠãããã®åãã»ã«ããšã«1ã€ã®ããŒã
ãŠãããã¯ã1ã€ã®ã»ã«ã§äœæãããŠããªãå Žåã«è¡šç€ºãããŸãããã®å Žåãå¥åŠã«èŠãããã¥ãŒãã®ã¯ã©ã¹ã¿ãŒãååŸããŸãããªãŒããŒã¬ã€ããããŠãããã²ãŒã ã«ãã£ãŠã¯ãè€æ°ã®ãŠãããã1ãæã«é
眮ã§ãããã®ãšããã§ãªããã®ããããŸããã»ã«ããšã«1ã€ã®ããŒã ã§äœæ¥ããæ¹ãç°¡åãªã®ã§ããã®ãªãã·ã§ã³ãéžæããŸããããã¯ãçŸåšã®ã»ã«ãå æãããŠããªãå Žåã«ã®ã¿æ°ããããŒã ãäœæããå¿
èŠãããããšãæå³ããŸããèŠã€ããããããã«ãHexCell
æšæºããããã£ã«è¿œå ããŸãUnit
ã public HexUnit Unit { get; set; }
ãã®ããããã£ã䜿çšããŠHexUnit.Location
ããŠãããããã®äžã«ãããã©ãããã»ã«ã«ç¥ãããŸãã public HexCell Location { get { return location; } set { location = value; value.Unit = this; transform.localPosition = value.Position; } }
çŸåšHexMapEditor.CreateUnit
ãçŸåšã®ã»ã«ã空ããŠãããã©ããã確èªã§ããŸãã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell && !cell.Unit) { HexUnit unit = Instantiate(unitPrefab); unit.Location = cell; unit.Orientation = Random.Range(0f, 360f); } }
ããžãŒã»ã«ã®ç·šé
æåã¯ããŠãããã¯æ£ããé
眮ãããŠããŸãããå°æ¥ã»ã«ãç·šéãããå Žåããã¹ãŠãå€æŽãããå¯èœæ§ããããŸããã»ã«ã®é«ããå€ãããšãã»ã«ãå æããŠãããŠããããã»ã«ã®äžã«ã¶ãäžããããã»ã«ã«çªå
¥ããŸããã¶ãäžããŠandããåé解決çã¯ãå€æŽãè¡ã£ãåŸãåéã®äœçœ®ã確èªããããšã§ãããããè¡ãã«ã¯ãã¡ãœãããã«è¿œå ãHexUnit
ãŸãããããŸã§ã®ãšããããã¿ããã¡ã³ãã®äœçœ®ã«ã®ã¿é¢å¿ããããããåçŽã«åèšå®ããŸãã public void ValidateLocation () { transform.localPosition = location.Position; }
ã»ã«ãæŽæ°ãããšããã¡ãœããRefresh
ãŸãã¯RefreshSelfOnly
ãªããžã§ã¯ããHexCell
åŒã³åºããããšãã«äœãèµ·ãããããã¿ããã¡ã³ãã®äœçœ®ã調æŽããå¿
èŠããããŸãããã¡ãããããã¯ã»ã«ã«å®éã«åé¢ãããå Žåã«ã®ã¿å¿
èŠã§ãã void Refresh () { if (chunk) { chunk.Refresh(); ⊠if (Unit) { Unit.ValidateLocation(); } } } void RefreshSelfOnly () { chunk.Refresh(); if (Unit) { Unit.ValidateLocation(); } }
ããŒã ãåé€ãã
ãŠããããäœæããããšã«å ããŠããŠããããç Žå£ããããšã¯æçšã§ãããããã£ãŠãHexMapEditor
ã¡ãœããã«è¿œå ãDestroyUnit
ãŸãã圌ã¯ãã«ãŒãœã«ã®äžã®ã»ã«ã«ãã¿ããã¡ã³ãããããã©ããã確èªããå¿
èŠããããŸããããå Žåã¯ããã¿ããã¡ã³ãã®ã²ãŒã ãªããžã§ã¯ããç Žå£ããŸãã void DestroyUnit () { HexCell cell = GetCellUnderCursor(); if (cell && cell.Unit) { Destroy(cell.Unit.gameObject); } }
åéã«çãããã«ãç§ãã¡ã¯ã»ã«ãééããããšã«æ³šæããŠãã ãããåéãšããåãããã«ã¯ãããŠã¹ããã®ã»ã«ã®äžã«ç§»åããã ãã§ãããããã£ãŠããããæ©èœããããã«ã¯ãããŒã ã«ã¯ã³ã©ã€ããŒãå¿
èŠãããŸããããã ããã³ã©ã€ããŒãè¿œå ãããšãåéã®èåŸã®ã»ã«ã«è¡çªããå
ç·ããããã¯ãããããããããç°¡åã«åé¢ã§ããŸããå·ŠShift + Uã®çµã¿åããã䜿çšããŠãåéãç Žå£ããŸãããUpdate
ã if (Input.GetKeyDown(KeyCode.U)) { if (Input.GetKey(KeyCode.LeftShift)) { DestroyUnit(); } else { CreateUnit(); } return; }
è€æ°ã®ãŠããããäœæããã³ç Žæ£ããå ŽåããŠããããåé€ããéã«æ³šæããŠããããã£ãã¯ãªã¢ããŸããããã€ãŸããåéãžã®ã»ã«ãªã³ã¯ãæ瀺çã«ã¯ãªã¢ããŸããããã«å¯ŸåŠããHexUnit
ã¡ãœããã«å ããŠãDie
ç¬èªã®ã²ãŒã ãªããžã§ã¯ããç Žå£ããŸãã public void Die () { location.Unit = null; Destroy(gameObject); }
ãã®ã¡ãœããã¯ã§åŒã³åºãHexMapEditor.DestroyUnit
ãåéãçŽæ¥ç Žå£ããŸããã void DestroyUnit () { HexCell cell = GetCellUnderCursor(); if (cell && cell.Unit) {
ãŠããã£ããã±ãŒãžããŒã ã®ä¿åãšèªã¿èŸŒã¿
ãããäžã«ãŠããããé
眮ã§ããããã«ãªã£ãã®ã§ãä¿åããã³èªã¿èŸŒã¿ããã»ã¹ã«ãŠããããå«ããå¿
èŠããããŸãããã®ã¿ã¹ã¯ã«ã¯2ã€ã®æ¹æ³ã§ã¢ãããŒãã§ããŸãã1ã€ã¯ãã»ã«ãšåéããŒã¿ãæ··åãããããã«ãã»ã«ãèšé²ãããšãã«åéããŒã¿ãèšé²ããããšã§ãã2çªç®ã®æ¹æ³ã¯ãã»ã«ãšåéã®ããŒã¿ãå¥ã
ã«ä¿åããããšã§ããæåã®ã¢ãããŒãã®æ¹ãå®è£
ãç°¡åã«æãããããããŸãããã2çªç®ã®ã¢ãããŒãã¯ããæ§é åãããããŒã¿ãæäŸããŸããããŒã¿ãå
±æããã°ãå°æ¥ããããšã®äœæ¥ã容æã«ãªããŸãããŠããã远跡
ãã¹ãŠã®ãŠãããããŸãšããããã«ããããã远跡ããå¿
èŠããããŸãããããè¡ãã«ã¯HexGrid
ããŠãããã®ãªã¹ãã«è¿œå ããŸãããã®ãªã¹ãã«ã¯ããããäžã®ãã¹ãŠã®ãŠããããå«ãŸããŠããå¿
èŠããããŸãã List<HexUnit> units = new List<HexUnit>();
æ°ããããããäœæãŸãã¯ããŒããããšãããããäžã®ãã¹ãŠã®ãŠããããåãé€ãå¿
èŠããããŸãããã®ããã»ã¹ãç°¡çŽ åããã«ClearUnits
ã¯ããªã¹ãå
ã®å
šå¡ã殺ããŠã¯ãªã¢ããã¡ãœãããäœæããŸãã void ClearUnits () { for (int i = 0; i < units.Count; i++) { units[i].Die(); } units.Clear(); }
ãã®ã¡ãœãããCreateMap
ãšã§åŒã³åºããŸãLoad
ãéãæé€ããŠãããããã public bool CreateMap (int x, int z) { ⊠ClearPath(); ClearUnits(); ⊠} ⊠public void Load (BinaryReader reader, int header) { ClearPath(); ClearUnits(); ⊠}
ã°ãªãããžã®ããŒã ã®è¿œå
ããã§ãæ°ãããŠããããäœæãããšãã«ããããããªã¹ãã«è¿œå ããå¿
èŠããããŸããããã®ã¡ãœãããèšå®ããŠã¿ãŸããããããAddUnit
ã¯ãåéã®äœçœ®ãšãã®èŠªãªããžã§ã¯ãã®ãã©ã¡ãŒã¿ãŒãåŠçããŸãã public void AddUnit (HexUnit unit, HexCell location, float orientation) { units.Add(unit); unit.transform.SetParent(transform, false); unit.Location = location; unit.Orientation = orientation; }
ããã§ããã¿ããã¡ã³ãã®æ°ããã€ã³ã¹ã¿ã³ã¹ããã®å Žæãã©ã³ãã ãªæ¹åã§HexMapEditor.CreatUnit
åŒã³åºãã ãã§ååAddUnit
ã§ãã void CreateUnit () { HexCell cell = GetCellUnderCursor(); if (cell && !cell.Unit) {
ã°ãªããããããŒã ãåé€ãã
åéãšcãåé€ããã¡ãœãããè¿œå ããŸãHexGrid
ããªã¹ãããããŒã ãåé€ããŠãæ»ã¬ããã«åœããŠãã ããã public void RemoveUnit (HexUnit unit) { units.Remove(unit); unit.Die(); }
HexMapEditor.DestroyUnit
ããŒã ãçŽæ¥ç Žå£ãã代ããã«ããã®ã¡ãœãããåŒã³åºããŸãã void DestroyUnit () { HexCell cell = GetCellUnderCursor(); if (cell && cell.Unit) {
ãŠãããã®ä¿å
ãã¹ãŠã®ãŠãããããŸãšããŠããã®ã§ããŠããããå ããã»ã«ãèŠããŠããå¿
èŠããããŸããæãä¿¡é Œã§ããæ¹æ³ã¯ããã®å Žæã®åº§æšãä¿åããããšã§ãããããå¯èœã«ããããã«ããã£ãŒã«ãXãšZ ããããæžã蟌ãHexCoordinates
ã¡ãœããã«è¿œå ãSave
ãŸãã using UnityEngine; using System.IO; [System.Serializable] public struct HexCoordinates { ⊠public void Save (BinaryWriter writer) { writer.Write(x); writer.Write(z); } }
ãã®æ¹æ³Save
ã®ããã®HexUnit
猶ã¯ä»ãŠãããã®åº§æšãšåããèšé²ããŸããããã¯ãçŸåšæã£ãŠãããŠãããã®ãã¹ãŠã®ããŒã¿ã§ãã using UnityEngine; using System.IO; public class HexUnit : MonoBehaviour { ⊠public void Save (BinaryWriter writer) { location.coordinates.Save(writer); writer.Write(orientation); } }
HexGrid
ãŠãããã远跡ããããããã®ã¡ãœããSave
ã¯ãŠãããã®ããŒã¿ãèšé²ããŸããæåã«ããŠãããã®ç·æ°ãæžãçããŠãããã«ãŒãå
ã§ãããããã¹ãŠåã£ãŠãã ããã public void Save (BinaryWriter writer) { writer.Write(cellCountX); writer.Write(cellCountZ); for (int i = 0; i < cells.Length; i++) { cells[i].Save(writer); } writer.Write(units.Count); for (int i = 0; i < units.Count; i++) { units[i].Save(writer); } }
ä¿åãããŠããããŒã¿ãå€æŽãããããããŒãžã§ã³çªå·SaveLoadMenu.Save
ã2ã«å¢ãããŸããå€ãããŒãã³ãŒãã¯ãåéããŒã¿ãèªã¿åããªããããåŒãç¶ãæ©èœããŸãããã ãããã¡ã€ã«ã«ãŠãããããŒã¿ãããããšã瀺ãã«ã¯ãããŒãžã§ã³çªå·ãå¢ããå¿
èŠããããŸãã void Save (string path) { using ( BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)) ) { writer.Write(2); hexGrid.Save(writer); } }
éšéã®èªã¿èŸŒã¿
ããHexCoordinates
ã¯æ§é äœã§ãããããéåžžã®ã¡ãœãããè¿œå ããããšã¯ããŸãæå³ããããŸããLoad
ãä¿åããã座æšãèªã¿èŸŒãã§è¿ãéçã¡ãœããã«ããŸãã public static HexCoordinates Load (BinaryReader reader) { HexCoordinates c; cx = reader.ReadInt32(); cz = reader.ReadInt32(); return c; }
ãŠãããã®æ°ã¯å¯å€ã§ãããããããŒã¿ãããŒãã§ããæ¢åã®ãŠãããã¯ãããŸãããããŒã¿ãèªã¿èŸŒãåã«ãŠãããã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæã§ããŸãããããã«ã¯HexGrid
ããŒãæã«æ°ãããŠãããã®ã€ã³ã¹ã¿ã³ã¹ãäœæããå¿
èŠããããŸãããã®ãŸãŸã«ããŠããæ¹ãè¯ãHexUnit
ã§ãããŸããéçã¡ãœããã䜿çšããŸãHexUnit.Load
ããããã®ããŒã ãåã«èªãããšããå§ããŸããããæ¹åãããŒãã®å€ãèªã¿åãã«ã¯ãã¡ãœããã䜿çšãBinaryReader.ReadSingle
ãŸãããªãç¬èº«ïŒfloat
, . , double
, . Unity .
public static void Load (BinaryReader reader) { HexCoordinates coordinates = HexCoordinates.Load(reader); float orientation = reader.ReadSingle(); }
次ã®ã¹ãããã¯ãæ°ããããŒã ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããããšã§ãããã ãããã®ããã«ã¯ããŠãããã®ãã¬ãããžã®ãªã³ã¯ãå¿
èŠã§ãããŸã è€éã«ãªããªãããã«ãããã«HexUnit
éçã¡ãœãããè¿œå ããŸãããã public static HexUnit unitPrefab;
ãã®ãªã³ã¯ãèšå®HexGrid
ããã«ã¯ããã€ãºãã¯ã¹ãã£ã§è¡ã£ãããã«ãå床䜿çšããŸããå€ãã®çš®é¡ã®ãŠãããããµããŒãããå¿
èŠãããå Žåãããè¯ããœãªã¥ãŒã·ã§ã³ã«é²ã¿ãŸãã public HexUnit unitPrefab; ⊠void Awake () { HexMetrics.noiseSource = noiseSource; HexMetrics.InitializeHashGrid(seed); HexUnit.unitPrefab = unitPrefab; CreateMap(cellCountX, cellCountZ); } ⊠void OnEnable () { if (!HexMetrics.noiseSource) { HexMetrics.noiseSource = noiseSource; HexMetrics.InitializeHashGrid(seed); HexUnit.unitPrefab = unitPrefab; } }
ãŠãããã®ãã¬ãããæž¡ããŸãããã£ãŒã«ããæ¥ç¶ããåŸãã«çŽæ¥ãªã³ã¯ããå¿
èŠã¯ãªããªããŸããHexMapEditor
ã代ããã«ã圌ã¯ã䜿çšã§ããŸãHexUnit.unitPrefab
ã
ããã§ãæ°ããããŒã ã®ã€ã³ã¹ã¿ã³ã¹ãäœæã§ããŸãHexUnit.Load
ãè¿ã代ããã«ãããŒãããã座æšãšæ¹åã䜿çšããŠã°ãªããã«è¿œå ã§ããŸãããããå¯èœã«ããã«ã¯ããã©ã¡ãŒã¿ãŒãè¿œå ããŸãHexGrid
ã public static void Load (BinaryReader reader, HexGrid grid) { HexCoordinates coordinates = HexCoordinates.Load(reader); float orientation = reader.ReadSingle(); grid.AddUnit( Instantiate(unitPrefab), grid.GetCell(coordinates), orientation ); }
æåŸã«ãHexGrid.Load
ãŠãããã®æ°ãã«ãŠã³ãããããã䜿çšããŠãæ ŒçŽãããŠãããã¹ãŠã®ãŠããããããŒãããè¿œå ã®åŒæ°ãšããŠèªåèªèº«ãæž¡ããŸãã public void Load (BinaryReader reader, int header) { ⊠int unitCount = reader.ReadInt32(); for (int i = 0; i < unitCount; i++) { HexUnit.Load(reader, this); } }
ãã¡ãããããã¯ãããŒãžã§ã³ã2以äžã®ä¿åãã¡ã€ã«ã«å¯ŸããŠã®ã¿æ©èœããŸããè¥ãããŒãžã§ã³ã§ã¯ãããŒããããŠãããããããŸããã if (header >= 2) { int unitCount = reader.ReadInt32(); for (int i = 0; i < unitCount; i++) { HexUnit.Load(reader, this); } }
ããŒãžã§ã³2ã®ãã¡ã€ã«ãæ£ããã¢ããããŒãã§ããããã«SaveLoadMenu.Load
ãªã£ãããããµããŒããããããŒãžã§ã³ã®æ°ã2 ã«å¢ãããŸãã void Load (string path) { if (!File.Exists(path)) { Debug.LogError("File does not exist " + path); return; } using (BinaryReader reader = new BinaryReader(File.OpenRead(path))) { int header = reader.ReadInt32(); if (header <= 2) { hexGrid.Load(reader, header); HexMapCamera.ValidatePosition(); } else { Debug.LogWarning("Unknown map format " + header); } } }
ãŠããã£ããã±ãŒãžè»éã®åã
åéã¯ã¢ãã€ã«ã§ããããããããäžã§ç§»åã§ããå¿
èŠããããŸããæ¢ã«ãã¹æ€çŽ¢ã³ãŒãããããŸããããããŸã§ã®ãšãããä»»æã®å Žæã«ã€ããŠã®ã¿ãã¹ãããŸããã次ã«ãå€ããã¹ãUIãåé€ããããŒã 管ççšã®æ°ããUIãäœæããå¿
èŠããããŸããããããšãã£ã¿ãŒã®ã¯ãªãŒã³ã¢ãã
ãã¹ã«æ²¿ã£ãŠãŠãããã移åããããšã¯ã²ãŒã ãã¬ã€ã®äžéšã§ãããããããšãã£ã¿ãŒã«ã¯é©çšãããŸããããããã£ãŠãHexMapEditor
ãã¹ã®æ€çŽ¢ã«é¢é£ãããã¹ãŠã®ã³ãŒããåãé€ããŸãã
ãã®ã³ãŒããåé€ããåŸãç·šéã¢ãŒãã§ã¯ãªããšãã«ãšãã£ã¿ãŒãã¢ã¯ãã£ãã®ãŸãŸã«ããŠããããšã¯æå³ããããŸããããããã£ãŠãã¢ãŒã远跡ãã£ãŒã«ãã®ä»£ããã«ãã³ã³ããŒãã³ããæå¹ãŸãã¯ç¡å¹ã«ããããšãã§ããŸãHexMapEditor
ãããã«ããšãã£ã¿ãŒã¯UIã©ãã«ãåŠçããå¿
èŠããªããªããŸããã
ããã©ã«ãã§ã¯ãããç·šéã¢ãŒãã§ã¯ãªããããã¢ãŠã§ã€ã¯ã§ã¯ãšãã£ã¿ãŒãç¡å¹ã«ããŸãã void Awake () { terrainMaterial.DisableKeyword("GRID_ON"); SetEditMode(false); }
ã¬ã€ãã£ã¹ãã䜿çšããŠãããããç·šéãããšãã«ã«ãŒãœã«ã®äžã®çŸåšã®ã»ã«ãæ€çŽ¢ãããŠããããå¶åŸ¡ããå¿
èŠããããŸããããããå°æ¥çã«ã¯ãä»ã®äœãã®ããã«ç§ãã¡ã«åœ¹ç«ã€ã§ããããã¬ã€ãã£ã¹ãã£ã³ã°ããžãã¯ããããŒã ãã©ã¡ãŒã¿ãŒã䜿çšHexGrid
ããæ°ããã¡ãœããã«ç§»åããŸãããGetCell
ã public HexCell GetCell (Ray ray) { RaycastHit hit; if (Physics.Raycast(ray, out hit)) { return GetCell(hit.point); } return null; }
HexMapEditor.GetCellUniderCursor
ã«ãŒãœã«ããŒã ã§ãã®ã¡ãœãããåŒã³åºãã ãã§ãã HexCell GetCellUnderCursor () { return hexGrid.GetCell(Camera.main.ScreenPointToRay(Input.mousePosition)); }
ã²ãŒã UI
ã²ãŒã ã¢ãŒãUIãå¶åŸ¡ããã«ã¯ãæ°ããã³ã³ããŒãã³ãã䜿çšããŸãã圌ã¯ãŠãããã®éžæãšç§»åã®ã¿ãæ±ããŸããæ°ããã³ã³ããŒãã³ãã¿ã€ããäœæããŸãHexGameUI
ã圌ã®ä»äºãããã«ã¯ãã°ãªãããžã®ãªã³ã¯ã§ååã§ãã using UnityEngine; using UnityEngine.EventSystems; public class HexGameUI : MonoBehaviour { public HexGrid grid; }
ãã®ã³ã³ããŒãã³ããUIéå±€ã®æ°ããã²ãŒã ãªããžã§ã¯ãã«è¿œå ããŸãã圌ã¯èªåã®ãªããžã§ã¯ããæã£ãŠããå¿
èŠã¯ãããŸããããã²ãŒã ã«ã¯å¥ã®UIãããããšã¯æããã§ããã²ãŒã UIãªããžã§ã¯ãã®ããã«HexGameUI
ã¡ãœãããè¿œå SetEditMode
ãHexMapEditor
ãŸããç·šéã¢ãŒãã§ãªããšãã¯ãã²ãŒã UIããªã³ã«ããå¿
èŠããããŸãããŸããã²ãŒã UIã¯ãã¹ã§æ©èœãããããããã«ã©ãã«ãå«ããå¿
èŠããããŸãã public void SetEditMode (bool toggle) { enabled = !toggle; grid.ShowUI(!toggle); }
ç·šéã¢ãŒãã¹ã€ããã®ã€ãã³ããªã¹ãã«ã²ãŒã UIã¡ãœãããè¿œå ããŸããããã¯ããã¬ãŒã€ãŒãã¢ãŒããå€æŽãããšãäž¡æ¹ã®ã¡ãœãããåŒã³åºãããããšãæå³ããŸããããã€ãã®ã€ãã³ãã¡ãœãããçŸåšã®ã»ã«ã远跡
ç¶æ³ã«å¿ããŠãHexGameUI
çŸåšã«ãŒãœã«ã®äžã«ããã»ã«ãç¥ãå¿
èŠããããŸãããããã£ãŠããã£ãŒã«ããè¿œå ããŸãcurrentCell
ã HexCell currentCell;
ã«ãŒãœã«ããŒã ãUpdateCurrentCell
䜿çšããŠHexGrid.GetCell
ãã®ãã£ãŒã«ããæŽæ°ããã¡ãœãããäœæããŸãã void UpdateCurrentCell () { currentCell = grid.GetCell(Camera.main.ScreenPointToRay(Input.mousePosition)); }
çŸåšã®ã»ã«ãæŽæ°ãããšããå€æŽãããŠãããã©ããã確èªããå¿
èŠãããå ŽåããããŸããUpdateCurrentCell
ãã®æ
å ±ã匷å¶çã«è¿ããŸãã bool UpdateCurrentCell () { HexCell cell = grid.GetCell(Camera.main.ScreenPointToRay(Input.mousePosition)); if (cell != currentCell) { currentCell = cell; return true; } return false; }
ãŠãããéžæ
åéã移åããåã«ããããéžæããŠè¿œè·¡ããå¿
èŠããããŸãããããã£ãŠããã£ãŒã«ããè¿œå ããŸãselectedUnit
ã HexUnit selectedUnit;
éžæãè©Šã¿ããšããçŸåšã®ã»ã«ãæŽæ°ããããšããå§ããå¿
èŠããããŸããçŸåšã®ã»ã«ããã®ã»ã«ãå ãããŠãããã§ããå ŽåãéžæããããŠãããã«ãªããŸããã»ã«ã«ãŠãããããªãå ŽåããŠãããã¯éžæãããŸããããã®ããã®ã¡ãœãããäœæããŸãããDoSelection
ã void DoSelection () { UpdateCurrentCell(); if (currentCell) { selectedUnit = currentCell.Unit; } }
ãŠãããã®éžæã¯ãããŠã¹ã1åã¯ãªãã¯ããã ãã§å®çŸããŸãããããã£ãŠãUpdate
ããŠã¹ãã¿ã³ãã¢ã¯ãã£ãã«ãªã£ããšãã«éžæãå®è¡ããã¡ãœãããè¿œå ããŸããããã¡ãããã«ãŒãœã«ãGUIèŠçŽ ã®äžã«ãªããšãã«ã®ã¿å®è¡ããå¿
èŠããããŸãã void Update () { if (!EventSystem.current.IsPointerOverGameObject()) { if (Input.GetMouseButtonDown(0)) { DoSelection(); } } }
ãã®æ®µéã§ãããŠã¹ãã¯ãªãã¯ããŠäžåºŠã«1ã€ã®ãŠããããéžæããããšãåŠã³ãŸããã空ã®ã»ã«ãã¯ãªãã¯ãããšããŠãããã®éžæãåé€ãããŸããããããããã«ã€ããŠã¯èŠèŠçãªç¢ºèªã¯åããŠããŸãããåéã§éãæ¢ã
ãŠããããéžæãããšããã®å Žæããã¹ãèŠã€ããããã®éå§ç¹ãšããŠäœ¿çšã§ããŸãããããã¢ã¯ãã£ãã«ããããã«ãããŠã¹ãã¿ã³ãããäžåºŠã¯ãªãã¯ããå¿
èŠã¯ãããŸããã代ããã«ãåéã®äœçœ®ãšçŸåšã®ã»ã«ã®éã®ãã¹ãèªåçã«èŠã€ããŠè¡šç€ºããŸããUpdate
éžæãè¡ãããå Žåãé€ããããã¯åžžã«ã§è¡ããŸãããããè¡ãã«ã¯ããã¿ããã¡ã³ãããããšãã«ãã¡ãœãããåŒã³åºããŸãDoPathfinding
ã void Update () { if (!EventSystem.current.IsPointerOverGameObject()) { if (Input.GetMouseButtonDown(0)) { DoSelection(); } else if (selectedUnit) { DoPathfinding(); } } }
DoPathfinding
çŸåšã®ã»ã«ãæŽæ°ãHexGrid.FindPath
ããšã³ããã€ã³ããããå Žåã«åŒã³åºããŸããåã³24ã®äžå®é床ã䜿çšããŸãã void DoPathfinding () { UpdateCurrentCell(); grid.FindPath(selectedUnit.Location, currentCell, 24); }
æŽæ°ããšã«æ°ãããã¹ãèŠã€ããå¿
èŠã¯ãããŸããããçŸåšã®ã»ã«ãå€æŽããããšãã«ã®ã¿èŠã€ããå¿
èŠãããããšã«æ³šæããŠãã ããã void DoPathfinding () { if (UpdateCurrentCell()) { grid.FindPath(selectedUnit.Location, currentCell, 24); } }
ãã¿ããã¡ã³ãã®ãã¹ãèŠã€ããããã§ããã¿ããã¡ã³ããéžæããåŸã«ã«ãŒãœã«ã移åãããšãã«è¡šç€ºããããã¹ã衚瀺ãããŸããããã«ãããã©ã®ãŠããããéžæãããŠããããæããã§ãããã ãããã¹ã¯åžžã«æ£ããã¯ãªã¢ããããšã¯éããŸããããŸããã«ãŒãœã«ããããå€ã«ããå Žåãå€ããã¹ãã¯ãªã¢ããŸãããã void DoPathfinding () { if (UpdateCurrentCell()) { if (currentCell) { grid.FindPath(selectedUnit.Location, currentCell, 24); } else { grid.ClearPath(); } } }
ãã¡ãããããã«ã¯HexGrid.ClearPath
å
±éæ§ãå¿
èŠãªã®ã§ããã®ãããªå€æŽãè¡ããŸãã public void ClearPath () { ⊠}
次ã«ããã¿ããã¡ã³ããéžæãããšãã«å€ããã¹ãã¯ãªã¢ããŸãã void DoSelection () { grid.ClearPath(); UpdateCurrentCell(); if (currentCell) { selectedUnit = currentCell.Unit; } }
æåŸã«ãç·šéã¢ãŒããå€æŽãããšãã«ãã¹ãã¯ãªã¢ããŸãã public void SetEditMode (bool toggle) { enabled = !toggle; grid.ShowUI(!toggle); grid.ClearPath(); }
æå¹ãªãšã³ããã€ã³ãã®ã¿ãæ€çŽ¢
æçµçãªã»ã«ã«å°éã§ããªãå Žåããããããåžžã«éãèŠã€ããããšã¯ã§ããŸããã ããã¯æ£åžžã§ãã
ããããæçµçãªã»ã«èªäœãåãå
¥ããããªãå ŽåããããŸããããšãã°ããã¹ã«ã¯æ°Žäžã»ã«ãå«ããããšã¯ã§ããªããšå€æããŸããããã ãããŠãããã«äŸåããå ŽåããããŸããHexUnit
ã»ã«ãæå¹ãªãšã³ããã€ã³ãã§ãããã©ãããéç¥ããã¡ãœããã«è¿œå ããŸããããæ°Žäžã®çŽ°èã¯ããã§ã¯ãããŸããã public bool IsValidDestination (HexCell cell) { return !cell.IsUnderwater; }
ããã«ãã»ã«å
ã«ç«ã€ããšãã§ãããŠãããã¯1ã€ã ãã§ãããããã£ãŠãæçµã»ã«ã¯ããžãŒã®å Žåã¯ç¡å¹ã«ãªããŸãã public bool IsValidDestination (HexCell cell) { return !cell.IsUnderwater && !cell.Unit; }
ãã®ã¡ãœããã䜿çšããŠãHexGameUI.DoPathfinding
ç¡å¹ãªãšã³ããã€ã³ããç¡èŠããŸãã void DoPathfinding () { if (UpdateCurrentCell()) { if (currentCell && selectedUnit.IsValidDestination(currentCell)) { grid.FindPath(selectedUnit.Location, currentCell, 24); } else { grid.ClearPath(); } } }
çµç¹ã«ç§»å
æå¹ãªãã¹ãããã°ãåéãçµç¹ã«ç§»åã§ããŸããHexGrid
ããããã€ã§ããããç¥ã£ãŠããŸãããã®æ
å ±ãæ°ããèªã¿åãå°çšããããã£ã«æž¡ããŸãHasPath
ã public bool HasPath { get { return currentPathExists; } }
åéã移åããã«ã¯ãHexGameUI
ã¡ãœããã«è¿œå ãDoMove
ãŸãããã®ã¡ãœããã¯ãã³ãã³ããçºè¡ããããšããããã³ãŠããããéžæããããšãã«åŒã³åºãããŸãããããã£ãŠã圌ã¯æ¹æ³ããããã©ããã確èªããå¿
èŠããããŸããããå Žåã¯ãåãé¢ãã®å Žæãå€æŽããŸããããã«ããŒã ãçµç¹ã«ãã¬ããŒãããŸãã次ã®ãã¥ãŒããªã¢ã«ã®ããããã§ãããŒã ãå®éã«æåŸãŸã§é²ããŸãã void DoMove () { if (grid.HasPath) { selectedUnit.Location = currentCell; grid.ClearPath(); } }
ããŠã¹ãã¿ã³1ïŒå³ã¯ãªãã¯ïŒã䜿çšããŠã³ãã³ããéä¿¡ããŸãããããã¿ããã¡ã³ããéžæãããŠããå Žåãããããã§ãã¯ããŸãããã¿ã³ãæŒãããŠããªãå Žåããã¹ãæ€çŽ¢ããŸãã void Update () { if (!EventSystem.current.IsPointerOverGameObject()) { if (Input.GetMouseButtonDown(0)) { DoSelection(); } else if (selectedUnit) { if (Input.GetMouseButtonDown(1)) { DoMove(); } else { DoPathfinding(); } } } }
ããã§ãŠãããã移åã§ããŸãïŒããããæã«ã¯åœŒãã¯ããã€ãã®çŽ°èãžã®éãèŠã€ããããšãæåŠããŸããç¹ã«ãå¥é¢ããã€ãŠãã£ã现èãããã¯HexUnit
ãæ°ããå Žæãèšå®ãããšãã«å€ãå ŽæãæŽæ°ããªãããã«çºçããŸãããããä¿®æ£ããããã«ãå€ãå Žæã®ããŒã ãžã®ãªã³ã¯ãã¯ãªã¢ããŸãã public HexCell Location { get { return location; } set { if (location) { location.Unit = null; } location = value; value.Unit = this; transform.localPosition = value.Position; } }
åéãé¿ãã
éãèŠã€ããããšãæ£ããæ©èœããããã«ãªãããŠãããã¯ãããäžã§ãã¬ããŒãã§ããŸãããã§ã«åéãæã£ãŠããã»ã«ã«ç§»åããããšã¯ã§ããŸããããéªéã«ãªã£ãŠããåé£éã¯ç¡èŠãããŸããéäžã§è»ç¡èŠ1ã€ã®æŽŸé¥ã®åéã¯ãéåžžãäºãã«éã移åããããšãã§ããŸããããããŸã§ã®ãšãããæã
ã¯æŽŸé¥ãæã£ãŠããŸããããããã£ãŠããã¹ãŠã®ãŠããããäºãã«åæããããã¹ããããã¯ããŠãããšèããŠã¿ãŸããããããã¯ãã®ããžãŒã»ã«ãã¹ãããããããšã§å®çŸã§ããŸãHexGrid.Search
ã if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } if (neighbor.IsUnderwater || neighbor.Unit) { continue; }
é¿ãåé£éã®unitypackageããŒã19ïŒã¢ãŒã·ã§ã³ã¢ãã¡ãŒã·ã§ã³
- ã»ã«éã§ãŠãããã移åããŸãã
- 移åããçµè·¯ãèŠèŠåããŸãã
- è»éãæ²ç·ã«æ²¿ã£ãŠç§»åããŸãã
- è»éã移åã®æ¹åã«åããããŸãã
ãã®ããŒãã§ã¯ããã¬ããŒããŒã·ã§ã³ã®ä»£ããã«ãŠãããããã©ãã¯ã«æ²¿ã£ãŠç§»åãããŸããéäžã®åééã«æ²¿ã£ãåã
åã®ããŒãã§ã¯ããŠããããšãããã移åããæ©èœãè¿œå ããŸãããæå¹ãªãšã³ããã€ã³ãã決å®ããããã«ãã¹ã®æ€çŽ¢ã䜿çšããŸããããã³ãã³ããäžããåŸãè»éã¯æçµçãªã»ã«ã«ãã¬ããŒãããŸããã圌ããå®éã«èŠã€ãã£ãçµè·¯ããã©ãããã«ããã®çµè·¯ã远跡ããåéãã»ã«ããã»ã«ã«åŒ·å¶çã«ç§»åãããã¢ãã¡ãŒã·ã§ã³ããã»ã¹ãäœæããå¿
èŠããããŸããã¢ãã¡ãŒã·ã§ã³ãèŠããšãåéãã©ã®ããã«åãããã«æ°ä»ãã®ãé£ãããããã®ãºã¢ã䜿çšããŠç§»åãããã¹ãèŠèŠåããŸããããããå
ã«é²ãåã«ããšã©ãŒãä¿®æ£ããå¿
èŠããããŸããã¿ãŒã³ãšã©ãŒ
ç£èŠã®ãããã»ã«ã«å°éããã³ãŒã¹ã誀ã£ãŠèšç®ããŸããããã§ãåèšè·é¢ãåéé床ã§å²ãããšã«ãããã³ãŒã¹ã決å®ããŸãã§ãæ®ããç Žæ£ããŸãããã®ãšã©ãŒã¯ãã»ã«ã«ç§»åãããšãã«ã移åããšã«æ®ãã®ãã¹ãŠã®ç§»åãã€ã³ããæ£ç¢ºã«è²»ããå¿
èŠããããšãã«çºçããŸããããšãã°ãåã¹ãããã®ã³ã¹ãã1ã§ãé床ã3ã®å Žåã1ã¿ãŒã³ããã3ã€ã®ã»ã«ã移åã§ããŸãããã ããæ¢åã®èšç®ã§ã¯ãæåã®ç§»åã§ã¯2ã€ã®ã¹ãããããå®è¡ã§ããŸãããã
誀ã£ãŠå®çŸ©ããã移åãé床3ã§ç§»åããç·ã³ã¹ãã移åãæ£ããèšç®ããã«ã¯ãå¢çãæåã®ã»ã«ãã1ã¹ããã移åããå¿
èŠããããŸãããããè¡ãã«ã¯ã移åãèšç®ããåã«è·é¢ã1æžããããšã«ããã3çªç®ã®ã¹ãããã®ç§»åã¯æ¬¡ã®ããã«ãªããŸããæ£ããåãèšç®åŒã ã
ãã®å€æŽãã«è¡ãHexGrid.Search
ãŸãã bool Search (HexCell fromCell, HexCell toCell, int speed) { ⊠while (searchFrontier.Count > 0) { ⊠int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } ⊠} } return false; }
ãŸããåãã®ããŒã¯ãå€æŽããŸãã void ShowPath (int speed) { if (currentPathExists) { HexCell current = currentPathTo; while (current != currentPathFrom) { int turn = (current.Distance - 1) / speed; ⊠} } ⊠}
ãã®ã¢ãããŒãã§ã¯ãåæã»ã«ãã¹ã-1ã§ããããšã«æ³šæããŠãã ãããããã¯è¡šç€ºãããªãããæ£åžžã§ãããæ€çŽ¢ã¢ã«ãŽãªãºã ã¯åŒãç¶ãåäœããŸããæ¹æ³ãååŸ
ãã¹ã«æ²¿ã£ãŠç§»åããããšã¯ããŒã ã®ã¿ã¹ã¯ã§ãã圌ããããè¡ãããã«ã¯ã圌ã¯æ¹æ³ãç¥ãå¿
èŠããããŸãããã®æ
å ±HexGrid
ãããã®ã§ãã»ã«ã®ãªã¹ãã®åœ¢åŒã§çŸåšã®ãã¹ãååŸããã¡ãœãããè¿œå ããŸãããã圌ã¯ãªã¹ãã®ããŒã«ãããããååŸããæ¬åœã«ãã¹ãããã°æ»ããŸãã public List<HexCell> GetPath () { if (!currentPathExists) { return null; } List<HexCell> path = ListPool<HexCell>.Get(); return path; }
ãªã¹ãã¯ããã¹ãèŠèŠåãããšãã«è¡ãããããã«ãæåŸã®ã»ã«ããæåã®ã»ã«ãžã®ãªã³ã¯ãã¹ããã©ãããšã§åããããŸãã List<HexCell> path = ListPool<HexCell>.Get(); for (HexCell c = currentPathTo; c != currentPathFrom; c = c.PathFrom) { path.Add(c); } return path;
ãã®å Žåãåæã»ã«ãå«ããã¹å
šäœãå¿
èŠã§ãã for (HexCell c = currentPathTo; c != currentPathFrom; c = c.PathFrom) { path.Add(c); } path.Add(currentPathFrom); return path;
ããã§ããã¹ã¯éã®é åºã«ãªããŸããã圌ãšä»äºãããããšã¯ã§ããŸãããããã¯ããŸãçŽæçã§ã¯ãããŸããããªã¹ããå転ãããŠãæåããæåŸãŸã§è¡ããŸãããã path.Add(currentPathFrom); path.Reverse(); return path;
ã¢ãŒã·ã§ã³ãªã¯ãšã¹ã
ããã§HexUnit
ã¡ãœããã«è¿œå ããŠããã¹ã«åŸãããã«åœŒã«åœä»€ããããšãã§ããŸããæåã¯ã圌ã«æåŸã®ã»ã«ã«ãã¬ããŒããããã ãã§ãããªã¹ãã¯ãã°ãã圹ç«ã€ã®ã§ãããã«ãªã¹ããããŒã«ã«è¿ããŸããã using UnityEngine; using System.Collections.Generic; using System.IO; public class HexUnit : MonoBehaviour { ⊠public void Travel (List<HexCell> path) { Location = path[path.Count - 1]; } ⊠}
移åãèŠæ±ããã«HexGameUI.DoMove
ã¯ããŠãããã®äœçœ®ãèšå®ããã ãã§ãªããçŸåšã®ãã¹ã§æ°ããã¡ãœãããåŒã³åºãããã«å€æŽããŸãã void DoMove () { if (grid.HasPath) {
ãã¹ã®å¯èŠå
åéã®ã¢ãã¡ãŒã·ã§ã³ãéå§ããåã«ããã¹ãæ£ããããšã確èªããŸããããHexUnit
ã®ãºã¢ã䜿çšããŠèŠèŠåã§ããããã«ã移åããå¿
èŠããããã¹ãèšæ¶ããããã«åœä»€ããããšã§ãããè¡ããŸãã List<HexCell> pathToTravel; ⊠public void Travel (List<HexCell> path) { Location = path[path.Count - 1]; pathToTravel = path; }
OnDrawGizmos
æåŸã®ãã¹ã衚瀺ããã¡ãœãããè¿œå ããŸãïŒååšããå ŽåïŒããŠãããããŸã 移åããŠããªãå Žåããã¹ã¯çãããªãnull
ãŸãããã ãããã¬ã€ã¢ãŒãã§ã®åã³ã³ãã€ã«åŸã®ç·šéäžã®Unityã®ã·ãªã¢ã«åã«ããã空ã®ãªã¹ãã«ãªãããšããããŸãã void OnDrawGizmos () { if (pathToTravel == null || pathToTravel.Count == 0) { return; } }
ãã¹ã衚瀺ããæãç°¡åãªæ¹æ³ã¯ããã¹ã®åã»ã«ã«ã®ãºã¢çãæãããšã§ããååŸã2åäœã®çäœãé©ããŠããŸãã void OnDrawGizmos () { if (pathToTravel == null || pathToTravel.Count == 0) { return; } for (int i = 0; i < pathToTravel.Count; i++) { Gizmos.DrawSphere(pathToTravel[i].Position, 2f); } }
ãã¿ããã¡ã³ãã®ãã¹ã衚瀺ããã®ã§ãæåŸã®ãã¹ããã¹ãŠåæã«èŠãããšãã§ããŸããã®ãºã¢ã¯ãæåŸã«ç§»åãããã¹ã衚瀺ããŸãã»ã«ã®æ¥ç¶ããããã衚瀺ããããã«ãåã®ã»ã«ãšçŸåšã®ã»ã«ã®éã®ç·ã«ã«ãŒãã§ããã€ãã®çäœãæç»ããŸãããããè¡ãã«ã¯ã2çªç®ã®ã»ã«ããããã»ã¹ãéå§ããå¿
èŠããããŸããçã¯ã0.1åäœã®å¢åã§ç·åœ¢è£éã䜿çšããŠé
眮ã§ãããããã»ã°ã¡ã³ãããšã«10åã®çãåŸãããŸãã for (int i = 1; i < pathToTravel.Count; i++) { Vector3 a = pathToTravel[i - 1].Position; Vector3 b = pathToTravel[i].Position; for (float t = 0f; t < 1f; t += 0.1f) { Gizmos.DrawSphere(Vector3.Lerp(a, b, t), 2f); } }
ããæçœãªæ¹æ³éã«æ²¿ã£ãŠæ»ã
åãæ¹æ³ã䜿çšããŠãŠãããã移åã§ããŸãããã®ããã®ã³ã«ãŒãã³ãäœæããŸããããã®ãºã¢ãæç»ãã代ããã«ãåéã®äœçœ®ãèšå®ããŸããå¢åãã代ããã«ã0.1æéã®ãã«ã¿ã䜿çšããåå埩ã§yieldãå®è¡ããŸãããã®å Žåãåéã¯1ç§ã§1ã€ã®ã»ã«ãã次ã®ã»ã«ã«ç§»åããŸãã using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; public class HexUnit : MonoBehaviour { ⊠IEnumerator TravelPath () { for (int i = 1; i < pathToTravel.Count; i++) { Vector3 a = pathToTravel[i - 1].Position; Vector3 b = pathToTravel[i].Position; for (float t = 0f; t < 1f; t += Time.deltaTime) { transform.localPosition = Vector3.Lerp(a, b, t); yield return null; } } } ⊠}
ã¡ãœããã®æåŸã«ã³ã«ãŒãã³ãéå§ãTravel
ãŸãããã ããæåã«ãæ¢åã®ã³ã«ãŒãã³ããã¹ãŠåæ¢ããŸãããã®ããã2ã€ã®ã³ã«ãŒãã³ãåæã«éå§ããªãããšãä¿èšŒããŸããããããªããšãéåžžã«å¥åŠãªçµæã«ãªããŸãã public void Travel (List<HexCell> path) { Location = path[path.Count - 1]; pathToTravel = path; StopAllCoroutines(); StartCoroutine(TravelPath()); }
1ç§éã«1ã€ã®ã»ã«ã移åããã®ã¯ããªãé
ãã§ããã²ãŒã äžã®ãã¬ã€ã€ãŒã¯ãããªã«é·ãåŸ
ã¡ãããªãã§ããããåéã®ç§»åé床ãæ§æãªãã·ã§ã³ã«ããããšãã§ããŸãããããã§ã¯å®æ°ã䜿çšããŸããç§ã¯åœŒå¥³ã«æ¯ç§4ã»ã«ã®å€ãå²ãåœãŠãŸãããããã¯éåžžã«é«éã§ãããäœãèµ·ãã£ãŠãããã確èªã§ããŸãã const float travelSpeed = 4f; ⊠IEnumerator TravelPath () { for (int i = 1; i < pathToTravel.Count; i++) { Vector3 a = pathToTravel[i - 1].Position; Vector3 b = pathToTravel[i].Position; for (float t = 0f; t < 1f; t += Time.deltaTime * travelSpeed) { transform.localPosition = Vector3.Lerp(a, b, t); yield return null; } } }
è€æ°ã®çµè·¯ãåæã«èŠèŠåã§ããããã«ãè€æ°ã®ãŠããããåæã«ç§»åãããããšãã§ããŸããã²ãŒã ã®ç¶æ
ã®èŠ³ç¹ããèŠããšãåãã¯äŸç¶ãšããŠãã¬ããŒããŒã·ã§ã³ã§ãããã¢ãã¡ãŒã·ã§ã³ã¯èŠèŠçã«ã®ã¿ã§ãããŠãããã¯å³åº§ã«æçµã»ã«ãå æããŸããæ¹æ³ãèŠã€ããŠãå°çããåã«æ°ããåããéå§ããããšãã§ããŸãããã®å Žåããããã¯èŠèŠçã«æ°ãããã¹ã®å§ãŸãã«ãã¬ããŒããããŸããããã¯ã移åäžã«ãŠããããŸãã¯UIå
šäœããããã¯ããããšã§åé¿ã§ããŸããããã®ãããªè¿
éãªåå¿ã¯ã移åãèšèšããã³ãã¹ããããšãã«éåžžã«äŸ¿å©ã§ãã移åãŠããããé«ãã®éãã¯ã©ãã§ããïŒ, . , . , . , . , Endless Legend, , . , .
ã³ã³ãã€ã«åŸã®äœçœ®
ã³ã«ãã³ã®æ¬ ç¹ã®1ã€ã¯ããã¬ã€ã¢ãŒãã§åã³ã³ãã€ã«ããŠããçãæ®ããªããããšã§ããã²ãŒã ã®ç¶æ
ã¯åžžã«çã§ãããããã¯ã圌ãããŸã åããŠããéã«åã³ã³ãã€ã«ãéå§ããããšãåéãæåŸã®ãã¹ã®ã©ããã§ç«ã¡åŸçããããšã«ã€ãªããå¯èœæ§ããããŸããçµæãç·©åããããã«ãåã³ã³ãã€ã«åŸããŠããããåžžã«æ£ããäœçœ®ã«ããããšã確èªããŸããããããã¯ãã®äœçœ®ãæŽæ°ããããšã§å®è¡ã§ããŸãOnEnable
ã void OnEnable () { if (location) { transform.localPosition = location.Position; } }
ãŠããã£ããã±ãŒãžã¹ã ãŒãºãªåã
ã»ã«ã®äžå¿ããäžå¿ãžã®åãã¯æ©æ¢°çãããããã«èŠããæ¹åãæ¥æ¿ã«å€åããŸããå€ãã®ã²ãŒã ã§ã¯ãããã¯æ£åžžã§ãããå°ãªããšãå°ãçŸå®çãªåããå¿
èŠãªå Žåã¯åãå
¥ããããŸãããããã§ã¯ãã ãŒãã¡ã³ããå€æŽããŠãå°ãææ©çã«èŠããããã«ããŸãã端ãã端ãžç§»åããŸã
ããŒã ã¯ã»ã«ã®äžå¿ããæ
ãå§ããŸããã»ã«ã®ç«¯ã®äžå€®ã«ç§»åãããã®åŸæ¬¡ã®ã»ã«ã«å
¥ããŸãã圌ã¯äžå€®ã«åãã£ãŠç§»åãã代ããã«ã圌ã亀差ããªããã°ãªããªã次ã®ãšããžã«åãã£ãŠãŸã£ããé²ãããšãã§ããŸããå®éããŠãããã¯æ¹åãå€ããå¿
èŠããããšãã«ãã¹ãã«ããããŸããããã¯ããã¹ã®çµç¹ãé€ããã¹ãŠã®ã»ã«ã§å¯èœã§ãã端ãã端ãžç§»åãã3ã€ã®æ¹æ³ ãã®æ¹æ³ã§çæããããã¹ã®è¡šç€ºã«é©å¿OnDrawGizmos
ããŸããããã»ã«ã®ãšããžéãè£éããå¿
èŠããããŸããããã¯ãé£æ¥ããã»ã«ã®äœçœ®ãå¹³ååããããšã§èŠã€ããããšãã§ããŸããå埩ããšã«1ã€ã®ãšããžãèšç®ããåã®å埩ããã®å€ãåå©çšããã ãã§ååã§ãããããã£ãŠãã¡ãœãããåæã»ã«ã«å¯ŸããŠæ©èœãããããšãã§ããŸããããšããžã®ä»£ããã«ãã®äœçœ®ãåããŸãã void OnDrawGizmos () { if (pathToTravel == null || pathToTravel.Count == 0) { return; } Vector3 a, b = pathToTravel[0].Position; for (int i = 1; i < pathToTravel.Count; i++) {
çµäºã»ã«ã®äžå¿ã«å°éããã«ã¯ãã»ã«ã®äœçœ®ããšããžã§ã¯ãªãæåŸã®ãã€ã³ããšããŠäœ¿çšããå¿
èŠããããŸãããã®ã±ãŒã¹ã®ãã§ãã¯ãã«ãŒãã«è¿œå ã§ããŸãããåçŽãªã³ãŒããªã®ã§ãã³ãŒããè€è£œããŠå°ãå€æŽããã ãã®æ¹ãæããã«ãªããŸãã void OnDrawGizmos () { ⊠for (int i = 1; i < pathToTravel.Count; i++) { ⊠} a = b; b = pathToTravel[pathToTravel.Count - 1].Position; for (float t = 0f; t < 1f; t += 0.1f) { Gizmos.DrawSphere(Vector3.Lerp(a, b, t), 2f); } }
ãªãããŒã¹ã®ãã¹çµæãšããŠçãããã¹ã¯ãžã°ã¶ã°ã®ããã«èŠãããæ倧å転è§åºŠã¯120°ãã90°ã«æžå°ããŸããããã¯æ¹åãšèŠãªãããšãã§ãããããåãå€æŽãã³ã«ãŒãã³TravelPath
ã«é©çšããŠãã¢ãã¡ãŒã·ã§ã³ã§ã©ã®ããã«èŠãããã確èªããŸãã IEnumerator TravelPath () { Vector3 a, b = pathToTravel[0].Position; for (int i = 1; i < pathToTravel.Count; i++) {
å€åããé床ã§ã®ç§»åè§åºŠãã«ããããåŸããã¹ã»ã°ã¡ã³ãã®é·ãã¯æ¹åã®å€åã«äŸåããããã«ãªããŸããããã ãã1ç§ãããã®ã»ã«æ°ã§é床ãèšå®ããŸãããã®çµæãåéã®é床ã¯ã©ã³ãã ã«å€åããŸãã次ã®æ²ç·
ã»ã«ã®å¢çãè¶ãããšãã®æ¹åãšé床ã®ç¬éçãªå€åã¯èŠèŠãããæ¹åã®æ®µéçãªå€æŽã䜿çšããããšããå§ãããŸããããããµããŒãããã«ã¯ãéšéã匷å¶çã«çŽç·ã§ã¯ãªãæ²ç·ã«æ²¿ã£ãŠè¿œåŸãããŸããããã«ã¯ããžã§æ²ç·ã䜿çšã§ããŸããç¹ã«ãã»ã«ã®äžå¿ãäžå€®ã®å¶åŸ¡ç¹ã«ãªã2次ããžãšæ²ç·ã䜿çšã§ããŸãããã®å Žåãé£æ¥ããæ²ç·ã®æ¥ç·ã¯äºãã«é¡åã«ãªããŸããã€ãŸãããã¹å
šäœãé£ç¶ããæ»ãããªæ²ç·ã«ãªããŸãããšããžãããšããžãžã® æ²ç·äºæ¬¡ããžã§æ²ç·äžã®ç¹ãååŸããæ¹æ³ã§è£å©ã¯ã©ã¹Bezier
ãäœæããŸããæ²ç·ãšã¹ãã©ã€ã³ã®ãã¥ãŒããªã¢ã«ã§èª¬æãããŠããããã«ãåŒã¯ãã®ããã«äœ¿çšãããŸãããã㧠ã
ãããŠ
ã¯å¶åŸ¡ç¹ã§ãtã¯è£éåšã§ãã using UnityEngine; public static class Bezier { public static Vector3 GetPoint (Vector3 a, Vector3 b, Vector3 c, float t) { float r = 1f - t; return r * r * a + 2f * r * t * b + t * t * c; } }
GetPointã¯0-1ã«å¶éãããã¹ãã§ã¯ãããŸãããïŒ0-1, . . , GetPointClamped
, t
. , GetPointUnclamped
.
ã§æ²ç·ã®ãã¹ã衚瀺ããã«ã¯OnDrawGizmos
ã2ã€ã§ã¯ãªã3ã€ã®ãã€ã³ãã远跡ããå¿
èŠããããŸããè¿œå ã®ãã€ã³ãã¯ãçŸåšã®å埩ã§äœæ¥ããŠããã»ã«ã®äžå¿ã§ãi - 1
ããµã€ã¯ã«ã¯1ããå§ãŸããããã€ã³ããã¯ã¹ããããŸãããã¹ãŠã®ãã€ã³ããåãåã£ããVector3.Lerp
ãã«çœ®ãæããããšãã§ãBezier.GetPoint
ãŸããéå§ç¹ãšçµäºç¹ã§ã¯ãçµäºç¹ãšäžéç¹ã®ä»£ããã«ãåçŽã«ã»ã«ã®äžå¿ã䜿çšã§ããŸãã void OnDrawGizmos () { if (pathToTravel == null || pathToTravel.Count == 0) { return; } Vector3 a, b, c = pathToTravel[0].Position; for (int i = 1; i < pathToTravel.Count; i++) { a = c; b = pathToTravel[i - 1].Position; c = (b + pathToTravel[i].Position) * 0.5f; for (float t = 0f; t < 1f; t += Time.deltaTime * travelSpeed) { Gizmos.DrawSphere(Bezier.GetPoint(a, b, c, t), 2f); } } a = c; b = pathToTravel[pathToTravel.Count - 1].Position; c = b; for (float t = 0f; t < 1f; t += 0.1f) { Gizmos.DrawSphere(Bezier.GetPoint(a, b, c, t), 2f); } }
ããžã§ã§äœæãããã¹ã®æ²ç·ãã¹ãéåžžã«è¯ãèŠããŸããåãå€æŽãé©çšããTravelPath
ãã®ã¢ãããŒãã§ãŠããããã©ã®ããã«ã¢ãã¡ãŒã·ã§ã³åããããã確èªããŸãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position; for (int i = 1; i < pathToTravel.Count; i++) { a = c; b = pathToTravel[i - 1].Position; c = (b + pathToTravel[i].Position) * 0.5f; for (float t = 0f; t < 1f; t += Time.deltaTime * travelSpeed) { transform.localPosition = Bezier.GetPoint(a, b, c, t); yield return null; } } a = c; b = pathToTravel[pathToTravel.Count - 1].Position; c = b; for (float t = 0f; t < 1f; t += Time.deltaTime * travelSpeed) { transform.localPosition = Bezier.GetPoint(a, b, c, t); yield return null; } }
ã«ãŒãã«æ²¿ã£ãŠç§»åãããšããã¿ããã®é床ãäžå®å®ãªå Žåã§ããã¢ãã¡ãŒã·ã§ã³ãã¹ã ãŒãºã«ãªããŸãããé£æ¥ããã»ã°ã¡ã³ãã®æ²ç·ã®æ¥ç·ãäžèŽãããããé床ã¯é£ç¶çã§ããé床ã®å€åã¯åŸã
ã«èµ·ãããå¥é¢ãã»ã«ãééãããšãã«èµ·ãããæ¹åãå€ãããšæžéããŸãã圌ãçŽé²ããå Žåãé床ã¯äžå®ã®ãŸãŸã§ããããã«ãåéã¯ãŒãé床ã§æ
ãéå§ããã³çµäºããŸããããã¯èªç¶ãªåããæš¡å£ããŠããã®ã§ããã®ãŸãŸã«ããŠãããŸããæéã®è¿œè·¡
ãã®æç¹ãŸã§ãåã»ã°ã¡ã³ãã®0ããå埩ãéå§ãã1ã«éãããŸã§ç¶ç¶ããŸãããããã¯äžå®ã®å€ã§å¢å ããå Žåã¯æ£åžžã«æ©èœããŸãããå埩ã¯ãã«ã¿æéã«äŸåããŸãã 1ã€ã®ã»ã°ã¡ã³ãã§ã®å埩ãå®äºãããšãæéå·®ã«å¿ããŠã1ãããçšåºŠè¶
ããå¯èœæ§ããããŸããããã¯ãé«ãã¬ãŒã ã¬ãŒãã§ã¯èŠããŸããããäœãã¬ãŒã ã¬ãŒãã§ã¯ãããããããããšããããŸããæéã®ãã¹ãé¿ãããããæ®ãã®æéãããã»ã°ã¡ã³ããã次ã®ã»ã°ã¡ã³ãã«è»¢éããå¿
èŠããããŸããããã¯t
ãåã»ã°ã¡ã³ãã ãã§ãªãããã¹å
šäœã«æ²¿ã£ãŠè¿œè·¡ããããšã§å®è¡ã§ããŸãã次ã«ãåã»ã°ã¡ã³ãã®çµããã«ã1ãæžç®ããŸãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position; float t = 0f; for (int i = 1; i < pathToTravel.Count; i++) { a = c; b = pathToTravel[i - 1].Position; c = (b + pathToTravel[i].Position) * 0.5f; for (; t < 1f; t += Time.deltaTime * travelSpeed) { transform.localPosition = Bezier.GetPoint(a, b, c, t); yield return null; } t -= 1f; } a = c; b = pathToTravel[pathToTravel.Count - 1].Position; c = b; for (; t < 1f; t += Time.deltaTime * traveSpeed) { transform.localPosition = Bezier.GetPoint(a, b, c, t); yield return null; } }
ãã§ã«ãããè¡ã£ãŠããå Žåã¯ããã¹ã®éå§æã«æéã®å·®åãèæ
®ãããããã«ããŸããã€ãŸããç§ãã¡ã¯ããã«åãå§ãã1ã€ã®ãã¬ãŒã ã®éã¢ã€ãã«ç¶æ
ã«ãªããŸããã float t = Time.deltaTime * travelSpeed;
ããã«ããã¹ãçµäºããæç¹ã§æ£ç¢ºã«çµäºããã®ã§ã¯ãªããå°ãåã«çµäºããŸããããã§ãéãã¯ãã¬ãŒã ã¬ãŒãã«ãäŸåããŸãããããã£ãŠãåéã«æ£ç¢ºã«çµç¹ã§ãã¹ãå®æãããŸãããã IEnumerator TravelPath () { ⊠transform.localPosition = location.Position; }
ãŠããã£ããã±ãŒãžãªãªãšã³ããŒã·ã§ã³ã¢ãã¡ãŒã·ã§ã³
ãŠãããã¯æ»ãããªæ²ç·ã«æ²¿ã£ãŠåãå§ããŸããããåãã®æ¹åã«å¿ããŠæ¹åãå€ããŸããã§ããããã®çµæã圌ãã¯æ»ãããã«èŠããŸããåããå®éã®åãã®ããã«èŠããããã«ãããããå転ãããå¿
èŠããããŸãã楜ãã¿ã«ããŠ
æ²ç·ãšã¹ãã©ã€ã³ã®ãã¥ãŒããªã¢ã«ã®ããã«ãæ²ç·ã®å°é¢æ°ã䜿çšããŠãŠãããã®æ¹åã決å®ã§ããŸããäºæ¬¡ããžã§æ²ç·ã®å°é¢æ°ã®åŒïŒ ã
Bezier
ã¡ãœããã«è¿œå ããŠèšç®ããŸãã public static Vector3 GetDerivative ( Vector3 a, Vector3 b, Vector3 c, float t ) { return 2f * ((1f - t) * (b - a) + t * (c - b)); }
埮åãã¯ãã«ã¯ãåãã®æ¹åãš1æ¬ã®çŽç·äžã«ãããŸãããã®ã¡ãœããQuaternion.LookRotation
ã䜿çšããŠãåéã¿ãŒã³ã«å€æã§ããŸããã®ãã¹ãŠã®ã¹ãããã§å®è¡ãHexUnit.TravelPath
ãŸãã transform.localPosition = Bezier.GetPoint(a, b, c, t); Vector3 d = Bezier.GetDerivative(a, b, c, t); transform.localRotation = Quaternion.LookRotation(d); yield return null; ⊠transform.localPosition = Bezier.GetPoint(a, b, c, t); Vector3 d = Bezier.GetDerivative(a, b, c, t); transform.localRotation = Quaternion.LookRotation(d); yield return null;
ãã¹ã®å§ãã«ééãã¯ãããŸãããïŒ, . ãã㊠, . , , , Quaternion.LookRotation
. , , . . , .
, ã
ãã¿ããã¡ã³ãã®äœçœ®ãšã¯å¯Ÿç
§çã«ããã¹ã®çµç¹ã§ã®æ¹åã®éçæ³æ§ã¯éèŠã§ã¯ãããŸããããã ãããã®åããæçµå転ã«å¯Ÿå¿ããããšã確èªããå¿
èŠããããŸãããããè¡ãã«ã¯ãå®äºåŸããã®åããYã®å転ãšåçã«ããŸãã transform.localPosition = location.Position; orientation = transform.localRotation.eulerAngles.y;
çŸåšããŠãããã¯æ°Žå¹³æ¹åãšåçŽæ¹åã®äž¡æ¹ã§ç§»åæ¹åãæ£ç¢ºã«èŠãŠããŸããããã¯ã圌ããååŸã«åŸããæé¢ããéããŠç»ãããšãæå³ããŸããããããåžžã«çã£çŽãã«ãªãããã«ãæ¹åãã¯ãã«ã®æåYã匷å¶çã«ãŒãã«ããŠããããŠãããã®å転ã決å®ããŸãã Vector3 d = Bezier.GetDerivative(a, b, c, t); dy = 0f; transform.localRotation = Quaternion.LookRotation(d); ⊠Vector3 d = Bezier.GetDerivative(a, b, c, t); dy = 0f; transform.localRotation = Quaternion.LookRotation(d);
移åããªãã楜ãã¿ãã€ã³ããèŠã
ãã¹å
šäœãéããŠããŠãããã¯åæ¹ãèŠãŸããã移åãéå§ããåã«ããŠãããã¯ä»ã®æ¹åãèŠãããšãã§ããŸãããã®å Žåã圌ãã¯å³åº§ã«åããå€ããŸãã移åãéå§ããåã«ãã¹ã®æ¹åã«æ²ããæ¹ãè¯ãã§ããããä»ã®ç¶æ³ã§ã¯æ£ããæ¹åãèŠãã®ã䟿å©ãªå Žåãããã®ã§LookAt
ãç¹å®ã®ãã€ã³ããèŠãããã«ããŒã ã®åãã匷å¶çã«å€æŽããã¡ãœãããäœæããŸããããã¡ãœããã䜿çšããŠãå¿
èŠãªå転ãèšå®ããã«ã¯Transform.LookAt
ããŸãããã¿ããã¡ã³ããšåãåçŽäœçœ®ã«ãã€ã³ããäœæããŸãããã®åŸãããŒã ã®æ¹åãæœåºã§ããŸãã void LookAt (Vector3 point) { point.y = transform.localPosition.y; transform.LookAt(point); orientation = transform.localRotation.eulerAngles.y; }
ãã¿ããã¡ã³ããå®éã«å転ãããããã«ãã¡ãœãããå¥ã®ã³ã«ãã³ã«å€ããäžå®ã®é床ã§å転ãããŸããå転é床ã調æŽã§ããŸãããããã§ãå®æ°ã䜿çšããŸããå転ã¯æ¯ç§çŽ180°ã®éãã§ãªããã°ãªããŸããã const float rotationSpeed = 180f; ⊠IEnumerator LookAt (Vector3 point) { ⊠}
æç¥ã§ããªãã®ã§ãã¿ãŒã³ã®å éããããå¿
èŠã¯ãããŸããã 2ã€ã®æ¹åã®éãåçŽã«è£éããã ãã§ååã§ããæ®å¿µãªãããè§åºŠã¯å圢ã§ãããããããã¯2ã€ã®æ°å€ã®å Žåã»ã©ç°¡åã§ã¯ãããŸãããããšãã°ã350°ãã10°ãžã®ç§»è¡ã§ã¯ãæèšåãã«20°å転ããŸãããåçŽãªè£éã§ã¯ãåæèšåãã«340°å転ããŸããæ£ããå転ãäœæããæãç°¡åãªæ¹æ³ã¯ãçé¢è£éã䜿çšããŠ2ã€ã®ã¯ã©ãŒã¿ããªã³éãè£éããããšã§ããããã¯æçã®ã¿ãŒã³ã«ã€ãªãããŸãããããè¡ãã«ã¯ãæåãšæåŸã®ã¯ã©ãŒã¿ããªã³ãååŸããã䜿çšããŠãããã®éã®ãã©ã³ãžã·ã§ã³ãäœæãQuaternion.Slerp
ãŸãã IEnumerator LookAt (Vector3 point) { point.y = transform.localPosition.y; Quaternion fromRotation = transform.localRotation; Quaternion toRotation = Quaternion.LookRotation(point - transform.localPosition); for (float t = Time.deltaTime; t < 1f; t += Time.deltaTime) { transform.localRotation = Quaternion.Slerp(fromRotation, toRotation, t); yield return null; } transform.LookAt(point); orientation = transform.localRotation.eulerAngles.y; }
ããã¯æ©èœããŸãããå転è§åºŠã«é¢ä¿ãªããè£éã¯åžžã«0ãã1ã«ãªããŸããè§é床ãåäžã«ããã«ã¯ãå転è§ã倧ãããªãã«ã€ããŠè£éãé
ãããå¿
èŠããããŸãã Quaternion fromRotation = transform.localRotation; Quaternion toRotation = Quaternion.LookRotation(point - transform.localPosition); float angle = Quaternion.Angle(fromRotation, toRotation); float speed = rotationSpeed / angle; for ( float t = Time.deltaTime * speed; t < 1f; t += Time.deltaTime * speed ) { transform.localRotation = Quaternion.Slerp(fromRotation, toRotation, t); yield return null; }
è§åºŠãããã£ãŠããã®ã§ãã¿ãŒã³ããŒãã«ãªã£ãå Žåãã¿ãŒã³ãå®å
šã«ã¹ãããã§ããŸãã float angle = Quaternion.Angle(fromRotation, toRotation); if (angle > 0f) { float speed = rotationSpeed / angle; for ( ⊠) { ⊠} }
ããã§ããŠãããã®å転ãã«è¿œå ã§ããŸãã2çªç®ã®ã»ã«ã®äœçœ®ã§TravelPath
æ©çãŸãLookAt
ã移åããåã«å®è¡ããã ãã§ããUnityã¯èªåçã«korutinuå®è¡ããLookAt
ããããŠTravelPath
ãã®å®äºãåŸ
ã¡ãŸãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position; yield return LookAt(pathToTravel[1].Position); float t = Time.deltaTime * travelSpeed; ⊠}
ã³ãŒãã確èªãããšãåéã¯æçµã»ã«ã«ãã¬ããŒãããããã§ã¿ãŒã³ãã次ã«ãã¹ã®å
é ã«ãã¬ããŒããããããã移åãéå§ããŸããããã¯Location
ãcoroutineã®éå§åã«ããããã£ã«å€ãå²ãåœãŠãããã«çºçããŸãTravelPath
ããã¬ããŒããŒã·ã§ã³ãåãé€ãTravelPath
ããã«ãæåã«ãã¿ããã¡ã³ãã®äœçœ®ãåæã»ã«ã«æ»ãããšãã§ããŸãã Vector3 a, b, c = pathToTravel[0].Position; transform.localPosition = c; yield return LookAt(pathToTravel[1].Position);
移åããåã«åãã¹ã€ãŒã
å¿
èŠãªåããåãåã£ãããã¡ãœãããåãé€ãããšãã§ããŸãOnDrawGizmos
ãå°æ¥ãã¹ã確èªããå¿
èŠãããå Žåã«åããŠãåé€ãããã³ã¡ã³ãã¢ãŠãããŠãã ããã
移åããæ¹åãèŠããå¿
èŠããªããªã£ããããæçµçTravelPath
ã«ã»ã«ã®ãªã¹ãã解æŸã§ããŸãã IEnumerator TravelPath () { ⊠ListPool<HexCell>.Add(pathToTravel); pathToTravel = null; }
æ¬ç©ã®ããŒã ã®ã¢ãã¡ãŒã·ã§ã³ã¯ã©ãã§ããïŒ, . 3D- . . , . Mecanim, TravelPath
.
ãŠããã£ããã±ãŒãž