Optimization
I’ve found that the normal roblox pathfinding is just not working the way I expect it to, so i’ve just decided to make my own, Its working as intended but the grid generation just takes too long on larger scale maps (especially with visuals on) and the pathfinding is also kinda slow at times
I’ve added some checks to the grid generation that give the server a little bit of time to rest, and it might just be that i need to fine tune the values a little bit more, but i cant help but think there might be a faster way to do it
- Note there is some residual code left from different things i tried, so its still a little bit rough
local MonsterFunctions = {}
type Node = {
Position: Vector3,
GridCoordinates: Vector2,
ConnectedNodes: {},
Index: number,
Active: boolean,
Visual: Model,
f: number,
g: number,
h: number,
PTFPos: number,
Parent: Node
}
function MonsterFunctions.GridCreation(AgentRadius: number, PassesBeforeWaitingMAX: number, GRID_DENSITY: number, GRID_SIZE_Y: number, GRID_SIZE_X: number, NavMesh:Model)
local RunService = game:GetService("RunService")
local PassesBeforeWaiting = PassesBeforeWaitingMAX
local NodeBase = game.ReplicatedStorage.TestingAssets.Node
local GRID_MAX_X = math.round(GRID_SIZE_X / GRID_DENSITY)
local GRID_MAX_Y = math.round(GRID_SIZE_Y / GRID_DENSITY)
local NodeList = {}
local NodeContructor = function(Pos: Vector3, coords: Vector2, Index: number)
local NewNode: Node = {}
NewNode.GridCoordinates = coords
NewNode.Position = Pos
NewNode.Active = nil
NewNode.Index = Index
NewNode.f = nil
NewNode.g = nil
NewNode.h = nil
NewNode.ConnectedNodes = {NewNode.Index + 1,
NewNode.Index - 1,
NewNode.Index - GRID_MAX_Y,
NewNode.Index - GRID_MAX_Y + 1,
NewNode.Index - GRID_MAX_Y - 1,
NewNode.Index + GRID_MAX_Y,
NewNode.Index + GRID_MAX_Y + 1,
NewNode.Index + GRID_MAX_Y - 1}
print(NewNode.ConnectedNodes, NewNode.Index)
return NewNode
end
local CreateGrid = function()
local Center = NavMesh.PrimaryPart.Position
local PassesLeft = GRID_MAX_Y
local Xcoord = 0
local Ycoord = 0
for Passes = 1, GRID_MAX_X * GRID_MAX_Y do
if PassesLeft == 0 then
PassesLeft = math.round((GRID_SIZE_Y/GRID_DENSITY))
Xcoord = Xcoord + 1
Ycoord = 0
end
local NodePos = Center - Vector3.new(GRID_SIZE_X/2 - (GRID_DENSITY * Xcoord), 0, GRID_SIZE_Y/2 - (GRID_DENSITY * Ycoord))
local coords = Vector2.new(Xcoord, Ycoord)
local Node = NodeContructor(NodePos, coords, Passes)
Ycoord = Ycoord + 1
PassesLeft = PassesLeft - 1
PassesBeforeWaiting = PassesBeforeWaiting - 1
if PassesBeforeWaiting == 0 then
PassesBeforeWaiting = PassesBeforeWaitingMAX
RunService.Heartbeat:Wait()
end
local NodeVisual = NodeBase:Clone()
NodeVisual.Parent = game.Workspace
NodeVisual:MoveTo(Node.Position)
Node.Visual = NodeVisual
Node.Visual.Parent = game.Workspace.Nodes
Node.Visual:SetAttribute("GridCoordinates", Node.GridCoordinates)
table.insert(NodeList, Node)
NodeVisual:AddTag(table.find(NodeList, Node))
end
end
CreateGrid()
print("Begin The Purge")
print(#NodeList.." Nodes Created")
for i, Node: Node in NodeList do
local OvParams = OverlapParams.new()
OvParams.FilterType = Enum.RaycastFilterType.Include
OvParams.FilterDescendantsInstances = NavMesh:GetChildren()
if table.find(game.Workspace:GetPartsInPart(Node.Visual:FindFirstChild("Collision"), OvParams), NavMesh.PrimaryPart) then
print("found", Node.GridCoordinates, i)
Node.Active = true
else
Node.Visual.PrimaryPart.Color = Color3.new(0.388235, 0.368627, 1)
Node.Active = false
print("not found", Node.GridCoordinates, i)
end
PassesBeforeWaiting = PassesBeforeWaiting - 1
if PassesBeforeWaiting == 0 then
PassesBeforeWaiting = PassesBeforeWaitingMAX
RunService.Heartbeat:Wait()
end
end
return NodeList
end
function MonsterFunctions.CreatePath(Posi: Vector2, ObjPos: Vector2, List: {}, Density: number)
local CheckedNode: Node = nil
local StartingNode: Node = nil
local GoalNode: Node = nil
local Dist = nil
local PathMaker
local FindClosestNode = function(Pos: Vector2, Goal: boolean)
for i, v:Node in List do
if v.Active then
if CheckedNode then
if (Vector2.new(v.Position.X, v.Position.Z) - Pos).Magnitude < Dist then
CheckedNode = v
Dist = (Vector2.new(CheckedNode.Position.X, CheckedNode.Position.Z) - Pos).Magnitude
if Dist < Density - 0.5 then
print("FOUND CLOSEST NODE")
if Goal then
GoalNode = CheckedNode
print("ADDED GOAL")
GoalNode.Visual.PrimaryPart.Color = Color3.new(0.988235, 1, 0.243137)
else
StartingNode = CheckedNode
StartingNode.Visual.PrimaryPart.Color = Color3.new(0.192157, 1, 0.247059)
StartingNode.f = 0
StartingNode.g = 0
StartingNode.PTFPos = 1
end
CheckedNode = nil
break
end
end
else
CheckedNode = v
Dist = (Vector2.new(CheckedNode.Position.X, CheckedNode.Position.Z) - Pos).Magnitude
if Dist < 1 then
print("FOUND CLOSEST NODE")
if Goal then
print("ADDED GOAL")
GoalNode = CheckedNode
GoalNode.Visual.PrimaryPart.Color = Color3.new(0.988235, 1, 0.243137)
else
StartingNode = CheckedNode
StartingNode.Visual.PrimaryPart.Color = Color3.new(0.192157, 1, 0.247059)
StartingNode.f = 0
StartingNode.g = 0
StartingNode.PTFPos = 1
end
CheckedNode = nil
break
end
end
end
end
StartingNode.Visual.PrimaryPart.Color = Color3.new(0.192157, 1, 0.247059)
end
task.spawn(FindClosestNode, Posi, false)
task.spawn(FindClosestNode, ObjPos, true)
local OpenList = {}
local ClosedList = {}
table.insert(OpenList, StartingNode)
PathMaker = function()
local FoundPath = {}
while task.wait() do
print("Running")
local stop = false
local Q: Node = nil
table.sort(OpenList, function(a:Node, b:Node)
return a.f < b.f
end)
Q = OpenList[1]
table.remove(OpenList, table.find(OpenList, Q))
local succesors = {}
for i = 1, 8 do
local Succesor: Node = List[Q.ConnectedNodes[i]]
if Succesor.Active then
--print(Q.ConnectedNodes[i])
table.insert(succesors, Succesor)
end
end
for i, C: Node in ipairs(succesors) do
if C == GoalNode then
C.Parent = Q
stop = true
break
else
local dx = math.abs(C.GridCoordinates.X - GoalNode.GridCoordinates.X)
local dy = math.abs(C.GridCoordinates.Y - GoalNode.GridCoordinates.Y)
local NewG = Q.g + 1
local NewH = 1 * (dx + dy) + (1.414 - 2 * 1) * math.min(dx, dy)
local NewF = NewG + NewH
local OpenIndex = table.find(OpenList, C)
if OpenIndex then
if OpenList[OpenIndex].f <= NewF then
continue
end
end
local ClosedIndex = table.find(ClosedList, C)
if ClosedIndex then
if ClosedList[ClosedIndex].f <= NewF then
continue
end
end
C.g = NewG
C.h = NewH
C.f = NewF
C.Parent = Q
table.insert(OpenList, C)
end
end
Q.Visual.PrimaryPart.Color = Color3.new(0.984314, 0.537255, 1)
table.insert(ClosedList, Q)
if stop then
local P = GoalNode
while task.wait() do
print(P.Index)
table.insert(FoundPath, P)
P.Visual.PrimaryPart.Color = Color3.new(1, 0, 0.0156863)
if P.Parent then
P = P.Parent
else
break
end
end
break
end
end
end
PathMaker()
end
return MonsterFunctions
