-
What do you want to achieve? Keep it simple and clear!
I want to fix my Pathfinding AI. -
What is the issue? Include screenshots / videos if possible!
My NPC’s movement seems janky and slow after working for a minute or two.
-
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I have searched through the devforum and even used AI, but I have not found a solution or solved my issue.
I am using both a module script and a server script in order to run this code
Module Script:
local SoundDetector = {}
local RunService = game:GetService("RunService")
local maxDetectionRange = 200 -- Max range
local minDistanceChange = 3
local checkInterval = 0.3
local npc = nil
local lastPosition = nil
function SoundDetector.SetNPC(character)
npc = character
end
function SoundDetector.GetLoudestSound()
task.wait(checkInterval)
local loudestSound = nil
local loudestVolume = 0
for _, sound in pairs(workspace:GetDescendants()) do
if sound:IsA("Sound") and sound.Playing and sound.Parent:IsA("BasePart") then
local soundPosition = sound.Parent.Position
local distanceToSound = (npc.HumanoidRootPart.Position - soundPosition).Magnitude
if distanceToSound > maxDetectionRange or distanceToSound > sound.MaxDistance then continue end -- Ignore out-of-range sounds
local effectiveVolume = (sound.Volume * (sound.MaxDistance - distanceToSound)) / (distanceToSound^2 + 1)
if effectiveVolume > loudestVolume then
loudestSound = sound
loudestVolume = effectiveVolume
end
end
end
if loudestSound and (not lastPosition or (lastPosition - loudestSound.Parent.Position).Magnitude > minDistanceChange) then
lastPosition = loudestSound.Parent.Position
return loudestSound
end
return nil
end
return SoundDetector
Server Script:
local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")
local SoundDetector = require(script:WaitForChild("SoundDetector"))
local npc = script.Parent
local humanoid = npc:FindFirstChildOfClass("Humanoid")
local movingToSound = false
local wandering = false
local stuckCounter = 0
local lastMoveTime = 0
if not humanoid then
warn("No humanoid found!")
return
end
SoundDetector.SetNPC(npc)
local function moveToSound(sound)
if movingToSound or wandering or not humanoid or tick() - lastMoveTime < 2 then return end
movingToSound = true
wandering = false
lastMoveTime = tick()
print("Moving to sound at:", sound.Parent.Position)
task.spawn(function()
local soundPosition = sound.Parent.Position
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentJumpHeight = 15,
AgentMaxSlope = 50,
})
local success, errorMessage = pcall(function()
path:ComputeAsync(npc.HumanoidRootPart.Position, soundPosition)
end)
if not success then
warn("Error computing path: " .. errorMessage)
movingToSound = false
return
end
if path.Status == Enum.PathStatus.Success then
stuckCounter = 0 -- Reset stuck counter
for _, waypoint in ipairs(path:GetWaypoints()) do
if not movingToSound then return end
humanoid:MoveTo(waypoint.Position)
local reached = humanoid.MoveToFinished:Wait(4)
if not reached then
warn("MoveTo failed or took too long, recalculating...")
stuckCounter = stuckCounter + 1
if stuckCounter >= 3 then
warn("NPC stuck, stopping movement.")
task.wait(2)
stuckCounter = 0
end
break
end
end
else
warn("No path found to the sound.")
end
task.wait(1.5)
movingToSound = false
end)
end
local function wander()
if wandering or movingToSound or not humanoid or tick() - lastMoveTime < 2 then return end
wandering = true
lastMoveTime = tick()
print("Wandering...")
task.spawn(function()
while wandering do
local randomDirection = Vector3.new(math.random(-50, 50), 0, math.random(-50, 50))
local wanderPosition = npc.HumanoidRootPart.Position + randomDirection
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentJumpHeight = 15,
AgentMaxSlope = 50,
})
local success, errorMessage = pcall(function()
path:ComputeAsync(npc.HumanoidRootPart.Position, wanderPosition)
end)
if success and path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(path:GetWaypoints()) do
if not wandering then return end
humanoid:MoveTo(waypoint.Position)
local reached = humanoid.MoveToFinished:Wait(4)
if not reached then
warn("MoveTo failed or took too long, recalculating...")
break
end
end
end
task.wait(math.random(5, 8))
end
end)
end
RunService.Heartbeat:Connect(function()
if movingToSound then return end
task.spawn(function()
local sound = SoundDetector.GetLoudestSound()
if sound then
print("Sound detected, switching to move mode")
moveToSound(sound)
else
print("No sound detected, continuing to wander")
--wander()
end
end)
end)
Any help is appreciated! Thank you!