ããŒã1ã3ïŒã°ãªãããè²ãã»ã«ã®é«ãããŒã4ã7ïŒç²ããå·ãããã³éè·¯ããŒã8-11ïŒæ°Žãå°åœ¢ãåå£ããŒã12ã15ïŒä¿åãšèªã¿èŸŒã¿ããã¯ã¹ãã£ãè·é¢ããŒã16ã19ïŒéãèŠã€ããããã¬ã€ã€ãŒããŒã ãã¢ãã¡ãŒã·ã§ã³ããŒã20-23ïŒæŠäºã®é§ãå°å³èª¿æ»ãæç¶ãçæããŒã24ã27ïŒæ°ŽåŸªç°ã䟵é£ããã€ãªãŒã ãåæ±å°å³ããŒã20ïŒæŠäºã®é§
- ãã¯ã¹ãã£ã«ã»ã«ããŒã¿ãä¿åããŸãã
- äžè§åœ¢åå²ãªãã§ã¬ãªãŒãã¿ã€ãã倿ŽããŸãã
- å¯èŠæ§ã远跡ããŸãã
- ç®ã«èŠããªããã¹ãŠãæãããŸãã
ãã®ããŒãã§ã¯ããããã«æŠäºã®é§ã®å¹æã远å ããŸãã
ããã§ãã·ãªãŒãºã¯Unity 2017.1.0ã§äœæãããŸãã
ä»ãç§ãã¡ã¯èŠãããšãã§ãããèŠãããšãã§ããªãããšãããããŸããã·ã§ãŒããŒã®ã»ã«ããŒã¿
å€ãã®æŠç¥ã²ãŒã ã§ã¯ãé§ã®æŠå¿µã䜿çšããŠããŸãã ããã¯ããã¬ã€ã€ãŒã®èŠçãå¶éãããããšãæå³ããŸãã 圌ã¯èªåã®ãŠããããŸãã¯ç®¡çãšãªã¢ã®è¿ãã«ãããã®ããèŠãããšãã§ããŸããã å®å¿æã¯ãããŸãããããã§äœãèµ·ãã£ãŠããã®ãããããŸããã éåžžãäžå¯èŠã®å°åœ¢ã¯ããæãã¬ã³ããªã³ã°ãããŸãã ãããå®çŸããã«ã¯ãã»ã«ã®å¯èŠæ§ã远跡ããããã«å¿ããŠã¬ã³ããªã³ã°ããå¿
èŠããããŸãã
é衚瀺ã®ã»ã«ã®å€èгã倿Žããæãç°¡åãªæ¹æ³ã¯ãã¡ãã·ã¥ããŒã¿ã«å¯èŠæ§ã¡ããªãã¯ã远å ããããšã§ãã ãã ãããã®å ŽåãèŠçãå€ãããšãæ°ããäžè§åœ¢åå²ãéå§ããå¿
èŠããããŸãã ã²ãŒã äžã«èŠçãçµ¶ããå€åãããããããã¯æªã決å®ã§ãã
ãã¬ã€ã€ãŒã«èŠããªãã»ã«ãéšåçã«ãã¹ã¯ãããåéæã®è¡šé¢ã®å°åœ¢ã«ã¬ã³ããªã³ã°ããæè¡ããã䜿çšãããŸãã ãã®æ¹æ³ã¯ãèŠéè§ãå¶éãããŠãããããæ¯èŒçå¹³åŠãªå°åœ¢ã«é©ããŠããŸãã ããããå°åœ¢ã«ã¯ããŸããŸãªè§åºŠããèŠãããšãã§ããéåžžã«å€æ§ãªé«ããšãªããžã§ã¯ããå«ããããšãã§ããããããã®ããã«ã¯å°åœ¢ã®åœ¢ç¶ã«äžèŽããéåžžã«è©³çްãªã¡ãã·ã¥ãå¿
èŠã§ãã ãã®æ¹æ³ã¯ãäžèšã®æãåçŽãªã¢ãããŒããããé«äŸ¡ã«ãªããŸãã
å¥ã®ã¢ãããŒãã¯ãã¬ãªãŒãã¡ãã·ã¥ãšã¯å¥ã«ã¬ã³ããªã³ã°ãããšãã«ãã»ã«ã®ããŒã¿ãã·ã§ãŒããŒã«è»¢éããããšã§ãã ããã«ãããäžè§åœ¢åå²ã1åã ãå®è¡ã§ããŸãã ã»ã«ããŒã¿ã¯ãã¯ã¹ãã£ã䜿çšããŠè»¢éã§ããŸãã ãã¯ã¹ãã£ã®å€æŽã¯ãå°åœ¢ã®äžè§æž¬éãããã¯ããã«ç°¡åãªããã»ã¹ã§ãã ããã«ãããã€ãã®è¿œå ã®ãã¯ã¹ãã£ãµã³ãã«ã®å®è¡ã¯ãåäžã®åéæã¬ã€ã€ãŒãã¬ã³ããªã³ã°ãããããé«éã§ãã
ã·ã§ãŒããŒé
åã®äœ¿çšã¯ã©ãã§ããïŒãã¯ãã«ã®é
åã䜿çšããŠãã»ã«ããŒã¿ãã·ã§ãŒããŒã«è»¢éããããšãã§ããŸãã ãã ããã·ã§ãŒããŒé
åã«ã¯æ°åãã€ãåäœã®ãµã€ãºå¶éãããããã¯ã¹ãã£ã«ã¯æ°çŸäžãã¯ã»ã«ãå«ããããšãã§ããŸãã 倧ããªãããããµããŒãããã«ã¯ããã¯ã¹ãã£ã䜿çšããŸãã
ã»ã«ããŒã¿ç®¡ç
ã»ã«ããŒã¿ãå«ããã¯ã¹ãã£ãå¶åŸ¡ããæ¹æ³ãå¿
èŠã§ãã ãããè¡ãæ°ãã
HexCellShaderData
ã³ã³ããŒãã³ããäœæããŸãããã
using UnityEngine; public class HexCellShaderData : MonoBehaviour { Texture2D cellTexture; }
æ°ããããããäœæãŸãã¯ããŒããããšããæ£ãããµã€ãºã§æ°ãããã¯ã¹ãã£ãäœæããå¿
èŠããããŸãã ãã®ããããã¯ã¹ãã£ãäœæããåæåã¡ãœããã远å ããŸãã ããããã¯ã¹ãã£ãšç·åœ¢è²ç©ºéã®ãªãRGBAãã¯ã¹ãã£ã䜿çšããŸãã ã»ã«ããŒã¿ãæ··åšãããå¿
èŠããªãããããã€ã³ããã£ã«ã¿ãªã³ã°ã䜿çšããŸãã ããã«ãããŒã¿ãæããããã¹ãã§ã¯ãããŸããã ãã¯ã¹ãã£ã®åãã¯ã»ã«ã«ã¯ã1ã€ã®ã»ã«ããã®ããŒã¿ãå«ãŸããŸãã
public void Initialize (int x, int z) { cellTexture = new Texture2D( x, z, TextureFormat.RGBA32, false, true ); cellTexture.filterMode = FilterMode.Point; cellTexture.wrapMode = TextureWrapMode.Clamp; }
ãã¯ã¹ãã£ãµã€ãºã¯ãããã®ãµã€ãºãšäžèŽããå¿
èŠããããŸããïŒãããããã¹ãŠã®ã»ã«ãä¿æããã®ã«ååãªãã¯ã»ã«ãããã°ååã§ãã ãããã®ãµã€ãºãšå®å
šã«äžèŽããå Žåã2ã®ã¹ãä¹ïŒNPOT以å€ïŒã§ãªããµã€ãºã®ãã¯ã¹ãã£ãäœæãããå¯èœæ§ãé«ãããã®ãã¯ã¹ãã£åœ¢åŒã¯æã广çã§ã¯ãããŸããã 2ã®çޝä¹ã®ãµã€ãºã®ãã¯ã¹ãã£ã§åäœããããã«ã³ãŒããæ§æã§ããŸãããããã¯ã»ã«ããŒã¿ãžã®ã¢ã¯ã»ã¹ãè€éã«ããå°ããªæé©åã§ãã
å®éãæ°ããããããäœæãããã³ã«æ°ãããã¯ã¹ãã£ãäœæããå¿
èŠã¯ãããŸããã ãã¯ã¹ãã£ãæ¢ã«ååšããå Žåããµã€ãºã倿Žããã ãã§ååã§ãã
Texture2D.Resize
ã¯ãããè¡ãã®ã«ååè³¢ãã®ã§ãæ¢ã«é©åãªãµã€ãºã§ãããã©ããã確èªããå¿
èŠãããããŸããã
public void Initialize (int x, int z) { if (cellTexture) { cellTexture.Resize(x, z); } else { cellTexture = new Texture2D( cellCountX, cellCountZ, TextureFormat.RGBA32, false, true ); cellTexture.filterMode = FilterMode.Point; cellTexture.wrapMode = TextureWrapMode.Clamp; } }
ã»ã«ããŒã¿ã1ãã¯ã»ã«ãã€é©çšãã代ããã«ãã«ã©ãŒãããã¡ãŒã䜿çšããŠããã¹ãŠã®ã»ã«ã®ããŒã¿ãäžåºŠã«é©çšããŸãã ãããè¡ãã«ã¯ã
Color32
é
åã䜿çšããŸãã å¿
èŠã«å¿ããŠã
Initialize
ã®æåŸã«æ°ããé
åã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã ãã§ã«æ£ãããµã€ãºã®é
åãããå Žåã ãã®å
容ãã¯ãªã¢ããŸãã
Texture2D cellTexture; Color32[] cellTextureData; public void Initialize () { ⊠if (cellTextureData == null || cellTextureData.Length != x * z) { cellTextureData = new Color32[x * z]; } else { for (int i = 0; i < cellTextureData.Length; i++) { cellTextureData[i] = new Color32(0, 0, 0, 0); } } }
color32ãšã¯äœã§ããïŒæšæºã®éå§çž®RGBAãã¯ã¹ãã£ã«ã¯4ãã€ãã®ãã¯ã»ã«ãå«ãŸããŠããŸãã 4ã€ã®ã«ã©ãŒãã£ãã«ã®ããããã1ãã€ããåãåããŸããã€ãŸãã256ã®å¯èœãªå€ããããŸãã Unity Color
æ§é ã䜿çšããå Žåã0ã1ã®ç¯å²ã®æµ®åå°æ°ç¹ã³ã³ããŒãã³ãã¯0ã255ã®ç¯å²ã®ãã€ãã«å€æãããŸãã ãµã³ããªã³ã°æã«ãGPUã¯é倿ãå®è¡ããŸãã
Color32
æ§é äœã¯ãã€ããçŽæ¥åŠçãããããå æããã¹ããŒã¹ãå°ãªãã倿ã®å¿
èŠããªãããã䜿çšå¹çãåäžããŸãã è²ã§ã¯ãªãã»ã«ããŒã¿ãä¿åããããã Color
ã§ã¯ãªãçã®ãã¯ã¹ãã£ããŒã¿ãçŽæ¥æäœããæ¹ãè«ççã§ãã
HexGrid
ã¯ãã·ã§ãŒããŒã§ãããã®ã»ã«ã®äœæãšåæåãåŠçããå¿
èŠããããŸãã ãããã£ãŠãããã«
cellShaderData
ãã£ãŒã«ãã远å ãã
Awake
å
ã«ã³ã³ããŒãã³ããäœæããŸãã
HexCellShaderData cellShaderData; void Awake () { HexMetrics.noiseSource = noiseSource; HexMetrics.InitializeHashGrid(seed); HexUnit.unitPrefab = unitPrefab; cellShaderData = gameObject.AddComponent<HexCellShaderData>(); CreateMap(cellCountX, cellCountZ); }
æ°ããããããäœæãããšãã«ã
cellShaderData
ã
cellShaderData
å¿
èŠããããŸãã
public bool CreateMap (int x, int z) { ⊠cellCountX = x; cellCountZ = z; chunkCountX = cellCountX / HexMetrics.chunkSizeX; chunkCountZ = cellCountZ / HexMetrics.chunkSizeZ; cellShaderData.Initialize(cellCountX, cellCountZ); CreateChunks(); CreateCells(); return true; }
ã»ã«ããŒã¿ã®ç·šé
ãããŸã§ãã»ã«ã®ããããã£ã倿Žããå Žåã1ã€ãŸãã¯è€æ°ã®ãã©ã°ã¡ã³ããæŽæ°ããå¿
èŠããããŸããããçŸåšã¯ã»ã«ã®ããŒã¿ãæŽæ°ããå¿
èŠãããå ŽåããããŸãã ã€ãŸããã»ã«ã«ã¯ã·ã§ãŒããŒã®ã»ã«ããŒã¿ãžã®ãªã³ã¯ãå¿
èŠã§ãã ãããè¡ãã«ã¯ãããããã£ã
HexCell
远å ããŸãã
public HexCellShaderData ShaderData { get; set; }
HexGrid.CreateCell
ãã·ã§ãŒããŒããŒã¿ã³ã³ããŒãã³ãããã®ããããã£ã«å²ãåœãŠãŸãã
void CreateCell (int x, int z, int i) { ⊠HexCell cell = cells[i] = Instantiate<HexCell>(cellPrefab); cell.transform.localPosition = position; cell.coordinates = HexCoordinates.FromOffsetCoordinates(x, z); cell.ShaderData = cellShaderData; ⊠}
ããã§ãã»ã«ã«ã·ã§ãŒããŒããŒã¿ãæŽæ°ãããããšãã§ããŸãã å¯èŠæ§ã远跡ããŠããŸããããã·ã§ãŒããŒããŒã¿ãä»ã®ç®çã«äœ¿çšã§ããŸãã ã»ã«ã®ã¬ãªãŒãã¿ã€ãã«ãã£ãŠãã¬ã³ããªã³ã°ã«äœ¿çšããããã¯ã¹ãã£ã決ãŸããŸãã ã»ã«ã®ãžãªã¡ããªã«ã¯åœ±é¿ããªããããã¡ãã·ã¥ããŒã¿ã§ã¯ãªãã»ã«ããŒã¿ã«æšé«ã¿ã€ãã®ã€ã³ããã¯ã¹ãä¿åã§ããŸãã ããã«ãããã»ã«ã®ã¬ãªãŒãã®ã¿ã€ãã倿Žãããšãã«äžè§æž¬éã®å¿
èŠæ§ãåãé€ãããšãã§ããŸãã
HexCellShaderData
ã¡ãœããã
RefreshTerrain
ã«è¿œå ããŠãç¹å®ã®ã»ã«ã®ãã®ã¿ã¹ã¯ãç°¡çŽ åããŸãã ããã§ã¯ããã®ã¡ãœããã空ã®ãŸãŸã«ããŸãã
public void RefreshTerrain (HexCell cell) { }
HexCell.TerrainTypeIndex
倿ŽããŠããã®ã¡ãœããã
HexCell.TerrainTypeIndex
ããã©ã°ã¡ã³ãã®æŽæ°ãåœä»€ããªãããã«ããŸãã
public int TerrainTypeIndex { get { return terrainTypeIndex; } set { if (terrainTypeIndex != value) { terrainTypeIndex = value;
ã»ã«ã®å°åœ¢ã®ã¿ã€ããåãåã£ãåŸã
HexCell.Load
åŒã³åºããŸãã
public void Load (BinaryReader reader) { terrainTypeIndex = reader.ReadByte(); ShaderData.RefreshTerrain(this); elevation = reader.ReadByte(); RefreshPosition(); ⊠}
ã»ã«ã€ã³ããã¯ã¹
ãããã®ã»ã«ã倿Žããã«ã¯ãã»ã«ã®ã€ã³ããã¯ã¹ãç¥ãå¿
èŠããããŸãã ãããè¡ãæãç°¡åãªæ¹æ³ã¯ã
Index
ããããã£ã
HexCell
远å ããããš
HexCell
ã ãããã®ã»ã«ã®ãªã¹ãã«ããã»ã«ã®ã€ã³ããã¯ã¹ã瀺ããŸããããã¯ãã·ã§ãŒããŒã®æå®ãããã»ã«ã®ã€ã³ããã¯ã¹ã«å¯Ÿå¿ããŸãã
public int Index { get; set; }
ãã®ã€ã³ããã¯ã¹ã¯ãã§ã«
HexGrid.CreateCell
ã«ãããããäœæããã»ã«ã«å²ãåœãŠãã ãã§ãã
void CreateCell (int x, int z, int i) { ⊠cell.coordinates = HexCoordinates.FromOffsetCoordinates(x, z); cell.Index = i; cell.ShaderData = cellShaderData; ⊠}
çŸåšã
HexCellShaderData.RefreshTerrain
ã¯ãã®ã€ã³ããã¯ã¹ã䜿çšããŠã»ã«ããŒã¿ãæå®ã§ããŸãã ã¿ã€ãããã€ãã«å€æããã ãã§ããã¯ã»ã«ã®ã¢ã«ãã¡ã³ã³ããŒãã³ãã«ãšã¬ããŒã·ã§ã³ã¿ã€ãã€ã³ããã¯ã¹ãä¿åããŸãããã ããã«ãããæå€§256çš®é¡ã®å°åœ¢ããµããŒããããŸããããã§ååã§ãã
public void RefreshTerrain (HexCell cell) { cellTextureData[cell.Index].a = (byte)cell.TerrainTypeIndex; }
ãã¯ã¹ãã£ã«ããŒã¿ãé©çšããŠGPUã«æž¡ãã«ã¯ã
Texture2D.SetPixels32
ãåŒã³åºããŠãã
Texture2D.SetPixels32
ãåŒã³åºãå¿
èŠããããŸãã ãã©ã°ã¡ã³ãã®å Žåãšåæ§ã«ã倿Žãããã»ã«ã®æ°ã«é¢ä¿ãªãããã¬ãŒã ããšã«1åããå®è¡ãããªãããã«ã
LateUpdate
ãããã®æäœãå»¶æããŸãã
public void RefreshTerrain (HexCell cell) { cellTextureData[cell.Index].a = (byte)cell.TerrainTypeIndex; enabled = true; } void LateUpdate () { cellTexture.SetPixels32(cellTextureData); cellTexture.Apply(); enabled = false; }
æ°ãããããã®äœæåŸã«ããŒã¿ã確å®ã«æŽæ°ãããããã«ããã«ã¯ãåæååŸã«ã³ã³ããŒãã³ããæå¹ã«ããŸãã
public void Initialize (int x, int z) { ⊠enabled = true; }
ã»ã«ã€ã³ããã¯ã¹äžè§æž¬é
ãããã®ã»ã«ã«æšé«ã¿ã€ãã®ã€ã³ããã¯ã¹ãä¿åããããã«ãªã£ããããäžè§æž¬éããã»ã¹ã«æšé«ã¿ã€ãã®ã€ã³ããã¯ã¹ãå«ããå¿
èŠããªããªããŸããã ãã ããã»ã«ããŒã¿ã䜿çšããã«ã¯ãã·ã§ãŒããŒã¯äœ¿çšããã€ã³ããã¯ã¹ãç¥ã£ãŠããå¿
èŠããããŸãã ãããã£ãŠãã¡ãã·ã¥ããŒã¿ã«ã»ã«ã€ã³ããã¯ã¹ãä¿åããæšé«ã¿ã€ãã®ã€ã³ããã¯ã¹ã眮ãæããå¿
èŠããããŸãã ããã«ããããã®ã»ã«ã䜿çšããå Žåãã»ã«ãæ··åããããã«ã¡ãã·ã¥ã®ã«ã©ãŒãã£ãã«ãå¿
èŠã§ãã
廿¢ãããå
±éãã£ãŒã«ã
useColors
ããã³
useTerrainTypes
ãŸãã ããããåäžã®ãã£ãŒã«ã
useCellData
眮ãæããŸãã
terrainTypes
ãªã¹ãã®ååã
cellIndices
ãŸãã ãŸãã
colors
ã
cellWeights
ãªãã¡ã¯ã¿ãªã³ã°ããŠã¿ãŸããã-ãã®ååã®æ¹ãããŸããããŸãã
Clear
倿ŽããŠããããã®ã»ã«ã䜿çšãããšãã«ãå¥ã
ã§ã¯ãªã2ã€ã®ãªã¹ããååŸããããã«ããŸãã
public void Clear () { hexMesh.Clear(); vertices = ListPool<Vector3>.Get(); if (useCellData) { cellWeights = ListPool<Color>.Get(); cellIndices = ListPool<Vector3>.Get(); }
Apply
åãã°ã«ãŒãåãå®è¡ããŸãã
public void Apply () { hexMesh.SetVertices(vertices); ListPool<Vector3>.Add(vertices); if (useCellData) { hexMesh.SetColors(cellWeights); ListPool<Color>.Add(cellWeights); hexMesh.SetUVs(2, cellIndices); ListPool<Vector3>.Add(cellIndices); }
ãã¹ãŠã®
AddTriangleColor
ããã³
AddTriangleTerrainTypes
åé€ã
AddTriangleTerrainTypes
ã ããããé©åãª
AddTriangleCellData
ã¡ãœããã«çœ®ãæããŸãããããã®ã¡ãœããã¯ãã€ã³ããã¯ã¹ãšéã¿ãäžåºŠã«è¿œå ããŸãã
public void AddTriangleCellData ( Vector3 indices, Color weights1, Color weights2, Color weights3 ) { cellIndices.Add(indices); cellIndices.Add(indices); cellIndices.Add(indices); cellWeights.Add(weights1); cellWeights.Add(weights2); cellWeights.Add(weights3); } public void AddTriangleCellData (Vector3 indices, Color weights) { AddTriangleCellData(indices, weights, weights, weights); }
é©åãª
AddQuad
ã¡ãœããã§åãããšãè¡ããŸãã
public void AddQuadCellData ( Vector3 indices, Color weights1, Color weights2, Color weights3, Color weights4 ) { cellIndices.Add(indices); cellIndices.Add(indices); cellIndices.Add(indices); cellIndices.Add(indices); cellWeights.Add(weights1); cellWeights.Add(weights2); cellWeights.Add(weights3); cellWeights.Add(weights4); } public void AddQuadCellData ( Vector3 indices, Color weights1, Color weights2 ) { AddQuadCellData(indices, weights1, weights1, weights2, weights2); } public void AddQuadCellData (Vector3 indices, Color weights) { AddQuadCellData(indices, weights, weights, weights, weights); }
HexGridChunkãªãã¡ã¯ã¿ãªã³ã°
ãã®æ®µéã§ã¯ã
HexGridChunk
ãå¿
èŠãª
HexGridChunk
ã§å€ãã®ã³ã³ãã€ã©ãšã©ãŒãçºçããŸãã ããããæåã«ãäžè²«æ§ãä¿ã€ããã«ãéçãªè²ãéã¿ã«ãªãã¡ã¯ã¿ãªã³ã°ããŸãã
static Color weights1 = new Color(1f, 0f, 0f); static Color weights2 = new Color(0f, 1f, 0f); static Color weights3 = new Color(0f, 0f, 1f);
TriangulateEdgeFan
ãä¿®æ£ããããšããå§ããŸãããã 以åã¯åãå¿
èŠã§ããããçŸåšã¯ã»ã«ã€ã³ããã¯ã¹ãå¿
èŠã§ãã
AddTriangleColor
ããã³
AddTriangleTerrainTypes
ã³ãŒãã察å¿ãã
AddTriangleCellData
ã³ãŒãã§
AddTriangleCellData
ãŸãã
void TriangulateEdgeFan (Vector3 center, EdgeVertices edge, float index) { terrain.AddTriangle(center, edge.v1, edge.v2); terrain.AddTriangle(center, edge.v2, edge.v3); terrain.AddTriangle(center, edge.v3, edge.v4); terrain.AddTriangle(center, edge.v4, edge.v5); Vector3 indices; indices.x = indices.y = indices.z = index; terrain.AddTriangleCellData(indices, weights1); terrain.AddTriangleCellData(indices, weights1); terrain.AddTriangleCellData(indices, weights1); terrain.AddTriangleCellData(indices, weights1);
ãã®ã¡ãœããã¯ããã€ãã®å Žæã§åŒã³åºãããŸãã ãããã調ã¹ãŠãå°åœ¢ã®ã¿ã€ãã§ã¯ãªããã»ã«ã®ã€ã³ããã¯ã¹ãããã«è»¢éãããããšã確èªããŸãããã
TriangulateEdgeFan(center, e, cell.Index);
次ã¯
TriangulateEdgeStrip
ã§ãã ããã§ã¯ãã¹ãŠãå°ãè€éã§ãããåãã¢ãããŒãã䜿çšããŠããŸãã ãŸãããã©ã¡ãŒã¿å
c1
ããã³
c2
ã
w1
ããã³
w2
ãªãã¡ã¯ã¿ãªã³ã°ããŸãã
void TriangulateEdgeStrip ( EdgeVertices e1, Color w1, float index1, EdgeVertices e2, Color w2, float index2, bool hasRoad = false ) { terrain.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); terrain.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); terrain.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); terrain.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); Vector3 indices; indices.x = indices.z = index1; indices.y = index2; terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2); terrain.AddQuadCellData(indices, w1, w2);
ãã®ã¡ãœããã®åŒã³åºãã倿ŽããŠãã»ã«ã€ã³ããã¯ã¹ãæž¡ãããããã«ããŸãã ãŸãã倿°åã®äžè²«æ§ãä¿ã¡ãŸãã
TriangulateEdgeStrip( m, weights1, cell.Index, e, weights1, cell.Index ); ⊠TriangulateEdgeStrip( e1, weights1, cell.Index, e2, weights2, neighbor.Index, hasRoad ); ⊠void TriangulateEdgeTerraces ( EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad ) { EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1); Color w2 = HexMetrics.TerraceLerp(weights1, weights2, 1); float i1 = beginCell.Index; float i2 = endCell.Index; TriangulateEdgeStrip(begin, weights1, i1, e2, w2, i2, hasRoad); for (int i = 2; i < HexMetrics.terraceSteps; i++) { EdgeVertices e1 = e2; Color w1 = w2; e2 = EdgeVertices.TerraceLerp(begin, end, i); w2 = HexMetrics.TerraceLerp(weights1, weights2, i); TriangulateEdgeStrip(e1, w1, i1, e2, w2, i2, hasRoad); } TriangulateEdgeStrip(e2, w2, i1, end, weights2, i2, hasRoad); }
次ã«ãè§åºŠã¡ãœããã«é²ã¿ãŸãã ãããã®å€æŽã¯ç°¡åã§ããã倧éã®ã³ãŒãã§è¡ãå¿
èŠããããŸãã ãŸã
TriangulateCorner
ã
void TriangulateCorner ( Vector3 bottom, HexCell bottomCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { ⊠else { terrain.AddTriangle(bottom, left, right); Vector3 indices; indices.x = bottomCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; terrain.AddTriangleCellData(indices, weights1, weights2, weights3);
TriangulateCornerTerraces
æ¥ãŠããŸãã
void TriangulateCornerTerraces ( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { Vector3 v3 = HexMetrics.TerraceLerp(begin, left, 1); Vector3 v4 = HexMetrics.TerraceLerp(begin, right, 1); Color w3 = HexMetrics.TerraceLerp(weights1, weights2, 1); Color w4 = HexMetrics.TerraceLerp(weights1, weights3, 1); Vector3 indices; indices.x = beginCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; terrain.AddTriangle(begin, v3, v4); terrain.AddTriangleCellData(indices, weights1, w3, w4);
ãã®åŸã
TriangulateCornerTerracesCliff
ã
void TriangulateCornerTerracesCliff ( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { float b = 1f / (rightCell.Elevation - beginCell.Elevation); if (b < 0) { b = -b; } Vector3 boundary = Vector3.Lerp( HexMetrics.Perturb(begin), HexMetrics.Perturb(right), b ); Color boundaryWeights = Color.Lerp(weights1, weights3, b); Vector3 indices; indices.x = beginCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; TriangulateBoundaryTriangle( begin, weights1, left, weights2, boundary, boundaryWeights, indices ); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle( left, weights2, right, weights3, boundary, boundaryWeights, indices ); } else { terrain.AddTriangleUnperturbed( HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary ); terrain.AddTriangleCellData( indices, weights2, weights3, boundaryWeights );
TriangulateCornerCliffTerraces
ã§ã¯å°ãç°ãªããŸãã
void TriangulateCornerCliffTerraces ( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell ) { float b = 1f / (leftCell.Elevation - beginCell.Elevation); if (b < 0) { b = -b; } Vector3 boundary = Vector3.Lerp( HexMetrics.Perturb(begin), HexMetrics.Perturb(left), b ); Color boundaryWeights = Color.Lerp(weights1, weights2, b); Vector3 indices; indices.x = beginCell.Index; indices.y = leftCell.Index; indices.z = rightCell.Index; TriangulateBoundaryTriangle( right, weights3, begin, weights1, boundary, boundaryWeights, indices ); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle( left, weights2, right, weights3, boundary, boundaryWeights, indices ); } else { terrain.AddTriangleUnperturbed( HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary ); terrain.AddTriangleCellData( indices, weights2, weights3, boundaryWeights );
åã®2ã€ã®ã¡ãœããã¯ãæŽæ°ãå¿
èŠãª
TriangulateBoundaryTriangle
䜿çšããŸãã
void TriangulateBoundaryTriangle ( Vector3 begin, Color beginWeights, Vector3 left, Color leftWeights, Vector3 boundary, Color boundaryWeights, Vector3 indices ) { Vector3 v2 = HexMetrics.Perturb(HexMetrics.TerraceLerp(begin, left, 1)); Color w2 = HexMetrics.TerraceLerp(beginWeights, leftWeights, 1); terrain.AddTriangleUnperturbed(HexMetrics.Perturb(begin), v2, boundary); terrain.AddTriangleCellData(indices, beginWeights, w2, boundaryWeights);
倿Žããå¿
èŠãããæåŸã®ã¡ãœããã¯
TriangulateWithRiver
ã§ãã
void TriangulateWithRiver ( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { ⊠terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); Vector3 indices; indices.x = indices.y = indices.z = cell.Index; terrain.AddTriangleCellData(indices, weights1); terrain.AddQuadCellData(indices, weights1); terrain.AddQuadCellData(indices, weights1); terrain.AddTriangleCellData(indices, weights1);
åäœãããã«ã¯ããã¬ãããã©ã°ã¡ã³ãã®ã¬ãªãŒãã®åèŠçŽ ã«ã»ã«ããŒã¿ã䜿çšããããšã瀺ãå¿
èŠããããŸãã
ã¬ãªãŒãã¯ã»ã«ããŒã¿ã䜿çšããŸãããã®æ®µéã§ã¯ãã¡ãã·ã¥ã«ã¯æšé«ã¿ã€ãã€ã³ããã¯ã¹ã®ä»£ããã«ã»ã«ã€ã³ããã¯ã¹ãå«ãŸããŠããŸãã ãã¬ã€ã³ã·ã§ãŒããŒã¯äŸç¶ãšããŠããããæšé«ã€ã³ããã¯ã¹ãšããŠè§£éãããããæåŸã®ãã¬ã€ã³ãã¯ã¹ãã£ã«å°éãããŸã§ãæåã®ã»ã«ãæåã®ãã¯ã¹ãã£ã§ã¬ã³ããªã³ã°ãããããšãããããŸãã
æšé«ãã¯ã¹ãã£ã€ã³ããã¯ã¹ãšããŠã»ã«ã€ã³ããã¯ã¹ã䜿çšããŸãããªãã¡ã¯ã¿ãªã³ã°ãããã³ãŒããæ©èœãããããšãã§ããŸããã äœãééã£ãŠããŸããïŒäžåºŠã«å€§éã®äžè§æž¬éã³ãŒãã倿Žããããããšã©ãŒãèŠèœãšãã®å¯èœæ§ãé«ããªããŸãã ãšã©ãŒãèŠã€ãããªãå Žåã¯ããã®ã»ã¯ã·ã§ã³ããããã±ãŒãžãããŠã³ããŒãããŠãé©åãªãã¡ã€ã«ãæœåºããŠã¿ãŠãã ããã ããããå¥ã®ãããžã§ã¯ãã«ã€ã³ããŒãããŠãç¬èªã®ã³ãŒããšæ¯èŒã§ããŸãã
ã»ã«ããŒã¿ãã·ã§ãŒããŒã«è»¢éãã
ãããã®ã»ã«ã䜿çšããã«ã¯ããã¬ã€ã³ã·ã§ãŒããŒããã¢ã¯ã»ã¹ããå¿
èŠããããŸãã ããã¯ãã·ã§ãŒããŒããããã£ãéããŠå®è£
ã§ããŸãã ãã®å Žåã
HexCellShaderData
ã¯ã¬ãªãŒããããªã¢ã«ã®ããããã£
HexCellShaderData
èšå®ãã
HexCellShaderData
ãããŸãã ãŸãã¯ããããã®ã»ã«ã®ãã¯ã¹ãã£ããã¹ãŠã®ã·ã§ãŒããŒã«ã°ããŒãã«ã«è¡šç€ºãããããšãã§ããŸãã ããã¯ããã€ãã®ã·ã§ãŒããŒã§å¿
èŠãªã®ã§äŸ¿å©ã§ãããã®ããããã®ã¢ãããŒãã䜿çšããŸãã
ã»ã«ãã¯ã¹ãã£ãäœæããåŸãéçãª
Shader.SetGlobalTexture
ã¡ãœãããåŒã³åºããŠã
Shader.SetGlobalTexture
ãšããŠã°ããŒãã«ã«è¡šç€ºã
ãŸã ã
public void Initialize (int x, int z) { ⊠else { cellTexture = new Texture2D( x, z, TextureFormat.RGBA32, false, true ); cellTexture.filterMode = FilterMode.Point; cellTexture.wrapMode = TextureWrapMode.Clamp; Shader.SetGlobalTexture("_HexCellData", cellTexture); } ⊠}
ã·ã§ãŒããŒããããã£ã䜿çšããŠãUnityã¯
textureName_TexelSize倿°ãä»ããŠã·ã§ãŒããŒã§ãã¯ã¹ãã£ãµã€ãºã䜿çšã§ããããã«ããŸãã ããã¯ãå¹
ãšé«ããããã³å¹
ãšé«ãèªäœã«åããå€ãå«ã4ã³ã³ããŒãã³ããã¯ãã©ã€ã¶ãŒã§ãã ãã ããã°ããŒãã«ãã¯ã¹ãã£ãèšå®ããå Žåãããã¯å®è¡ãããŸããã ãããã£ãŠããã¯ã¹ãã£ãäœæãŸãã¯ãµã€ãºå€æŽããåŸã
Shader.SetGlobalVector
ã䜿çšããŠèªåã§å®è¡ããŸãã
else { cellTexture = new Texture2D( x, z, TextureFormat.RGBA32, false, true ); cellTexture.filterMode = FilterMode.Point; cellTexture.wrapMode = TextureWrapMode.Clamp; Shader.SetGlobalTexture("_HexCellData", cellTexture); } Shader.SetGlobalVector( "_HexCellData_TexelSize", new Vector4(1f / x, 1f / z, x, z) );
ã·ã§ãŒããŒããŒã¿ã¢ã¯ã»ã¹
HexCellDataãšãã
ååã®ãããªã¢ã«ãã©ã«ããŒã«æ°ããã·ã§ãŒããŒã€ã³ã¯ã«ãŒããã¡ã€ã«ãäœæããŸãã ãã®äžã§ããããã®ã»ã«ã®ãã¯ã¹ãã£ãšãµã€ãºã«é¢ããæ
å ±ã®å€æ°ãå®çŸ©ããŸãã ãŸããæå®ãããé ç¹ã¡ãã·ã¥ããŒã¿ã®ã»ã«ããŒã¿ãååŸãã颿°ãäœæããŸãã
sampler2D _HexCellData; float4 _HexCellData_TexelSize; float4 GetCellData (appdata_full v) { }
æ°ããã€ã³ã¯ã«ãŒããã¡ã€ã«ããã¬ã€ã³ã¿ã€ãã®å Žåãšåæ§ã«ãã»ã«ã€ã³ããã¯ã¹ã¯
v.texcoord2
ã«æ ŒçŽãããŸãã æåã®ã€ã³ããã¯ã¹
v.texcoord2.x
ããå§ããŸãããã æ®å¿µãªãããã€ã³ããã¯ã¹ãçŽæ¥äœ¿çšããŠãããã®ã»ã«ã®ãã¯ã¹ãã£ããµã³ããªã³ã°ããããšã¯ã§ããŸããã UV座æšã«å€æããå¿
èŠããããŸãã
U座æšãäœæããæåã®ã¹ãããã¯ãã»ã«ã€ã³ããã¯ã¹ããã¯ã¹ãã£ã®å¹
ã§é€ç®ããããšã§ãã ãããè¡ãã«ã¯ã
_HexCellData_TexelSize.x
ä¹ç®ã
_HexCellData_TexelSize.x
ã
float4 GetCellData (appdata_full v) { float2 uv; uv.x = v.texcoord2.x * _HexCellData_TexelSize.x; }
çµæã¯ZU圢åŒã®æ°å€ã«ãªããŸããZã¯è¡ã€ã³ããã¯ã¹ã§ãUã¯Uã»ã«ã®åº§æšã§ããæååãæœåºããã«ã¯ãæ°å€ãåãæšãŠãŠããæ°å€ããæžç®ããŠU座æšãååŸããŸãã float4 GetCellData (appdata_full v) { float2 uv; uv.x = v.texcoord2.x * _HexCellData_TexelSize.x; float row = floor(uv.x); uv.x -= row; }
V座æšã¯ãã©ã€ã³ããã¯ã¹ãã£ã®é«ãã§å²ã£ãŠããŸãã float4 GetCellData (appdata_full v) { float2 uv; uv.x = v.texcoord2.x * _HexCellData_TexelSize.x; float row = floor(uv.x); uv.x -= row; uv.y = row * _HexCellData_TexelSize.y; }
ãã¯ã¹ãã£ããµã³ããªã³ã°ããŠããããããã¯ã»ã«ã®ãšããžã§ã¯ãªãããã¯ã»ã«ã®äžå¿ã®åº§æšã䜿çšããå¿
èŠããããŸããããã«ãããæ£ãããã¯ã»ã«ã確å®ã«ãµã³ããªã³ã°ãããŸãããããã£ãŠããã¯ã¹ãã£ã®ãµã€ãºã§å²ã£ãåŸãœã远å ããŸãã float4 GetCellData (appdata_full v) { float2 uv; uv.x = (v.texcoord2.x + 0.5) * _HexCellData_TexelSize.x; float row = floor(uv.x); uv.x -= row; uv.y = (row + 0.5) * _HexCellData_TexelSize.y; }
ããã«ãããé ç¹ããŒã¿ã«ä¿åãããŠããæåã®ã»ã«ã®ã€ã³ããã¯ã¹ã®æ£ããUV座æšãåŸãããŸãããã ããäžéšã«ã¯æå€§3ã€ã®ç°ãªãã€ã³ããã¯ã¹ãèšå®ã§ããŸãããããã£ãŠãGetCellData
ã©ã®ã€ã³ããã¯ã¹ã§ãæ©èœããããã«ããŸããæŽæ°ãã©ã¡ãŒã¿ã远å ããŸãindex
ãããã䜿çšããŠãã»ã«ã€ã³ããã¯ã¹ãæã€ãã¯ãã«ã³ã³ããŒãã³ãã«ã¢ã¯ã»ã¹ããŸãã float4 GetCellData (appdata_full v, int index) { float2 uv; uv.x = (v.texcoord2[index] + 0.5) * _HexCellData_TexelSize.x; float row = floor(uv.x); uv.x -= row; uv.y = (row + 0.5) * _HexCellData_TexelSize.y; }
ãããã®ã»ã«ã«å¿
èŠãªåº§æšããã¹ãŠæã£ãã®ã§ããµã³ããªã³ã°ããããšãã§ããŸã_HexCellData
ãé ç¹ããã°ã©ã ã§ãã¯ã¹ãã£ããµã³ããªã³ã°ããŠããããã䜿çšããããããã¯ã¹ãã£ãã·ã§ãŒããŒã«æç€ºçã«æç€ºããå¿
èŠããããŸããããã¯tex2Dlod
ã4ã€ã®ãã¯ã¹ãã£ã®åº§æšãå¿
èŠãšãã颿°ã䜿çšããŠå®è¡ã§ããŸãããããã®ã»ã«ã«ã¯ããããã¯ã¹ãã£ããªãããã远å ã®åº§æšã«ãŒãå€ãå²ãåœãŠãŸãã float4 GetCellData (appdata_full v, int index) { float2 uv; uv.x = (v.texcoord2[index] + 0.5) * _HexCellData_TexelSize.x; float row = floor(uv.x); uv.x -= row; uv.y = (row + 0.5) * _HexCellData_TexelSize.y; float4 data = tex2Dlod(_HexCellData, float4(uv, 0, 0)); }
4çªç®ã®ããŒã¿ã³ã³ããŒãã³ãã«ã¯ãã¬ãªãŒãã¿ã€ãã€ã³ããã¯ã¹ãå«ãŸããããããã€ããšããŠçŽæ¥ä¿åããŸãããã ããGPUã¯0ã1ã®ç¯å²ã®æµ®åå°æ°ç¹å€ã«èªåçã«å€æããŸãããæ£ããå€ã«æ»ãã«ã¯ã255ãæããŸãããã®åŸãããŒã¿ãè¿ãããšãã§ããŸãã float4 data = tex2Dlod(_HexCellData, float4(uv, 0, 0)); data.w *= 255; return data;
ãã®æ©èœã䜿çšããã«ã¯ããã¬ã€ã³ã·ã§ãŒããŒã§HexCellDataãæå¹ã«ããŸãããã®ã·ã§ãŒããŒããããªã¢ã«/å°åœ¢ã«é
眮ãããããçžå¯Ÿãã¹../HexCellData.cgincã䜿çšããå¿
èŠããããŸãã #include "../HexCellData.cginc" UNITY_DECLARE_TEX2DARRAY(_MainTex)
é ç¹ããã°ã©ã ã§ã¯ãé ç¹ããŒã¿ã«æ ŒçŽãããŠãã3ã€ã®ã»ã«ã€ã³ããã¯ã¹ãã¹ãŠã®ã»ã«ããŒã¿ãååŸããŸããæ¬¡ã«data.terrain
ãæšé«ã€ã³ããã¯ã¹ãå²ãåœãŠãŸãã void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); // data.terrain = v.texcoord2.xyz; float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); float4 cell2 = GetCellData(v, 2); data.terrain.x = cell0.w; data.terrain.y = cell1.w; data.terrain.z = cell2.w; }
ãã®æç¹ã§ããããã¯åã³æ£ããå°åœ¢ã衚瀺ãå§ããŸããã倧ããªéãã¯ãå°åœ¢ã¿ã€ãã®ã¿ãç·šéããŠãæ°ããäžè§åœ¢åå²ãè¡ãããªãããšã§ããç·šéäžã«ä»ã®ã»ã«ããŒã¿ã倿Žãããå Žåãäžè§æž¬éã¯éåžžã©ããå®è¡ãããŸãããŠããã£ããã±ãŒãžå¯èŠæ§
ãããã®ã»ã«ã®åºç€ãäœæããããæ¬¡ã«å¯èŠæ§ã®ãµããŒãã«é²ã¿ãŸãããããè¡ãã«ã¯ãã·ã§ãŒããŒãã»ã«èªäœãããã³å¯èŠæ§ã決å®ãããªããžã§ã¯ãã䜿çšããŸããäžè§æž¬éããã»ã¹ã¯ããã«ã€ããŠãŸã£ããäœãç¥ããªãããšã«æ³šæããŠãã ãããã·ã§ãŒããŒ
ãŸãããã¬ã€ã³ã·ã§ãŒããŒã«å¯èŠæ§ãäŒããããšããå§ããŸããããé ç¹ããã°ã©ã ããå¯èŠæ§ããŒã¿ãåãåããæ§é äœã䜿çšããŠãã©ã°ã¡ã³ãããã°ã©ã ã«æž¡ãInput
ãŸãã3ã€ã®åå¥ã®æšé«ã€ã³ããã¯ã¹ãæž¡ãããã3ã€ã®å¯èŠæ§å€ãæž¡ããŸãã struct Input { float4 color : COLOR; float3 worldPos; float3 terrain; float3 visibility; };
å¯èŠæ§ãä¿åããã«ã¯ããããã®ã»ã«ã®æåã®ã³ã³ããŒãã³ãã䜿çšããŸãã void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); float4 cell2 = GetCellData(v, 2); data.terrain.x = cell0.w; data.terrain.y = cell1.w; data.terrain.z = cell2.w; data.visibility.x = cell0.x; data.visibility.y = cell1.x; data.visibility.z = cell2.x; }
0ã®å¯èŠæ§ã¯ãã»ã«ãçŸåšé衚瀺ã§ããããšãæå³ããŸããå¯èŠã§ããã°ãå¯èŠæ§1ã®å€ã«ãªããŸãããããã£ãŠãçµæGetTerrainColor
ã«å¯èŠæ§ã®å¯Ÿå¿ãããã¯ãã«ãæããããšã§ãå°åœ¢ãæãããããšãã§ããŸãããããã£ãŠãåæ··åã»ã«ã®ã¬ãªãŒãè²ãåå¥ã«èª¿æŽããŸãã float4 GetTerrainColor (Input IN, int index) { float3 uvw = float3(IN.worldPos.xz * 0.02, IN.terrain[index]); float4 c = UNITY_SAMPLE_TEX2DARRAY(_MainTex, uvw); return c * (IN.color[index] * IN.visibility[index]); }
现èãé»ããªã£ãã代ããã«ãé ç¹ããã°ã©ã ã§å¯èŠæ§ãçµã¿åãããããšã¯ã§ããŸãããïŒ, . . . , . , .
å®å
šãªæéã¯ãäžæçã«èŠããªã现èã«ãšã£ãŠã¯ããéãã§ããæµ®ã圫ããèŠããããã«ããã«ã¯ãé衚瀺ã®ã»ã«ã«äœ¿çšããã€ã³ãžã±ãŒã¿ãŒãå¢ããå¿
èŠããããŸãã0â1ããÂŒâ 1ã«ç§»åããŸãããlerp
ãããã¯ãé ç¹ããã°ã©ã ã®æåŸã«ãã颿°ã䜿çšããŠå®è¡ã§ããŸãã void vert (inout appdata_full v, out Input data) { ⊠data.visibility.x = cell0.x; data.visibility.y = cell1.x; data.visibility.z = cell2.x; data.visibility = lerp(0.25, 1, data.visibility); }
圱ä»ãã»ã«ãã»ã«å¯èŠæ§è¿œè·¡
å¯èŠæ§ãæ©èœããã«ã¯ãã»ã«ãå¯èŠæ§ã远跡ããå¿
èŠããããŸããããããã»ã«ã¯ãããèŠãããã©ãããã©ã®ããã«æ±ºå®ããŸããïŒãããè¡ããšã³ãã£ãã£ã®æ°ã远跡ããããšã§ãããè¡ãããšãã§ããŸãã誰ããã»ã«ãèŠå§ãããããã®ã»ã«ãå ±åããªããã°ãªããŸããããããŠã誰ããã»ã«ãèŠãããšããããããããã«ã€ããŠã圌女ã«éç¥ããªããã°ãªããŸãããã»ã«ã¯ããšã³ãã£ãã£ãäœã§ããããŠã©ããã£ãŒã®æ°ãåçŽã«è¿œè·¡ããŸããã»ã«ã®å¯èŠæ§ã®å€ãå°ãªããšã1ã®å Žåãã»ã«ã¯è¡šç€ºãããããã§ãªãå Žåã¯é衚瀺ã«ãªããŸãããã®åäœãå®è£
ããã«ã¯ãHexCell
2ã€ã®ã¡ãœãããšããããã£ã倿°ã«è¿œå ããŸãã public bool IsVisible { get { return visibility > 0; } } ⊠int visibility; ⊠public void IncreaseVisibility () { visibility += 1; } public void DecreaseVisibility () { visibility -= 1; }
次ã«ãHexCellShaderData
ã¡ãœããRefreshVisibility
ã«ã远å ããŸããããã¯ãRefreshTerrain
å¯èŠæ§ã®ããã ããšåãããšãè¡ããŸããããŒã¿ãããŒã¿ã»ã«ã®ã³ã³ããŒãã³ãRã«ä¿åããŸããå€0ã1ã«å€æããããã€ããåŠçãããããå¯èŠæ§ã瀺ãããã«äœ¿çšããŸã(byte)255
ã public void RefreshVisibility (HexCell cell) { cellTextureData[cell.Index].r = cell.IsVisible ? (byte)255 : (byte)0; enabled = true; }
0ãã1ã®éã§å€ã倿ŽããŠãå¯èŠæ§ã墿žããŠãã®ã¡ââãœãããåŒã³åºããŸãã public void IncreaseVisibility () { visibility += 1; if (visibility == 1) { ShaderData.RefreshVisibility(this); } } public void DecreaseVisibility () { visibility -= 1; if (visibility == 0) { ShaderData.RefreshVisibility(this); } }
åéã®å¯èŠæ§ã®äœæ
ãŠããããå æããŠããã»ã«ãèŠãããšãã§ããããã«ããŸããããããã¯IncreaseVisibility
ãã¿ã¹ã¯äžã®ãŠãããã®æ°ããå Žæãžã®åŒã³åºãã䜿çšããŠéæãããŸãHexUnit.Location
ããŸããå€ãå ŽæïŒååšããå ŽåïŒãåŒã³åºããŸãDecreaseVisibility
ã public HexCell Location { get { return location; } set { if (location) { location.DecreaseVisibility(); location.Unit = null; } location = value; value.Unit = this; value.IncreaseVisibility(); transform.localPosition = value.Position; } }
ãŠãããã¯çŸåšå°ã確èªã§ããŸããæåŸã«ãå¯èŠæ§ã䜿çšããŸããïŒãŠãããããããã«è¿œå ãããšãã»ã«ã衚瀺ãããŸããããã«ãæ°ããå Žæã«ç§»åãããšãã¹ã³ãŒãããã¬ããŒããããŸãããã ããããããããŠããããåé€ããŠãããããã®ã¹ã³ãŒãã¯ã¢ã¯ãã£ãã®ãŸãŸã§ãããããä¿®æ£ããããã«ããŠããããç Žå£ãããšãã®äœçœ®ã®å¯èŠæ§ãæžãããŸãã public void Die () { if (location) { location.DecreaseVisibility(); } location.Unit = null; Destroy(gameObject); }
å¯èŠç¯å²
ãããŸã§ã®ãšããããã¿ããã¡ã³ããé
眮ãããŠããã»ã«ã®ã¿ã衚瀺ãããŠãããããã«ããå¯èœæ§ãå¶éãããŠããŸããå°ãªããšã飿¥ããã»ã«ã確èªããå¿
èŠããããŸããäžè¬çãªå ŽåããŠãããã¯ããŠãããã«äŸåããç¹å®ã®è·é¢å
ã®ãã¹ãŠã®ã»ã«ãèŠãããšãã§ããŸããã¡ãœããã«è¿œå ããŠHexGrid
ãç¯å²ãèæ
®ããŠ1ã€ã®ã»ã«ããèŠãããã¹ãŠã®ã»ã«ãèŠã€ããŸãããããè€è£œããŠå€æŽããããšã§ããã®ã¡ãœãããäœæã§ããŸãSearch
ããã©ã¡ãŒã¿ã倿Žãããªã¹ãããŒã«ã䜿çšã§ããã»ã«ã®ãªã¹ããè¿ãããã«ããŸããåå埩ã§ãçŸåšã®ã»ã«ããªã¹ãã«è¿œå ãããŸããæçµçãªã»ã«ã¯ãªãããããã®ãã€ã³ãã«å°éããŠãæ€çŽ¢ã¯çµäºããŸããããŸããç§»åã®ããžãã¯ãšç§»åã®ã³ã¹ããåãé€ããŸããããããã£ãäœæããPathFrom
ç§ãã¡ã¯ããããå¿
èŠãšãããã°ãªããã«æ²¿ã£ããã¹ã«å¹²æžããããªãã®ã§ããã¯ãå°ããããŸããã§ãããåã¹ãããã§ãè·é¢ã¯1ã ãå¢å ããŸããç¯å²ãè¶
ããå Žåããã®ã»ã«ã¯ã¹ããããããŸãããŸããæ€çŽ¢ãã¥ãŒãªã¹ãã£ãã¯ã¯å¿
èŠãªããããå€0ã§åæåããŸããã€ãŸããå®éã«ã¯ãã€ã¯ã¹ãã©ã¢ã«ãŽãªãºã ã«æ»ããŸããã List<HexCell> GetVisibleCells (HexCell fromCell, int range) { List<HexCell> visibleCells = ListPool<HexCell>.Get(); 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; visibleCells.Add(current);
ããç°¡åãªã¢ã«ãŽãªãºã ã䜿çšããŠãç¯å²å
ã®ãã¹ãŠã®ã»ã«ãèŠã€ããããšã¯ã§ããŸãããïŒ, , .
HexGrid
ã¡ãœããIncreaseVisibility
ãšã远å ããŸãDecreaseVisibility
ã圌ãã¯ã»ã«ãšç¯å²ãååŸãã察å¿ããã»ã«ã®ãªã¹ããååŸãããããã®å¯èŠæ§ã墿žããŸããå®äºãããããªã¹ããããŒã«ã«æ»ãå¿
èŠããããŸãã public void IncreaseVisibility (HexCell fromCell, int range) { List<HexCell> cells = GetVisibleCells(fromCell, range); for (int i = 0; i < cells.Count; i++) { cells[i].IncreaseVisibility(); } ListPool<HexCell>.Add(cells); } public void DecreaseVisibility (HexCell fromCell, int range) { List<HexCell> cells = GetVisibleCells(fromCell, range); for (int i = 0; i < cells.Count; i++) { cells[i].DecreaseVisibility(); } ListPool<HexCell>.Add(cells); }
ãããã®ã¡ãœããã䜿çšHexUnit
ããã«ã¯ãã°ãªããã«ã¢ã¯ã»ã¹ããå¿
èŠããããããããã«ããããã£ã远å ããŸãGrid
ã public HexGrid Grid { get; set; }
ã°ãªããã«ããŒã ã远å ãããšãã°ãªããããã®ããããã£ã«å²ãåœãŠãããŸãHexGrid.AddUnit
ã public void AddUnit (HexUnit unit, HexCell location, float orientation) { units.Add(unit); unit.Grid = this; unit.transform.SetParent(transform, false); unit.Location = location; unit.Orientation = orientation; }
ãŸãã3ã€ã®ã»ã«ã®å¯èŠæ§ã®ç¯å²ã§ååã§ãããããè¡ãã«ã¯ãHexUnit
宿°ã«è¿œå ããŸããããã¯å°æ¥ãåžžã«å€æ°ã«ãªããŸããæ¬¡ã«ãåéãã°ãªããIncreaseVisibility
ãšã®ã¡ãœãããåŒã³åºãããã«ããDecreaseVisibility
ãã®å Žæã«ç§»åããã ãã§ãªãããã®å¯èŠç¯å²ãéä¿¡ããŸãã const int visionRange = 3; ⊠public HexCell Location { get { return location; } set { if (location) {
ãªãŒããŒã©ããå¯èœãªå¯èŠç¯å²ãæã€ãŠããããç§»åæã®å¯èŠæ§
çŸæç¹ã§ã¯ãç§»åã³ãã³ãåŸã®ãŠãããã®èŠèªç¯å²ã¯ãããã«çµç¹ã«ãã¬ããŒããããŸãããã¿ããã¡ã³ããšãã®èŠçãäžç·ã«ç§»åãããšãèŠãç®ãè¯ããªããŸããããã®æåã®ã¹ãããã¯ãããããã£Location
cãèšå®ããªãããšHexUnit.Travel
ã§ãã代ããã«ãlocation
ããããã£ã³ãŒããåé¿ããŠããã£ãŒã«ããçŽæ¥å€æŽããŸãããããã£ãŠãå€ãå Žæãæåã§ã¯ãªã¢ããæ°ããå Žæãæ§æããŸããå¯èŠæ§ã¯å€æŽãããŸããã public void Travel (List<HexCell> path) {
ã³ã«ãŒãã³å
ã§TravelPath
ã¯ãå®äºåŸã«ã®ã¿æåã®ã»ã«ã®å¯èŠæ§ãäœäžããLookAt
ãŸãããã®åŸãæ°ããã»ã«ã«ç§»åããåã«ããã®ã»ã«ããã®å¯èŠæ§ãé«ããŸãããããçµãããšãåã³å¯èŠæ§ãäœäžããŸããæåŸã«ãæåŸã®ã»ã«ã®å¯èŠæ§ãé«ããŸãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position;
é転æã®èŠçããã¿ããã¡ã³ããç§»åããæç¹ã§æ°ããæ³šæãçºè¡ãããå Žåãé€ããããã¯ãã¹ãŠæ©èœããŸããããã¯ãã¬ããŒããŒã·ã§ã³ã«ã€ãªãããå¯èŠæ§ã«ãé©çšãããã¯ãã§ãããããå®çŸããã«ã¯ããŠãããã®çŸåšäœçœ®ã®åãã远跡ããå¿
èŠããããŸãã HexCell location, currentTravelLocation;
åéãæçµã»ã«ã«å°éãããŸã§ãç§»åäžã«æ°ããã»ã«ã«ããããããã³ã«ãã®äœçœ®ãæŽæ°ããŸãããã®åŸããªã»ããããå¿
èŠããããŸãã IEnumerator TravelPath () { ⊠for (int i = 1; i < pathToTravel.Count; i++) { currentTravelLocation = pathToTravel[i]; a = c; b = pathToTravel[i - 1].Position; c = (b + currentTravelLocation.Position) * 0.5f; Grid.IncreaseVisibility(pathToTravel[i], visionRange); for (; t < 1f; t += Time.deltaTime * travelSpeed) { transform.localPosition = Bezier.GetPoint(a, b, c, t); Vector3 d = Bezier.GetDerivative(a, b, c, t); dy = 0f; transform.localRotation = Quaternion.LookRotation(d); yield return null; } Grid.DecreaseVisibility(pathToTravel[i], visionRange); t -= 1f; } currentTravelLocation = null; ⊠}
ããã§ã黿ºãå
¥ããåŸTravelPath
ããã¹ã®å€ãäžéäœçœ®ãããã£ãŠãããã©ããã確èªã§ããŸããã¯ãã®å Žåã¯ããã¹ã®å
é ã§ã¯ãªãããã®ã»ã«ã®å¯èŠæ§ãäžããå¿
èŠããããŸãã IEnumerator TravelPath () { Vector3 a, b, c = pathToTravel[0].Position; yield return LookAt(pathToTravel[1].Position); Grid.DecreaseVisibility( currentTravelLocation ? currentTravelLocation : pathToTravel[0], visionRange ); ⊠}
ãŸããããŒã ã®ç§»åäžã«çºçããåã³ã³ãã€ã«åŸã®å¯èŠæ§ãä¿®æ£ããå¿
èŠããããŸããäžéäœçœ®ããŸã ããã£ãŠããå Žåã¯ãäžéäœçœ®ã®å¯èŠæ§ãäžããŠããšã³ããã€ã³ãã®å¯èŠæ§ãé«ããŠãããäžéäœçœ®ããªã»ããããŸãã void OnEnable () { if (location) { transform.localPosition = location.Position; if (currentTravelLocation) { Grid.IncreaseVisibility(location, visionRange); Grid.DecreaseVisibility(currentTravelLocation, visionRange); currentTravelLocation = null; } } }
ãŠããã£ããã±ãŒãžéè·¯ãšæ°Žã®å¯èŠæ§
ã¬ãªãŒãã®è²ã®å€åã¯èŠèªæ§ã«åºã¥ããŠããŸãããããã¯éè·¯ãæ°Žã«ã¯åœ±é¿ããŸãããèŠããªã现èã«ã¯æããããŸããéè·¯ãšæ°Žã«å¯èŠæ§ãé©çšããã«ã¯ãã»ã«ã€ã³ããã¯ã¹ã远å ããã¡ãã·ã¥ããŒã¿ã«ãŠã§ã€ãããã¬ã³ãããå¿
èŠããããŸãããããã£ãŠããã¬ãããã©ã°ã¡ã³ãã®å·ãéè·¯ãæ°Žãæ°ŽèŸºãæ²³å£ã®ã»ã«ããŒã¿ã®äœ¿çšã®åããã§ãã¯ããŸããéè·¯
éè·¯ããå§ããŸãããã®æ¹æ³ã¯HexGridChunk.TriangulateRoadEdge
ãã»ã«ã®äžå¿ã«éè·¯ã®å°ããªéšåãäœæããããã«äœ¿çšãããããã1ã€ã®ã»ã«ã€ã³ããã¯ã¹ãå¿
èŠã§ãããã©ã¡ãŒã¿ãŒã远å ããŠãäžè§åœ¢ã®ã»ã«ããŒã¿ãçæããŸãã void TriangulateRoadEdge ( Vector3 center, Vector3 mL, Vector3 mR, float index ) { roads.AddTriangle(center, mL, mR); roads.AddTriangleUV( new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f) ); Vector3 indices; indices.x = indices.y = indices.z = index; roads.AddTriangleCellData(indices, weights1); }
éè·¯ãäœæãããã1ã€ã®ç°¡åãªæ¹æ³ã¯TriangulateRoadSegment
ã§ããã»ã«ã®å
éšãšã»ã«ã®äž¡æ¹ã§äœ¿çšãããããã2ã€ã®ç°ãªãã€ã³ããã¯ã¹ã§åäœããã¯ãã§ãããã®ããã«ã¯ãã€ã³ããã¯ã¹ãã¯ãã«ãã©ã¡ãŒã¿ãŒã䜿çšãããšäŸ¿å©ã§ããéè·¯ã»ã°ã¡ã³ãã¯æ£ã®äžéšã§ããå¯èœæ§ããããããéã¿ããã©ã¡ãŒã¿ã«æž¡ãå¿
èŠããããŸãã void TriangulateRoadSegment ( Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Vector3 v5, Vector3 v6, Color w1, Color w2, Vector3 indices ) { roads.AddQuad(v1, v2, v4, v5); roads.AddQuad(v2, v3, v5, v6); roads.AddQuadUV(0f, 1f, 0f, 0f); roads.AddQuadUV(1f, 0f, 0f, 0f); roads.AddQuadCellData(indices, w1, w2); roads.AddQuadCellData(indices, w1, w2); }
TriangulateRoad
ã§ã¯ãã»ã«å
ã«éè·¯ãäœæããã«é²ã¿ãŸããããã€ã³ããã¯ã¹ãã©ã¡ãŒã¿ãå¿
èŠã§ãã圌ã¯ããã®ããŒã¿ãåŒã³åºããéè·¯ã¡ãœããã«æž¡ããäœæããäžè§åœ¢ã«è¿œå ããŸãã void TriangulateRoad ( Vector3 center, Vector3 mL, Vector3 mR, EdgeVertices e, bool hasRoadThroughCellEdge, float index ) { if (hasRoadThroughCellEdge) { Vector3 indices; indices.x = indices.y = indices.z = index; Vector3 mC = Vector3.Lerp(mL, mR, 0.5f); TriangulateRoadSegment( mL, mC, mR, e.v2, e.v3, e.v4, weights1, weights1, indices ); roads.AddTriangle(center, mL, mC); roads.AddTriangle(center, mC, mR); roads.AddTriangleUV( new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(1f, 0f) ); roads.AddTriangleUV( new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 0f) ); roads.AddTriangleCellData(indices, weights1); roads.AddTriangleCellData(indices, weights1); } else { TriangulateRoadEdge(center, mL, mR, index); } }
å¿
èŠãªã¡ãœããåŒæ°ãTriangulateRoad
ãTriangulateRoadEdge
ããã³ã«è¿œå ããŠãTriangulateRoadSegment
ãã¹ãŠã®ã³ã³ãã€ã©ãšã©ãŒãä¿®æ£ããŸãã void TriangulateWithoutRiver ( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { TriangulateEdgeFan(center, e, cell.Index); if (cell.HasRoads) { Vector2 interpolators = GetRoadInterpolators(direction, cell); TriangulateRoad( center, Vector3.Lerp(center, e.v1, interpolators.x), Vector3.Lerp(center, e.v5, interpolators.y), e, cell.HasRoadThroughEdge(direction), cell.Index ); } } ⊠void TriangulateRoadAdjacentToRiver ( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { ⊠TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge, cell.Index); if (previousHasRiver) { TriangulateRoadEdge(roadCenter, center, mL, cell.Index); } if (nextHasRiver) { TriangulateRoadEdge(roadCenter, mR, center, cell.Index); } } ⊠void TriangulateEdgeStrip ( ⊠) { ⊠if (hasRoad) { TriangulateRoadSegment( e1.v2, e1.v3, e1.v4, e2.v2, e2.v3, e2.v4, w1, w2, indices ); } }
ããã§ã¡ãã·ã¥ããŒã¿ãæ£ããã®ã§ãRoadã·ã§ãŒããŒã«é²ã¿ãŸããé ç¹ããã°ã©ã ãå¿
èŠã§ãHexCellDataãå«ãŸããŠããå¿
èŠããããŸãã #pragma surface surf Standard fullforwardshadows decal:blend vertex:vert #pragma target 3.0 #include "HexCellData.cginc"
è€æ°ã®ãããªã¢ã«ãæ··åšãããŠããªãããããã©ã°ã¡ã³ãããã°ã©ã ã«å¯èŠæ§ã®ã€ã³ãžã±ãŒã¿ã1ã€æž¡ãã ãã§ååã§ãã struct Input { float2 uv_MainTex; float3 worldPos; float visibility; };
æ°ããé ç¹ããã°ã©ã ã2ã€ã®ã»ã«ããããŒã¿ãåä¿¡ããã®ã«ååã§ããããã«å¯èŠæ§ãããã¯ã¹ãã調æŽããŠåºåã«è¿œå ããŸãã void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); data.visibility = cell0.x * v.color.x + cell1.x * v.color.y; data.visibility = lerp(0.25, 1, data.visibility); }
ãã©ã°ã¡ã³ãããã°ã©ã ã§ã¯ãè²ã«å¯èŠæ§ã远å ããã ãã§ãã void surf (Input IN, inout SurfaceOutputStandard o) { float4 noise = tex2D(_MainTex, IN.worldPos.xz * 0.025); fixed4 c = _Color * ((noise.y * 0.75 + 0.25) * IN.visibility); ⊠}
å¯èŠæ§ã®ããéè·¯ããªãŒãã³ãŠã©ãŒã¿ãŒ
èŠçã¯ãã§ã«æ°Žã«åœ±é¿ãäžããŠããããã«èŠãããããããŸããããããã¯æ°Žã«æµžãããå°åœ¢ã®è¡šé¢ã«ãããŸããããŸãããªãŒãã³ãŠã©ãŒã¿ãŒã«å¯èŠæ§ãé©çšããããšããå§ããŸãããããã®ããã«å€æŽããå¿
èŠããããŸãHexGridChunk.TriangulateOpenWater
ã void TriangulateOpenWater ( HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center ) { ⊠water.AddTriangle(center, c1, c2); Vector3 indices; indices.x = indices.y = indices.z = cell.Index; water.AddTriangleCellData(indices, weights1); if (direction <= HexDirection.SE && neighbor != null) { ⊠water.AddQuad(c1, c2, e1, e2); indices.y = neighbor.Index; water.AddQuadCellData(indices, weights1, weights2); if (direction <= HexDirection.E) { ⊠water.AddTriangle( c2, e2, c2 + HexMetrics.GetWaterBridge(direction.Next()) ); indices.z = nextNeighbor.Index; water.AddTriangleCellData( indices, weights1, weights2, weights3 ); } } }
ãŸããæµ·å²žè¿ãã®äžè§åœ¢ã®ãã¡ã³ã«ã»ã«ããŒã¿ã远å ããå¿
èŠããããŸãã void TriangulateWaterShore ( HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center ) { ⊠water.AddTriangle(center, e1.v1, e1.v2); water.AddTriangle(center, e1.v2, e1.v3); water.AddTriangle(center, e1.v3, e1.v4); water.AddTriangle(center, e1.v4, e1.v5); Vector3 indices; indices.x = indices.y = indices.z = cell.Index; water.AddTriangleCellData(indices, weights1); water.AddTriangleCellData(indices, weights1); water.AddTriangleCellData(indices, weights1); water.AddTriangleCellData(indices, weights1); ⊠}
Waterã·ã§ãŒããŒã¯ãRoadã·ã§ãŒããŒãšåãæ¹æ³ã§å€æŽããå¿
èŠããããŸããã2ã€ã§ã¯ãªã3ã€ã®ã»ã«ã®å¯èŠæ§ãçµã¿åãããå¿
èŠããããŸãã #pragma surface surf Standard alpha vertex:vert #pragma target 3.0 #include "Water.cginc" #include "HexCellData.cginc" sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 worldPos; float visibility; }; ⊠void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); float4 cell2 = GetCellData(v, 2); data.visibility = cell0.x * v.color.x + cell1.x * v.color.y + cell2.x * v.color.z; data.visibility = lerp(0.25, 1, data.visibility); } void surf (Input IN, inout SurfaceOutputStandard o) { float waves = Waves(IN.worldPos.xz, _MainTex); fixed4 c = saturate(_Color + waves); o.Albedo = c.rgb * IN.visibility; ⊠}
å¯èŠæ§ã®ãããªãŒãã³ãŠã©ãŒã¿ãŒãæµ·å²žãšæ²³å£
海岞ããµããŒãããã«ã¯ãååºŠå€æŽããå¿
èŠãããHexGridChunk.TriangulateWaterShore
ãŸããæ¢ã«ã€ã³ããã¯ã¹ãã¯ãã«ãäœæããŸãããããªãŒãã³ãŠã©ãŒã¿ãŒã«ã¯1ã€ã®ã»ã«ã€ã³ããã¯ã¹ã®ã¿ã䜿çšããŸãããã³ãŒã¹ãã«ã¯ãã€ããŒã€ã³ããã¯ã¹ãå¿
èŠãªã®ã§ãã³ãŒãã倿ŽããŸãã Vector3 indices;
ã»ã«ããŒã¿ã海岞ã®åè§åœ¢ãšäžè§åœ¢ã«è¿œå ããŸãããŸããåŒã³åºãã§ã€ã³ããã¯ã¹ãæž¡ããŸãTriangulateEstuary
ã if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary( e1, e2, cell.IncomingRiver == direction, indices ); } else { ⊠waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadCellData(indices, weights1, weights2); waterShore.AddQuadCellData(indices, weights1, weights2); waterShore.AddQuadCellData(indices, weights1, weights2); waterShore.AddQuadCellData(indices, weights1, weights2); } HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { ⊠waterShore.AddTriangleUV( ⊠); indices.z = nextNeighbor.Index; waterShore.AddTriangleCellData( indices, weights1, weights2, weights3 ); }
å¿
èŠãªãã©ã¡ãŒã¿ãŒã远å TriangulateEstuary
ããæµ·å²žãšå£ã®ãããã®ã»ã«ãåŠçããŸããå£ãå°åœ¢ã§ã§ããŠãããäž¡åŽã«æµ·å²žã®2ã€ã®äžè§åœ¢ãããããšãå¿ããªãã§ãã ãããééãæ£ããé åºã§è»¢éãããããšã確èªããŠãã ããã void TriangulateEstuary ( EdgeVertices e1, EdgeVertices e2, bool incomingRiver, Vector3 indices ) { waterShore.AddTriangle(e2.v1, e1.v2, e1.v1); waterShore.AddTriangle(e2.v5, e1.v5, e1.v4); waterShore.AddTriangleUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f) ); waterShore.AddTriangleUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f) ); waterShore.AddTriangleCellData(indices, weights2, weights1, weights1); waterShore.AddTriangleCellData(indices, weights2, weights1, weights1); estuaries.AddQuad(e2.v1, e1.v2, e2.v2, e1.v3); estuaries.AddTriangle(e1.v3, e2.v2, e2.v4); estuaries.AddQuad(e1.v3, e1.v4, e2.v4, e2.v5); estuaries.AddQuadUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0f) ); estuaries.AddTriangleUV( new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(1f, 1f) ); estuaries.AddQuadUV( new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f) ); estuaries.AddQuadCellData( indices, weights2, weights1, weights2, weights1 ); estuaries.AddTriangleCellData(indices, weights1, weights2, weights2); estuaries.AddQuadCellData(indices, weights1, weights2); ⊠}
3ã€ã®ã»ã«ã®å¯èŠæ§ãæ··åããŠãWaterShoreã·ã§ãŒããŒãšWaterã·ã§ãŒããŒã«åã倿Žãå ããå¿
èŠããããŸãã #pragma surface surf Standard alpha vertex:vert #pragma target 3.0 #include "Water.cginc" #include "HexCellData.cginc" sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 worldPos; float visibility; }; ⊠void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); float4 cell2 = GetCellData(v, 2); data.visibility = cell0.x * v.color.x + cell1.x * v.color.y + cell2.x * v.color.z; data.visibility = lerp(0.25, 1, data.visibility); } void surf (Input IN, inout SurfaceOutputStandard o) { ⊠fixed4 c = saturate(_Color + max(foam, waves)); o.Albedo = c.rgb * IN.visibility; ⊠}
ã·ã£ã€ããŒæ²³å£ããã¯ã¹2ã€ã®ã»ã«ã®å¯èŠæ§ã ãã§ãªããã·ã§ãŒãéè·¯äžè¬çãªèª¬æãå·ã®UV座æšãéä¿¡ããå¿
èŠãããããã圌ã«ã¯ãã§ã«é ç¹ããã°ã©ã ããããŸãã #include "Water.cginc" #include "HexCellData.cginc" sampler2D _MainTex; struct Input { float2 uv_MainTex; float2 riverUV; float3 worldPos; float visibility; }; half _Glossiness; half _Metallic; fixed4 _Color; void vert (inout appdata_full v, out Input o) { UNITY_INITIALIZE_OUTPUT(Input, o); o.riverUV = v.texcoord1.xy; float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); o.visibility = cell0.x * v.color.x + cell1.x * v.color.y; o.visibility = lerp(0.25, 1, o.visibility); } void surf (Input IN, inout SurfaceOutputStandard o) { ⊠fixed4 c = saturate(_Color + water); o.Albedo = c.rgb * IN.visibility; ⊠}
èŠèªæ§ã®ããæµ·å²žãšæ²³å£ãå·
æåŸã«äœ¿çšããæ°Žåã¯å·ã§ããHexGridChunk.TriangulateRiverQuad
2ã€ã®ã»ã«ã®å¯èŠæ§ãç¶æã§ããããã«ãã€ã³ããã¯ã¹ãã¯ãã«ããã©ã¡ãŒã¿ãŒã«è¿œå ããã¡ãã·ã¥ã«è¿œå ããŸãã void TriangulateRiverQuad ( Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, float y, float v, bool reversed, Vector3 indices ) { TriangulateRiverQuad(v1, v2, v3, v4, y, y, v, reversed, indices); } void TriangulateRiverQuad ( Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, float y1, float y2, float v, bool reversed, Vector3 indices ) { ⊠rivers.AddQuadCellData(indices, weights1, weights2); }
TriangulateWithRiverBeginOrEnd
ã»ã«ã®äžå¿ã«åè§åœ¢ãšäžè§åœ¢ã®ããå·ã®çµç¹ãäœæããŸããããã«å¿
èŠãªã»ã«ããŒã¿ã远å ããŸãã void TriangulateWithRiverBeginOrEnd ( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { ⊠if (!cell.IsUnderwater) { bool reversed = cell.HasIncomingRiver; Vector3 indices; indices.x = indices.y = indices.z = cell.Index; TriangulateRiverQuad( m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices ); center.y = m.v2.y = m.v4.y = cell.RiverSurfaceY; rivers.AddTriangle(center, m.v2, m.v4); ⊠rivers.AddTriangleCellData(indices, weights1); } }
ãããã®ã»ã«ã€ã³ããã¯ã¹ã¯ãã§ã«å
¥ã£ãŠããTriangulateWithRiver
ã®ã§ãåŒã³åºãã§ããããæž¡ãã ãTriangulateRiverQuad
ã§ãã void TriangulateWithRiver ( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { ⊠if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad( centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed, indices ); TriangulateRiverQuad( m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices ); } }
ãŸããæ·±æµ·ã«æ³šãæ»ã«ã€ã³ããã¯ã¹ãµããŒãã远å ããŸãã void TriangulateWaterfallInWater ( Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, float y1, float y2, float waterY, Vector3 indices ) { ⊠rivers.AddQuadCellData(indices, weights1, weights2); }
ãããŠæåŸã«ãTriangulateConnection
å¿
èŠãªææšãå·ãæ»ã®æ¹æ³ã«æž¡ãããã«å€æŽããŸãã void TriangulateConnection ( HexDirection direction, HexCell cell, EdgeVertices e1 ) { ⊠if (hasRiver) { e2.v3.y = neighbor.StreamBedY; Vector3 indices; indices.x = indices.z = cell.Index; indices.y = neighbor.Index; if (!cell.IsUnderwater) { if (!neighbor.IsUnderwater) { TriangulateRiverQuad( e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f, cell.HasIncomingRiver && cell.IncomingRiver == direction, indices ); } else if (cell.Elevation > neighbor.WaterLevel) { TriangulateWaterfallInWater( e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, neighbor.WaterSurfaceY, indices ); } } else if ( !neighbor.IsUnderwater && neighbor.Elevation > cell.WaterLevel ) { TriangulateWaterfallInWater( e2.v4, e2.v2, e1.v4, e1.v2, neighbor.RiverSurfaceY, cell.RiverSurfaceY, cell.WaterSurfaceY, indices ); } } ⊠}
Riverã·ã§ãŒããŒã¯ãRoadã·ã§ãŒããŒãšåã倿Žãè¡ãå¿
èŠããããŸãã #pragma surface surf Standard alpha vertex:vert #pragma target 3.0 #include "Water.cginc" #include "HexCellData.cginc" sampler2D _MainTex; struct Input { float2 uv_MainTex; float visibility; }; ⊠void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float4 cell0 = GetCellData(v, 0); float4 cell1 = GetCellData(v, 1); data.visibility = cell0.x * v.color.x + cell1.x * v.color.y; data.visibility = lerp(0.25, 1, data.visibility); } void surf (Input IN, inout SurfaceOutputStandard o) { float river = River(IN.uv_MainTex, _MainTex); fixed4 c = saturate(_Color + river); o.Albedo = c.rgb * IN.visibility; ⊠}
å¯èŠæ§ã®ããå·ããŠããã£ããã±ãŒãžãªããžã§ã¯ããšå¯èŠæ§
çŸåšãå¯èŠæ§ã¯æé ã§çæããããã¬ã€ã³å
šäœã§æ©èœããŸããããããŸã§ã®ãšãããã¬ã€ã³ãã£ãŒãã£ã«ã¯åœ±é¿ããŸããã建ç©ãèŸ²å Žãæšã¯ãæç¶ãåãžãªã¡ããªããã§ã¯ãªãããã¬ããããäœæããããããã»ã«ã€ã³ããã¯ã¹ã远å ããããé ç¹ã«éã¿ãæ··ããããšã¯ã§ããŸããããããã®ãªããžã§ã¯ãã¯ãããã1ã€ã®ã»ã«ã«ã®ã¿å±ããŠãããããã©ã®ã»ã«ã«å±ããŠãããã倿ããå¿
èŠããããŸãããããå®è¡ã§ããå Žåã察å¿ããã»ã«ã®ããŒã¿ã«ã¢ã¯ã»ã¹ããå¯èŠæ§ãé©çšããŸãããã§ã«äžçã®XZäœçœ®ãã»ã«ã€ã³ããã¯ã¹ã«å€æã§ããŸãããã®å€æã¯ãå°åœ¢ã®ç·šéãšåéã®ç®¡çã«äœ¿çšãããŸããããã ãã察å¿ããã³ãŒãã¯éèŠã§ããæŽæ°æŒç®ã䜿çšãããšããžãæäœããããžãã¯ãå¿
èŠã§ããããã¯ã·ã§ãŒããŒã«ã¯å®çšçã§ã¯ãªããããããžãã¯ã®å€§éšåããã¯ã¹ãã£ã§ãã€ã¯åŠçããŠäœ¿çšã§ããŸãããã§ã«å
è§åœ¢ãã¿ãŒã³ã®ãã¯ã¹ãã£ã䜿çšããŠãå°åœ¢ã«ã¡ãã·ã¥ãæåœ±ããŠããŸãããã®ãã¯ã¹ãã£ã¯ã2Ã2ã®ã»ã«é åãå®çŸ©ããŸãããããã£ãŠãã©ã®é åã«ããããç°¡åã«èšç®ã§ããŸãããã®åŸããã®é åã®ã»ã«ã«Xãªãã»ãããšZãªãã»ãããå«ããã¯ã¹ãã£ãé©çšãããã®ããŒã¿ã䜿çšããŠèªåãããã»ã«ãèšç®ã§ããŸããããã¯åæ§ã®ãã¯ã¹ãã£ã§ãã Xãªãã»ããã¯èµ€ãã£ã³ãã«ã«ä¿åãããZãªãã»ããã¯ç·ãã£ã³ãã«ã«ä¿åãããŸãã 2Ã2ã»ã«ã®é åãã«ããŒããããã0ãš2ããã®ãªãã»ãããå¿
èŠã§ãããã®ãããªããŒã¿ã¯ã«ã©ãŒãã£ã³ãã«ã«ä¿åã§ããªãããããªãã»ããã¯ååã«åæžãããŸããã»ã«ã®æç¢ºãªãšããžã¯å¿
èŠãªããããå°ããªãã¯ã¹ãã£ã§ååã§ããã°ãªãã座æšã®ãã¯ã¹ãã£ããããžã§ã¯ãã«ãã¯ã¹ãã£ã远å ããŸããä»ã®ã¡ãã·ã¥ãã¯ã¹ãã£ãšåæ§ã«ãWrap ModeãRepeatã«èšå®ããŸããããã·ã³ã°ã¯å¿
èŠãªãã®ã§ããã¬ã³ãã¢ãŒãã§ã¯å€PointãéžæããŸãããŸããããŒã¿ãæªãŸãªãããã«ãå§çž®ããªãã«ããŸããsRGBã¢ãŒãããªãã«ããŠãç·åœ¢ã¢ãŒãã§ã¬ã³ããªã³ã°ãããšãã«è²ç©ºé倿ãå®è¡ãããªãããã«ããŸããæåŸã«ãããããã¯ã¹ãã£ã¯å¿
èŠãããŸããããã¯ã¹ãã£ã®ã€ã³ããŒããªãã·ã§ã³ãå¯èŠæ§ã®ãããªããžã§ã¯ãã·ã§ãŒããŒ
æ°ããæ©èœã·ã§ãŒããŒãäœæããŠããªããžã§ã¯ãã«å¯èŠæ§ãµããŒãã远å ããŸããããã¯ãé ç¹ããã°ã©ã ãåããã·ã³ãã«ãªãµãŒãã§ã¹ã·ã§ãŒããŒã§ããHexCellDataã远å ããŠãå¯èŠæ§ã€ã³ãžã±ãŒã¿ããã©ã°ã¡ã³ãããã°ã©ã ã«æž¡ããéåžžã©ãããè²ã§æ€èšããŸããããã§ã®éãã¯GetCellData
ãå¿
èŠãªã¡ãã·ã¥ããŒã¿ãååšããªããã䜿çšã§ããªãããšã§ãã代ããã«ãç§ãã¡ã«ã¯äžçã§ã®å°äœããããŸãããã ããçŸæç¹ã§ã¯ãå¯èŠæ§ã1ã®ãŸãŸã«ããŠãããŸãã Shader "Custom/Feature" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 [NoTilingOffset] _GridCoordinates ("Grid Coordinates", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows vertex:vert #pragma target 3.0 #include "../HexCellData.cginc" sampler2D _MainTex, _GridCoordinates; half _Glossiness; half _Metallic; fixed4 _Color; struct Input { float2 uv_MainTex; float visibility; }; void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float3 pos = mul(unity_ObjectToWorld, v.vertex); data.visibility = 1; } void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb * IN.visibility; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; } ENDCG } FallBack "Diffuse" }
æ°ããã·ã§ãŒããŒã䜿çšããããã«ãªããžã§ã¯ãã®ãã¹ãŠã®ãããªã¢ã«ã倿Žããã°ãªãã座æšã®ãã¯ã¹ãã£ãå²ãåœãŠãŸããã¡ãã·ã¥ãã¯ã¹ãã£ãšéœåžãã»ã«ããŒã¿ã«ã¢ã¯ã»ã¹ãã
é ç¹ããã°ã©ã ã§ã°ãªãã座æšã®ãã¯ã¹ãã£ããµã³ããªã³ã°ããã«ã¯tex2Dlod
ã4ã³ã³ããŒãã³ãã®ãã¯ã¹ãã£åº§æšãã¯ãã«ãåã³å¿
èŠã§ããæåã®2ã€ã®åº§æšã¯ãäžçã®XZäœçœ®ã§ããä»ã®2ã€ã¯ä»¥åãšåæ§ã«ãŒãã§ãã void vert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input, data); float3 pos = mul(unity_ObjectToWorld, v.vertex); float4 gridUV = float4(pos.xz, 0, 0); data.visibility = 1; }
ãã¬ã€ã³ã·ã§ãŒããŒã®ããã«ãUV座æšãã¹ãã¬ããããŠããã¯ã¹ãã£ãå
è§åœ¢ã®ã°ãªããã«å¯Ÿå¿ããæ£ããã¢ã¹ãã¯ãæ¯ã«ãªãããã«ããŸãã float4 gridUV = float4(pos.xz, 0, 0); gridUV.x *= 1 / (4 * 8.66025404); gridUV.y *= 1 / (2 * 15.0);
UV座æšå€ãåãæšãŠãããšã«ããã2Ã2ã»ã«ã®ã©ã®éšåã«ããããããããŸããããã¯ãã»ã«åº§æšã®åºç€ã圢æããŸãã float4 gridUV = float4(pos.xz, 0, 0); gridUV.x *= 1 / (4 * 8.66025404); gridUV.y *= 1 / (2 * 15.0); float2 cellDataCoordinates = floor(gridUV.xy);
çŸåšã®ã»ã«ã®åº§æšãèŠã€ããã«ã¯ããã¯ã¹ãã£ã«ä¿åãããŠããå€äœã远å ããŸãã float2 cellDataCoordinates = floor(gridUV.xy) + tex2Dlod(_GridCoordinates, gridUV).rg;
ã°ãªããã®äžéšã®ãµã€ãºã¯2Ã2ã§ããããªãã»ããã¯ååã«ãªããããçµæã2åã«ããŠæçµçãªåº§æšãååŸããå¿
èŠããããŸãã float2 cellDataCoordinates = floor(gridUV.xy) + tex2Dlod(_GridCoordinates, gridUV).rg; cellDataCoordinates *= 2;
ããã§ããããã®ã»ã«ã®UV座æšã«å€æããå¿
èŠãããã»ã«ã°ãªããã®XZ座æšãåŸãããŸãããããã¯ããã¯ã»ã«ã®äžå¿ã«ç§»åãããããããã¯ã¹ãã£ãµã€ãºã«åå²ããã ãã§å®è¡ã§ããŸãããããã£ãŠããµã³ããªã³ã°ãåŠçããHexCellDataã€ã³ã¯ã«ãŒããã¡ã€ã«ã«ãã®ããã®é¢æ°ã远å ããŸãããã float4 GetCellData (float2 cellDataCoordinates) { float2 uv = cellDataCoordinates + 0.5; uv.x *= _HexCellData_TexelSize.x; uv.y *= _HexCellData_TexelSize.y; return tex2Dlod(_HexCellData, float4(uv, 0, 0)); }
ä»ãç§ãã¡ã¯ãé ç¹ã·ã§ãŒãããã°ã©ã ã§ããã䜿çšããããšãã§ããæ©èœã cellDataCoordinates *= 2; data.visibility = GetCellData(cellDataCoordinates).x; data.visibility = lerp(0.25, 1, data.visibility);
å¯èŠæ§ãæã€ãªããžã§ã¯ããæåŸã«ãå¯èŠæ§ã¯åžžã«è¡šç€ºããããŠããããé€ãããããå
šäœã«åœ±é¿ããŸããåé ç¹ã®ãªããžã§ã¯ãã®å¯èŠæ§ã決å®ãããããã»ã«ã®å¢çãæšªåããªããžã§ã¯ãã®å Žåããããéããã»ã«ã®å¯èŠæ§ã¯æ··åãããŸãããããããªããžã§ã¯ãã¯éåžžã«å°ãããããäœçœ®ã®æªã¿ãèæ
®ããŠããåžžã«ã»ã«å
ã«æ®ããŸãããã ããäžéšã¯å¥ã®ã»ã«ã®é ç¹ã®äžéšã§ããå ŽåããããŸãããããã£ãŠãç§ãã¡ã®ã¢ãããŒãã¯å®äŸ¡ã§ãããäžå®å
šã§ããããã¯ãå£ã®å Žåã«æãé¡èã§ããããã®èŠèªæ§ã¯é£æ¥ããã»ã«ã®å¯èŠæ§ã®éã§ç°ãªããŸããèŠçãå€åããå£ãå£ã»ã°ã¡ã³ãã¯æç¶ãçã«çæããããããã»ã«ããŒã¿ãã¡ãã·ã¥ã«è¿œå ããã¬ãªãŒãã«äœ¿çšããã¢ãããŒãã䜿çšã§ããŸããæ®å¿µãªãããã¿ã¯ãŒã¯ãã¬ããã§ãããããäŸç¶ãšããŠççŸãçããŸããäžè¬çã«èšãã°ãæ¢åã®ã¢ãããŒãã¯åçŽãªãžãªã¡ããªã«ã¯ååã«èŠããŸããå°æ¥çã«ã¯ããã詳现ãªã¢ãã«ãšå£ãæ€èšããããããããã®å¯èŠæ§ãæ··åããæ¹æ³ãæ¹åããŸãããŠããã£ããã±ãŒãžããŒã21ïŒå°å³èª¿æ»
- ç·šéäžã«ãã¹ãŠã衚瀺ããŸãã
- 調æ»ããã»ã«ã远跡ããŸãã
- ãŸã ç¥ãããŠããªããã®ãé ããŸãã
- ãŠãããã«æªæ¢çŽ¢ã®ãšãªã¢ãé¿ããããã«åŒ·å¶ããŸãã
åã®ããŒãã§ã¯ãæŠäºã®é§ã远å ããŸããããããæ¹è¯ããŠãå°å³ç ç©¶ãå®è£
ããŸããç§ãã¡ã¯äžçãæ¢çŽ¢ããæºåãã§ããŠããŸããç·šéã¢ãŒãã§ãããå
šäœã衚瀺ããŸã
ãã®ç ç©¶ã®æå³ã¯ããããŸã§èŠãããªãã£ã现èã¯æªç¥ã§ãããšèŠãªããããããã£ãŠç®ã«èŠããªããšããããšã§ããããããäžæçã«ããããšã¯ã§ããŸãããã衚瀺ããããšã¯ã§ããŸããããããã£ãŠã調æ»ãµããŒãã远å ããåã«ãç·šéã¢ãŒãã§ã®å¯èŠæ§ãæå¹ã«ããŸããå¯èŠæ§ã®åãæ¿ã
ã°ãªããäžã®ãªãŒããŒã¬ã€ã§è¡ãããããã«ãããŒã¯ãŒãã䜿çšããŠã·ã§ãŒããŒãå¯èŠæ§ã䜿çšãããã©ãããå¶åŸ¡ã§ããŸããHEX_MAP_EDIT_MODEããŒã¯ãŒãã䜿çšããŠãç·šéã¢ãŒãã®ç¶æ
ã瀺ããŸããããããã€ãã®ã·ã§ãŒããŒã¯ãã®ããŒã¯ãŒããç¥ã£ãŠããå¿
èŠããããããéçã¡ãœããShader.EnableKeyWord
ãšã䜿çšããŠã°ããŒãã«ã«å®çŸ©ããŸãShader.DisableKeyword
ãHexGameUI.SetEditMode
ç·šéã¢ãŒãã倿Žãããšãã«é©åãªã¡ãœãããåŒã³åºããŸãã public void SetEditMode (bool toggle) { enabled = !toggle; grid.ShowUI(!toggle); grid.ClearPath(); if (toggle) { Shader.EnableKeyword("HEX_MAP_EDIT_MODE"); } else { Shader.DisableKeyword("HEX_MAP_EDIT_MODE"); } }
ç·šéã¢ãŒãã·ã§ãŒããŒ
HEX_MAP_EDIT_MODEãå®çŸ©ãããŠããå Žåãã·ã§ãŒããŒã¯å¯èŠæ§ãç¡èŠããŸããããã¯ãã»ã«ã®å¯èŠæ§ãåžžã«1ãšèŠãªããããšããäºå®ã«èŠçŽãããŸããHexCellData include-fileã®å
é ã«ããããŒã¯ãŒãã«å¿ããŠãã»ã«ã®ããŒã¿ããã£ã«ã¿ãŒãã颿°ã远å ããŸãããã sampler2D _HexCellData; float4 _HexCellData_TexelSize; float4 FilterCellData (float4 data) { #if defined(HEX_MAP_EDIT_MODE) data.x = 1; #endif return data; }
äž¡æ¹ã®é¢æ°ã®çµæãGetCellData
è¿ãåã«ããã®é¢æ°ãééãããŸãã float4 GetCellData (appdata_full v, int index) { ⊠return FilterCellData(data); } float4 GetCellData (float2 cellDataCoordinates) { ⊠return FilterCellData(tex2Dlod(_HexCellData, float4(uv, 0, 0))); }
ãã¹ãŠãæ©èœããããã«ã¯ãHEX_MAP_EDIT_MODEããŒã¯ãŒããå®çŸ©ãããŠããå Žåã«ãé¢é£ãããã¹ãŠã®ã·ã§ãŒããŒãmulti_compileãã£ã¬ã¯ãã£ããåãåã£ãŠãªãã·ã§ã³ãäœæããå¿
èŠããããŸããã¿ãŒã²ãããã£ã¬ã¯ãã£ããšæåã®includeãã£ã¬ã¯ãã£ãã®éã®ã·ã§ãŒããŒæ²³å£ããã£ãŒãã£ãŒãå·ãéè·¯ãå°åœ¢ãæ°Žãããã³æ°ŽèŸºã«é©åãªã©ã€ã³ã远å ããŸãã #pragma multi_compile _ HEX_MAP_EDIT_MODE
ããã§ããããç·šéã¢ãŒãã«åãæ¿ãããšãæŠäºã®é§ãæ¶ããŸãããŠããã£ããã±ãŒãžçްèç ç©¶
ããã©ã«ãã§ã¯ãã»ã«ã¯æªæ¢çŽ¢ãšèŠãªãããå¿
èŠããããŸããéšéã圌ããèŠããšã圌ãã¯æ¢æ€ãããŸãããã®åŸãåé£éãããããèŠãããšãã§ããå Žåã圌ãã¯èª¿æ»ããç¶ããŸãã远跡調æ»ã¹ããŒã¿ã¹
ç ç©¶ã®ã¹ããŒã¿ã¹ãç£èŠããããã®ãµããŒãã远å ããããã«ãHexCell
äžè¬ããããã£ã«è¿œå ããŸãIsExplored
ã public bool IsExplored { get; set; }
ç ç©¶ã®ç¶æ
ã¯ãã»ã«èªäœã«ãã£ãŠæ±ºå®ãããŸãããããã£ãŠããã®ããããã£ã¯ã®ã¿èšå®ããå¿
èŠããããŸãHexCell
ããã®ãããªå¶éã远å ããã«ã¯ãã»ãã¿ãŒããã©ã€ããŒãã«èšå®ããŸãã public bool IsExplored { get; private set; }
ã»ã«ã®å¯èŠæ§ãåããŠãŒããã倧ãããªããšãã»ã«ã¯èª¿æ»å¯Ÿè±¡ãšèŠãªãããããã«ãªãããIsExplored
ãå€ãå²ãåœãŠãå¿
èŠããããŸãtrue
ãå®éãå¯èŠæ§ã1ã«å¢å ãããšãã«ãã»ã«ãæ€æ»æžã¿ãšããŠããŒã¯ããã ãã§ååã§ããããã¯ãåŒã³åºãã®åã«è¡ãå¿
èŠããããŸãRefreshVisibility
ã public void IncreaseVisibility () { visibility += 1; if (visibility == 1) { IsExplored = true; ShaderData.RefreshVisibility(this); } }
ç ç©¶ç¶æ
ãã·ã§ãŒããŒã«è»¢éãã
ã»ã«ã®å¯èŠæ§ã®å Žåãšåæ§ã«ãã·ã§ãŒããŒããŒã¿ãéããŠã·ã§ãŒããŒã«ç ç©¶ç¶æ
ãæž¡ããŸããçµå±ãããã¯åãªãå¥ã®ã¿ã€ãã®å¯èŠæ§ã§ããHexCellShaderData.RefreshVisibility
ããŒã¿ãã£ãã«Rã«å¯èŠæ§ç¶æ
ãä¿åããŸãããã£ã³ãã«GããŒã¿ã§èª¿æ»ã®ç¶æ
ãä¿æããŸãããã public void RefreshVisibility (HexCell cell) { int index = cell.Index; cellTextureData[index].r = cell.IsVisible ? (byte)255 : (byte)0; cellTextureData[index].g = cell.IsExplored ? (byte)255 : (byte)0; enabled = true; }
é»ã®æªèžã®ææž
ããã§ãã·ã§ãŒããŒã䜿çšããŠçްèç ç©¶ã®ç¶æ
ãèŠèŠåã§ããŸãããã¹ãŠãæ£åžžã«æ©èœããããšã確èªããããã«ãæªæ¢çŽ¢ã®å°åœ¢ãé»ã«ããŸããããããæåã«ãç·šéã¢ãŒããæ©èœãããFilterCellData
ããã«ãç ç©¶ããŒã¿ãé€å€ããããã«å€æŽããŸãã float4 FilterCellData (float4 data) { #if defined(HEX_MAP_EDIT_MODE) data.xy = 1; #endif return data; }
ãã¬ã€ã³ã·ã§ãŒããŒã¯ã3ã€ã®ã»ã«ãã¹ãŠã®å¯èŠæ§ããŒã¿ããã©ã°ã¡ã³ãããã°ã©ã ã«æž¡ããŸããç ç©¶ç¶æ
ã®å Žåãé ç¹ããã°ã©ã ã§ããããçµã¿åãããŠãå¯äžã®å€ããã©ã°ã¡ã³ãããã°ã©ã ã«è»¢éããŸããvisibility
ãã®å Žæã確ä¿ããããã«ã4çªç®ã®ã³ã³ããŒãã³ããå
¥åã«è¿œå ããŸãã struct Input { float4 color : COLOR; float3 worldPos; float3 terrain; float4 visibility; };
é ç¹ããã°ã©ã ã§ã¯ãå¯èŠæ§ã€ã³ããã¯ã¹ã倿Žãããšãã«ãæç€ºçã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸãdata.visibility.xyz
ã void vert (inout appdata_full v, out Input data) { ⊠data.visibility.xyz = lerp(0.25, 1, data.visibility.xyz); }
ãã®åŸã調æ»ã®ç¶æ
ãçµã¿åãããŠãçµæãã«æžã蟌ã¿data.visibility.w
ãŸããããã¯ãä»ã®ã·ã§ãŒããŒã§å¯èŠæ§ãçµã¿åãããããšãšåæ§ã§ããããããã®ã»ã«ã®ã³ã³ããŒãã³ãYã䜿çšããŸãã data.visibility.xyz = lerp(0.25, 1, data.visibility.xyz); data.visibility.w = cell0.y * v.color.x + cell1.y * v.color.y + cell2.y * v.color.z;
çŸåšããã©ã°ã¡ã³ãããã°ã©ã ã§ç ç©¶ã¹ããŒã¿ã¹ãå©çšã§ããŸãIN.visibility.w
ãã¢ã«ããã®èšç®ã§èæ
®ããŠãã ããã void surf (Input IN, inout SurfaceOutputStandard o) { ⊠float explored = IN.visibility.w; o.Albedo = c.rgb * grid * _Color * explored; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; }
æªæ¢çŽ¢ã®å°åœ¢ã¯é»ã«ãªããŸãããæªæ¢çŽ¢ã®çްèã®æµ®ã圫ãã¯é»è²ã«ãªããŸãããããããããã¯ãŸã ãªããžã§ã¯ããéè·¯ãæ°Žã«åœ±é¿ããŠããŸããããã ããããã¯èª¿æ»ãæ©èœããããšã確èªããã®ã«ååã§ããç ç©¶ã¹ããŒã¿ã¹ã®ä¿åãšèªã¿èŸŒã¿
調æ»ãµããŒãã远å ããã®ã§ãããããä¿åããã³ããŒããããšãã«èª¿æ»ã¹ããŒã¿ã¹ãèæ
®ãããããã«ããå¿
èŠããããŸãããããã£ãŠãããããã¡ã€ã«ã®ããŒãžã§ã³ã3ã«å¢ããå¿
èŠããããŸãããããã®å€æŽããã䟿å©ã«ããSaveLoadMenu
ããã«ããã®å®æ°ã远å ããŸãããã const int mapFileVersion = 3;
ã«ãã¡ã€ã«ããŒãžã§ã³ãæžã蟌ããšããSave
ããã³ãã¡ã€ã«ãµããŒãããã§ãã¯ãããšãã«ããã®å®æ°ã䜿çšãLoad
ãŸãã void Save (string path) { using ( BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)) ) { writer.Write(mapFileVersion); hexGrid.Save(writer); } } 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 <= mapFileVersion) { hexGrid.Load(reader, header); HexMapCamera.ValidatePosition(); } else { Debug.LogWarning("Unknown map format " + header); } } }
æåŸã®ã¹ããããšããŠHexCell.Save
ã調æ»ã®ã¹ããŒã¿ã¹ãèšé²ããŸãã public void Save (BinaryWriter writer) { ⊠writer.Write(IsExplored); }
ãããŠãæåŸã«ãããèªã¿ãŸãLoad
ããã®åŸRefreshVisibility
ã調æ»ã®ç¶æ
ãåã®ãã®ãšç°ãªãå Žåã«åŒã³åºããŸãã public void Load (BinaryReader reader) { ⊠IsExplored = reader.ReadBoolean(); ShaderData.RefreshVisibility(this); }
å€ãä¿åãã¡ã€ã«ãšã®åŸæ¹äºææ§ãç¶æããããã«ããã¡ã€ã«ããŒãžã§ã³ã3æªæºã®å Žåãä¿åç¶æ
ã®èªã¿åããã¹ãããããå¿
èŠããããŸãããã®å Žåãããã©ã«ãã§ã¯ãã»ã«ã®ç¶æ
ã¯ãæªæ¢çŽ¢ãã«ãªããŸãããããè¡ãã«ã¯ããã©ã¡ãŒã¿ãŒãšããŠLoad
ããããŒããŒã¿ã远å ããå¿
èŠããããŸãã public void Load (BinaryReader reader, int header) { ⊠IsExplored = header >= 3 ? reader.ReadBoolean() : false; ShaderData.RefreshVisibility(this); }
次ã«HexGrid.Load
ãHexCell.Load
ããããŒããŒã¿ãæž¡ãå¿
èŠããããŸãã public void Load (BinaryReader reader, int header) { ⊠for (int i = 0; i < cells.Length; i++) { cells[i].Load(reader, header); } ⊠}
ããã§ãããããä¿åããã³ããŒããããšãã«ãã»ã«ã®æ¢çŽ¢ç¶æ
ãèæ
®ãããŸãããŠããã£ããã±ãŒãžäžæãªã»ã«ãé衚瀺
çŸåšã®æ®µéã§ã¯ãæªæ¢çŽ¢ã®ã»ã«ã¯é»ãæµ®ã圫ãã§èŠèŠçã«ç€ºãããŸããããããå®éã«ã¯ããããã®ã»ã«ã¯äžæã§ããããç®ã«èŠããªãããã«ããŸããäžéæãªãžãªã¡ããªãéæã«ããŠã衚瀺ãããªãããã«ããããšãã§ããŸãããã ããUnityãµãŒãã§ã¹ã·ã§ãŒããŒãã¬ãŒã ã¯ãŒã¯ã¯ããã®å¯èœæ§ãèæ
®ããã«èšèšãããŸãããçã®éæåºŠã䜿çšãã代ããã«ãã·ã§ãŒããŒãèæ¯ã«åãããŠå€æŽããŸããããã«ãããã·ã§ãŒããŒãé衚瀺ã«ãªããŸããã¬ãªãŒããæ¬åœã«é»ã«ãã
調æ»ããã¬ãªãŒãã¯é»ã§ããããŸã é¡é¢åå°å
ããããããèªèã§ããŸããç
§æãåãé€ãã«ã¯ãå®å
šã«ããããªé»ã«ããå¿
èŠããããŸããä»ã®è¡šé¢ç¹æ§ã«åœ±é¿ãäžããªãããã«ãé¡é¢åå°è²ãé»ã«å€æŽããã®ãæãç°¡åã§ããããã¯ãé¡é¢åå°ã§åäœãããµãŒãã§ã¹ã·ã§ãŒããŒã䜿çšããå Žåã«å¯èœã§ãããçŸåšã¯æšæºã®ã¡ã¿ãªãã¯ã䜿çšããŠããŸããããã§ã¯ããã¬ã€ã³ã·ã§ãŒããŒãã¹ããã¥ã©ãŒã«åãæ¿ããŠã¿ãŸããããã«ã©ãŒããããã£ã«çœ®ãæã_Metallicãããããã£ã«_Specularãããã©ã«ãã§ã¯ãè²ã®å€ã¯ïŒ0.2ã0.2ã0.2ïŒã«çãããªããã°ãªããŸããããããã£ãŠãã¡ã¿ãªãã¯ããŒãžã§ã³ã®å€èгãšäžèŽããããšãä¿èšŒããŸãã Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Terrain Texture Array", 2DArray) = "white" {} _GridTex ("Grid Texture", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 // _Metallic ("Metallic", Range(0,1)) = 0.0 _Specular ("Specular", Color) = (0.2, 0.2, 0.2) }
ãŸãã察å¿ããã·ã§ãŒããŒå€æ°ã倿ŽããŸããé¡é¢ãµãŒãã§ã¹ã·ã§ãŒãã®è²ã¯ãšããŠå®çŸ©ãããŠããfixed3
ã®ã§ãããã䜿çšããŸãããã half _Glossiness;
å€åãã©ã°ã衚é¢ãµãŒãæšæºã®StandardSpecularãããã«ãããUnityã¯ã¹ããã¥ã©ãŒã䜿çšããŠã·ã§ãŒããŒãçæããŸãã #pragma surface surf StandardSpecular fullforwardshadows vertex:vert
ããã§ã颿°surf
ã¯2çªç®ã®ãã©ã¡ãŒã¿ãŒã®åãå¿
èŠSurfaceOutputStandardSpecular
ã§ããããã«ãã§ã¯ãªão.Metallic
ãã§ã¯ãªãå€ãå²ãåœãŠãå¿
èŠããão.Specular
ãŸãã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { ⊠float explored = IN.visibility.w; o.Albedo = c.rgb * grid * _Color * explored; // o.Metallic = _Metallic; o.Specular = _Specular; o.Smoothness = _Glossiness; o.Alpha = ca; }
explored
é¡é¢åå°è²ãèæ
®ããããšã«ããããã€ã©ã€ããäžæçã«ããããšãã§ããŸãã o.Specular = _Specular * explored;
åå°ç
§æã®ãªãæªèžã®å°åœ¢ãåçã§ãããããã«ãæªæ¢çŽ¢ã®ã¬ãªãŒãã¯ãããã é»ã«èŠããŸãããã ããæ¥ç·è§åºŠã§èŠããšã衚é¢ã¯é¡ã«å€ãããŸãããã®ãããã¬ãªãŒãã¯ç°å¢ãã€ãŸãã¹ã«ã€ããã¯ã¹ãåæ ãå§ããŸãã衚é¢ãé¡ã«ãªãã®ã¯ãªãã§ããïŒ æªéæã®å°åã¯ãŸã ç°å¢ãåæ ããŠããŸãããããã®åå°ãåãé€ãããã«ãæªæ¢çŽ¢ã®æµ®ã圫ããå®å
šã«é°åœ±ä»ããããŠããããšãèæ
®ããŸããããã¯explored
ãåå°ãã¹ã¯ãšããŠäœ¿çšãããªã¯ã«ãŒãžã§ã³ãã©ã¡ãŒã¿ãŒã«å€ãå²ãåœãŠãããšã§å®çŸãããŸãã float explored = IN.visibility.w; o.Albedo = c.rgb * grid * _Color * explored; o.Specular = _Specular * explored; o.Smoothness = _Glossiness; o.Occlusion = explored; o.Alpha = ca;
åå°ã®ãªãæªèžãäžèŽããèæ¯
æªæ¢çŽ¢ã®å°åœ¢ã¯ãã¹ãŠã®ç
§æãç¡èŠããããã«ãªã£ãã®ã§ãèæ¯ãšäžèŽãããå¿
èŠããããŸããã«ã¡ã©ã¯åžžã«äžããèŠãããããèæ¯ã¯åžžã«ç°è²ã§ãã䜿çšããè²ããã¬ã€ã³ã·ã§ãŒããŒã«æç€ºããã«ã¯ã_BackgroundColorããããã£ã远å ããŸããããã©ã«ãã¯é»ã§ãã Properties { ⊠_BackgroundColor ("Background Color", Color) = (0,0,0) } ⊠half _Glossiness; fixed3 _Specular; fixed4 _Color; half3 _BackgroundColor;
ãã®è²ã䜿çšããã«ã¯ãçºå
è²ãšããŠè¿œå ããŸããããã¯o.Emission
ãæ¢çŽ¢ããããã€ãã¹1ãæããèæ¯è²ã®å€ãå²ãåœãŠãããšã«ãã£ãŠå®çŸãããŸãã o.Occlusion = explored; o.Emission = _BackgroundColor * (1 - explored);
ããã©ã«ãã®ã¹ã«ã€ããã¯ã¹ã䜿çšããŠããããã衚瀺ãããèæ¯è²ã¯å®éã«ã¯åãã§ã¯ãããŸãããäžè¬ã«ããããã«èµ€ã¿ããã£ãç°è²ãæé©ãªè²ã«ãªããŸããã¬ãªãŒããããªã¢ã«ãèšå®ãããšãã¯ãHex Colorã«ã³ãŒã68615BFF ã䜿çšã§ããŸããç°è²ã®èæ¯è²ã®ã¬ãªãŒãçŽ æãäžè¬çã«ã¯åäœããŸãããã©ããèŠãã¹ããç¥ã£ãŠããã°ãéåžžã«åŒ±ãã·ã«ãšããã«æ°ã¥ãã§ãããããã¬ãŒã€ãŒãããããèŠãããšãã§ããªãããã«ãã¹ã«ã€ããã¯ã¹ã®ä»£ããã«68615BFFã®åäžãªèæ¯è²ãã«ã¡ã©ã«å²ãåœãŠãããšãã§ããŸããåäžãªèæ¯è²ã®ã«ã¡ã©ãã¹ã«ã€ããã¯ã¹ãåé€ããŠã¿ãŸãããïŒ, , environmental lighting . , .
ããã§ãèæ¯ã®ã»ã«ãšæªæ¢çŽ¢ã®ã»ã«ãåºå¥ã§ããªããªããŸãããé«ãæªæ¢æ»ã®å°åœ¢ã¯ãäœãã«ã¡ã©ã¢ã³ã°ã«ã§ã®äœã調æ»å°åœ¢ãäŸç¶ãšããŠäžæçã«ããå¯èœæ§ããããŸããããã«ãæªæ¢çŽ¢ã®ããŒãã¯ãŸã æ¢çŽ¢ãããéšåã«åœ±ãèœãšããŸãããããããããã®æå°éã®æãããã¯ç¡èŠã§ããŸããæªæ¢çŽ¢ã®ã»ã«ã¯è¡šç€ºãããªããªããŸãããåäžãªèæ¯è²ã䜿çšããªãå Žåã¯ã©ããªããŸããïŒ, , . . , . , , , UV- .
ã¬ãªãŒããªããžã§ã¯ããé ã
ããã§ãã¬ãªãŒãã®ã¡ãã·ã¥ã®ã¿ãé衚瀺ã«ãªããŸãããç ç©¶ã®æ®ãã®ç¶æ
ã¯ãŸã 圱é¿ãåããŠããŸããããããŸã§ã®ãšãããå®reliefã ããé ãããŠããŸãã Terrainã®ãããªäžéæãªã·ã§ãŒããŒã§ããFeatureã·ã§ãŒããŒã倿ŽããŸãããããããé¡é¢ã·ã§ãŒããŒã«å€ããŠãèæ¯è²ã远å ããŸããããããã£ããå§ããŸãããã Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 // _Metallic ("Metallic", Range(0,1)) = 0.0 _Specular ("Specular", Color) = (0.2, 0.2, 0.2) _BackgroundColor ("Background Color", Color) = (0,0,0) [NoScaleOffset] _GridCoordinates ("Grid Coordinates", 2D) = "white" {} }
åãšåãããã«ã次ã®ãã©ã°ããµãŒãã§ã¹ãšå€æ°ã #pragma surface surf StandardSpecular fullforwardshadows vertex:vert ⊠half _Glossiness;
visibility
ãã1ã€ã®ã³ã³ããŒãã³ããå¿
èŠã§ããã®ã§æ©èœã¯åé ç¹ã®ããã®å¯èŠæ§ãå
Œãåããã圌ã¯äžã€ã®å€ã ããããŒããå¿
èŠãšããŠããŸãããããã§2ã€å¿
èŠã§ãã struct Input { float2 uv_MainTex; float2 visibility; };
vert
å¯èŠæ§ããŒã¿ãæç€ºçã«äœ¿çšããããã«å€æŽããŠããdata.visibility.x
ãdata.visibility.y
å€ãã¹ã¿ãã£ããŒã¿ã«å²ãåœãŠãŸãã void vert (inout appdata_full v, out Input data) { ⊠float4 cellData = GetCellData(cellDataCoordinates); data.visibility.x = cellData.x; data.visibility.x = lerp(0.25, 1, data.visibility.x); data.visibility.y = cellData.y; }
Terrainã®surf
ãããªæ°ããããŒã¿ã䜿çšããããã«å€æŽããŸãã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; float explored = IN.visibility.y; o.Albedo = c.rgb * (IN.visibility.x * explored); // o.Metallic = _Metallic; o.Specular = _Specular * explored; o.Smoothness = _Glossiness; o.Occlusion = explored; o.Emission = _BackgroundColor * (1 - explored); o.Alpha = ca; }
é衚瀺ã®ã¬ãªãŒããªããžã§ã¯ããæ°Žãé ã
次ã¯ãŠã©ãŒã¿ãŒã·ã§ãŒããŒãšãŠã©ãŒã¿ãŒã·ã§ã¢ã·ã§ãŒããŒã§ããããããã¹ããã¥ã©ãŒã·ã§ãŒããŒã«å€æããããšããå§ããŸãããããã ããéæãªã·ã§ãŒããŒã§ãããããèæ¯è²ã¯å¿
èŠãããŸããã倿åŸãvisibility
ãã1ã€ã®ã³ã³ããŒãã³ãã远å ããããã«å¿ããŠå€æŽãvert
ãŸããäž¡æ¹ã®ã·ã§ãŒããŒã¯ã3ã€ã®ã»ã«ããã®ããŒã¿ãçµåããŸãã struct Input { ⊠float2 visibility; }; ⊠void vert (inout appdata_full v, out Input data) { ⊠data.visibility.x = cell0.x * v.color.x + cell1.x * v.color.y + cell2.x * v.color.z; data.visibility.x = lerp(0.25, 1, data.visibility.x); data.visibility.y = cell0.y * v.color.x + cell1.y * v.color.y + cell2.y * v.color.z; }
WaterãšWater Shoreã¯surf
ç°ãªãæäœãå®è¡ããŸããã衚é¢ã®ããããã£ãåãããã«èšå®ããŸããéæãªã®ã§explore
ãã¢ã«ãã¡ãã£ã³ãã«ãèæ
®ããæŸåºãèšå®ããŸããã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { ⊠float explored = IN.visibility.y; o.Albedo = c.rgb * IN.visibility.x; o.Specular = _Specular * explored; o.Smoothness = _Glossiness; o.Occlusion = explored; o.Alpha = ca * explored; }
é ãããæ°Žãæ²³å£ãå·ãéè·¯ãé ã
ç§ãã¡ã¯ãã·ã§ãŒãæ»åšæ²³å£ãæ²³å·ãšéè·¯ã®äžè¬çãªèª¬æãã3ã€ã¯ãã¹ãŠééçã§ããã2ã€ã®ã»ã«ã®ããŒã¿ãçµåããŸãããããããã¹ãŠé¡é¢åå°ã«åãæ¿ããŠãããvisibility
ç ç©¶ããŒã¿ã«è¿œå ããŸãã struct Input { ⊠float2 visibility; }; ⊠void vert (inout appdata_full v, out Input data) { ⊠data.visibility.x = cell0.x * v.color.x + cell1.x * v.color.y; data.visibility.x = lerp(0.25, 1, data.visibility.x); data.visibility.y = cell0.y * v.color.x + cell1.y * v.color.y; }
æ°ããããŒã¿ã䜿çšããããã«ãæ²³å£ããã³å·surf
ã·ã§ãŒããŒã®æ©èœã倿ŽããŸããã©ã¡ããåã倿Žãè¡ãå¿
èŠããããŸãã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { ⊠float explored = IN.visibility.y; fixed4 c = saturate(_Color + water); o.Albedo = c.rgb * IN.visibility.x; o.Specular = _Specular * explored; o.Smoothness = _Glossiness; o.Occlusion = explored; o.Alpha = ca * explored; }
Shader Roadã¯ã远å ã®æ··åã¡ããªãã¯ã䜿çšãããããå°ãç°ãªããŸãã void surf (Input IN, inout SurfaceOutputStandardSpecular o) { float4 noise = tex2D(_MainTex, IN.worldPos.xz * 0.025); fixed4 c = _Color * ((noise.y * 0.75 + 0.25) * IN.visibility.x); float blend = IN.uv_MainTex.x; blend *= noise.x + 0.5; blend = smoothstep(0.4, 0.7, blend); float explored = IN.visibility.y; o.Albedo = c.rgb; o.Specular = _Specular * explored; o.Smoothness = _Glossiness; o.Occlusion = explored; o.Alpha = blend * explored; }
ãã¹ãŠãé ãããŠããŸãããŠããã£ããã±ãŒãžæªæ¢çŽ¢ã®ã»ã«ã®åé¿
æªç¥ã®ãã®ã¯ãã¹ãŠèŠèŠçã«é ãããŠããŸããããã¹ãæ€çŽ¢ããéã«èª¿æ»ã®ç¶æ
ã¯èæ
®ãããŸããããã®çµæããŠãããã¯æªæ¢çŽ¢ã®ã»ã«ãç§»åããããã«åœä»€ãããéæ³ã®ããã«ç§»åããæ¹æ³ã決å®ã§ããŸããæªæ¢çŽ¢ã®ã»ã«ãé¿ããããã«ãŠãããã匷å¶ããå¿
èŠããããŸããæªæ¢çŽ¢ã®ã»ã«ãããã²ãŒãããŸããåéãç§»åã³ã¹ããæ±ºå®ãã
æªèžã®çްèå
ã«å
¥ãåã«ãã®ã¯ãã³ã¹ãã®åãã«è»¢éããããã®ã³ãŒããæçŽãããŸãããHexGrid
ã§ã¯HexUnit
ãããã«ãããç°ãªãç§»åã«ãŒã«ãæã€ãŠãããã®ãµããŒããç°¡çŽ åãããŸããäžè¬çãªæ¹æ³ã«è¿œå ããŠãç§»åã®ã³ã¹ããæ±ºå®ããŸãã圌ã¯ã©ã®çްèã现èéãç§»åããŠãããããŸãæ¹åãç¥ãå¿
èŠããããŸãããã®ã¡ãœããã«ç§»è¡ããã³ã¹ãã®å¯Ÿå¿ããã³ãŒããã³ããŒãã倿°ã®ååã倿ŽããŸããHexUnit
GetMoveCost
HexGrid.Search
public int GetMoveCost ( HexCell fromCell, HexCell toCell, HexDirection direction) { HexEdgeType edgeType = fromCell.GetEdgeType(toCell); if (edgeType == HexEdgeType.Cliff) { continue; } int moveCost; if (fromCell.HasRoadThroughEdge(direction)) { moveCost = 1; } else if (fromCell.Walled != toCell.Walled) { continue; } else { moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost += toCell.UrbanLevel + toCell.FarmLevel + toCell.PlantLevel; } }
ã¡ãœããã¯ç§»åã®ã³ã¹ããè¿ãå¿
èŠããããŸããå€ãã³ãŒãã䜿çšããŠç¡å¹ãªç§»åãã¹ãããããŸãããcontinue
ããã®ã¢ãããŒãã¯ããã§ã¯æ©èœããŸãããç§»åãäžå¯èœãªå Žåã¯ãç§»åã®è² ã®ã³ã¹ããè¿ããŸãã public int GetMoveCost ( HexCell fromCell, HexCell toCell, HexDirection direction) { HexEdgeType edgeType = fromCell.GetEdgeType(toCell); if (edgeType == HexEdgeType.Cliff) { return -1; } int moveCost; if (fromCell.HasRoadThroughEdge(direction)) { moveCost = 1; } else if (fromCell.Walled != toCell.Walled) { return -1; } else { moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost += toCell.UrbanLevel + toCell.FarmLevel + toCell.PlantLevel; } return moveCost; }
ããã§ãé床ã ãã§ãªããéžæãããŠãããããã¹ãèŠã€ãããšãã«ç¥ãå¿
èŠããããŸããããã«å¿ããŠå€æŽãHexGameUI.DoPathFinding
ãŸãã void DoPathfinding () { if (UpdateCurrentCell()) { if (currentCell && selectedUnit.IsValidDestination(currentCell)) { grid.FindPath(selectedUnit.Location, currentCell, selectedUnit); } else { grid.ClearPath(); } } }
ããŒã ã®ã¹ããŒãã«ã¢ã¯ã»ã¹ããå¿
èŠããããããHexUnit
ããããã£ã«è¿œå ããŸãSpeed
ãäžæ¹ã24ã®å®æ°å€ãè¿ããŸãã public int Speed { get { return 24; } }
HexGrid
倿ŽFindPath
ããããŠSearch
ã圌ãã¯ç§ãã¡ã®æ°ããã¢ãããŒãã§äœæ¥ã§ããããã«ããŸãã public void FindPath (HexCell fromCell, HexCell toCell, HexUnit unit) { ClearPath(); currentPathFrom = fromCell; currentPathTo = toCell; currentPathExists = Search(fromCell, toCell, unit); ShowPath(unit.Speed); } bool Search (HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; ⊠}
次ã«Search
ãæ¬¡ã®ã»ã«ã«ç§»åã§ãããã©ãããããã³ç§»åã®ã³ã¹ããæ±ºå®ããå€ãã³ãŒãããåé€ããŸãã代ããã«ããããåŒã³åºãããŸãHexUnit.IsValidDestination
ãšHexUnit.GetMoveCost
ãç§»åã³ã¹ããè² ã®å Žåãã»ã«ãã¹ãããããŸãã for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; }
æªæ¢çŽ¢ã®ãšãªã¢ããã€ãã¹ãã
æªæ¢çŽ¢ã®ã»ã«ãé¿ããããã«å¿
èŠãªããšã¯HexUnit.IsValidDestination
ãã»ã«ãæ€æ»ããããã©ããã確èªããããšã ãã§ãã public bool IsValidDestination (HexCell cell) { return cell.IsExplored && !cell.IsUnderwater && !cell.Unit; }
ããå€ãã®ãŠããããæªæ¢çŽ¢ã®ã»ã«ã«å°éããããšã¯ã§ããŸãããæªæ¢çŽ¢ã®ã»ã«ã¯æå¹ãªãšã³ããã€ã³ãã§ã¯ãªããããåéã¯ãšã³ããã€ã³ãã«ç§»åãããšãã«ããããåé¿ããŸããã€ãŸããæªéæã®ãšãªã¢ã¯éå£ãšããŠæ©èœããçµè·¯ãå»¶é·ããããäžå¯èœã«ãããããããšãããããŸããæåã«ãšãªã¢ãæ¢çŽ¢ããã«ã¯ããŠããããæªç¥ã®å°åœ¢ã«è¿ã¥ããå¿
èŠããããŸããç§»åäžã«çããã¹ã衚瀺ããããã©ããªããŸããïŒ. , . .
, , . , .
ãŠããã£ããã±ãŒãžããŒã22ïŒå¯èŠæ§ã®åŒ·å
- å¯èŠæ§ãã¹ã ãŒãºã«å€æŽããŸãã
- ã»ã«ã®é«ãã䜿çšããŠç¯å²ã決å®ããŸãã
- ãããã®ç«¯ãé衚瀺ã«ããŸãã
å°å³æ¢çŽ¢ã®ãµããŒãã远å ããããšã«ãããèšç®ãšå¯èŠæ§ã®é·ç§»ãæ¹åããŸããããã«èŠãã«ã¯ãé«ãç»ããŸããå¯èŠæ§ã®é·ç§»
ã»ã«ã¯ãåãé¢ãã®ç¯å²å
ã«ãããã©ããã«ãã£ãŠã衚瀺ãŸãã¯é衚瀺ã«ãªããŸãããŠããããã»ã«éãç§»åããã®ã«æéãå¿
èŠãšæãããå Žåã§ãããã®èŠéã¯ã»ã«ããã»ã«ãžç¬æã«ãžã£ã³ãããŸãããã®çµæãåšå²ã®ã»ã«ã®å¯èŠæ§ãåçã«å€åããŸããåéã®åãã¯ã¹ã ãŒãºã«èŠããŸãããèŠçã®å€åã¯çªç¶ã§ããçæ³çã«ã¯ãå¯èŠæ§ãã¹ã ãŒãºã«å€åããã¯ãã§ãããã£ããèŠéã«å
¥ããšã现èã¯åŸã
ã«ç
§ãããããããæ®ããŠãåŸã
ã«æããªããŸãããããšããã€ã³ã¹ã¿ã³ããã©ã³ãžã·ã§ã³ã奜ãã§ããããïŒHexCellShaderData
ã€ã³ã¹ã¿ã³ããã©ã³ãžã·ã§ã³ãåãæ¿ããããããã£ã«è¿œå ããŸããããããã©ã«ãã§ã¯ãç§»è¡ã¯ã¹ã ãŒãºã«ãªããŸãã public bool ImmediateMode { get; set; }
é·ç§»ã»ã«ã®è¿œè·¡
ã¹ã ãŒãºãªé·ç§»ã衚瀺ããå Žåã§ããçã®å¯èŠæ§ããŒã¿ã¯äŸç¶ãšããŠãã€ããªã®ãŸãŸã§ããã€ãŸãã广ã¯èŠèŠçãªãã®ã«ãããŸãããããã¯ãå¯èŠæ§ã®é·ç§»ãåŠçããå¿
èŠãããããšãæå³ãHexCellShaderData
ãŸããé·ç§»ãå®è¡ãããã»ã«ã®ãªã¹ããæäŸããŸããååæåã§ç©ºã§ããããšã確èªããŠãã ããã using System.Collections.Generic; using UnityEngine; public class HexCellShaderData : MonoBehaviour { Texture2D cellTexture; Color32[] cellTextureData; List<HexCell> transitioningCells = new List<HexCell>(); public bool ImmediateMode { get; set; } public void Initialize (int x, int z) { ⊠transitioningCells.Clear(); enabled = true; } ⊠}
çŸæç¹ã§ã¯ãã»ã«ããŒã¿ãRefreshVisibility
çŽæ¥èšå®ããŠããŸããããã¯ãã€ã³ã¹ã¿ã³ããã©ã³ãžã·ã§ã³ã§ã¯äŸç¶ãšããŠæ£ããã§ãããç¡å¹ã«ãªã£ãŠããå Žåã¯ããã©ã³ãžã·ã§ã³ã»ã«ã®ãªã¹ãã«ã»ã«ã远å ããå¿
èŠããããŸãã public void RefreshVisibility (HexCell cell) { int index = cell.Index; if (ImmediateMode) { cellTextureData[index].r = cell.IsVisible ? (byte)255 : (byte)0; cellTextureData[index].g = cell.IsExplored ? (byte)255 : (byte)0; } else { transitioningCells.Add(cell); } enabled = true; }
çŸæç¹ã§ã¯ããªã¹ãå
ã®ã»ã«ã«å¯ŸããŠäœãå®è¡ããŠããªããããå¯èŠæ§ã¯ããæ©èœããŠããªãããã§ããã«ãŒãå
ã®ã»ã«ãã«ãŒããã
察å¿ããå€ãå³åº§ã«255ãŸãã¯0ã«èšå®ãã代ããã«ããããã®å€ãåŸã
ã«å¢æžããŸããé·ç§»ã®æ»ãããã¯ãå€åçã«äŸåããŸããéåžžã«é«éã§ãäœéã§ããªãã¯ãã§ããçŸãããã©ã³ãžã·ã§ã³ãšã²ãŒã ã®å©äŸ¿æ§ã®éã®é©åãªåŠ¥åç¹ã¯ã1ç§ä»¥å
ã«å€æŽããããšã§ãã倿Žããããããããã«ãããã«å®æ°ãèšå®ããŸãããã const float transitionSpeed = 255f;
ããã§LateUpdate
ãå€ã«é©çšããããã«ã¿ãå®çŸ©ã§ããŸãããããè¡ãã«ã¯ãæéå·®ã«é床ãæããŸããæŽæ°ã§ããå¿
èŠããããŸããã©ã®ãããã®å€§ããã«ãªããããããªãããã§ãããã¬ãŒã ã¬ãŒããæ¥æ¿ã«äœäžãããšããã«ã¿ã255ãè¶
ããå¯èœæ§ããããŸããããã«ãé·ç§»ã»ã«ãããéã«æŽæ°ããå¿
èŠããããŸãããã®ããããªã¹ãã«äœããããéã¯ã³ãŒããå«ããå¿
èŠããããŸãã void LateUpdate () { int delta = (int)(Time.deltaTime * transitionSpeed); cellTexture.SetPixels32(cellTextureData); cellTexture.Apply(); enabled = transitioningCells.Count > 0; }
éåžžã«çè«çã«å¯èœãªéåžžã«é«ããã¬ãŒã ã¬ãŒããäœãé·ç§»é床ãšçµã¿åãããŠãããã¯0ã®ãã«ã¿ãäžããããšãã§ããŸãã倿Žãè¡ãããã«ããã«ã¿ã®æå°å€ã匷å¶çã«1ã«ããŸãã int delta = (int)(Time.deltaTime * transitionSpeed); if (delta == 0) { delta = 1; }
ãã«ã¿ãåãåã£ããããã¹ãŠã®é·ç§»ã»ã«ãã«ãŒãããŠããŒã¿ãæŽæ°ã§ããŸãããã®ããã®ã¡ãœãããããUpdateCellData
ããã®ãã©ã¡ãŒã¿ãŒã¯å¯Ÿå¿ããã»ã«ãšãã«ã¿ã§ãããšããŸãã int delta = (int)(Time.deltaTime * transitionSpeed); if (delta == 0) { delta = 1; } for (int i = 0; i < transitioningCells.Count; i++) { UpdateCellData(transitioningCells[i], delta); }
ããæç¹ã§ãã»ã«ã®ç§»è¡ãå®äºããã¯ãã§ããã¡ãœããããé·ç§»ããŸã é²è¡äžãã©ããã«é¢ããæ
å ±ãè¿ããšä»®å®ããŸããåŠçã忢ãããããªã¹ãããã»ã«ãåé€ã§ããŸãããã®åŸãã»ã«ãã¹ãããããªãããã«å埩åããã¯ãªã¡ã³ãããå¿
èŠããããŸãã for (int i = 0; i < transitioningCells.Count; i++) { if (!UpdateCellData(transitioningCells[i], delta)) { transitioningCells.RemoveAt(i--); } }
é·ç§»ã»ã«ãåŠçãããé åºã¯éèŠã§ã¯ãããŸããããããã£ãŠãçŸåšã®ã€ã³ããã¯ã¹ã®ã»ã«ãåé€ããå¿
èŠã¯ãããŸãããåé€ãããšãRemoveAt
ãã¹ãŠã®ã»ã«ã匷å¶çã«ç§»åãããŸãã代ããã«ãæåŸã®ã»ã«ãçŸåšã®ã€ã³ããã¯ã¹ã«ç§»åããŠãããæåŸã®ã»ã«ãåé€ããŸãã if (!UpdateCellData(transitioningCells[i], delta)) { transitioningCells[i--] = transitioningCells[transitioningCells.Count - 1]; transitioningCells.RemoveAt(transitioningCells.Count - 1); }
次ã«ãã¡ãœãããäœæããå¿
èŠããããŸãUpdateCellData
ã圌ã®ä»äºãããããã«ã圌ã¯ã€ã³ããã¯ã¹ãšã»ã«ããŒã¿ãå¿
èŠãšããã®ã§ãããããååŸããããšããå§ããŸãããããŸããã»ã«ã®æŽæ°ãç¶è¡ãããã©ãããæ±ºå®ããå¿
èŠããããŸããããã©ã«ãã§ã¯ãããã¯å¿
èŠãªããšä»®å®ããŸããäœæ¥ã®å®äºåŸã倿ŽãããããŒã¿ãé©çšããã¹ããŒã¿ã¹ãæŽæ°ãç¶ç¶äžããè¿ãå¿
èŠããããŸãã bool UpdateCellData (HexCell cell, int delta) { int index = cell.Index; Color32 data = cellTextureData[index]; bool stillUpdating = false; cellTextureData[index] = data; return stillUpdating; }
ã»ã«ããŒã¿ã®æŽæ°
ãã®æ®µéã§ãç§»è¡äžãŸãã¯æ¢ã«å®äºããã»ã«ããããŸãããŸããã»ã«ãããŒãã®ç¶æ
ã確èªããŸããããã»ã«ã調ã¹ããããããã®Gå€ããŸã 255ã«çãããªãå Žåãé·ç§»ã®ããã»ã¹ã«ããããããããç£èŠããŸãã bool stillUpdating = false; if (cell.IsExplored && data.g < 255) { stillUpdating = true; } cellTextureData[index] = data;
é·ç§»ãå®è¡ããã«ã¯ãã»ã«ã®Gå€ã«ãã«ã¿ã远å ããŸããç®è¡æŒç®ã¯ãã€ãã§ã¯æ©èœãããæåã«æŽæ°ã«å€æãããŸãããããã£ãŠãåèšã¯æŽæ°åœ¢åŒã«ãªãããã€ãã«å€æããå¿
èŠããããŸãã if (cell.IsExplored && data.g < 255) { stillUpdating = true; int t = data.g + delta; data.g = (byte)t; }
ãã ãã倿ã®åã«ãå€ã255ãè¶
ããªãããã«ããå¿
èŠããããŸãã int t = data.g + delta; data.g = t >= 255 ? (byte)255 : (byte)t;
次ã«ãRã®å€ã䜿çšããå¯èŠæ§ã«ã€ããŠãåãããšãè¡ãå¿
èŠããããŸãã if (cell.IsExplored && data.g < 255) { ⊠} if (cell.IsVisible && data.r < 255) { stillUpdating = true; int t = data.r + delta; data.r = t >= 255 ? (byte)255 : (byte)t; }
ã»ã«ãåã³äžå¯èŠã«ãªãå¯èœæ§ããããããRã®å€ãæžããå¿
èŠããããã©ããã確èªããå¿
èŠããããŸããããã¯ãã»ã«ãäžå¯èŠã§ãããRããŒããã倧ããå Žåã«çºçããŸãã if (cell.IsVisible) { if (data.r < 255) { stillUpdating = true; int t = data.r + delta; data.r = t >= 255 ? (byte)255 : (byte)t; } } else if (data.r > 0) { stillUpdating = true; int t = data.r - delta; data.r = t < 0 ? (byte)0 : (byte)t; }
ããã§UpdateCellData
æºåãæŽããå¯èŠæ§ã®ç§»è¡ãæ£ããå®è¡ãããŸããå¯èŠæ§ã®é·ç§»ãéè€ããé·ç§»èŠçŽ ã«å¯Ÿããä¿è·
ãã©ã³ãžã·ã§ã³ã¯æ©èœããŸãããéè€ããã¢ã€ãã ããªã¹ãã«è¡šç€ºãããå ŽåããããŸããããã¯ãç§»è¡äžã®ã»ã«ã®è¡šç€ºç¶æ
ãå€åããå Žåã«çºçããŸããããšãã°ãåéã®ç§»åäžã«çæéã ãã»ã«ã衚瀺ãããå Žåãéè€ããèŠçŽ ã®åºçŸã®çµæãšããŠãã»ã«é·ç§»ã¯ãã¬ãŒã ããšã«æ°åæŽæ°ãããé·ç§»ã®é«éåãšäœåãªäœæ¥ã«ã€ãªãããŸãããããé²ãã«ã¯ãã»ã«ã远å ããåã«ããã§ã«ãªã¹ãã«ãããã©ããã確èªããŸãããã ãããã¹ãŠã®åŒã³åºãã§ãªã¹ãæ€çŽ¢RefreshVisibility
ç¹ã«ãè€æ°ã®ã»ã«é·ç§»ãå®è¡ãããå Žåãã³ã¹ããããããŸãã代ããã«ãã»ã«ãç§»è¡äžãã©ããã瀺ãããã«ãŸã 䜿çšãããŠããªãå¥ã®ãã£ãã«ãããšãã°å€Bã䜿çšããŸããã»ã«ããªã¹ãã«è¿œå ãããšããå€255ãå²ãåœãŠãå€ã255ã«çãããªãã»ã«ã®ã¿ã远å ããŸãã public void RefreshVisibility (HexCell cell) { int index = cell.Index; if (ImmediateMode) { cellTextureData[index].r = cell.IsVisible ? (byte)255 : (byte)0; cellTextureData[index].g = cell.IsExplored ? (byte)255 : (byte)0; } else if (cellTextureData[index].b != 255) { cellTextureData[index].b = 255; transitioningCells.Add(cell); } enabled = true; }
ãããæ©èœããã«ã¯ãã»ã«é·ç§»ã®å®äºåŸã«Bã®å€ããªã»ããããå¿
èŠããããŸãã bool UpdateCellData (HexCell cell, int delta) { ⊠if (!stillUpdating) { data.b = 0; } cellTextureData[index] = data; return stillUpdating; }
éè€ã®ãªãé·ç§»ãå¯èŠæ§ã®å³æèªã¿èŸŒã¿
å¯èŠæ§ã®å€æŽã¯ãããããããŒãããŠãããšãã§ãåžžã«ç·©ããã§ãããããã¯ã»ã«ããã§ã«è¡šç€ºãããŠããç¶æ
ã衚ããŠãããããããã¯éè«ççã§ãããããã£ãŠãé·ç§»ã¯ããã§ã¯äžé©åã§ããããã«ã倧ããªãããã®å€ãã®å¯èŠã»ã«ã«å¯ŸããŠãã©ã³ãžã·ã§ã³ãå®è¡ãããšãããŒãåŸã«ã²ãŒã ãé
ããªãå¯èœæ§ããããŸãããããã£ãŠãã»ã«ãšåéãããŒãããåHexGrid.Load
ã«ãã€ã³ã¹ã¿ã³ãé·ç§»ã¢ãŒãã«åãæ¿ããŸãããã public void Load (BinaryReader reader, int header) { ⊠cellShaderData.ImmediateMode = true; for (int i = 0; i < cells.Length; i++) { cells[i].Load(reader, header); } ⊠}
ãããã£ãŠãã€ã³ã¹ã¿ã³ãé·ç§»ã¢ãŒãã®åæèšå®ãããããäœã§ããåå®çŸ©ããŸããããããæ¢ã«ç¡å¹åãããŠããããæ§æãªãã·ã§ã³ãäœæãããŠãããããåæã¢ãŒããèšæ¶ããäœæ¥ã®å®äºåŸã«åãæ¿ããŸãã public void Load (BinaryReader reader, int header) { ⊠bool originalImmediateMode = cellShaderData.ImmediateMode; cellShaderData.ImmediateMode = true; ⊠cellShaderData.ImmediateMode = originalImmediateMode; }
ãŠããã£ããã±ãŒãžé«ãäŸåã¹ã³ãŒã
ãããŸã§ããã¹ãŠã®ãŠãããã«3ã€ã®äžå®ã®ã¹ã³ãŒãã䜿çšããŸããããå®éã«ã¯ãã£ãšè€éã§ããäžè¬çãªå Žåãæ¬¡ã®2ã€ã®çç±ã§ãªããžã§ã¯ããèŠãããšãã§ããŸãããäœããã®é害ã«ãããªããžã§ã¯ããèŠããªããããªããžã§ã¯ããå°ãããããé ãããŸãããã®ã²ãŒã ã§ã¯ãã¹ã³ãŒãå¶éã®ã¿ãå®è£
ããŸããå°çã¯ç§ãã¡ã®èŠéãéããŠãããããå°çã®å察åŽã«ãããã®ãèŠãããšãã§ããŸãããå°å¹³ç·ããèŠããŸãããææã¯ã»ãŒçäœãšèŠãªãããšãã§ãããããèŠç¹ãé«ãã»ã©ãããå€ãã®è¡šé¢ãèŠãããšãã§ããŸããã€ãŸããå°å¹³ç·ã¯é«ãã«äŸåããŸããå°å¹³ç·ã¯èŠç¹ã®é«ãã«äŸåããŸããç§ãã¡ã®ãŠãããã®éãããå¯èŠæ§ã¯ãå°çã®æ²çã«ãã£ãŠäœæãããå°å¹³ç·å¹æãæš¡å£ããŠããŸããã¬ãã¥ãŒã®ç¯å²ã¯ãææã®ãµã€ãºãšå°å³ã®çž®å°ºã«ãã£ãŠç°ãªããŸããå°ãªããšãããã¯è«ççãªèª¬æã§ããããããç¯å²ãçž®å°ããäž»ãªçç±ã¯ã²ãŒã ãã¬ã€ã§ãããããã¯æŠäºã®é§ãšåŒã°ããå¶éã§ãããã ããèŠéã®åºç€ãšãªãç©çåŠãçè§£ãããšãå°å¹³ç·ããé ããããããäœãé害ç©ãèŠãããšãã§ãããããé«ãèŠç¹ã«ã¯æŠç¥ç䟡å€ããããšçµè«ä»ããããšãã§ããŸãããããããããŸã§ã®ãšãããç§ãã¡ã¯ãããå®çŸããŠããŸãããã¬ãã¥ãŒã®é«ã
ã¹ã³ãŒããæ±ºå®ãããšãã«é«ããèæ
®ããã«ã¯ãé«ããç¥ãå¿
èŠããããŸããããã¯ãéžäžã®ã»ã«ãæ°Žãã«ãã£ãŠãéåžžã®é«ããŸãã¯æ°Žã®ã¬ãã«ã«ãªããŸãããããHexCell
ããããã£ã«è¿œå ããŸãããã public int ViewElevation { get { return elevation >= waterLevel ? elevation : waterLevel; } }
ãã ããé«ããã¹ã³ãŒãã«åœ±é¿ããå Žåãã»ã«ã®è¡šç€ºé«ããå€ãããšãå¯èŠæ§ã®ç¶æ³ãå€ããå¯èœæ§ããããŸããã»ã«ãè€æ°ã®ãŠãããã®ç¯å²ããããã¯ããŠããããçŸåšãããã¯ããŠããããã倿Žãå¿
èŠãªãã®ã倿ããã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸãããã»ã«èªäœã¯ãã®åé¡ã解決ã§ããªããããç¶æ³ã®å€åãå ±åããHexCellShaderData
ãŸããHexCellShaderData
ãã®ããã®ã¡ãœããããããšããŸãViewElevationChanged
ãHexCell.Elevation
å¿
èŠã«å¿ããŠãå²ãåœãŠæã«åŒã³åºããŸãã public int Elevation { get { return elevation; } set { if (elevation == value) { return; } int originalViewElevation = ViewElevation; elevation = value; if (ViewElevation != originalViewElevation) { ShaderData.ViewElevationChanged(); } ⊠} }
åãããšãåœãŠã¯ãŸãWaterLevel
ãŸãã public int WaterLevel { get { return waterLevel; } set { if (waterLevel == value) { return; } int originalViewElevation = ViewElevation; waterLevel = value; if (ViewElevation != originalViewElevation) { ShaderData.ViewElevationChanged(); } ValidateRivers(); Refresh(); } }
å¯èŠæ§ããªã»ãã
次ã«ãã¡ãœãããäœæããå¿
èŠããããŸãHexCellShaderData.ViewElevationChanged
ãäžè¬çãªå¯èŠæ§ã®ç¶æ³ã®å€åã倿ããããšã¯ãç¹ã«è€æ°ã®ã»ã«ãåæã«å€æŽããå Žåã¯é£ããäœæ¥ã§ãããããã£ãŠãããªãã¯ãæãä»ãã®ã§ã¯ãªãããã¹ãŠã®ã»ã«ã®å¯èŠæ§ããªã»ããããããšãèšç»ããŸãããããè¡ãå¿
èŠããããã©ããã远跡ããããŒã«ãã£ãŒã«ãã远å ããŸããã¡ãœããå
ã§ã¯ãåçŽã«trueã«èšå®ããã³ã³ããŒãã³ããå«ããŸããåæã«å€æŽãããã»ã«ã®æ°ã«é¢ä¿ãªããããã¯åäžã®ãªã»ããã«ã€ãªãããŸãã bool needsVisibilityReset; ⊠public void ViewElevationChanged () { needsVisibilityReset = true; enabled = true; }
ãã¹ãŠã®ã»ã«ã®å¯èŠæ§ã®å€ããªã»ããããã«ã¯ããããã«ã¢ã¯ã»ã¹ã§ããå¿
èŠããããŸããHexCellShaderData
ãæã£ãŠããŸãããããã§ã¯ããã®è²¬ä»»ãå§ä»»ããŸãããHexGrid
ããããè¡ãã«ã¯ãHexCellShaderData
ããããã£ã远å ããå¿
èŠããããŸããããã«ãããã°ãªãããåç
§ã§ããŸããæ¬¡ã«ãããã䜿çšããŠLateUpdate
ãªã»ãããèŠæ±ã§ããŸãã public HexGrid Grid { get; set; } ⊠void LateUpdate () { if (needsVisibilityReset) { needsVisibilityReset = false; Grid.ResetVisibility(); } ⊠}
次ã«é²ã¿ãŸããããã·ã§ãŒããŒããŒã¿ãäœæããåŸHexGrid
ãã°ãªãããžã®ãªã³ã¯ãèšå®ãHexGrid.Awake
ãŸãã void Awake () { HexMetrics.noiseSource = noiseSource; HexMetrics.InitializeHashGrid(seed); HexUnit.unitPrefab = unitPrefab; cellShaderData = gameObject.AddComponent<HexCellShaderData>(); cellShaderData.Grid = this; CreateMap(cellCountX, cellCountZ); }
HexGrid
ResetVisibility
ãã¹ãŠã®ã»ã«ããªã»ããããã¡ãœãããååŸããå¿
èŠããããŸããã«ãŒãå
ã®ãã¹ãŠã®ã»ã«ãå·¡åããããªã»ãããèªåèªèº«ã«å§ä»»ããã ãã§ãã public void ResetVisibility () { for (int i = 0; i < cells.Length; i++) { cells[i].ResetVisibility(); } }
次ã«ãHexCell
ã¡ãœããã«è¿œå ããå¿
èŠãããResetVisibilty
ãŸããåã«å¯èŠæ§ããŒãã«ããå¯èŠæ§ã®æŽæ°ãããªã¬ãŒããŸããããã¯ãã»ã«ã®å¯èŠæ§ããŒããã倧ããå Žåã«å®è¡ããå¿
èŠããããŸãã public void ResetVisibility () { if (visibility > 0) { visibility = 0; ShaderData.RefreshVisibility(this); } }
ãã¹ãŠã®å¯èŠæ§ããŒã¿ããªã»ããããåŸHexGrid.ResetVisibility
ããã¹ãŠã®ãŠãããã«å¯èŠæ§ãå床é©çšããå¿
èŠããããŸãããã®ããã«ã¯ãåãŠãããã®ã¹ã³ãŒããç¥ãå¿
èŠããããŸããããããã£ã䜿çšããŠååŸã§ãããšããŸãVisionRange
ã public void ResetVisibility () { for (int i = 0; i < cells.Length; i++) { cells[i].ResetVisibility(); } for (int i = 0; i < units.Count; i++) { HexUnit unit = units[i]; IncreaseVisibility(unit.Location, unit.VisionRange); } }
ãããæ©èœããããã«ãååã®å€æŽHexUnit.visionRange
ããªãã¡ã¯ã¿ãªã³ã°HexUnit.VisionRange
ããŠããããã£ã«å€æããŸãã3ã®å®æ°å€ãåãåããŸãããå°æ¥çã«ã¯å€æŽãããŸãã public int VisionRange { get { return 3; } }
ãã®ãããã»ã«ã®è¡šç€ºé«ãã倿ŽããŠããå¯èŠæ§ããŒã¿ã¯ãªã»ãããããæ£ãããŸãŸã«ãªããŸãããã ããã¹ã³ãŒããæ±ºå®ããã«ãŒã«ã倿Žããåçã¢ãŒãã§åã³ã³ãã€ã«ãå®è¡ããå¯èœæ§ããããŸããã¹ã³ãŒããç¬ç«ããŠå€æŽHexGrid.OnEnable
ããã«ã¯ãåã³ã³ãã€ã«ãæ€åºããããšãã«ãªã»ãããéå§ããŸãããã void OnEnable () { if (!HexMetrics.noiseSource) { ⊠ResetVisibility(); } }
ããã§ããã¬ã€ã¢ãŒãã®ãŸãŸã§ãã¹ã³ãŒãã³ãŒãã倿ŽããŠçµæã確èªã§ããŸããå°å¹³ç·ãåºãã
ã¹ã³ãŒãã®èšç®ã決å®ããHexGrid.GetVisibleCells
ãŸããé«ããã¹ã³ãŒãã«åœ±é¿ããããã«fromCell
ãééé åãäžæçã«åå®çŸ©ããããšã«ãããåã«è¡šç€ºã®é«ãã䜿çšã§ããŸãããããã£ãŠããããæ©èœãããã©ãããç°¡åã«ç¢ºèªã§ããŸãã List<HexCell> GetVisibleCells (HexCell fromCell, int range) { ⊠range = fromCell.ViewElevation; fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); ⊠}
ã¹ã³ãŒããšããŠé«ãã䜿çšããŸããå¯èŠæ§ã®é害
衚瀺é«ããã¹ã³ãŒããšããŠé©çšããããšã¯ãä»ã®ãã¹ãŠã®ã»ã«ã®é«ãããŒãã®å Žåã«ã®ã¿æ£ããæ©èœããŸãããã ãããã¹ãŠã®ã»ã«ã®é«ããèŠç¹ãšåãå Žåãã¹ã³ãŒãã¯ãŒãã«ãªããŸããããã«ãé«ããé«ãã»ã«ã¯ãèåŸã®äœãã»ã«ã®å¯èŠæ§ããããã¯ããå¿
èŠããããŸãããããŸã§ã®ãšãããããã¯å®è£
ãããŠããŸãããã¹ã³ãŒãã¯äœã劚ããŸãããã¹ã³ãŒããæ±ºå®ããæãæ£ããæ¹æ³ã¯ãå
ç·ã®æŸå°ã§ç¢ºèªããããšã§ãããããã«ã³ã¹ããããããããã§ãå¥åŠãªçµæãçæãããŸããå®ç§ã§ããå¿
èŠã®ãªããååãªçµæãçã¿åºãè¿
éãªãœãªã¥ãŒã·ã§ã³ãå¿
èŠã§ããããã«ãã¹ã³ãŒããæ±ºå®ããããã®ã«ãŒã«ã¯ããã¬ãŒã€ãŒã«ãšã£ãŠã·ã³ãã«ã§çŽæçã§äºæž¬å¯èœãªãã®ã§ããããšãéèŠã§ãã解決çã¯æ¬¡ã®ãšããã§ããã»ã«ã®å¯èŠæ§ã倿ãããšãã飿¥ããã»ã«ã®è¡šç€ºé«ãã察象è·é¢ã«è¿œå ããŸããå®éãããã«ããããããã®ã»ã«ãèŠããšãã«ã¹ã³ãŒããçž®å°ãããããããã¹ããããããå Žåããã®èåŸã®ã»ã«ã«å°éã§ããªããªããŸãã int distance = current.Distance + 1; if (distance + neighbor.ViewElevation > range) { continue; }
é«ãã»ã«ã¯ãã¥ãŒããããã¯ããŸããç§ãã¡ã¯é ãã«é«ã现èãèŠãã¹ãã§ã¯ãããŸãããïŒ, , , . , .
è§ãèŠåããªãã§ãã ãã
çŸåšãé«ãã»ã«ã¯ãã¥ãŒãäœãäœçœ®ã«ãããã¯ããŠããããã«èŠããŸãããã¹ã³ãŒãã貫éããããšããããŸãããããã§ã¯ãªãããã§ããããã¯ãæ€çŽ¢ã¢ã«ãŽãªãºã ãããããã³ã°ã»ã«ããã€ãã¹ããŠãããã®ã»ã«ãžã®ãã¹ãæ€åºããããã§ãããã®çµæãèŠçãé害ç©ãåé¿ã§ãããã®ããã«èŠããŸãããããåé¿ããã«ã¯ãã»ã«ã®å¯èŠæ§ã倿ãããšãã«æçãã¹ã®ã¿ãèæ
®ãããããã«ããå¿
èŠããããŸããããã¯ãå¿
èŠä»¥äžã«é·ããªããã¹ãããããããããšã§å®è¡ã§ããŸãã HexCoordinates fromCoordinates = fromCell.coordinates; while (searchFrontier.Count > 0) { ⊠for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { ⊠int distance = current.Distance + 1; if (distance + neighbor.ViewElevation > range || distance > fromCoordinates.DistanceTo(neighbor.coordinates) ) { continue; } ⊠} }
æçãã¹ã®ã¿ã䜿çšããŸããããã§ãæããã«ééãã®ããã±ãŒã¹ã®ã»ãšãã©ãä¿®æ£ããŸãããè¿ãã®ã»ã«ã§ã¯ãæçã®ãã¹ããååšããªããããããã¯ããŸãæ©èœããŸããã»ã«ãé ãã»ã©ãã¹ã®ãªãã·ã§ã³ãå¢ãããããé è·é¢ã§ãå¯èŠæ§ãšã³ãããŒããçºçããå¯èœæ§ããããŸããå¯èŠé åãå°ãããŸãŸã§ã飿¥ããé«ãã®å·®ã倧ããããªãå Žåãããã¯åé¡ã«ãªããŸãããæåŸã«ãéä¿¡ããããã¥ãŒã®ãã£ãŒã«ãã眮ãæãã代ããã«ããã¥ãŒã®é«ãã远å ããŸããããŒã ã®èŠçã¯ããã®é«ããé£è¡é«åºŠãåµå¯èœåã瀺ããŠããŸãã range += fromCell.ViewElevation;
äœãèŠç¹ã§ã®å®å
šãªèŠéã§ã®è¡šç€ºãã€ãŸããèŠçã«å¯Ÿããã»ã«ã®é«ãã®éããèæ
®ããŠãèŠéãžã®æççµè·¯ã«æ²¿ã£ãŠç§»åããå ŽåãèŠçã®æçµèŠåãèŠèŠã«é©çšãããŸããã»ã«ãã¹ã³ãŒãå€ã«ããå Žåãã»ã«ã¯ãã¹ãŠã®ãã¹ããããã¯ããŸãããã®çµæããã¥ãŒã劚ãããã®ããªãé«ã芳枬ãã€ã³ãã¯ãæŠç¥çã«äŸ¡å€ããããŸãããªããžã§ã¯ãã®å¯èŠæ§ã劚ããããšã¯ã©ãã§ããïŒ, , . , , . .
ãŠããã£ããã±ãŒãžæ¢çŽ¢ã§ããªã现è
å¯èŠæ§ã«é¢ããæåŸã®åé¡ã¯ããããã®ç«¯ã«é¢ãããã®ã§ãããšããžã®ã»ã«ã«é£æ¥ã»ã«ããªãããããã©ã³ãžã·ã§ã³ãªãã§çªç¶ã¬ãªãŒããçµäºããŸãããããã®ããŒã¯ããããšããžãçæ³çã«ã¯ãæªæ¢çŽ¢ã®é åãšå°å³ã®ç«¯ã®èŠèŠçãªè¡šç€ºã¯åãã§ãªããã°ãªããŸããããšããžãäžè§åœ¢åå²ããå Žåã飿¥ãããšããžããªãå Žåã«ç¹æ®ãªã±ãŒã¹ã远å ããããšã§ãããå®çŸã§ããŸãããããã«ã¯è¿œå ã®ããžãã¯ãå¿
èŠã§ãããæ¬ æã»ã«ãåŠçããå¿
èŠããããŸãããããã£ãŠããã®ãããªè§£æ±ºçã¯éèŠã§ããå¥ã®æ¹æ³ã¯ããããã®å¢çã»ã«ãåéã®ç¯å²å
ã«ããå Žåã§ãã匷å¶çã«æªæ¢çŽ¢ã«ããããšã§ãããã®ã¢ãããŒãã¯ã¯ããã«åçŽãªã®ã§ã䜿çšããŸãããããŸããæªæ¢çŽ¢ã®ã»ã«ãä»ã®ã»ã«ãšããŠããŒã¯ããããšãã§ããããããããã®äžåäžãªãšããžãç°¡åã«äœæã§ããŸããããã«ã端ã«ããé衚瀺ã®ã»ã«ã䜿çšãããšãå·ãšéè·¯ã®ãããã«åºå
¥ãããéè·¯ãšå·ãäœæã§ããŸãããããã®çµç¹ã¯ç¯å²å€ã«ãªãããã§ãããŸãããã®ãœãªã¥ãŒã·ã§ã³ã®å©ããåããŠãã«ãŒãã«åºå
¥ããããŠãããã远å ã§ããŸããã»ã«ãèª¿æ»æžã¿ãšããŠããŒã¯ããŸã
ã»ã«ãæ€æ»ã§ããããšã瀺ãã«ã¯ãHexCell
ããããã£ã«è¿œå ããŸãExplorable
ã public bool Explorable { get; set; }
ããã§ã調æ»å¯Ÿè±¡ã®ã»ã«ã衚瀺ãããããã«ãªããããIsVisible
ãããèæ
®ããŠããããã£ã倿ŽããŸãã public bool IsVisible { get { return visibility > 0 && Explorable; } }
åãããšãé©çšããIsExplored
ãŸãããã ãããã®ããã«æšæºããããã£ã調æ»ããŸãããã²ãã¿ãŒã®ããžãã¯ã倿Žã§ããããã«ãæç€ºçãªããããã£ã«å€æããå¿
èŠããããŸãã public bool IsExplored { get { return explored && Explorable; } private set { explored = value; } } ⊠bool explored;
å°å³ã®ç«¯ãé ã
ã¡ãœããã§é·æ¹åœ¢ãããã®ãšããžãé衚瀺ã«ã§ãHexGrid.CreateCell
ãŸãã端ã«ãªãã»ã«ã¯èª¿æ»ãããæ®ãã¯ãã¹ãŠæªæ¢çŽ¢ã§ãã void CreateCell (int x, int z, int i) { ⊠HexCell cell = cells[i] = Instantiate<HexCell>(cellPrefab); cell.transform.localPosition = position; cell.coordinates = HexCoordinates.FromOffsetCoordinates(x, z); cell.Index = i; cell.ShaderData = cellShaderData; cell.Explorable = x > 0 && z > 0 && x < cellCountX - 1 && z < cellCountZ - 1; ⊠}
ä»ãã«ãŒãã¯ç«¯ã®åšãã§æããªãããããã®åŸãã«å·šå€§ãªæªèžã®ã¹ããŒã¹ãé ããŸãããã®çµæããããã®èª¿æ»å¯Ÿè±¡ãšãªã¢ã®ãµã€ãºã¯ã忬¡å
ã§2ãã€æžå°ããŸãããããã®æªæ¢çŽ¢ã®ãšããžãç ç©¶ç¶æ
ãç·šéå¯èœã«ããããšã¯å¯èœã§ããïŒ, , . .
æªæ¢çŽ¢ã®ã»ã«ã¯å¯èŠæ§ã劚ããŸã
æåŸã«ãã»ã«ãæ€æ»ã§ããªãå Žåã¯ãå¯èŠæ§ã劚ããã¯ãã§ããHexGrid.GetVisibleCells
ãããèæ
®ããŠå€æŽããŠãã ããã if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase || !neighbor.Explorable ) { continue; }
ãŠããã£ããã±ãŒãžããŒã23ïŒåå°ã®çæ
- çæããã颚æ¯ã§æ°ããããããå¡ãã€ã¶ããŸãã
- åå°ãåå°ã®æŽªæ°Žãèµ·ãããŸãã
- äœæãããåå°ã®éããã®é«ããããã³å¹åžãå¶åŸ¡ããŸãã
- ããŸããŸãªæ§æãªãã·ã§ã³ã®ãµããŒãã远å ããŠã倿°ããããäœæããŸãã
- åãããããå床çæã§ããããã«ããŸãã
ãã¥ãŒããªã¢ã«ã®ãã®éšåã¯ãæé ãããçæã®ã·ãªãŒãºã®å§ãŸãã§ãããã®éšåã¯Unity 2017.1.0ã§äœæãããŸãããçæããã倿°ã®ãããã®1ã€ãã«ãŒãçæ
ä»»æã®ããããäœæã§ããŸãããæéãããããŸããã¢ããªã±ãŒã·ã§ã³ããã¶ã€ããŒã®ããã«ã«ãŒããçæãã奜ã¿ã«åãããŠå€æŽã§ããããã«ããŠãããšäŸ¿å©ã§ããå¥ã®æé ãå®è¡ããŠãèšèšãæåã§å®å
šã«äœæãã宿ããããããçæãã責任ãã¢ããªã±ãŒã·ã§ã³ã«å®å
šã«ç§»ãããšãã§ããŸãããã®ãããã²ãŒã ã¯æ¯åæ°ãããããã§ãã¬ã€ã§ããåã²ãŒã ã»ãã·ã§ã³ã¯ç°ãªããŸããããããã¹ãŠãå¯èœã«ããã«ã¯ããããçæã¢ã«ãŽãªãºã ãäœæããå¿
èŠããããŸããå¿
èŠãªçæã¢ã«ãŽãªãºã ã®ã¿ã€ãã¯ãå¿
èŠãªã«ãŒãã®ã¿ã€ãã«ãã£ãŠç°ãªããŸããæ£ããã¢ãããŒãã¯ãããŸãããä¿¡é Œæ§ãšãã¬ã€ã¢ããªãã£ã®éã®åŠ¥åç¹ãåžžã«æ¢ãå¿
èŠããããŸããã«ãŒããä¿¡ããããããã«ã¯ããã¬ã€ã€ãŒã«ãšã£ãŠéåžžã«å¯èœæ§ãããçŸå®çã§ããå¿
èŠããããŸããããã¯ãå°å³ãå°çã®äžéšã®ããã«èŠããããšãæå³ãããã®ã§ã¯ãããŸãããããã¯ãç°ãªãææãŸãã¯å®å
šã«ç°ãªãçŸå®ãããããŸããããããããããããå°çã®å®reliefã瀺ããªããããã¯å°ãªããšãéšåçã«ããã«äŒŒãŠããªããã°ãªããŸããããã¬ã€ã¢ããªãã£ã¯ãã«ãŒããã²ãŒã ãã¬ã€ã«ã©ã®ããã«å¯Ÿå¿ãããã«é¢é£ããŠããŸãã信念ãšççŸããããšããããŸããããšãã°ãå±±èã¯çŸããããã«èŠããŸãããåæã«ãŠãããã®ç§»åãšãã¥ãŒã倧ããå¶éããŸãããããæãŸãããªãå Žåã¯ãå±±ãªãã§è¡ãå¿
èŠããããä¿¡é Œæ§ãäœäžããã²ãŒã ã®è¡šçŸåãå¶éãããŸãããŸãã¯ãå±±ãæãããšãã§ããŸãããã²ãŒã ãã¬ã€ãžã®åœ±é¿ãæžããããšãã§ããä¿¡é Œæ§ãäœäžããŸããããã«ãå®çŸå¯èœæ§ãèæ
®ããå¿
èŠããããŸããããšãã°ãæ§é ãã¬ãŒãã䟵é£ãéšãç«å±±åŽç«ãmetç³ãæã®åœ±é¿ãªã©ãã·ãã¥ã¬ãŒãããããšã«ãããéåžžã«ãªã¢ã«ãªå°çã®ãããªææãäœæã§ããŸãããããããã®ãããªã·ã¹ãã ã®éçºã«ã¯å€ãã®æéãå¿
èŠã§ããããã«ããã®ãããªææãçæããã®ã«é·ãæéããããå¯èœæ§ãããããã¬ã€ã€ãŒã¯æ°ããã²ãŒã ãéå§ããåã«æ°ååŸ
ã€å¿
èŠã¯ãããŸãããã€ãŸããã·ãã¥ã¬ãŒã·ã§ã³ã¯åŒ·åãªããŒã«ã§ãããäŸ¡æ ŒãããããŸããã²ãŒã ã¯ãã°ãã°ãçæ£æ§ããã¬ã€å¯èœæ§ãããã³å®çŸå¯èœæ§ã®éã®ãã¬ãŒããªãã䜿çšããŸãããã®ãããªåŠ¥åã¯ç®ã«èŠãããå®å
šã«æ£åžžã«èŠããããšãããã°ãéçºããã»ã¹äžã«äžãããæ±ºå®ã«å¿ããŠãã©ã³ãã ãäžè²«æ§ã®ãªãããŸãã¯ç¡ç§©åºã«èŠããããšããããŸããããã¯ãã«ãŒãçæã ãã§ãªããæç¶ãåã«ãŒããžã§ãã¬ãŒã¿ãŒãéçºããéã«ã¯ãããã«ç¹å¥ãªæ³šæãæãå¿
èŠããããŸããããªããäœæããŠããã²ãŒã ã«ãšã£ãŠåœ¹ã«ç«ããªãããšã倿ããçŸããã«ãŒããçæããã¢ã«ãŽãªãºã ãäœæããã®ã«å€ãã®æéãè²»ããããšãã§ããŸãããã®ãã¥ãŒããªã¢ã«ã·ãªãŒãºã§ã¯ãåå°ã®ãããªã¬ãªãŒããäœæããŸããé¢çœãã倧ããªå€åæ§ãšå€§ããªåäžãªé åã®æ¬ åŠãèŠãããã¯ãã§ããã¬ãªãŒãã¹ã±ãŒã«ã¯å€§ããããããã¯1ã€ä»¥äžã®å€§éžãæµ·æŽã®é åããŸãã¯ææå
šäœãã«ããŒããŸããåå°ã®è³ªéãæ°åãå°åã®æ°ãå°åœ¢ã®éèµ·ãªã©ãå°çã管çããå¿
èŠããããŸãããã®ããŒãã§ã¯ã寿åžäœãã®åºç€ãç¯ããŸããç·šéã¢ãŒãã§éå§ãã
ã²ãŒã ãã¬ã€ã§ã¯ãªããããã«çŠç¹ãåœãŠãã®ã§ãç·šéã¢ãŒãã§ã¢ããªã±ãŒã·ã§ã³ãèµ·åããæ¹ã䟿å©ã§ããããã«ãããããã«ã«ãŒããèŠãããšãã§ããŸãããããã£ãŠãHexMapEditor.Awake
ç·šéã¢ãŒããtrueã«èšå®ãããã®ã¢ãŒãã®ã·ã§ãŒããŒããŒã¯ãŒãããªã³ã«ããŠå€æŽããŸãã void Awake () { terrainMaterial.DisableKeyword("GRID_ON"); Shader.EnableKeyword("HEX_MAP_EDIT_MODE"); SetEditMode(true); }
ã«ãŒããžã§ãã¬ãŒã¿ãŒ
æç¶ãåããããçæããã«ã¯éåžžã«å€ãã®ã³ãŒããå¿
èŠãªãããã«çŽæ¥è¿œå ããŸããHexGrid
ã代ããã«ãç§ãã¡ã¯ãæ°ããã³ã³ããŒãã³ããäœæãHexMapGenerator
ããããŠHexGrid
ããã¯ãªãã ããç¥ã£ãŠããŸããããã«ãããå¿
èŠã«å¿ããŠå¥ã®ã¢ã«ãŽãªãºã ãžã®ç§»è¡ãç°¡åã«ãªããŸãããžã§ãã¬ãŒã¿ãŒã«ã¯ã°ãªãããžã®ãªã³ã¯ãå¿
èŠãªã®ã§ãäžè¬çãªãã£ãŒã«ãã远å ããŸããããã«GenerateMap
ãã¢ã«ãŽãªãºã ãåŠçããäžè¬çãªã¡ãœããã远å ããŸãããããã®å¯žæ³ããã©ã¡ãŒã¿ãŒãšããŠæå®ããããã䜿çšããŠæ°ãã空ã®ããããäœæããŸãã using System.Collections.Generic; using UnityEngine; public class HexMapGenerator : MonoBehaviour { public HexGrid grid; public void GenerateMap (int x, int z) { grid.CreateMap(x, z); } }
ã³ã³ããŒãã³ããæã€ãªããžã§ã¯ããã·ãŒã³ã«è¿œå ããHexMapGenerator
ãããã°ãªããã«æ¥ç¶ããŸããããããžã§ãã¬ãŒã¿ãŒãªããžã§ã¯ããæ°ãããããã®ã¡ãã¥ãŒã倿Žãã
NewMapMenu
空ã®ã«ãŒããäœæããã ãã§ãªããã«ãŒããçæã§ããããã«å€æŽããŸããgenerateMaps
ããã©ã«ãã§å€ãæã€ããŒã«åãã£ãŒã«ããä»ããŠæ©èœãå¶åŸ¡ããŸãtrue
ãoptionsãåãæ¿ããããã«è¡ã£ãããã«ããã®ãã£ãŒã«ããèšå®ããäžè¬çãªæ¹æ³ãäœæããŸãããHexMapEditor
ãé©åãªã¹ã€ãããã¡ãã¥ãŒã«è¿œå ããã¡ãœããã«æ¥ç¶ããŸãã bool generateMaps = true; public void ToggleMapGeneration (bool toggle) { generateMaps = toggle; }
ã¹ã€ããä»ãã®æ°ããã«ãŒãã®ã¡ãã¥ãŒãã¡ãã¥ãŒã«ããããžã§ãã¬ãŒã¿ãŒãžã®ãªã³ã¯ãæå®ããŸããæ¬¡ã«ãå¿
èŠã«å¿ããŠãã°ãªããGenerateMap
ãå®è¡ããã ãã§ãªãããžã§ãã¬ãŒã¿ãŒã¡ãœãããåŒã³åºããŸãCreateMap
ã public HexMapGenerator mapGenerator; ⊠void CreateMap (int x, int z) { if (generateMaps) { mapGenerator.GenerateMap(x, z); } else { hexGrid.CreateMap(x, z); } HexMapCamera.ValidatePosition(); Close(); }
ãžã§ãã¬ãŒã¿ãŒãžã®æ¥ç¶ãã»ã«ã¢ã¯ã»ã¹
ãžã§ãã¬ãŒã¿ãŒãæ©èœããããã«ã¯ãã»ã«ã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸããç§ãã¡ã¯HexGrid
ããã§ã«äžè¬çãªæ¹æ³æã£ãŠããGetCell
å¿
èŠãäœçœ®ãã¯ãã«ããŸãã¯å
è§åœ¢ã®åº§æšãããžã§ãã¬ãŒã¿ã¯ã©ã¡ããäžæ¹ã䜿çšããå¿
èŠããªãããHexGrid.GetCell
ãã»ã«ã®ãªãã»ãããŸãã¯ã€ã³ããã¯ã¹ã®åº§æšã䜿çšãã2ã€ã®äŸ¿å©ãªã¡ãœããã远å ããŸãã public HexCell GetCell (int xOffset, int zOffset) { return cells[xOffset + zOffset * cellCountX]; } public HexCell GetCell (int cellIndex) { return cells[cellIndex]; }
ããã§HexMapGenerator
ãã»ã«ãçŽæ¥åä¿¡ã§ããŸããããšãã°ãæ°ããããããäœæããåŸãèã®åº§æšã䜿çšããŠãã»ã«ã®äžå€®ã®åã®èµ·äŒãšããŠèãèšå®ã§ããŸãã public void GenerateMap (int x, int z) { grid.CreateMap(x, z); for (int i = 0; i < z; i++) { grid.GetCell(x / 2, i).TerrainTypeIndex = 1; } }
å°ããªå°å³äžã®èã®åããŠããã£ããã±ãŒãžå¯¿åžäœã
ããããçæãããšããåå°ãªãã§å®å
šã«éå§ããŸããå
šäžçã1ã€ã®å·šå€§ãªæµ·ã§ããµããŠãããšæ³åã§ããŸããéžå°ã¯ãæµ·åºã®äžéšãæŒãäžããããŠæ°Žé¢äžã«æµ®ããã ãšãã«äœæãããŸãããã®æ¹æ³ã§ã©ã®ãããã®åå°ãäœæããããã©ãã«è¡šç€ºããããã©ã®ãããªåœ¢ç¶ã«ããããæ±ºå®ããå¿
èŠããããŸããã¬ãªãŒããäžãã
å°ããå§ããŸããã-ç§ãã¡ã¯æ°Žã®äžã«äžæã®åå°ãäžããŸãããã®ããRaiseTerrain
ã«ãããããã®ãµã€ãºãå¶åŸ¡ãããã©ã¡ãŒã¿ãŒãæã€ã¡ãœãããäœæããŸãããã®ã¡ãœãããã§åŒã³åºãGenerateMap
ã以åã®ãã¹ãã³ãŒãã眮ãæããŸãã7ã€ã®ã»ã«ã§æ§æãããå°ããªåå°ããå§ããŸãããã public void GenerateMap (int x, int z) { grid.CreateMap(x, z);
ãããŸã§ã®ãšããããèãã¿ã€ãã®ã¬ãªãŒãã䜿çšããŠé«å°ã瀺ããæåã®ãç ãã¬ãªãŒãã¯æµ·ãæããŸãã匷èŠRaiseTerrain
æã
ã¯åå°ã®é©åãªéãåŸããŸã§ãã©ã³ãã ãªã»ã«ãåãããã®ææžã®çš®é¡ã倿ŽããŸããã©ã³ãã ã»ã«ãååŸããã«ã¯GetRandomCell
ãã©ã³ãã ã»ã«ã€ã³ããã¯ã¹ã決å®ããã°ãªãããã察å¿ããã»ã«ãååŸããã¡ãœããã远å ããŸãã void RaiseTerrain (int chunkSize) { for (int i = 0; i < chunkSize; i++) { GetRandomCell().TerrainTypeIndex = 1; } } HexCell GetRandomCell () { return grid.GetCell(Random.Range(0, grid.cellCountX * grid.cellCountZ)); }
7ã€ã®ã©ã³ãã ãªå¯¿åžã»ã«ãæçµçã«ã¯å€ãã®ã©ã³ãã ãªã»ã«ãå¿
èŠã«ãªããããã¹ãŠã®ã»ã«ãæ°åã«ãŒãããå¿
èŠããããããã»ã«èªäœã®ã»ã«ã®æ°ã远跡ããŸãããHexMapGenerator
ã int cellCount; public void GenerateMap (int x, int z) { cellCount = x * z; ⊠} ⊠HexCell GetRandomCell () { return grid.GetCell(Random.Range(0, cellCount)); }
1ã€ã®ãµã€ãã®äœæ
ãããŸã§ã®ãšããã7ã€ã®ã©ã³ãã ãªã»ã«ãåå°ã«å€ããŠããŸãããã©ãã«ã§ãé
眮ã§ããŸããã»ãšãã©ã®å Žåãåäžã®åå°ãšãªã¢ã圢æããŠããŸãããããã«ãåãã»ã«ãè€æ°åéžæã§ãããããåå°ãå°ãªããªããŸããäž¡æ¹ã®åé¡ãç¡å¶éã«è§£æ±ºããã«ã¯ãæåã®ã»ã«ã®ã¿ãéžæããŸãããã®åŸã以åã«éžæããã»ã«ã®é£ã«ããã»ã«ã®ã¿ãéžæããå¿
èŠããããŸãããããã®å¶éã¯ãã¹æ€çŽ¢ã®å¶éã«äŒŒãŠãããããããã§ãåãã¢ãããŒãã䜿çšããŸããã«ããããã«HexMapGenerator
ãç¬èªã®ããããã£ãšæ€çŽ¢å¢çã®ãã§ãŒãºã®ã«ãŠã³ã¿ãŒã远å ããŸãHexGrid
ã HexCellPriorityQueue searchFrontier; int searchFrontierPhase;
åªå
ãã¥ãŒãå¿
èŠã«ãªãåã«ååšããããšã確èªããŸãã public void GenerateMap (int x, int z) { cellCount = x * z; grid.CreateMap(x, z); if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } RaiseTerrain(7); }
æ°ããããããäœæããåŸããã¹ãŠã®ã»ã«ã®æ€çŽ¢å¢çã¯ãŒãã«ãªããŸãããã ãããããçæã®ããã»ã¹ã§ã»ã«ãæ€çŽ¢ããå Žåããã®ããã»ã¹ã§æ€çŽ¢å¢çãå¢ãããŸãã倿°ã®æ€çŽ¢æäœãå®è¡ããå Žåããããã¯èšé²ãããæ€çŽ¢å¢çã®ãã§ãŒãºã®åã«ããå¯èœæ§ããããŸãHexGrid
ãããã¯ããŠããããã¹ã®æ€çŽ¢ã劚ããå¯èœæ§ããããŸãããããåé¿ããããã«ããããçæããã»ã¹ã®æåŸã«ããã¹ãŠã®ã»ã«ã®æ€çŽ¢ãã§ãŒãºããŒãã«ãªã»ããããŸãã RaiseTerrain(7); for (int i = 0; i < cellCount; i++) { grid.GetCell(i).SearchPhase = 0; }
次ã«RaiseTerrain
ãé©åãªã»ã«ãæ¢ããŠãã©ã³ãã ã«éžæããå¿
èŠã¯ãããŸããããã®ããã»ã¹ã¯ãã®æ€çŽ¢æ¹æ³ã«éåžžã«äŒŒãŠããŸãHexGrid
ããã ããã»ã«ã«è€æ°åã¢ã¯ã»ã¹ããããšã¯ãªããããæ€çŽ¢å¢çã®äœçžã2ã§ã¯ãªã1å¢ããã ãã§ååã§ãããã®åŸãã©ã³ãã ã«éžæãããæåã®ã»ã«ã§å¢çãåæåããŸããéåžžã©ãããæ€çŽ¢ãã§ãŒãºã®æå®ã«å ããŠãè·é¢ãšãã¥ãŒãªã¹ãã£ãã¯ã«ãŒãã®å€ãå²ãåœãŠãŸãã void RaiseTerrain (int chunkSize) {
ãã®åŸãæ€çŽ¢ã«ãŒãã¯ã»ãšãã©ããªãã¿ã«ãªããŸããããã«ãå¢çã空ã«ãªããŸã§æ€çŽ¢ãç¶è¡ããã«ã¯ããã©ã°ã¡ã³ããç®çã®ãµã€ãºã«éãããšãã«åæ¢ããå¿
èŠãããããã远跡ããŸããåå埩ã§ããã¥ãŒããæ¬¡ã®ã»ã«ãæœåºããææžã®ã¿ã€ããèšå®ãããµã€ãºã倧ããããŠããããã®ã»ã«ã®é£æ¥ã»ã«ããã€ãã¹ããŸãããã¹ãŠã®é£äººã¯ããŸã 远å ãããŠããªãå Žåãåã«åœå¢ã«è¿œå ãããŸãã倿Žãæ¯èŒãè¡ãå¿
èŠã¯ãããŸãããå®äºããããå¢çç·ãã¯ãªã¢ããå¿
èŠããããŸãã searchFrontier.Enqueue(firstCell); int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.TerrainTypeIndex = 1; size += 1; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor && neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = 0; neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } } } searchFrontier.Clear();
ã»ã«ã®ã©ã€ã³ãé©åãªãµã€ãºã®åäžã®ãããããåŸãŸãããã»ã«ã®æ°ãååã§ãªãå Žåã«ã®ã¿å°ãããªããŸããå¢çç·ãå¡ãã€ã¶ããããããããããã¯åžžã«å西ã«äŒžã³ãç·ã§æ§æãããŸãããããã®ç«¯ã«å°éãããšãã«ã®ã¿æ¹åã倿ŽããŸããã»ã«ãã€ãªã
éžå°ãç·ã«äŒŒãŠããããšã¯ãã£ãã«ãããŸããããç·ã䌌ãŠããå Žåãåžžã«åãæ¹åã«åããŠãããšã¯éããŸããããµã€ãã®åœ¢ç¶ã倿Žããã«ã¯ãã»ã«ã®åªå
é äœã倿Žããå¿
èŠããããŸããæåã®ã©ã³ãã ãªã»ã«ã¯ãããããã®äžå¿ãšããŠäœ¿çšã§ããŸãããããããšãä»ã®ãã¹ãŠã®ã»ã«ãŸã§ã®è·é¢ã¯ããã®ç¹ãåºæºã«ããŠããŸãããã®ãããäžå¿ã«è¿ãã»ã«ã«é«ãåªå
é äœãäžããããããµã€ãã¯ç·ãšããŠã§ã¯ãªãäžå¿ã®åšãã«æé·ããŸãã searchFrontier.Enqueue(firstCell); HexCoordinates center = firstCell.coordinates; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.TerrainTypeIndex = 1; size += 1; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor && neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = neighbor.coordinates.DistanceTo(center); neighbor.SearchHeuristic = 0; searchFrontier.Enqueue(neighbor); } } }
现èã®èç©ãå®éãäžå€®ã®ã»ã«ããããã®ç«¯ã«è¡šç€ºãããªãå Žåã7ã€ã®ã»ã«ã¯ã³ã³ãã¯ããªå
è§åœ¢ã®é åã«çŸããè©°ã蟌ãŸããŠããŸãã30ã®ãããããµã€ãºã䜿çšããŠã¿ãŸãããã RaiseTerrain(30);
30ã»ã«ã®å¯¿åžãã¹ãæ£ããå
è§åœ¢ãåŸãã®ã«ååãªã»ã«ããããŸããã§ããããåã³åã圢ç¶ã«ãªããŸãããããããã®ååŸã倧ããããããããã®ç«¯ã«è¿ããªãå¯èœæ§ãé«ããªããããããå¥ã®åœ¢ç¶ã«åŒ·å¶ããŸãã寿åžã®ã©ã³ãã å
ãã¹ãŠã®é åãåãããã«èŠããããšãæãŸãªããããã»ã«ã®åªå
床ããããã«å€æŽããŸããå¢çã«é£æ¥ããã»ã«ã远å ãããã³ã«ãæ¬¡ã®æ°å€ãRandom.value
ç¹å®ã®ãããå€ãããå°ããå Žåããã®ã»ã«ã®ãã¥ãŒãªã¹ãã£ãã¯ã¯0ã§ã¯ãªã1ã«ãªããŸãããããå€ãšããŠå€0.5ã䜿çšããŸãã neighbor.Distance = neighbor.coordinates.DistanceTo(center); neighbor.SearchHeuristic = Random.value < 0.5f ? 1: 0; searchFrontier.Enqueue(neighbor);
æªãã é åãã»ã«ã®æ€çŽ¢ãã¥ãŒãªã¹ãã£ãã¯ãå¢ããããšã§ãäºæ³ãããé
ãã¢ã¯ã»ã¹ããŸãããåæã«ããã¥ãŒãªã¹ãã£ãã¯ãå¢å ãããªãéããäžå¿ãã1ã¹ãããé¢ããå Žæã«ããä»ã®ã»ã«ãæ©ãã¢ã¯ã»ã¹ãããŸããã€ãŸãããã¹ãŠã®ã»ã«ã®ãã¥ãŒãªã¹ãã£ãã¯ã1ã€ã®å€ã ãå¢ãããŠãããããã«ã¯ãŸã£ãã圱é¿ããŸãããã€ãŸãããããå€0ã®ãããªãããå€1ã®å¹æã¯ãããŸããããŸãããããå€0.8ã¯0.2ã«çžåœããŸããã€ãŸãã確çã0.5ã®å Žåãæ€çŽ¢ããã»ã¹ãæããéããŠãããããšã«ãªããŸããæ¯åã®é©åãªéã¯ãåžæããå°åœ¢ã®ã¿ã€ãã«ãã£ãŠç°ãªããŸãã®ã§ãã«ã¹ã¿ãã€ãºå¯èœã«ããŸããããjitterProbability
屿§ãæã€äžè¬çãªãããŒããã£ãŒã«ãããžã§ãã¬ãŒã¿ãŒã«è¿œå ããŸãRange
0ã0.5ã®ç¯å²ã§å¶éãããŸãããã®ééã®å¹³åãã€ãŸã0.25ã«çããããã©ã«ãå€ãèšå®ããŸããããããã«ãããUnityã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠã§ãžã§ãã¬ãŒã¿ãŒãæ§æã§ããŸãã [Range(0f, 0.5f)] public float jitterProbability = 0.25f;
å€åã®ç¢ºçãã²ãŒã UIã§ã«ã¹ã¿ãã€ãºå¯èœã«ã§ããŸããïŒ, . UI, . , UI. , . , .
ããã§ããã¥ãŒãªã¹ãã£ãã¯ã1ã«ãªãã¿ã€ãã³ã°ã決å®ããããã«ã宿°å€ã®ä»£ããã«ç¢ºçã䜿çšããŸãã neighbor.SearchHeuristic = Random.value < jitterProbability ? 1: 0;
ãã¥ãŒãªã¹ãã£ãã¯å€0ãš1ã䜿çšããŸãããã倧ããªå€ã䜿çšã§ããŸãããããã«ããã»ã¯ã·ã§ã³ã®å€åœ¢ã倧å¹
ã«æªåããã»ãšãã©ã®å Žåãã¹ãã©ã€ãã®æã«ãªããŸããããã€ãã®åå°ãäžãã
1ã€ã®åå°ã®çæã«éå®ãããŸãããããšãã°RaiseTerrain
ãã«ãŒãå
ã«åŒã³åºããé
眮ãââãŠã5ã€ã®ã»ã¯ã·ã§ã³ãååŸããŸãã for (int i = 0; i < 5; i++) { RaiseTerrain(30); }
åå°ã®5ã€ã®åºç»ãçŸåšã¯ãããã30ã»ã«ã®5ã€ã®ãããããçæããŠããŸãããå¿
ããã150ã»ã«ã®åå°ãååŸããŠããããã§ã¯ãããŸãããåãµã€ãã¯åå¥ã«äœæããããããäºããèªèããŠããªãããã亀差ããå¯èœæ§ããããŸããããã¯éåžžã®ããšã§ããå€ç«ããã»ã¯ã·ã§ã³ã®ã»ãããããè峿·±ãã©ã³ãã¹ã±ãŒããäœæã§ããããã§ããåå°ã®å€åæ§ãé«ããããã«ãåããããã®ãµã€ãºã倿Žããããšãã§ããŸãã2ã€ã®æŽæ°ãã£ãŒã«ãã远å ããŠãããããã®æå°ãµã€ãºãšæå€§ãµã€ãºãå¶åŸ¡ããŸãããããã«ååãªééãããšãã°20ã200ãå²ãåœãŠãŸããæšæºã®æå°å€ã30ãæšæºã®æå€§å€ã100ã«ããŸãã [Range(20, 200)] public int chunkSizeMin = 30; [Range(20, 200)] public int chunkSizeMax = 100;
ãµã€ãžã³ã°ééããããã®ãã£ãŒã«ãã䜿çšããŠãåŒã³åºããRaiseTerrain
ããšãã«é åã®ãµã€ãºãã©ã³ãã ã«æ±ºå®ããŸãã RaiseTerrain(Random.Range(chunkSizeMin, chunkSizeMax + 1));
äžå€®ã®ãããäžã®ã©ã³ãã ã«ãµã€ãºèšå®ããã5ã€ã®ã»ã¯ã·ã§ã³ãååãªå¯¿åžãäœã
çæãããåå°ã®éãç¹ã«å¶åŸ¡ããããšã¯ã§ããŸããããããããæ°ã®æ§æãªãã·ã§ã³ã远å ã§ããŸãããããããèªäœã®ãµã€ãºã¯ã©ã³ãã ã§ããããããã«ãŸãã¯åŒ·ãéãªãå ŽåããããŸãããããã£ãŠããµã€ãã®æ°ã¯ãå¿
èŠãªåå°ã®å°å³äžã®é åæžãä¿èšŒãããã®ã§ã¯ãããŸãããæŽæ°ãšããŠè¡šãããåå°ã®å²åãçŽæ¥å¶åŸ¡ãããªãã·ã§ã³ã远å ããŸãããã100ïŒ
ã®åå°ãæ°Žã¯ããŸãããããããªãã®ã§ã5ã95ã®ééã«å¶éããŸããããã©ã«ãã§ã¯50ã§ãã [Range(5, 95)] public int landPercentage = 50;
寿åžã®å²åãé©åãªéââã®åå°ã®äœæãä¿èšŒããããã«ãååãªéãåŸããããŸã§å°åœ¢ã®ãšãªã¢ãäžãç¶ããå¿
èŠããããŸãããããè¡ãã«ã¯ãåå°ã®çæãè€éã«ããããã»ã¹ãå¶åŸ¡ããå¿
èŠããããŸãããããã£ãŠãæ°ããã¡ãœãããåŒã³åºããŠããµã€ããäžããæ¢åã®ãµã€ã¯ã«ã眮ãæããŸãããCreateLand
ããã®ã¡ãœãããæåã«è¡ãããšã¯ãåå°ã«ãªãã»ã«ã®æ°ãèšç®ããããšã§ãããã®éã¯ã寿åžçްèã®åèšã«ãªããŸãã public void GenerateMap (int x, int z) { âŠ
CreateLand
RaiseTerrain
现èå
šäœã䜿ãæãããŸã§ éé¡ãè¶
ããªãããã«ããããRaiseTerrain
ã远å ã®ãã©ã¡ãŒã¿ãšããŠéé¡ãåãåãããã«å€æŽããŸããä»äºãçµããåŸãåœŒã¯æ®ãã®éé¡ãè¿ããªããã°ãªããŸããã
ã»ã«ãå¢çããåé€ãããåå°ã«å€æããããã³ã«ãéã¯æžå°ããã¯ãã§ãããã®åŸãå
šé¡ã䜿çšãããå Žåãæ€çŽ¢ã忢ããŠãµã€ããå®äºããå¿
èŠããããŸãããŸããããã¯ãçŸåšã®ã»ã«ããŸã åå°ã§ãªãå Žåã«ã®ã¿å®è¡ããå¿
èŠããããŸãã while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); if (current.TerrainTypeIndex == 0) { current.TerrainTypeIndex = 1; if (--budget == 0) { break; } } size += 1; ⊠}
ä»ã§CreateLand
ã¯ã现èã®å
šéã䜿ããŸã§åå°ãäžããããšãã§ããŸãã void CreateLand () { int landBudget = Mathf.RoundToInt(cellCount * landPercentage * 0.01f); while (landBudget > 0) { landBudget = RaiseTerrain( Random.Range(chunkSizeMin, chunkSizeMax + 1), landBudget ); } }
ãããã®ã¡ããã©ååãåå°ã«ãªããŸããããŠããã£ããã±ãŒãžé«ããèæ
®ã«å
¥ãã
åå°ã¯åãªã海岞ç·ã§ã¯ãªããæµ·å²žç·ã«ãã£ãŠå¶éãããŠããŸãã圌女ã¯ãäžãå±±ãè°·ãæ¹ãªã©ãå«ããå€åããé«ããæã£ãŠããŸãããã£ãããšç§»åããæ§é ãã¬ãŒãã®çžäºäœçšã«ãããé«ãã«å€§ããªéãããããŸããã·ãã¥ã¬ãŒãããŸããããç§ãã¡ã®åå°ã¯äœããã®åœ¢ã§ãã®ãããªãã¬ãŒãã«äŒŒãŠããã¯ãã§ãããµã€ãã¯ç§»åããŸãããã亀差ããå ŽåããããŸãããããŠããããå©çšã§ããŸããåå°ãæŒãäžãã
åã»ã¯ã·ã§ã³ã¯ãæµ·åºããæŒãåºãããåå°ã®äžéšã瀺ããŠããŸãããããã£ãŠãçŸåšã®ã»ã«ã®é«ããåžžã«å¢ãããŠãRaiseTerrain
äœãèµ·ããããèŠãŠã¿ãŸãããã HexCell current = searchFrontier.Dequeue(); current.Elevation += 1; if (current.TerrainTypeIndex == 0) { ⊠}
é«ãã®ããåå°ãé«ãã¯ããããŸããããèŠã«ããã§ããå°ççãªéå±€åãªã©ãåé«ãã¬ãã«ã«ç¬èªã®å°åœ¢ã¿ã€ãã䜿çšãããšãããããããèªã¿ãããããããšãã§ããŸããããã¯ãé«ããããç®ç«ãããããã«ã®ã¿è¡ãã®ã§ãåã«é«ãã¬ãã«ãæšé«ã€ã³ããã¯ã¹ãšããŠäœ¿çšã§ããŸããé«ããå°åœ¢ã¿ã€ãã®æ°ãè¶
ãããšã©ããªããŸããïŒ. , .
é«ãã倿Žãããã³ã«ã»ã«ã®å°åœ¢ã¿ã€ããæŽæ°ãã代ããã«ãSetTerrainType
ãã¹ãŠã®å°åœ¢ã¿ã€ãã1åã ãèšå®ããå¥ã®ã¡ãœãããäœæããŸãããã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); cell.TerrainTypeIndex = cell.Elevation; } }
寿åžãäœæããåŸã«ãã®ã¡ãœãããåŒã³åºããŸãã public void GenerateMap (int x, int z) { ⊠CreateLand(); SetTerrainType(); ⊠}
ä»ã圌RaiseTerrain
ã¯ã¿ã€ãã®ææžã«å¯ŸåŠããããšãã§ãããé«ãã«éäžããããšãã§ããŸããããããè¡ãã«ã¯ããã®ããžãã¯ã倿Žããå¿
èŠããããŸããçŸåšã®ã»ã«ã®æ°ããé«ãã1ã§ããå Žåããã®ã»ã«ã¯ãã也ç¥ããŠãããããã»ã«ã®åèšãæžå°ãããµã€ãã®æé·ã®å®äºã«ã€ãªããå¯èœæ§ããããŸãã HexCell current = searchFrontier.Dequeue(); current.Elevation += 1; if (current.Elevation == 1 && --budget == 0) { break; }
å±€ã®å±€åãæ°Žãå ãã
ãã¹ãŠã®ã»ã«ã®æ°Žäœã1ã«èšå®ããŠãã©ã®ã»ã«ãæ°ŽãŸãã¯åå°ã§ããããæç€ºçã«ç€ºããŸãããGenerateMap
ãåå°ãäœæããåã«ãããå®è¡ããŸãã public void GenerateMap (int x, int z) { cellCount = x * z; grid.CreateMap(x, z); if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } for (int i = 0; i < cellCount; i++) { grid.GetCell(i).WaterLevel = 1; } CreateLand(); ⊠}
åå°ã¬ã€ã€ãŒã®æå®ã«ã¯ãããããã¿ã€ãã®å°åœ¢ã䜿çšã§ããŸããæäžå±€ã®ã»ã«ãšåæ§ã«ããã¹ãŠã®æµ·åºã»ã«ã¯ç ã®ãŸãŸã§ããããã¯ãé«ãããæ°Žäœãæžç®ãããã®å€ãã¬ãªãŒãã¿ã€ãã®ã€ã³ããã¯ã¹ãšããŠäœ¿çšããããšã§å®è¡ã§ããŸãã void SetTerrainType () { for (int i = 0; i < cellCount; i++) { HexCell cell = grid.GetCell(i); if (!cell.IsUnderwater) { cell.TerrainTypeIndex = cell.Elevation - cell.WaterLevel; } } }
åå°ãšæ°Žãæ°Žäœãäžãã
1ã€ã®æ°Žäœã«éå®ãããŸãããééã1ã5ã§ããã©ã«ãå€ã3ã®å
±éãã£ãŒã«ãã䜿çšããŠãã«ã¹ã¿ãã€ãºå¯èœã«ããŸãããããã®ã¬ãã«ã䜿çšããŠãã»ã«ãåæåããŸãã [Range(1, 5)] public int waterLevel = 3; ⊠public void GenerateMap (int x, int z) { ⊠for (int i = 0; i < cellCount; i++) { grid.GetCell(i).WaterLevel = waterLevel; } ⊠}
æ°Žäœ3ãæ°Žäœã3ã®å Žåãäºæ³ãããå°ãªãåå°ãåŸãããŸããããã¯ãRaiseTerrain
æ°Žäœã1ã§ãããšãŸã ä¿¡ããŠããããã§ãããããä¿®æ£ããŸãããã HexCell current = searchFrontier.Dequeue(); current.Elevation += 1; if (current.Elevation == waterLevel && --budget == 0) { break; }
ããé«ãæ°Žäœã䜿çšãããšãããã«ã€ãªãããŸãã现èãããã«åå°ã«ãªããªãããšãæ°Žäœã2ã®å Žåãæåã®ã»ã¯ã·ã§ã³ã¯æ°Žé¢äžã«æ®ããŸããæµ·ã®åºã¯äžæããŠããŸããããŸã æ°Žé¢äžã«ãããŸããåå°ã¯ãå°ãªããšã2ã€ã®ã»ã¯ã·ã§ã³ã®äº€å·®ç¹ã§ã®ã¿åœ¢æãããŸããæ°Žäœãé«ãã»ã©ãåå°ãäœæããããã«ããå€ãã®ãµã€ããæšªæããå¿
èŠããããŸãããããã£ãŠãæ°Žäœãäžæãããšãåå°ã¯ããæ··oticãšããŸããããã«ãããå€ãã®ãããããå¿
èŠãªå Žåãæ¢åã®åå°ã§äº€å·®ããå¯èœæ§ãé«ããªããŸãããã®ãããããå°ããªããããã䜿çšããå Žåã®ããã«ãå±±ãããäžè¬çã§ãããå¹³åŠãªåå°ã¯ããŸããããŸãããæ°Žäœã¯2ã5ã§ã寿åžã¯åžžã«50ïŒ
ã§ãããŠããã£ããã±ãŒãžäžäžå
ãããŸã§ã§ããããããäžåºŠã«1ã¬ãã«äžããŸããããããã«éå®ããå¿
èŠã¯ãããŸãããé«ããµã€ã
åã»ã¯ã·ã§ã³ã¯ã»ã«ã®é«ãã1ã¬ãã«å¢ãããŸãããã¯ãªããã³ã°ãçºçããå ŽåããããŸããããã¯ã2ã€ã®ã»ã¯ã·ã§ã³ã®ãšããžãæ¥è§Šãããšãã«çºçããŸããããã«ããå€ç«ããåŽãã§ããŸãããé·ãåŽç·ã¯ãŸãã§ããããããã®é«ãã1ã¹ããã以äžå¢ããããšã§ãåºçŸé »åºŠãå¢ããããšãã§ããŸãããã ããããã¯ç¹å®ã®å²åã®ãµã€ãã«å¯ŸããŠã®ã¿è¡ãå¿
èŠããããŸãããã¹ãŠã®ãšãªã¢ãé«ããªããšãå°åœ¢ã«æ²¿ã£ãŠç§»åããããšãéåžžã«å°é£ã«ãªããŸãã0.25ã®ããã©ã«ãå€ãæã€ç¢ºçãã£ãŒã«ãã䜿çšããŠããã®ãã©ã¡ãŒã¿ãŒãã«ã¹ã¿ãã€ãºå¯èœã«ããŸãããã [Range(0f, 1f)] public float highRiseProbability = 0.25f;
现èã®åŒ·ãäžæã®å¯èœæ§ãé«ãé åã§ã¯é«ãã®å¢å ã䜿çšã§ããŸãããããã¯ããã«æã«è² ããªããªããŸããé«ãã®å·®2ã¯ãã§ã«åŽãäœã£ãŠããã®ã§ãããã§ååã§ããæ°Žäœã«çããé«ããã¹ãããã§ãããããã»ã«ãéžå°ã«ãªã£ããã©ããã倿ããæ¹æ³ã倿Žããå¿
èŠããããŸããæ°Žäœãäžåããåãã¬ãã«ä»¥äžã«ãªã£ãå Žåãæ°ããåå°ã»ã«ãäœæããŸããã int rise = Random.value < highRiseProbability ? 2 : 1; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; current.Elevation = originalElevation + rise; if ( originalElevation < waterLevel && current.Elevation >= waterLevel && --budget == 0 ) { break; } size += 1; ⊠}
é«ãã倧å¹
ã«å¢å ãã確çã¯ã0.25ã0.50ã0.75ãããã³1ã§ããåå°ãäžãã
åå°ã¯åžžã«äžæããããã§ã¯ãªããæã«ã¯äžéããããšããããŸããåå°ãååã«äœããªããšãæ°Žããã£ã±ãã«ãªãã倱ãããŸãããããŸã§ã®ãšããããããè¡ã£ãŠããŸãããç§ãã¡ã¯ãšãªã¢ãæŒãäžããã ããªã®ã§ãéåžžãåå°ã¯ãŸãšãŸãã®ãªãäžžããšãªã¢ã®ã»ããã®ããã«èŠããŸããæã
ãšãªã¢ãäžãããšããã倿§ãªãã©ãŒã ãåŸãããŸããæ²ãã 寿åžã®ãªã倧ããªå°å³ãå¥ã®ç¢ºçãã£ãŒã«ãã䜿çšããŠãå°ç€æ²äžã®é »åºŠãå¶åŸ¡ã§ããŸããäœäžã¯åå°ãç Žå£ããå¯èœæ§ããããããäœäžã®ç¢ºçã¯åžžã«äžæã®ç¢ºçããäœããªããã°ãªããŸãããããããªããšãé©åãªå²åã®åå°ãååŸããã®ã«éåžžã«æéããããå ŽåããããŸãããããã£ãŠã0.4ã®æå€§äœäžç¢ºçãš0.2ã®ããã©ã«ãå€ã䜿çšããŸãããã [Range(0f, 0.4f)] public float sinkProbability = 0.2f;
äœäžã®ç¢ºçããµã€ããäžããããšã¯äžããããšãšäŒŒãŠããŸãããããã€ãã®éãããããŸãããããã£ãŠãã¡ãœãããè€è£œããRaiseTerrain
ãã®ååãã«å€æŽãSinkTerrain
ãŸããäžæã®å€§ããã倿ãã代ããã«ãåãããžãã¯ã䜿çšã§ããäœäžå€ãå¿
èŠã§ããåæã«ãæ°Žé¢ãééãããã©ããã確èªããããã®æ¯èŒãè£è¿ãå¿
èŠããããŸããããã«ãã¬ãªãŒããäžãããšããã»ã«ã®åèšã«éå®ãããŸããã代ããã«ã倱ããã寿åžã®ã»ã«ããšã«æ¶è²»ããéé¡ãè¿ãããããããããå¢ãããŠäœæ¥ãç¶ããŸãã int SinkTerrain (int chunkSize, int budget) { ⊠int sink = Random.value < highRiseProbability ? 2 : 1; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; current.Elevation = originalElevation - sink; if ( originalElevation >= waterLevel && current.Elevation < waterLevel
ããã§ãå
éšã®åå埩ã§ãCreateLand
äœäžãã確çã«å¿ããŠãåå°ãäœäžãŸãã¯äžæãããå¿
èŠããããŸãã void CreateLand () { int landBudget = Mathf.RoundToInt(cellCount * landPercentage * 0.01f); while (landBudget > 0) { int chunkSize = Random.Range(chunkSizeMin, chunkSizeMax - 1); if (Random.value < sinkProbability) { landBudget = SinkTerrain(chunkSize, landBudget); } else { landBudget = RaiseTerrain(chunkSize, landBudget); } } }
ããããã®ç¢ºçã¯ã0.1ã0.2ã0.3ãããã³0.4ã§ããé«ããå¶éãã
çŸåšã®æ®µéã§ã¯ãæœåšçã«å€ãã®ã»ã¯ã·ã§ã³ããªãŒããŒã©ãããããããšãã§ããŸããå Žåã«ãã£ãŠã¯ãããã€ãã®é«ãã®å¢å ããããäžéšã¯äžãã£ãŠããåã³äžæããããšããããŸããåæã«ãç¹ã«é«ãå²åã®åå°ãå¿
èŠãªå Žåã«ã¯ãéåžžã«é«ããå Žåã«ãã£ãŠã¯éåžžã«äœãé«ããäœæã§ããŸãã90ïŒ
ã®åå°ã§ã®å·šå€§ãªé«ããé«ããå¶éããã«ã¯ãã«ã¹ã¿ã ã®æå°å€ãšæå€§å€ã远å ããŸããããåççãªæå°å€ã¯-4ã0ã®éã§ã蚱容ãããæå€§å€ã¯6ã10ã®ç¯å²ã§ããããã©ã«ãå€ã-2ãš8ã«ããŸããããããæåã§ç·šéããå Žåã蚱容ç¯å²å€ã«ãªããããUIãšãã£ã¿ãŒã®ã¹ã©ã€ããŒã倿Žãããããã®ãŸãŸã«ããŠããããšãã§ããŸãã [Range(-4, 0)] public int elevationMinimum = -2; [Range(6, 10)] public int elevationMaximum = 8;
æå°ããã³æå€§ã®é«ããããRaiseTerrain
ã§ãé«ãã蚱容æå€§å€ãè¶
ããªãããã«ããå¿
èŠããããŸããããã¯ãçŸåšã®ã»ã«ãé«ããããã©ããã確èªããããšã§å®è¡ã§ããŸãããã®å Žåãé«ãã倿Žããã«ããããã®é£äººã远å ããã«ããããã¹ãããããŸããããã¯ãéžå°ãæå€§ã®é«ãã«éããå°åãé¿ãããã®åšèŸºã§æé·ãããšããäºå®ã«ã€ãªãããŸãã HexCell current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; int newElevation = originalElevation + rise; if (newElevation > elevationMaximum) { continue; } current.Elevation = newElevation; if ( originalElevation < waterLevel && newElevation >= waterLevel && --budget == 0 ) { break; } size += 1;
ã§åãããšãããŸãããSinkTerrain
ããã ããæå°ã®é«ãã«ã€ããŠã§ãã HexCell current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; int newElevation = current.Elevation - sink; if (newElevation < elevationMinimum) { continue; } current.Elevation = newElevation; if ( originalElevation >= waterLevel && newElevation < waterLevel ) { budget += 1; } size += 1;
åå°ã90ïŒ
ã®éãããé«ããè² ã®é«åºŠã®ä¿å
ãã®æç¹ã§ãä¿åããã³ããŒãã³ãŒãã¯è² ã®é«ããåŠçã§ããŸãããããã¯ãé«ãããã€ããšããŠä¿åããããã§ããè² ã®æ°ã¯ã倧ããªæ£ã®å€ã«ä¿åããããšãã«å€æãããŸãããã®ãããçæãããããããä¿åããã³ããŒããããšãå
ã®æ°Žäžã»ã«ã®ä»£ããã«éåžžã«é«ããããã衚瀺ãããå ŽåããããŸããè² ã®é«ãã®ãµããŒãã远å ããã«ã¯ããã€ãã§ã¯ãªãæŽæ°ãšããŠä¿åããŸãããã ããè€æ°ã¬ãã«ã®é«ãããµããŒãããå¿
èŠã¯ãããŸãããããã«ã127ã远å ããããšã§ãæ ŒçŽãããå€ãã·ããã§ããŸããããã«ããã1ãã€ãå
ã§-127ã128ã®ç¯å²ã®é«ããæ£ããæ ŒçŽã§ããŸããHexCell.Save
ããã«å¿ããŠå€æŽããŸãã public void Save (BinaryWriter writer) { writer.Write((byte)terrainTypeIndex); writer.Write((byte)(elevation + 127)); ⊠}
ãããããŒã¿ã®ä¿åæ¹æ³ã倿ŽããããSaveLoadMenu.mapFileVersion
ã4ã«å¢ãããŸããã const int mapFileVersion = 4;
ãããŠæåŸã«ãHexCell.Load
ããŒãžã§ã³4ãã¡ã€ã«ããããŒããããé«ããã127ãåŒãããã«å€æŽããŸãã public void Load (BinaryReader reader, int header) { terrainTypeIndex = reader.ReadByte(); ShaderData.RefreshTerrain(this); elevation = reader.ReadByte(); if (header >= 4) { elevation -= 127; } ⊠}
ãŠããã£ããã±ãŒãžåãããããåäœæãã
ããã§ãããŸããŸãªããããäœæã§ããŸããããããã®æ°ããçµæãçæãããšããã©ã³ãã ã«ãªããŸããèšå®ãªãã·ã§ã³ã§ã¯ãã«ãŒãã®ç¹æ§ã®ã¿ãå¶åŸ¡ã§ããŸãããæãæ£ç¢ºãªãã©ãŒã ã¯å¶åŸ¡ã§ããŸããããã ãããŸã£ããåãããããååºŠäœæããå¿
èŠãããå ŽåããããŸããããšãã°ãçŸããå°å³ãå人ãšå
±æããããæåã§ç·šéããåŸã«åã³éå§ãããããŸããã²ãŒã éçºããã»ã¹ã§ã圹ç«ã¡ãŸãã®ã§ããã®æ©èœã远å ããŸããããã·ãŒãã䜿çšãã
ãããçæããã»ã¹ãäºæž¬äžèœã«ããããã«Random.Range
ãand ã䜿çšãRandom.value
ãŸããåãæ¬äŒŒä¹±æ°åãå床ååŸããã«ã¯ãåãã·ãŒãå€ã䜿çšããå¿
èŠããããŸãã以åã«ãåæ§ã®ã¢ãããŒãããã§ã«æ¡çšããŠãHexMetrics.InitializeHashGrid
ãŸããæåã«ãç¹å®ã®ã·ãŒãå€ã§åæåãããæ°å€ãžã§ãã¬ãŒã¿ãŒã®çŸåšã®ç¶æ
ãä¿åããŠãããå
ã®ç¶æ
ã埩å
ããŸããã«ãåãã¢ãããŒãã䜿çšã§ããŸãHexMapGenerator.GenerateMap
ãã䜿çšããä»ã®èŠçŽ ã«å¹²æžããªãããã«ãå€ãç¶æ
ãååºŠèšæ¶ããå®äºåŸã«åŸ©å
ã§ããŸãRandom
ã public void GenerateMap (int x, int z) { Random.State originalRandomState = Random.state; ⊠Random.state = originalRandomState; }
次ã«ãæåŸã®ã«ãŒãã®çæã«äœ¿çšããã·ãŒããå©çšå¯èœã«ããå¿
èŠããããŸããããã¯ãäžè¬çãªæŽæ°ãã£ãŒã«ãã䜿çšããŠè¡ãããŸãã public int seed;
ã·ãŒãã衚瀺ããŸããããã§ãåæåããã·ãŒãå€ãå¿
èŠRandom
ã§ããã©ã³ãã ã«ãŒããäœæããã«ã¯ãã©ã³ãã ã·ãŒãã䜿çšããå¿
èŠããããŸããæãç°¡åãªã¢ãããŒãã¯ãä»»æã®ã·ãŒãå€ã䜿çšããŠãçæããããšRandom.Range
ã§ããåæã©ã³ãã ç¶æ
ã«åœ±é¿ãäžããªãããã«ãä¿ååŸã«ãããè¡ãå¿
èŠããããŸãã public void GenerateMap (int x, int z) { Random.State originalRandomState = Random.state; seed = Random.Range(0, int.MaxValue); Random.InitState(seed); ⊠}
å®äºåŸãã©ã³ãã ãªç¶æ
ã埩å
ãããããããã«å¥ã®ã«ãŒããçæãããšãçµæãšããŠåãã·ãŒãå€ãååŸãããŸããããã«ãåæã©ã³ãã ç¶æ
ãã©ã®ããã«åæåããããã¯ããããŸããããããã£ãŠãããã¯ä»»æã®éå§ç¹ãšããŠæ©èœããŸãããåŒã³åºãããšã«ã©ã³ãã åããããã«ããã«äœããå¿
èŠã§ããä¹±æ°ãžã§ãã¬ãŒã¿ãŒãåæåããã«ã¯ããŸããŸãªæ¹æ³ããããŸãããã®å Žåãåºãç¯å²ã§å€åããè€æ°ã®ä»»æã®å€ãåçŽã«çµã¿åãããããšãã§ããŸããã€ãŸããåãã«ãŒããåçæããå¯èœæ§ã¯äœããªããŸããããšãã°ããµã€ã¯ã«ã§è¡šãããã·ã¹ãã æéã®äžäœ32ããããšãã¢ããªã±ãŒã·ã§ã³ã®çŸåšã®ã©ã³ã¿ã€ã ã䜿çšããŸããçµæãããã»ã©å€§ãããªããªãããã«ããããããšã®æä»çORæŒç®ã䜿çšããŠãããã®å€ãçµã¿åãããŸãã seed = Random.Range(0, int.MaxValue); seed ^= (int)System.DateTime.Now.Ticks; seed ^= (int)Time.unscaledTime; Random.InitState(seed);
çµæã®æ°å€ã¯è² ã®å€ã«ãªãå ŽåããããŸããããããªãã¯ããªã¥ãŒã·ãŒãã®å Žåã¯ããŸãèŠæ ãããããããŸããã笊å·ãããããªã»ããããæå€§æŽæ°å€ã§ãããåäœã®ãã¹ã¯ã䜿çšããããšã§ãå³å¯ã«æ£ã«ããããšãã§ããŸãã seed ^= (int)Time.unscaledTime; seed &= int.MaxValue; Random.InitState(seed);
åå©çšå¯èœãªã·ãŒã
ã©ã³ãã ãªã«ãŒãã¯åŒãç¶ãçæãããŸãããããããã®ã·ãŒãå€ã䜿çšãããããšãããããŸããåãããããåäœæããã«ã¯ãæ°ããã·ãŒããäœæããã®ã§ã¯ãªãããžã§ãã¬ãŒã¿ã«åãã·ãŒãå€ãå床䜿çšããããã«åœä»€ããå¿
èŠããããŸãããããè¡ãã«ã¯ãããŒã«ãã£ãŒã«ãã䜿çšããŠã¹ã€ããã远å ããŸãã public bool useFixedSeed;
宿°ã·ãŒãã䜿çšãããªãã·ã§ã³ã宿°ã·ãŒããéžæãããŠããå Žåã¯ãåã«æ°ããã·ãŒãã®çæãã¹ããããGenerateMap
ãŸããã·ãŒããã£ãŒã«ããæåã§å€æŽããªãå Žåãçµæã¯åã³åããããã«ãªããŸãã Random.State originalRandomState = Random.state; if (!useFixedSeed) { seed = Random.Range(0, int.MaxValue); seed ^= (int)System.DateTime.Now.Ticks; seed ^= (int)Time.time; seed &= int.MaxValue; } Random.InitState(seed);
ããã§ãå°æ¥åã³çæããããã«ã奜ããªãããã®ã·ãŒãå€ãã³ããŒããŠã©ããã«ä¿åã§ããŸãããŸã£ããåããžã§ãã¬ãŒã¿ãŒãã©ã¡ãŒã¿ãŒãã€ãŸãåãã«ãŒããµã€ãºãããã³ä»ã®ãã¹ãŠã®æ§æãªãã·ã§ã³ã䜿çšããå Žåã«ã®ã¿ãåãã«ãŒããåãåãããšãå¿ããªãã§ãã ããããããã®ç¢ºçã®ããããªå€åã§ããããŸã£ããç°ãªãããããäœæã§ããŸãããããã£ãŠãã·ãŒãã«å ããŠããã¹ãŠã®èšå®ãèšæ¶ããå¿
èŠããããŸããã·ãŒãå€0ããã³929396788ã®å€§ããªã«ãŒããæšæºãã©ã¡ãŒã¿ãŒããŠããã£ããã±ãŒãž