This commit is contained in:
MrTorex committed 2026-02-18 10:43:12 +03:00
1 parent 1b564e47e9
commit 7f65ead644
44 files changed
+4582 -2

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e6ed2809466848c8b1fbb7d87a465803
timeCreated: 1771392678
+42
View File
@@ -0,0 +1,42 @@
using System;
namespace Code.Lab6
{
[Serializable]
public class Edge : IComparable<Edge>
{
public float cost;
public readonly Vertex Vertex;
public Edge(Vertex vertex = null, float cost = 1f)
{
Vertex = vertex;
this.cost = cost;
}
public int CompareTo(Edge other)
{
var result = cost - other.cost;
var idA = Vertex.GetInstanceID();
var idB = other.Vertex.GetInstanceID();
if (idA == idB) return 0;
return (int)result;
}
public bool Equals(Edge other)
{
return other.Vertex.id == Vertex.id;
}
public override bool Equals(object obj)
{
var other = (Edge)obj;
return other != null && other.Vertex.id == Vertex.id;
}
public override int GetHashCode()
{
return Vertex.GetHashCode();
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d1cc93fbb8b74a3dbb53466e2ec007ad
timeCreated: 1771392690
+244
View File
@@ -0,0 +1,244 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Code.Lab6
{
public abstract class Graph : MonoBehaviour
{
public GameObject vertexPrefab;
protected List<Vertex> Vertices;
protected List<List<Vertex>> Neighbours;
protected List<List<float>> Costs;
public virtual void Start()
{
if (Application.isPlaying)
{
Load();
}
}
public virtual void Load() { }
public virtual int GetSize()
{
if (ReferenceEquals(Vertices, null)) return 0;
return Vertices.Count;
}
public virtual Vertex GetNearestVertex(Vector3 position)
{
return null;
}
public virtual Vertex GetVertexObj(int id)
{
if (ReferenceEquals(Vertices, null) || Vertices.Count == 0)
return null;
if (id < 0 || id >= Vertices.Count)
return null;
return Vertices[id];
}
public virtual Vertex[] GetNeighbours(Vertex v)
{
if (ReferenceEquals(Neighbours, null) || Neighbours.Count == 0 || v.id < 0 || v.id >= Neighbours.Count)
return Array.Empty<Vertex>();
return Neighbours[v.id].ToArray();
}
public virtual Edge[] GetEdges(Vertex v)
{
return v.neighbours == null ? Array.Empty<Edge>() : v.neighbours.ToArray();
}
public List<Vertex> GetPathBfs(GameObject srcObj, GameObject dstObj)
{
if (!srcObj || !dstObj)
return new List<Vertex>();
var src = GetNearestVertex(srcObj.transform.position);
var dst = GetNearestVertex(dstObj.transform.position);
if (!src || !dst)
{
Debug.LogWarning("Source or destination vertex is null");
return new List<Vertex>();
}
Debug.Log($"BFS from {src.id} to {dst.id}");
var previous = new Dictionary<int, int>();
var visited = new HashSet<int>();
var queue = new Queue<Vertex>();
visited.Add(src.id);
previous[src.id] = src.id;
queue.Enqueue(src);
while (queue.Count > 0)
{
var current = queue.Dequeue();
if (current.id == dst.id)
{
Debug.Log("BFS: Path found!");
return BuildPath(src.id, dst.id, previous);
}
var neighbours = GetNeighbours(current);
foreach (var neighbour in neighbours)
{
if (!neighbour) continue;
if (!visited.Add(neighbour.id)) continue;
previous[neighbour.id] = current.id;
queue.Enqueue(neighbour);
}
}
Debug.LogWarning("BFS: No path found");
return new List<Vertex>();
}
public List<Vertex> GetPathDfs(GameObject srcObj, GameObject dstObj)
{
if (!srcObj || !dstObj)
return new List<Vertex>();
var src = GetNearestVertex(srcObj.transform.position);
var dst = GetNearestVertex(dstObj.transform.position);
if (!src || !dst)
{
Debug.LogWarning("Source or destination vertex is null");
return new List<Vertex>();
}
Debug.Log($"DFS from {src.id} to {dst.id}");
var previous = new Dictionary<int, int>();
var visited = new HashSet<int>();
var stack = new Stack<Vertex>();
visited.Add(src.id);
previous[src.id] = src.id;
stack.Push(src);
while (stack.Count > 0)
{
var current = stack.Pop();
if (current.id == dst.id)
{
Debug.Log("DFS: Path found!");
return BuildPath(src.id, dst.id, previous);
}
var neighbours = GetNeighbours(current);
foreach (var neighbour in neighbours)
{
if (!neighbour) continue;
if (!visited.Add(neighbour.id)) continue;
previous[neighbour.id] = current.id;
stack.Push(neighbour);
}
}
Debug.LogWarning("DFS: No path found");
return new List<Vertex>();
}
private List<Vertex> BuildPath(int srcId, int dstId, Dictionary<int, int> previous)
{
var path = new List<Vertex>();
if (!previous.ContainsKey(dstId))
{
Debug.LogError("Destination not in previous dictionary");
return path;
}
var currentId = dstId;
while (currentId != srcId)
{
var currentVertex = GetVertexById(currentId);
if (!currentVertex)
{
Debug.LogError($"Vertex with id {currentId} not found");
break;
}
path.Add(currentVertex);
if (!previous.TryGetValue(currentId, out var previou))
{
Debug.LogError($"Previous not found for id {currentId}");
break;
}
currentId = previou;
}
var srcVertex = GetVertexById(srcId);
if (srcVertex is not null)
{
path.Add(srcVertex);
}
path.Reverse();
Debug.Log($"Path built with {path.Count} vertices");
return path;
}
private Vertex GetVertexById(int id)
{
return Vertices?.FirstOrDefault(v => v && v.id == id);
}
private List<Vertex> BuildPath(int srcId, int dstId, ref int[] prevList)
{
var path = new List<Vertex>();
var prev = dstId;
do
{
var v = GetVertexById(prev);
if (v == null)
{
Debug.LogError($"Vertex with id {prev} not found");
break;
}
path.Add(v);
if (prev < 0 || prev >= prevList.Length)
{
Debug.LogError($"Index {prev} out of range for prevList (size {prevList.Length})");
break;
}
prev = prevList[prev];
} while (prev != srcId && prev != -1);
if (prev != -1)
{
var srcV = GetVertexById(srcId);
if (srcV != null)
path.Add(srcV);
}
path.Reverse();
return path;
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d9a37e08f9ec46ab848036cca23dfbd4
timeCreated: 1771392722
+324
View File
@@ -0,0 +1,324 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace Code.Lab6
{
public class GraphGrid : Graph
{
public GameObject obstaclePrefab;
public string mapName = "arena.map";
public bool get8Vicinity = false;
public float cellSize = 1f;
[Range(0, Mathf.Infinity)]
public float defaultCost = 1f;
private const string MapsDir = "Resources/Maps";
private int _numCols;
private int _numRows;
private GameObject[] _vertexObj;
private bool[,] _mapVertices;
private Dictionary<int, int> _gridIdToVertexIndex;
private int GridToId(int x, int y)
{
return _numCols * y + x;
}
private Vector2Int IdToGrid(int id)
{
return new Vector2Int(id % _numCols, id / _numCols);
}
private void LoadMap(string filename)
{
var path = Application.dataPath + "/" + MapsDir + "/" + filename;
try
{
var strmRdr = new StreamReader(path);
using (strmRdr)
{
strmRdr.ReadLine();
var line = strmRdr.ReadLine();
if (line != null && line.StartsWith("height"))
{
_numRows = int.Parse(line.Split(' ')[1]);
}
else
{
Debug.LogError("Invalid map format: height line not found");
return;
}
line = strmRdr.ReadLine();
if (line != null && line.StartsWith("width"))
{
_numCols = int.Parse(line.Split(' ')[1]);
}
else
{
Debug.LogError("Invalid map format: width line not found");
return;
}
strmRdr.ReadLine();
var totalCells = _numRows * _numCols;
Vertices = new List<Vertex>();
Neighbours = new List<List<Vertex>>();
Costs = new List<List<float>>();
_vertexObj = new GameObject[totalCells];
_mapVertices = new bool[_numRows, _numCols];
_gridIdToVertexIndex = new Dictionary<int, int>();
Debug.Log($"Loading map {_numRows}x{_numCols} (total cells: {totalCells})");
for (var row = 0; row < _numRows; row++)
{
line = strmRdr.ReadLine();
if (string.IsNullOrEmpty(line) || line.Length < _numCols)
{
Debug.LogError($"Map line {row} is too short or missing");
continue;
}
for (var col = 0; col < _numCols; col++)
{
var cellChar = line[col];
var isGround = (cellChar == '.' || cellChar == 'G' || cellChar == ' ');
_mapVertices[row, col] = isGround;
var position = new Vector3(col * cellSize, 0f, row * cellSize);
var gridId = GridToId(col, row);
GameObject obj;
if (isGround && vertexPrefab != null)
{
obj = Instantiate(vertexPrefab, position, Quaternion.identity);
}
else if (!isGround && obstaclePrefab != null)
{
obj = Instantiate(obstaclePrefab, position, Quaternion.identity);
}
else
{
obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj.transform.position = position;
var renderer1 = obj.GetComponent<Renderer>();
if (renderer1 != null)
{
renderer1.material.color = isGround ? Color.green : Color.red;
}
}
if (obj == null) continue;
obj.name = $"{(isGround ? "Ground" : "Obstacle")}_{gridId}";
obj.transform.parent = transform;
var scale = obj.transform.localScale;
scale.x = cellSize;
scale.z = cellSize;
scale.y = isGround ? 0.1f : 1f;
obj.transform.localScale = scale;
_vertexObj[gridId] = obj;
if (!isGround) continue;
var v = obj.GetComponent<Vertex>();
if (v == null)
v = obj.AddComponent<Vertex>();
v.id = gridId;
v.neighbours = new List<Edge>();
var vertexIndex = Vertices.Count;
Vertices.Add(v);
Neighbours.Add(new List<Vertex>());
Costs.Add(new List<float>());
_gridIdToVertexIndex[gridId] = vertexIndex;
}
}
Debug.Log($"Created {Vertices.Count} walkable vertices");
foreach (var kvp in _gridIdToVertexIndex)
{
var gridId = kvp.Key;
var vertexIndex = kvp.Value;
var gridPos = IdToGrid(gridId);
SetNeighbours(gridPos.x, gridPos.y, vertexIndex);
}
Debug.Log($"Map loaded successfully. {Vertices.Count} walkable vertices");
}
}
catch (Exception e)
{
Debug.LogError($"Failed to load map: {e.Message}");
Debug.LogException(e);
}
}
protected void SetNeighbours(int x, int y, int vertexIndex)
{
var currentVertex = Vertices[vertexIndex];
var gridId = currentVertex.id;
Neighbours[vertexIndex].Clear();
Costs[vertexIndex].Clear();
currentVertex.neighbours.Clear();
Vector2Int[] directions;
if (get8Vicinity)
{
directions = new[]
{
new Vector2Int(x, y - 1), new Vector2Int(x + 1, y - 1), new Vector2Int(x + 1, y), new Vector2Int(x + 1, y + 1), new Vector2Int(x, y + 1), new Vector2Int(x - 1, y + 1), new Vector2Int(x - 1, y), new Vector2Int(x - 1, y - 1)
};
}
else
{
directions = new[]
{
new Vector2Int(x, y - 1), new Vector2Int(x + 1, y), new Vector2Int(x, y + 1), new Vector2Int(x - 1, y)
};
}
var diagonalCost = defaultCost * 1.4f;
foreach (var dir in directions)
{
if (dir.x < 0 || dir.x >= _numCols || dir.y < 0 || dir.y >= _numRows)
continue;
if (!_mapVertices[dir.y, dir.x])
continue;
var neighbourGridId = GridToId(dir.x, dir.y);
if (!_gridIdToVertexIndex.TryGetValue(neighbourGridId, out var neighbourIndex))
continue;
var neighbourVertex = Vertices[neighbourIndex];
var cost = defaultCost;
if (dir.x != x && dir.y != y)
{
cost = diagonalCost;
}
Neighbours[vertexIndex].Add(neighbourVertex);
Costs[vertexIndex].Add(cost);
currentVertex.neighbours.Add(new Edge(neighbourVertex, cost));
}
}
public override void Load()
{
LoadMap(mapName);
}
public override Vertex GetNearestVertex(Vector3 position)
{
var col = Mathf.RoundToInt(position.x / cellSize);
var row = Mathf.RoundToInt(position.z / cellSize);
col = Mathf.Clamp(col, 0, _numCols - 1);
row = Mathf.Clamp(row, 0, _numRows - 1);
if (!_mapVertices[row, col])
{
return FindNearestWalkable(col, row);
}
var gridId = GridToId(col, row);
return _gridIdToVertexIndex.TryGetValue(gridId, out var vertexIndex) ? Vertices[vertexIndex] : null;
}
private Vertex FindNearestWalkable(int startCol, int startRow)
{
var queue = new Queue<Vector2Int>();
var explored = new HashSet<Vector2Int>();
queue.Enqueue(new Vector2Int(startCol, startRow));
explored.Add(new Vector2Int(startCol, startRow));
const int maxSearchRadius = 20;
var steps = 0;
while (queue.Count > 0 && steps < maxSearchRadius * maxSearchRadius)
{
var pos = queue.Dequeue();
if (_mapVertices[pos.y, pos.x])
{
var gridId = GridToId(pos.x, pos.y);
if (_gridIdToVertexIndex.TryGetValue(gridId, out var vertexIndex))
{
return Vertices[vertexIndex];
}
}
var neighbours = new[]
{
new Vector2Int(pos.x, pos.y - 1),
new Vector2Int(pos.x + 1, pos.y),
new Vector2Int(pos.x, pos.y + 1),
new Vector2Int(pos.x - 1, pos.y)
};
foreach (var n in neighbours)
{
if (n.x < 0 || n.x >= _numCols || n.y < 0 || n.y >= _numRows || !explored.Add(n)) continue;
queue.Enqueue(n);
}
steps++;
}
Debug.LogWarning($"No walkable vertex found near ({startCol}, {startRow})");
return Vertices.Count > 0 ? Vertices[0] : null;
}
public override Vertex[] GetNeighbours(Vertex v)
{
if (!v || Vertices == null || Neighbours == null || !_gridIdToVertexIndex.TryGetValue(v.id, out var vertexIndex) || vertexIndex < 0 || vertexIndex >= Neighbours.Count || Neighbours[vertexIndex] == null)
return Array.Empty<Vertex>();
return Neighbours[vertexIndex].ToArray();
}
public override Edge[] GetEdges(Vertex v)
{
if (!v || v.neighbours == null)
return Array.Empty<Edge>();
return v.neighbours.ToArray();
}
public override Vertex GetVertexObj(int id)
{
if (!_gridIdToVertexIndex.TryGetValue(id, out var vertexIndex)) return null;
if (vertexIndex >= 0 && vertexIndex < Vertices.Count)
return Vertices[vertexIndex];
return null;
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 507ba3373b14402a9205a88c6d3d7e94
timeCreated: 1771392736
+37
View File
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Code.Lab6
{
[System.Serializable]
public class Vertex : MonoBehaviour
{
public int id = -1;
public List<Edge> neighbours;
[HideInInspector]
public Vertex prev;
private void Awake()
{
neighbours ??= new List<Edge>();
}
private void OnDrawGizmos()
{
Gizmos.color = Color.cyan;
Gizmos.DrawSphere(transform.position, 0.2f);
}
private void OnDrawGizmosSelected()
{
if (neighbours == null) return;
Gizmos.color = Color.yellow;
foreach (var edge in neighbours.Where(edge => edge?.Vertex != null))
{
Gizmos.DrawLine(transform.position, edge.Vertex.transform.position);
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 27d037f459ac450d9902f69b5b339d54
timeCreated: 1771392709
+198
View File
@@ -0,0 +1,198 @@
using Code.Base;
using System.Collections.Generic;
using Code.Lab1;
using UnityEngine;
namespace Code.Lab6
{
public class VertexPathFollower : Seek
{
private List<Vertex> _path;
private int _currentTargetIndex;
private bool _isFollowing;
public float waypointReachedDistance = 0.5f;
public bool loopPath;
public bool drawGizmos = true;
public float agentHeight = 1f;
public bool fixYPosition = true;
private float _startY;
public override void Awake()
{
base.Awake();
if (target == null)
{
target = new GameObject("PathFollower_Target");
}
_path = new List<Vertex>();
_isFollowing = false;
_startY = transform.position.y;
}
public void SetPath(List<Vertex> newPath)
{
if (newPath == null || newPath.Count == 0)
{
Debug.LogWarning("Path is empty!");
StopFollowing();
return;
}
_path = newPath;
_currentTargetIndex = 0;
_isFollowing = true;
Debug.Log($"Path set! Starting movement to {_path.Count} waypoints");
UpdateTargetPosition();
}
public void StopFollowing()
{
_isFollowing = false;
_path?.Clear();
}
private void UpdateTargetPosition()
{
if (!target || _path == null || _path.Count == 0)
return;
if (_currentTargetIndex < _path.Count && _path[_currentTargetIndex] != null)
{
var targetPos = _path[_currentTargetIndex].transform.position;
targetPos.y = agentHeight;
target.transform.position = targetPos;
}
}
public override Steering GetSteering()
{
if (!_isFollowing || _path == null || _path.Count == 0 || _currentTargetIndex >= _path.Count)
{
return new Steering();
}
if (fixYPosition)
{
var currentPos = transform.position;
currentPos.y = agentHeight;
transform.position = currentPos;
}
var distanceToTarget = Vector3.Distance(
new Vector3(transform.position.x, 0, transform.position.z),
new Vector3(target.transform.position.x, 0, target.transform.position.z)
);
if (distanceToTarget < waypointReachedDistance)
{
_currentTargetIndex++;
if (_currentTargetIndex >= _path.Count)
{
if (loopPath)
{
_currentTargetIndex = 0;
Debug.Log("Path completed! Looping...");
}
else
{
Debug.Log("Path completed! Stopping.");
StopFollowing();
return new Steering();
}
}
UpdateTargetPosition();
}
var steering = base.GetSteering();
steering.Linear = new Vector3(steering.Linear.x, 0, steering.Linear.z);
return steering;
}
private void FixedUpdate()
{
if (fixYPosition)
{
var pos = transform.position;
pos.y = agentHeight;
transform.position = pos;
}
}
public bool IsFollowing()
{
return _isFollowing && _path != null && _path.Count > 0 && _currentTargetIndex < _path.Count;
}
public Vertex GetCurrentTarget()
{
if (!_isFollowing || _path == null || _path.Count == 0 || _currentTargetIndex >= _path.Count)
return null;
return _path[_currentTargetIndex];
}
public int GetRemainingWaypoints()
{
if (!_isFollowing || _path == null)
return 0;
return Mathf.Max(0, _path.Count - _currentTargetIndex);
}
private void OnDrawGizmos()
{
if (!drawGizmos || _path == null) return;
Gizmos.color = Color.green;
for (var i = 0; i < _path.Count - 1; i++)
{
if (_path[i] != null && _path[i + 1] != null)
{
var start = _path[i].transform.position;
var end = _path[i + 1].transform.position;
start.y = agentHeight;
end.y = agentHeight;
Gizmos.DrawLine(start, end);
}
}
if (_isFollowing && _currentTargetIndex < _path.Count && _path[_currentTargetIndex] != null)
{
var targetPos = _path[_currentTargetIndex].transform.position;
targetPos.y = agentHeight;
Gizmos.color = Color.red;
Gizmos.DrawSphere(targetPos, 0.3f);
Gizmos.color = Color.yellow;
var agentPos = transform.position;
agentPos.y = agentHeight;
Gizmos.DrawLine(agentPos, targetPos);
}
#if UNITY_EDITOR
for (var i = 0; i < _path.Count; i++)
{
if (_path[i] == null) continue;
var labelPos = _path[i].transform.position;
labelPos.y = agentHeight + 0.5f;
UnityEditor.Handles.color = Color.white;
UnityEditor.Handles.Label(labelPos, $"#{i}");
}
#endif
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5347d94ded854559b5594b4ed46e03ee
timeCreated: 1771393841
+244
View File
@@ -0,0 +1,244 @@
using System.Collections.Generic;
using Code.Base;
using Code.Lab6;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Code.UI
{
public class Lab6Controller : MonoBehaviour
{
public Graph graph;
public Agent agent;
public Transform targetMarker;
public Button toMenuButton;
public Button resetButton;
public Button findPathButton;
public Button dfsButton;
public Button bfsButton;
public Button stopButton;
public LineRenderer pathLine;
public Color pathColor = Color.green;
public TextMeshProUGUI statusText;
private List<Vertex> _currentPath;
private VertexPathFollower _pathFollower;
private bool _useBfs = true;
private void Awake()
{
if (toMenuButton != null)
toMenuButton.onClick.AddListener(LoadMainMenu);
if (resetButton != null)
resetButton.onClick.AddListener(ResetScene);
if (findPathButton != null)
findPathButton.onClick.AddListener(FindPathToTarget);
if (dfsButton != null)
dfsButton.onClick.AddListener(() => SetAlgorithm(false));
if (bfsButton != null)
bfsButton.onClick.AddListener(() => SetAlgorithm(true));
if (stopButton != null)
stopButton.onClick.AddListener(StopAgent);
_pathFollower = agent?.GetComponent<VertexPathFollower>();
if (_pathFollower == null && agent != null)
{
_pathFollower = agent.gameObject.AddComponent<VertexPathFollower>();
}
if (pathLine != null)
{
pathLine.startColor = pathColor;
pathLine.endColor = pathColor;
pathLine.startWidth = 0.2f;
pathLine.endWidth = 0.2f;
}
_currentPath = new List<Vertex>();
}
private void Start()
{
if (graph == null)
graph = FindFirstObjectByType<Graph>();
if (agent == null)
agent = FindFirstObjectByType<Agent>();
if (targetMarker == null)
{
var marker = GameObject.CreatePrimitive(PrimitiveType.Sphere);
marker.name = "Target Marker";
marker.transform.position = new Vector3(5, 0.5f, 5);
marker.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
var renderer1 = marker.GetComponent<Renderer>();
renderer1.material.color = Color.red;
Destroy(marker.GetComponent<Collider>());
targetMarker = marker.transform;
}
if (agent == null) return;
var pos = agent.transform.position;
pos.y = 0.5f;
agent.transform.position = pos;
}
private void Update()
{
if (Input.GetMouseButtonDown(1))
{
if (Camera.main != null)
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
var targetPos = hit.point;
targetPos.y = 0.5f;
targetMarker.position = targetPos;
FindPathToTarget();
}
}
}
DrawPath();
UpdateStatusText();
}
private void UpdateStatusText()
{
if (!statusText) return;
var status = $"Algorithm: {(_useBfs ? "BFS" : "DFS")}\n";
if (_pathFollower && _pathFollower.IsFollowing())
{
status += $"Status: Moving to waypoint {_pathFollower.GetRemainingWaypoints()}/{_currentPath.Count}\n";
var currentTarget = _pathFollower.GetCurrentTarget();
if (currentTarget)
{
status += $"Target pos: {currentTarget.transform.position}\n";
}
}
else
{
status += "Status: Idle\n";
}
status += $"Path nodes: {_currentPath.Count}";
statusText.text = status;
}
public void SetAlgorithm(bool useBfs)
{
_useBfs = useBfs;
Debug.Log(useBfs ? "Using BFS algorithm" : "Using DFS algorithm");
if (targetMarker != null)
{
FindPathToTarget();
}
}
public void StopAgent()
{
if (_pathFollower != null)
{
_pathFollower.StopFollowing();
}
_currentPath.Clear();
}
public void FindPathToTarget()
{
if (!graph || !agent || !targetMarker)
{
Debug.LogError("Missing references!");
return;
}
var targetPos = targetMarker.position;
targetPos.y = 0.5f;
targetMarker.position = targetPos;
var path = _useBfs ? graph.GetPathBfs(agent.gameObject, targetMarker.gameObject) : graph.GetPathDfs(agent.gameObject, targetMarker.gameObject);
if (path is { Count: > 0 })
{
_currentPath = path;
Debug.Log($"Path found! Length: {path.Count} nodes");
if (_pathFollower)
{
_pathFollower.SetPath(path);
}
}
else
{
Debug.LogWarning("No path found!");
_currentPath.Clear();
if (_pathFollower)
{
_pathFollower.StopFollowing();
}
}
}
private void DrawPath()
{
if (!pathLine || _currentPath == null || _currentPath.Count < 2)
{
if (pathLine)
pathLine.positionCount = 0;
return;
}
pathLine.positionCount = _currentPath.Count;
for (var i = 0; i < _currentPath.Count; i++)
{
if (!_currentPath[i]) continue;
var pos = _currentPath[i].transform.position;
pos.y += 0.2f;
pathLine.SetPosition(i, pos);
}
}
private static void ResetScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
private static void LoadMainMenu()
{
SceneManager.LoadScene("MainMenu");
}
private void OnDestroy()
{
if (toMenuButton != null)
toMenuButton.onClick.RemoveListener(LoadMainMenu);
if (resetButton != null)
resetButton.onClick.RemoveListener(ResetScene);
if (findPathButton != null)
findPathButton.onClick.RemoveListener(FindPathToTarget);
if (dfsButton != null)
dfsButton.onClick.RemoveAllListeners();
if (bfsButton != null)
bfsButton.onClick.RemoveAllListeners();
if (stopButton != null)
stopButton.onClick.RemoveListener(StopAgent);
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 58f148e1e6954b1fb160c3279addc512
timeCreated: 1771392756
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 424046df745f4430a4f5de4cb65b1f6e
timeCreated: 1771392826
+14
View File
@@ -0,0 +1,14 @@
type octile
height 10
width 10
map
..........
.########.
..........
.########.
..........
.########.
..........
.########.
..........
..........
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cd8591aa3b6941019629427ac5bf1265
timeCreated: 1771392844
@@ -0,0 +1,19 @@
type octile
height 15
width 15
map
...............
.#############.
.#.#.#.#.#.#.#.
.#.#.#.#.#.#.#.
.............#.
##########.##.#.
.............#.
#.#############.
#.............#
#.###########.#
#.#.........#.#
#.#.#######.#.#
#.#.#.....#.#.#
#...#.....#...#
.............#.
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6bc34bd28b8f89ccd841b91c63d13942
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+24
View File
@@ -0,0 +1,24 @@
type octile
height 20
width 20
map
....................
.##################.
.#................#.
.#.##############.#.
.#.#............#.#.
.#.#.##########.#.#.
.#.#.#........#.#.#.
.#.#.#.######.#.#.#.
.#.#.#.#....#...#.#.
.#.#.#......#.#.#.#.
.#...#.######.#.#.#.
.#.#.#........#.#.#.
.#.#.##########.#.#.
.#.#............#...
.#.##############.#.
.#..............#.#.
.##################.
....................
....................
....................
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e94ce48a714b813a585e83ab9952ef60
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+15
View File
@@ -0,0 +1,15 @@
type octile
height 11
width 11
map
...........
....###....
....###....
....###....
...........
#####.#####
...........
....###....
....###....
....###....
...........
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ceb7a48def4d49eb4ac1bf3cfab3ed43
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+16
View File
@@ -0,0 +1,16 @@
type octile
height 12
width 12
map
............
.##########.
.#........#.
.#........#.
.#........#.
.#...##...#.
.#...#..#...
.#...##...#.
.#........#.
.#........#.
.##########.
............
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3c3b0cfb1e3bbe7a4858eecb5f2d8297
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+16
View File
@@ -0,0 +1,16 @@
type octile
height 12
width 12
map
............
.###....###.
.#.#....#.#.
.###....###.
............
....####....
....#..#....
....####....
............
.###....###.
.#.#....#.#.
.###....###.
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8b82cc3cb9ff249329f9841f43448cec
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+24
View File
@@ -0,0 +1,24 @@
type octile
height 20
width 20
map
....................
.##################.
.#........#.......#.
.#.########.#####.#.
.#.#......#.#...#.#.
.#.#.####.#.#.#.#.#.
.#.#.#..#.#.#.#.#...
.#.#.#.##.#.#.#.#.#.
.#.#.#....#.#.#.#.#.
.#.#.######.#.#.#.#.
.#.#........#.#.#.#.
.#.##########.#.#.#.
.#............#...#.
.##################.
....................
....................
....................
....................
....................
....................
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: dbc33ec6d98a3724e8b1277f078071b7
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+14
View File
@@ -0,0 +1,14 @@
type octile
height 10
width 10
map
..........
.########.
.#......#.
.#.####.#.
.#.#..#.#.
.#.#..#.#.
.#.##.#.#.
.#........
.########.
..........
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b75d46e0a63ac81deba7346be40b4d57
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+19
View File
@@ -0,0 +1,19 @@
type octile
height 15
width 15
map
...............
...............
...............
.....#####.....
.....#####.....
.....#####.....
.....#####.....
.....#####.....
.....#####.....
.....#####.....
.....#####.....
.....#####.....
...............
...............
...............
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 28c733d5db31019eba41d24406a8ba49
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+19
View File
@@ -0,0 +1,19 @@
type octile
height 14
width 14
map
...............
.#############.
.#...........#.
.#.#########.#.
.#.#.......#.#.
.#.#.#####.#.#.
.#.#.#...#.#.#.
.#.#.#.#.#.#.#.
.#.#...#.#.#.#.
.#.#####.#.#.#.
.#.......#.#.#.
.#########.#.#.
...........#.#.
###########.#.
...............
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b132ab25a0f5e5b368a9cf7135aeccfd
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+34
View File
@@ -0,0 +1,34 @@
type octile
height 30
width 30
map
..............................
.############################.
.#..........................#.
.#.########################.#.
.#.#......................#.#.
.#.#.####################.#.#.
.#.#.#..................#.#.#.
.#.#.#.################.#.#.#.
.#.#.#.#..............#.#.#.#.
.#.#.#.#.############.#.#.#.#.
.#.#.#.#.#..........#.#.#.#.#.
.#.#.#.#.#.########.#.#.#.#.#.
.#.#.#.#.#.#......#.#.#.#.#.#.
.#.#.#.#.#.#.####.#.#.#.#.#.#.
.#.#.#.#.#.#.#..#.#.#.#.#.#.#.
.#.#.#.#.#.#.#....#.#.#.#.#.#.
.#.#.#.#.#.#.######.#.#.#.#.#.
.#.#.#.#.#.#........#.#.#.#.#.
.#.#.#.#.#.##########.#.#.#.#.
.#.#.#.#.#............#.#.#.#.
.#.#.#.#.##############.#.#.#.
.#.#.#.#................#.#.#.
.#.#.#.##################.#.#.
.#.#.#....................#.#.
.#.#.######################.#.
.#.#........................#.
.#.##########################.
.#............................
.############################.
..............................
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a48adec52da02859e8c9f56646c797ed
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,114 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6882310331696677138
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5101199452410304459}
- component: {fileID: 2385059013361613609}
- component: {fileID: 2691138752481339392}
- component: {fileID: 898326774768670629}
m_Layer: 0
m_Name: GroundVertex
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5101199452410304459
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882310331696677138}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 0.1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2385059013361613609
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882310331696677138}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &2691138752481339392
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882310331696677138}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 3e850d60702ce93b3994ef01094e2e42, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &898326774768670629
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882310331696677138}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4d7c12eb4b772c3aab445627ad3f145e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+114
View File
@@ -0,0 +1,114 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2115503217562294470
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4607686180085906616}
- component: {fileID: 6003346949700990906}
- component: {fileID: 5857785671233074533}
- component: {fileID: 7699923361560625798}
m_Layer: 0
m_Name: Obstacle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4607686180085906616
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2115503217562294470}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6003346949700990906
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2115503217562294470}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &5857785671233074533
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2115503217562294470}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: ddfb323e19afdc8a2bc4a12cdadfec71, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &7699923361560625798
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2115503217562294470}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: aa5336f29776501f09475b59339c4338
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+1 -1
View File
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: ee8e25040bf8dca46a66cc5bde646eb9
guid: 63607fcacd9868e7983d5bdc57371e9b
DefaultImporter:
externalObjects: {}
userData:
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ee8e25040bf8dca46a66cc5bde646eb9
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: