Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Logs
Assembly-CSharp.csproj
Assembly-CSharp-Editor.csproj
CsharpMainProject.sln
.vs
5 changes: 2 additions & 3 deletions Assets/Resources/PlayerUnits/PlayerUnit3.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
_healthBar: {fileID: 178258570018206233}
_debugPathOutput: {fileID: 0}
--- !u!114 &3664015912038799981
MonoBehaviour:
m_ObjectHideFlags: 0
Expand All @@ -67,10 +68,8 @@ MonoBehaviour:
_maxHealth: 400
_brainUpdateDelay: 0.25
_moveDelay: 0.25
_attackDelay: 0.75
_attackDelay: 0.15
_attackRange: 3.5
_shotsPerTarget: 1
_targetsInVolley: 1
_projectileType: 0
_damage: 15
--- !u!1 &526913648782850647
Expand Down
2 changes: 1 addition & 1 deletion Assets/Scripts/EnterPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class EnterPoint : MonoBehaviour
{
[SerializeField] private Settings _settings;
[SerializeField] private Canvas _targetCanvas;
private float _timeScale = 1;
private float _timeScale = 1f;

void Start()
{
Expand Down
10 changes: 8 additions & 2 deletions Assets/Scripts/UnitBrains/BaseUnitBrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ public abstract class BaseUnitBrain
public virtual string TargetUnitName => string.Empty;
public virtual bool IsPlayerUnitBrain => true;
public virtual BaseUnitPath ActivePath => _activePath;


protected Unit unit { get; private set; }
protected IReadOnlyRuntimeModel runtimeModel => ServiceLocator.Get<IReadOnlyRuntimeModel>();
private BaseUnitPath _activePath = null;


/// <summary>
protected bool _actionSwitched = false;
/// </summary>

private readonly Vector2[] _projectileShifts = new Vector2[]
{
new (0f, 0f),
Expand All @@ -36,10 +41,11 @@ public virtual Vector2Int GetNextStep()
if (HasTargetsInRange())
return unit.Pos;

_actionSwitched = true;
var target = runtimeModel.RoMap.Bases[
IsPlayerUnitBrain ? RuntimeModel.BotPlayerId : RuntimeModel.PlayerId];

_activePath = new DummyUnitPath(runtimeModel, unit.Pos, target);
_activePath = new Pathfinding.AdvancedUnitPath(runtimeModel, unit.Pos, target);
return _activePath.GetNextStepFrom(unit.Pos);
}

Expand Down
163 changes: 163 additions & 0 deletions Assets/Scripts/UnitBrains/Pathfinding/AdvancedUnitPath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace UnitBrains.Pathfinding
{
public class NewUnitPath : BaseUnitPath
{
protected Vector2Int[] dx = {
Vector2Int.down,
Vector2Int.up,
Vector2Int.left,
Vector2Int.right
};
protected const int MaxLength = 150;

public NewUnitPath(IReadOnlyRuntimeModel runtimeModel, Vector2Int startPoint, Vector2Int endPoint) : base(runtimeModel, startPoint, endPoint)
{

}

protected override void Calculate()
{
var listPath = FindPath();
// Проверка на случай, если ничего не было записано в найденный путь
if (FindPath().Count < 1)
{
path = null;
}
else
{
path = listPath.ToArray();
}
}

protected List<Vector2Int> FindPath()
{
// Проверка на случай, если старт и цель совпадают или находятся в 1 клетке друг от друга
bool isCardinalDirection = dx.Contains(endPoint - startPoint);
if (startPoint.Equals(endPoint) || isCardinalDirection == true)
return new List<Vector2Int> { startPoint };

Node startNode = new Node(startPoint);
Node targetNode = new Node(endPoint);

List<Node> openNode = new List<Node> { startNode };
HashSet<Node> closedList = new HashSet<Node>();
int counter = 0;
Node bestNodeSoFar = startNode; // Хранит лучший найденный узел (ближайший к цели)
float bestDistanceSoFar = float.MaxValue; // Расстояние лучшего узла до цели

// Инициализируем стартовый узел
startNode.CalculateEstimate(targetNode.Pos);
startNode.CalculateValue();

while (openNode.Count > 0 && counter < MaxLength)
{
int minIndex = 0;
Node currentNode = openNode[0];

for (int i = 1; i < openNode.Count; i++)
{
if (openNode[i].Value < currentNode.Value)
{
currentNode = openNode[i];
minIndex = i;
}
}

// Удаляем по индексу
openNode.RemoveAt(minIndex);

// Пропускаем, если узел уже обработан
if (closedList.Contains(currentNode))
continue;

closedList.Add(currentNode);

// Обновляем лучший узел, если текущий ближе к цели
float currentDistance = CalculateDistance(currentNode.Pos, endPoint);
if (currentDistance < bestDistanceSoFar)
{
bestDistanceSoFar = currentDistance;
bestNodeSoFar = currentNode;
}

// Проверяем, достигли ли цели
if (endPoint.Equals(currentNode.Pos))
return buildPath(currentNode);

// Исследуем соседей
foreach (var direction in dx)
{
var nextStep = direction + currentNode.Pos;

// Проверяем проходимость
if (!runtimeModel.IsTileWalkable(nextStep) && !nextStep.Equals(endPoint))
continue;

Node neighbor = new Node(nextStep);

// Пропускаем, если узел уже закрыт
if (closedList.Contains(neighbor))
continue;

// Проверяем, есть ли сосед уже в openNode
bool alreadyInOpen = false;
for (int i = 0; i < openNode.Count; i++)
{
if (openNode[i].Equals(neighbor))
{
// Если нашли узел с той же позицией, обновляем его параметры,
// если новый путь лучше (меньшее Value)
int newCost = currentNode.Cost + neighbor.Cost;
if (newCost < openNode[i].Cost)
{
openNode[i].Parent = currentNode;
openNode[i].Cost = newCost;
openNode[i].CalculateValue();
}
alreadyInOpen = true;
break;
}
}

if (!alreadyInOpen)
{
neighbor.Parent = currentNode;
neighbor.Cost = currentNode.Cost + 10;
neighbor.CalculateEstimate(targetNode.Pos);
neighbor.CalculateValue();
openNode.Add(neighbor);
}
}

counter++;
}

// Если достигли MaxLength, но не нашли путь — возвращаем путь к ближайшему найденному узлу
return buildPath(bestNodeSoFar);
}

private float CalculateDistance(Vector2Int a, Vector2Int b)
{
var diff = a - b;
return Mathf.Sqrt(diff.x * diff.x + diff.y * diff.y);
}

protected List<Vector2Int> buildPath(Node node)
{
List<Vector2Int> result = new();
while (node != null)
{
result.Add(node.Pos);
node = node.Parent;
}
result.Reverse();
return result;
}
}
}
11 changes: 11 additions & 0 deletions Assets/Scripts/UnitBrains/Pathfinding/AdvancedUnitPath.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 19 additions & 2 deletions Assets/Scripts/UnitBrains/Pathfinding/DebugPathOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,27 @@ public void HighlightPath(BaseUnitPath path)

private IEnumerator HighlightCoroutine(BaseUnitPath path)
{
// TODO Implement me
yield break;
while (true)
{
foreach (var atCell in path.GetPath())
{
CreateHighlight(atCell);
if (allHighlights.Count >= maxHighlights)
{
DestroyHighlight(0);
}
yield return new WaitForSeconds(0.1f);
}
while (allHighlights.Count > 0)
{
DestroyHighlight(0);
yield return new WaitForSeconds(0.1f);
}
}
}



private void CreateHighlight(Vector2Int atCell)
{
var pos = Gameplay3dView.ToWorldPosition(atCell, 1f);
Expand Down
4 changes: 2 additions & 2 deletions Assets/Scripts/UnitBrains/Pathfinding/DummyUnitPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace UnitBrains.Pathfinding
{
public class DummyUnitPath : BaseUnitPath
public class AdvancedUnitPath : BaseUnitPath
{
private const int MaxLength = 100;

public DummyUnitPath(IReadOnlyRuntimeModel runtimeModel, Vector2Int startPoint, Vector2Int endPoint) : base(runtimeModel, startPoint, endPoint)
public AdvancedUnitPath(IReadOnlyRuntimeModel runtimeModel, Vector2Int startPoint, Vector2Int endPoint) : base(runtimeModel, startPoint, endPoint)
{
}

Expand Down
42 changes: 42 additions & 0 deletions Assets/Scripts/UnitBrains/Pathfinding/Node.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace UnitBrains.Pathfinding
{
public class Node
{
public Vector2Int Pos;
public int Cost = 10;
public int Estimate;
public int Value;
public Node Parent;

public Node(Vector2Int pos)
{
Pos = pos;
}

public void CalculateEstimate(Vector2Int target)
{
var diff = target - Pos;
Estimate = (Math.Abs(diff.x) + Math.Abs(diff.y)) * 10;
}

public void CalculateValue()
{
Value = Cost + Estimate;
}

public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj)) return true;
if (obj is Node other)
return Pos.Equals(other.Pos);
return false;
}

public override int GetHashCode() => Pos.GetHashCode();
}
}
11 changes: 11 additions & 0 deletions Assets/Scripts/UnitBrains/Pathfinding/Node.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading