My program struggles to meet get near the performance of this tutorial
using System;
using System.Diagnostics;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.VisualScripting;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Experimental.GlobalIllumination;
using static PathfindingSystemChunk;
//[ExtensionOfNativeClass]
[BurstCompile]
public partial class PathfindingSystemChunk : SystemBase
{
/// <summary>
/// Y is actualy the Z big important
/// and thanks code monkey :)
/// </summary>
//private static float lastCallTime = 0f;
private const int moveStraightCost = 10;
private const int moveDiagonalCost = 14;
private const int frameBudget = 40;
[ReadOnly] private const int size = 200;
/* private void Start()
{
//FindPath(new int2(0, 0), new int2(3, 3));
FindPathJob findPathJob = new FindPathJob()
{
startPosition = new int2(0,0),
endPosition = new int2(3,3),
};
findPathJob.Schedule();
}*/
public void OnCreate(ref SystemState state)
{
//LastCallTime = SystemAPI.Time.ElapsedTime;
}
public void OnUpdate(ref SystemState state)
{
/*NativeList<JobHandle> jobHandleList = new NativeList<JobHandle>(100,Allocator.Temp);
Entities
};
findPathJob.ScheduleParallel();
.ForEach((Entity entity, ref LocalTransform transform, ref Pather pather, ref DynamicBuffer<PathPosition> pathBuffer) =>
{
if (pather.needsUpdate)
{
//DynamicBuffer<PathPosition> pathBuffer = pather.pathBuffer;
//pather.needsUpdate = false;
//for (int i = 0; i < 0; i++)
//{
//JobHandle jobHandle = findPathJob.ScheduleSingle(entity);
//
//jobHandleList.Add(findPathJob.Schedule());
//dependency = jobHandleList[jobHandleList.Length];
//}
//job.Complete();
}
}).Run();
JobHandle.CompleteAll(jobHandleList.AsArray());
//JobHandle.CompleteAll(jobHandleList.AsArray());
jobHandleList.Dispose();*/
}
protected override void OnUpdate()
{
int budget = frameBudget;
NativeList<JobHandle> jobList = new NativeList<JobHandle> (Allocator.Temp);
Entities
.ForEach((Entity entity, ref LocalTransform transform, ref Pather pather, ref DynamicBuffer<PathPosition> pathBuffer) =>
{
if (budget > 0)
{
//UnityEngine.Debug.Log("pathing sorta run");
UpdatePathsSegementJob updatePathsSegementJob = new UpdatePathsSegementJob()
{
pathPositionBuffer = pathBuffer,
startPositionWorld = new int2((int)transform.Position.x, (int)transform.Position.z),
endPositionWorld = pather.destination,
gridSize = size,
};
jobList.Add(updatePathsSegementJob.Schedule());
budget--;
}
}).Run();
JobHandle.CombineDependencies(jobList.AsArray());
JobHandle.CompleteAll(jobList.AsArray());
jobList.Dispose();
}
[BurstCompile]
public partial struct UpdatePathsSegementJob : IJob
{
[NativeDisableContainerSafetyRestriction]
public DynamicBuffer<PathPosition> pathPositionBuffer;
public int2 startPositionWorld;
public int2 endPositionWorld;
[ReadOnly]public int gridSize;
[BurstCompile]
public void Execute()
{
// throwing if no buffer is on that entity.
//UnityEngine.Debug.Log("hi");
int2 startPosition = ToGrid(startPositionWorld, gridSize);
int2 endPosition = ToGrid(endPositionWorld, gridSize);
if (!IsPositionInsideGrid(startPosition, gridSize) || !IsPositionInsideGrid(endPosition, gridSize))
{
return;
}
NativeArray<PathNode> pathNodeArray = new NativeArray<PathNode>(gridSize * gridSize, Allocator.Temp);
for (int x = 0; x < gridSize; x++)
{
for (int y = 0; y < gridSize; y++)
{
PathNode pathNode = new PathNode();
pathNode.x = x;
pathNode.y = y;
pathNode.index = CalculateIndex(x, y, gridSize);
pathNode.gCost = int.MaxValue;
pathNode.hCost = CalculateDistanceCost(new int2(x, y), endPosition);
pathNode.isWalkable = true;
pathNode.cameFromNodeIndex = -1;
pathNode.CalculateFCost();
pathNodeArray[pathNode.index] = pathNode;
}
}
PathNode pathNodeNonWalkable = pathNodeArray[CalculateIndex(1, 1, gridSize)];
pathNodeNonWalkable.SetIsWalkable(false);
pathNodeArray[CalculateIndex(1, 1, gridSize)] = pathNodeNonWalkable;
NativeArray<int2> neighborOffsetArray = new NativeArray<int2>(8, Allocator.Temp);
neighborOffsetArray[0] = new int2(-1, 0);
neighborOffsetArray[1] = new int2(0, 1);
neighborOffsetArray[2] = new int2(1, 0);
neighborOffsetArray[3] = new int2(0, -1);
neighborOffsetArray[4] = new int2(-1, 1);
neighborOffsetArray[5] = new int2(1, 1);
neighborOffsetArray[6] = new int2(1, -1);
neighborOffsetArray[7] = new int2(-1, -1);
int endNodeIndex = CalculateIndex(endPosition.x, endPosition.y, gridSize);
PathNode startNode = pathNodeArray[CalculateIndex(startPosition.x, startPosition.y, gridSize)];
startNode.gCost = 0;
startNode.CalculateFCost();
pathNodeArray[startNode.index] = startNode;
NativeList<int> openList = new NativeList<int>(Allocator.Temp);
NativeList<int> closedList = new NativeList<int>(Allocator.Temp);
openList.Add(startNode.index);
while (openList.Length > 0)
{
int currentNodeIndex = GetLowestCostFNodeIndex(openList, pathNodeArray);
PathNode currentNode = pathNodeArray[currentNodeIndex];
if (currentNodeIndex == endNodeIndex)
{
//we reached the destination :))))))))
break;
}
// removeing current node from open
for (int i = 0; i < openList.Length; i++)
{
if (openList[i] == currentNodeIndex)
{
openList.RemoveAtSwapBack(i);
break;
}
}
closedList.Add(currentNodeIndex);
for (int i = 0; i < neighborOffsetArray.Length; i++)
{
int2 neighbourOffset = neighborOffsetArray[i];
int2 neighbourPosition = new int2(currentNode.x + neighbourOffset.x, currentNode.y + neighbourOffset.y);
if (!IsPositionInsideGrid(neighbourPosition, gridSize))
{
//not in da grid
continue;
}
int neighbourNodeIndex = CalculateIndex(neighbourPosition.x, neighbourPosition.y, gridSize);
if (closedList.Contains(neighbourNodeIndex))
{
// we already seached this node
continue;
}
PathNode neighbourNode = pathNodeArray[neighbourNodeIndex];
if (!neighbourNode.isWalkable)
{
//no go is obstacle
continue;
}
int2 CurrentNodePosition = new int2(currentNode.x, currentNode.y);
int tentativeGCost = currentNode.gCost + CalculateDistanceCost(CurrentNodePosition.x, CurrentNodePosition.y);
if (tentativeGCost < neighbourNode.gCost)
{
neighbourNode.cameFromNodeIndex = currentNodeIndex;
neighbourNode.gCost = tentativeGCost;
neighbourNode.CalculateFCost();
// actualy setting the array from the "sample"
pathNodeArray[neighbourNodeIndex] = neighbourNode;
if (!openList.Contains(neighbourNode.index))
{
openList.Add(neighbourNode.index);
}
}
}
}
pathPositionBuffer.Clear();
PathNode endNode = pathNodeArray[endNodeIndex];
if (endNode.cameFromNodeIndex == -1)
{
// no path :(
}
else
{
CalculatePath(pathNodeArray, endNode, pathPositionBuffer);
//path.Dispose();
// found one :)
}
pathNodeArray.Dispose();
openList.Dispose();
closedList.Dispose();
neighborOffsetArray.Dispose();
}
[BurstCompile]
private int2 ToGrid(int2 pos,int size)
{
return pos + new int2(size / 2, size / 2);
}
[BurstCompile]
private int2 ToWorld(int2 pos,int size)
{
return pos - new int2(size / 2, size / 2);
}
[BurstCompile]
private void CalculatePath(NativeArray<PathNode> pathNodeArray, PathNode endNode, DynamicBuffer<PathPosition> pathPositionBuffer)
{
if (endNode.cameFromNodeIndex == -1)
{
// no path :(
}
else
{
// found one :)
//adding fist element of end
pathPositionBuffer.Add(new PathPosition
{
position = ToWorld(new int2(endNode.x, endNode.y), gridSize),
});
//path.Add(new int2(endNode.x, endNode.y));
PathNode currentNode = endNode;
//tracking back from the end
while (currentNode.cameFromNodeIndex != -1)
{
PathNode cameFromNode = pathNodeArray[currentNode.cameFromNodeIndex];
pathPositionBuffer.Add(new PathPosition
{
position = ToWorld(new int2(cameFromNode.x, cameFromNode.y), gridSize),
});
//path.Add(new int2(cameFromNode.x, cameFromNode.y));
currentNode = cameFromNode;
}
}
}
[BurstCompile]
private bool IsPositionInsideGrid(int2 gridPosition, int2 gridSize)
{
return
gridPosition.x >= 0 &&
gridPosition.y >= 0 &&
gridPosition.x < gridSize.x &&
gridPosition.y < gridSize.y;
}
[BurstCompile]
private int CalculateIndex(int x, int z, int gridWidth)
{
return x + z * gridWidth;
}
[BurstCompile]
private int GetLowestCostFNodeIndex(NativeList<int> openList, NativeArray<PathNode> pathNodeArray)
{
PathNode lowestCostPathNode = pathNodeArray[openList[0]];
for (int i = 1; i < openList.Length; i++)
{
PathNode testPathNode = pathNodeArray[openList[i]];
if (testPathNode.fCost < lowestCostPathNode.fCost)
{
lowestCostPathNode = testPathNode;
}
}
return lowestCostPathNode.index;
}
[BurstCompile]
private int CalculateDistanceCost(int2 aPosition, int2 bPosition)
{
int xDistance = math.abs(aPosition.x - bPosition.x);
int yDistance = math.abs(aPosition.y - bPosition.y);
int remaining = math.abs(xDistance - yDistance);
return moveDiagonalCost * math.min(xDistance, yDistance) + moveStraightCost * remaining;
}
[BurstCompile]
private struct PathNode
{
public int x;
public int y;
public int index;
public int gCost;
public int hCost;
public int fCost;
public bool isWalkable;
public int cameFromNodeIndex;
public void CalculateFCost()
{
fCost = gCost + hCost;
}
public void SetIsWalkable(bool value)
{
isWalkable = value;
}
}
}
// Start is called before the first frame update
}