106 lines
3.2 KiB
C#
106 lines
3.2 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class MengaturGridE : MonoBehaviour
|
|
{
|
|
public LayerMask unwalkableMask;
|
|
public Vector2 gridWorldSize;
|
|
public float nodeRadius;
|
|
[HideInInspector] public int visitedNodeCount = 0;
|
|
|
|
|
|
Node[,] grid;
|
|
float nodeDiameter;
|
|
int gridSizeX, gridSizeY;
|
|
|
|
void Awake()
|
|
{
|
|
nodeDiameter = nodeRadius * 2;
|
|
gridSizeX = Mathf.RoundToInt(gridWorldSize.x / nodeDiameter);
|
|
gridSizeY = Mathf.RoundToInt(gridWorldSize.y / nodeDiameter);
|
|
CreateGrid();
|
|
}
|
|
|
|
void CreateGrid()
|
|
{
|
|
grid = new Node[gridSizeX, gridSizeY];
|
|
Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2;
|
|
|
|
for (int x = 0; x < gridSizeX; x++)
|
|
{
|
|
for (int y = 0; y < gridSizeY; y++)
|
|
{
|
|
Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
|
|
bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask));
|
|
grid[x, y] = new Node(walkable, worldPoint, x, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Node NodeFromWorldPoint(Vector3 worldPosition)
|
|
{
|
|
float percentX = (worldPosition.x - transform.position.x + gridWorldSize.x / 2) / gridWorldSize.x;
|
|
float percentY = (worldPosition.z - transform.position.z + gridWorldSize.y / 2) / gridWorldSize.y;
|
|
|
|
percentX = Mathf.Clamp01(percentX);
|
|
percentY = Mathf.Clamp01(percentY);
|
|
|
|
int x = Mathf.RoundToInt((gridSizeX - 1) * percentX);
|
|
int y = Mathf.RoundToInt((gridSizeY - 1) * percentY);
|
|
|
|
return grid[x, y];
|
|
}
|
|
|
|
public List<Node> GetNeighbours(Node node)
|
|
{
|
|
List<Node> neighbours = new List<Node>();
|
|
|
|
int[,] arah = new int[,]
|
|
{
|
|
{ 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, // 4 arah utama
|
|
{ 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 } // 4 arah diagonal
|
|
};
|
|
|
|
for (int i = 0; i < arah.GetLength(0); i++)
|
|
{
|
|
int checkX = node.gridX + arah[i, 0];
|
|
int checkY = node.gridY + arah[i, 1];
|
|
|
|
if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY)
|
|
{
|
|
//cek tabrakan
|
|
if (Mathf.Abs(arah[i, 0]) == 1 && Mathf.Abs(arah[i, 1]) == 1)
|
|
{
|
|
Node n1 = grid[node.gridX + arah[i, 0], node.gridY];
|
|
Node n2 = grid[node.gridX, node.gridY + arah[i, 1]];
|
|
if (!n1.walkable || !n2.walkable)
|
|
continue; // Lewat diagonal dicegah jika sisi sampingnya tembok
|
|
}
|
|
|
|
neighbours.Add(grid[checkX, checkY]);
|
|
}
|
|
}
|
|
|
|
return neighbours;
|
|
}
|
|
|
|
|
|
|
|
// // Untuk debug visual di editor
|
|
// void OnDrawGizmos()
|
|
// {
|
|
// Gizmos.DrawWireCube(transform.position, new Vector3(gridWorldSize.x, 1, gridWorldSize.y));
|
|
|
|
// if (grid != null)
|
|
// {
|
|
// foreach (Node n in grid)
|
|
// {
|
|
// Gizmos.color = (n.walkable) ? Color.white : Color.red;
|
|
// Gizmos.DrawCube(n.worldPosition + Vector3.up * 0.1f, Vector3.one * (nodeRadius * 1.5f));
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
|