Hello! I wrote this AI, most of it atleast, and it moves fine the first time, but the second time it begins moving, then stops completely.
I tried debugging it but maybe I just needs a fresh pair of eyes to see it
Heres the code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local PathfindingService = game:GetService("PathfindingService")
local AIModels = ServerStorage.AIModels :: Folder
local Packages = ReplicatedStorage.Packages
local Trove = require(Packages.Trove)
local PositionGenerator = require(script.Parent.PositionGenerator)
local Class = {}
Class.__index = Class
function Class.new(type)
local self = setmetatable({
lastMoveTime = os.clock(),
nextMoveTime = os.clock() + Random.new():NextInteger(3, 10),
waypoints = {},
nextWaypointIndex = 0,
reachedConnection = nil,
blockedConnection = nil,
isMoving = false,
}, Class)
local thisTrove = Trove.new()
local thisModel
local modelReturnSuccess, _modelReturnError = pcall(function()
thisModel = AIModels:FindFirstChild(type):Clone()
end)
if not modelReturnSuccess then
warn(`Failed to find AI model under type "{type}"`)
return nil
end
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 3,
AgentCanJump = false,
WaypointSpacing = 10,
})
local height = thisModel.Humanoid.HipHeight + (thisModel.PrimaryPart.Size.Y / 2)
local thisPosition = PositionGenerator:GenerateRandomMapPosition(height)
thisModel:PivotTo(CFrame.new(thisPosition) * CFrame.Angles(0, Random.new():NextInteger(0, 360), 0))
self.model = thisModel
self.trove = thisTrove
self.path = path
self.height = height
self.updateRate = 0.1
self.lastUpdate = 0
thisTrove:Add(thisModel)
thisTrove:Connect(RunService.Heartbeat, function(deltaTime)
local updateDeltaTime = os.clock() - self.lastUpdate
if updateDeltaTime >= self.updateRate then
self.lastUpdate = os.clock()
self:Update(deltaTime)
end
end)
thisModel.Parent = workspace
return self
end
function Class:Destroy()
self.trove:Destroy()
table.clear(self)
setmetatable(self, nil)
table.freeze(self)
end
function Class:Update(_deltaTime: number)
if self.isMoving then
return
end
task.desynchronize()
local moveDeltaTime = os.clock()
local canNpcMove = if moveDeltaTime >= self.nextMoveTime then true else false
if canNpcMove then
print("Moving, Elapsed Move Time: " .. math.floor(os.clock() - self.lastMoveTime))
self.lastMoveTime = os.clock()
self.nextMoveTime = os.clock() + 10 ^ 10
self.isMoving = true
self:Move()
self.isMoving = false
end
end
function Class:Move()
local myModel = self.model :: Model
local myHumanoidRootPart = myModel.HumanoidRootPart :: BasePart
local _myLookVector = myHumanoidRootPart.CFrame.LookVector
task.synchronize()
while true do
local targetPosition = self:generateRandomPosition()
local success = self:followPath(targetPosition)
if success then
break
end
task.wait()
end
end
function Class:generateRandomPosition()
local params = OverlapParams.new()
params.FilterDescendantsInstances = { workspace }
params.FilterType = Enum.RaycastFilterType.Include
local model = self.model :: Model
local extentsSize = model:GetExtentsSize()
while true do
task.wait()
local randomPosition =
PositionGenerator:GenerateMoveToPosition(model.PrimaryPart.Position, self.height, -45, 45)
local partsInArea = workspace:GetPartBoundsInBox(CFrame.new(randomPosition), extentsSize)
for _, part in partsInArea do
if not part:HasTag("Floor") then
continue
end
end
return randomPosition
end
end
-- Mostly driven from the roblox docs - https://create.roblox.com/docs/characters/pathfinding#moving-along-paths
-- (if it aint broke dont fix it) --
function Class:followPath(targetPosition: Vector3)
local path = self.path :: Path
local model = self.model :: Model
local primaryPart = model.PrimaryPart :: BasePart
local humanoid = model.Humanoid :: Humanoid
local success, output = pcall(function()
return path:ComputeAsync(primaryPart.Position, targetPosition)
end)
if success and path.Status == Enum.PathStatus.Success then
self.waypoints = path:GetWaypoints()
print(("Pathfinding success. Total number of waypoints: %d"):format(#self.waypoints))
self.blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
warn(("Blocked at index %d"):format(blockedWaypointIndex))
if blockedWaypointIndex >= self.nextWaypointIndex then
self.blockedConnection:Disconnect()
warn(`Path was blocked, redirecting...`)
self:followPath(targetPosition)
end
end)
if not self.reachedConnection then
self.reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
print("MoveToFinished fired, processing...")
if reached and self.nextWaypointIndex < #self.waypoints then
print(("Moving to the next waypoint (%d)"):format(self.nextWaypointIndex + 1))
self.nextWaypointIndex += 1
humanoid:MoveTo(self.waypoints[self.nextWaypointIndex].Position)
else
local nextMoveTime = Random.new():NextInteger(5, 10)
print("Reached")
self.lastMoveTime = os.clock()
self.nextMoveTime = os.clock() + nextMoveTime
print(("Moving again in %d seconds..."):format(nextMoveTime))
self.reachedConnection:Disconnect()
self.blockedConnection:Disconnect()
end
end)
end
self.nextWaypointIndex = 2
humanoid:MoveTo(self.waypoints[self.nextWaypointIndex].Position)
return true
else
warn(output)
end
return false
end
return Class
This is what the console is outputting:
Thank you for your time!