Hi, It looks like my humanoid is ignoring when the goal route changes , the path should change too, but it doesn’t, is there any way around this?, since i don’t want to remove MoveToFinished:wait() , i am using NodeGraphV2 Plugin, anyone knows why this happens ?
My script :
task.wait(.1)
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Nodegraphs = require(ReplicatedStorage:WaitForChild("NodeGraphs"))
local character = script.Parent
local humanoid: Humanoid = character:FindFirstChildWhichIsA("Humanoid")
local EndPart = workspace:WaitForChild("endd")
local path
local destructor
local pos: Vector3
local goal: Vector3
pos = character:GetPivot().Position
local previousIndexCount: number
while task.wait(.1) do
if destructor then
destructor()
end
pos = character:GetPivot().Position
goal = EndPart.Position
path = Nodegraphs.NewGraph:getPath(goal,pos)
if path then
previousIndexCount = #path.path
else
previousIndexCount = 1
end
destructor = Nodegraphs.NewGraph:drawPath(path)
--humanoid:MoveTo(path.path[1].Position)
--humanoid.MoveToFinished:Wait()
if path then
for index,node in pairs(path.path) do
if index > 1 then
if index <= #path.path then
-- print(index, node.Position)
humanoid:MoveTo(path.path[tonumber(index)].Position)
end
humanoid.MoveToFinished:Wait()
if index >= previousIndexCount then
humanoid:MoveTo(path.path[tonumber(#path.path)].Position)
end
previousIndexCount = #path.path
else
humanoid:MoveTo(goal)
end
end
warn("Goal Finished")
else
humanoid:MoveTo(goal)
end
end
NodeGraphs Module :
--[[ NodeGraphs
Automatically populate NodeGraphs with tagged NodeGraph folders
Example:
local nodeGraphs = require(PATH)
local nodeGraph = nodeGraphs.NewGraph
Optional helper API with fast A* pathfinding:
nodeGraph:draw()
-> draws the nodegraph, same as what you see in the plugin
nodeGraph:getPath(startPosition : Vector3,endPosition: Vector3)
-> returns the closest path
example:
local path = nodeGraph:getPath(START,END)
for index,node in path.path do
print(index,node.Position)
end
nodeGraph:drawPath(path)
-> draws a path and returns a destructor
example:
local path = nodeGraph:getPath(START,END)
Maid:Add(nodeGraph:drawPath(path))
Maid:Cleanup()
nodeGraph:getClosestNode(position : Vector3)
-> returns the closest node
]]
local CollectionService = game:GetService("CollectionService")
local HttpService = game:GetService("HttpService")
local TAG = "NodeGraph"
local NodeGraphs = {}
local Pathfinder = require(script.Pathfinder)
local Resources = script.Resources
for i,folder in CollectionService:GetTagged(TAG) do
--[[ Init nodes ]]
local newNodeGraph = {
nodes = {},
getPath = function(self,...)
return Pathfinder:_getPath(self,...)
end,
drawPath = function(self,path)
return Pathfinder:_drawPath(path)
end,
getClosestNode = function(self,pos)
local lastdist=999
local closest
for i,node in self.nodes do
local dist = (node.Position - pos).magnitude
if dist<lastdist then
lastdist=dist
closest=node
end
end
return closest
end,
draw = function(self)
if self.Drawn then
return
end
self.Drawn = true
for i,dataNode in folder.Data.Nodes:GetChildren() do
local placementNode = Resources.Node:Clone()
local placedNode = placementNode:Clone()
placedNode.Name = dataNode.Name
placedNode.Position = dataNode:GetAttribute("Position")
placedNode.Parent = folder.Working.Nodes
end
for i,dataLine in folder.Data.Lines:GetChildren() do
local nodeA = dataLine:GetAttribute("NodeA")
local nodeB = dataLine:GetAttribute("NodeB")
local nodeAObject = folder.Working.Nodes:FindFirstChild(nodeA)
local nodeBObject = folder.Working.Nodes:FindFirstChild(nodeB)
if nodeAObject and nodeBObject then
local line = Resources.Line:Clone()
line.Name = dataLine.Name
local dist = (nodeBObject.Position - nodeAObject.Position).Magnitude
local size = Vector3.new(0.1,0.1,dist)
local cf = CFrame.lookAt(nodeAObject.Position,nodeBObject.Position,Vector3.yAxis) * CFrame.new(0,0,-dist/2)
line.CFrame = cf
line.Size = size
line.Parent = folder.Working.Lines
end
end
end,
}
for i,nodeFolder in folder.Data.Nodes:GetChildren() do
local node = {
Position = nodeFolder:GetAttribute("Position"),
Connections = {}
}
newNodeGraph.nodes[nodeFolder.Name] = node
end
--
--[[ Init connections ]]
for i,lineFolder in folder.Data.Lines:GetChildren() do
local nodeA = lineFolder:GetAttribute("NodeA")
local nodeB = lineFolder:GetAttribute("NodeB")
local nodeAObj = newNodeGraph.nodes[nodeA]
local nodeBObj = newNodeGraph.nodes[nodeB]
if nodeAObj and nodeBObj then
table.insert(nodeAObj.Connections,nodeBObj)
table.insert(nodeBObj.Connections,nodeAObj)
end
end
if NodeGraphs[folder.Name] then
folder.Name = "NodeGraph"..HttpService:GenerateGUID(false)
end
NodeGraphs[folder.Name] = newNodeGraph
end
return NodeGraphs
Pathfinder Module :
--[[ A* Pathfinder for Nodegraphs ]]
local Pathfinder = {
PathCache = {}
}
local Heap = require(script.Heap)
function Pathfinder:_init(nodeGraph)
for i,node in nodeGraph.nodes do
node.gCost = 0
node.hCost = 0
node.Enabled = true
end
nodeGraph.PathfinderInit = true
end
function Pathfinder:_getClosestNode(nodeGraph,pos)
if not nodeGraph.PathfinderInit then
self:_init(nodeGraph)
end
local lastdist=999
local closest
for i,node in nodeGraph.nodes do
if node.Enabled then
local dist = (node.Position - pos).magnitude
if dist<lastdist then
lastdist=dist
closest=node
end
end
end
return closest
end
function Pathfinder:_drawPath(path)
if not path then
return
end
local nodes = path.path
local lines = {}
local function drawLine(posA,posB)
local nodepos = posB
local lastnodePos = posA
local dist = (nodepos - lastnodePos).magnitude
local line = Instance.new("Part",workspace.Terrain)
line.Anchored = true
line.CanCollide = false
line.Transparency = 0.5
line.Color = Color3.new(0.333333, 0.333333, 1)
line.Material = "Neon"
local thickness = 0.85
line.Size = Vector3.new(thickness,thickness,dist)
line.CFrame = CFrame.new(lastnodePos,nodepos) * CFrame.new(0,self.DebugYOffset,-dist/2)
table.insert(lines,line)
end
local lastnode
for i = 1,#nodes do
local node = nodes[i]
if lastnode then
drawLine(lastnode.Position,node.Position)
end
lastnode = node
end
return function()
for i,line in lines do
line:Destroy()
end
end
end
function Pathfinder:_getPath(nodeGraph,fromPos,toPos)
if not nodeGraph.PathfinderInit then
self:_init(nodeGraph)
end
local fromNode = self:_getClosestNode(nodeGraph,fromPos)
local toNode = self:_getClosestNode(nodeGraph,toPos)
if not fromNode or not toNode then
return
end
local Cache = self.PathCache
if not Cache[fromNode] then
Cache[fromNode] = {}
end
local path = Cache[fromNode][toNode]
if path == nil then
path = self:_pathfind(fromNode,toNode)
Cache[fromNode][toNode] = path
end
return path
end
function Pathfinder:_pathfind(fromNode,toNode)
if not fromNode or not toNode then
return
end
local gCosts = {}
local hCosts = {}
local parents = {}
gCosts[fromNode] = 0
hCosts[fromNode] = (toNode.Position - fromNode.Position).Magnitude
local function retracePath()
local path = {}
local target = toNode
local angleSum = 0
while target ~= fromNode do
path[#path + 1] = target
local parent = parents[target]
local grandParent = parent and parents[parent]
if parent and grandParent then
local dir0 = (parent.Position - grandParent.Position).Unit
local dir1 = (target.Position - parent.Position).Unit
angleSum += math.acos(dir0:Dot(dir1))
end
target = parent
end
path[#path + 1] = fromNode
return {
path = path,
StartNode = fromNode,
EndNode = toNode,
Cost = gCosts[toNode],
AngleSum = angleSum
}
end
local function getFCost(node)
-- Greedy BFS
local gCostInfluence = 1
return (gCosts[node] * gCostInfluence) + hCosts[node]
end
if fromNode == toNode then
return retracePath()
end
local Open = Heap.new()
local Closed = {}
Open:Add(fromNode, getFCost(fromNode))
while Open.Size > 0 do
local currentNode = Open:Pop()
if currentNode == toNode then
return retracePath()
end
Closed[currentNode] = true
local currentCost = gCosts[currentNode]
for _,adjacentNode in currentNode.Connections do
if Closed[adjacentNode] or not adjacentNode.Enabled then
continue
end
local costToNeighbor = currentCost + (adjacentNode.Position - currentNode.Position).Magnitude
local previousCost = gCosts[adjacentNode]
if not previousCost or costToNeighbor < previousCost then
gCosts[adjacentNode] = costToNeighbor
parents[adjacentNode] = currentNode
if not previousCost then
hCosts[adjacentNode] = (toNode.Position - adjacentNode.Position).Magnitude
end
Open:Add(adjacentNode, getFCost(adjacentNode))
end
end
end
end
return Pathfinder