So I have an NPC which moves around and when it gets close enough to a player it chases them, if it gets very close to the player it will start attacking.
However there is one problem; when the npc gets close to the player it stops for a second like this:
im not the best at pathfinding but here is my code:
local pathfindingService = game:GetService("PathfindingService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local foundtarget = nil
local targetpos = nil
local humanoid = script.Parent.Humanoid
local humanoidrootpart = script.Parent.HumanoidRootPart
local body = script.Parent:FindFirstChild("Torso")
local stunned = script.Parent.Stunned
local destination = game.Workspace.CampingPath:GetChildren()
-- << Initial Setup >>
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local Char = body.Parent
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
Params.FilterDescendantsInstances = {Char} --- remember to define our character!
local newHitbox = RaycastHitbox.new(script.Parent.Knife)
newHitbox.RaycastParams = Params
RaycastHitbox.DetectionMode = 1
task.wait()
local Cooldown = .75
local HitDebounce = false
local SwingDebounce = false
local AttackDebounce = false
local MaxAttackDistance = 5
local SwingSounds = Char.AttackZone.SwingSounds:GetChildren()
local HitSounds = Char.AttackZone.HitSounds:GetChildren()
newHitbox.OnHit:Connect(function(hit, humanoid, hum)
if HitDebounce == false then
HitDebounce = true
local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
print(humanoid)
RandomHitSound:Play()
humanoid:TakeDamage(10)
print("hit")
newHitbox:HitStop()
task.wait(Cooldown)
HitDebounce = false
end
end)
local IdleAnim = humanoid.Animator:LoadAnimation(script.Parent.Idle)
local WalkAnim = humanoid.Animator:LoadAnimation(script.Parent.Walk)
local RunAnim = humanoid.Animator:LoadAnimation(script.Parent.Run)
local Attack1Anim = humanoid.Animator:LoadAnimation(script.Parent.Attack)
local Attack2Anim = humanoid.Animator:LoadAnimation(script.Parent.Attack2)
Attack1Anim.Stopped:Connect(function()
newHitbox:HitStop()
end)
Attack2Anim.Stopped:Connect(function()
newHitbox:HitStop()
end)
local blockedConnection
humanoidrootpart:SetNetworkOwner(nil)
local points = {}
for _,part in ipairs(destination) do
table.insert(points,part)
task.wait()
end
foundtarget = nil
function walkRandomly()
foundtarget = nil
local point = points[math.random(1,#points)]
local target = FindTarget()
local path = game:GetService("PathfindingService"):CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true
})
path:ComputeAsync(humanoidrootpart.Position, point.Position)
local waypoints = path:GetWaypoints()
for _, waypoint in ipairs(waypoints) do
if foundtarget == nil then
print("DEBUG: WALKING RANDOMLY TO WAYPOINT")
humanoid:MoveTo(waypoint.Position)
path.Blocked:Connect(function()
print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
main()
end)
if waypoint.Action == Enum.PathWaypointAction.Jump then
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
if foundtarget == 1 then path:Destroy() break end
humanoid.MoveToFinished:Wait()
FindTarget()
end
end
--[[
local path = game:GetService("PathfindingService"):CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = false
})
--]]
local function findPath(target)
local path = game:GetService("PathfindingService"):CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true
})
path:ComputeAsync(humanoidrootpart.Position,target.Position)
local waypoints = path:GetWaypoints()
for _, waypoint in ipairs(waypoints) do
if checkSight(target) == true then
repeat
humanoid:MoveTo(target.Position)
path.Blocked:Connect(function()
print("DEBUG: PATH BLOCKED (findPath")
findPath(target)
end)
task.wait()
if target == nil then
break
elseif target.Parent == nil then
break
end
until checkSight(target) == false
if not stunned.Value then
humanoidrootpart:SetNetworkOwner(nil)
end
print("DEBUG: LOST TARGET, DESTROYING PATH (findPath)")
-- foundtarget = nil
break
else
if waypoint.Action == Enum.PathWaypointAction.Jump then
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(waypoint.Position)
local waitCheck = humanoid.MoveToFinished:Wait(1)
if not waitCheck then
findPath(target)
break
end
if (humanoidrootpart.Position - waypoints[1].Position).Magnitude > 30 then
print("DEBUG: FINDPATH(TARGET) (findPath)")
findPath(target)
break
end
end
end
end
--[[
function findPath(target)
local path = game:GetService("PathfindingService"):CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = true
})
path:ComputeAsync(humanoidrootpart.Position,target.Position)
local waypoints = path:GetWaypoints()
for _, waypoint in ipairs(waypoints) do
humanoid:MoveTo(waypoint.Position)
if waypoint.Action == Enum.PathWaypointAction.Jump then
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
if checkSight(target) == true then
repeat
humanoid:MoveTo(target.Position)
path.Blocked:Connect(function()
print("DEBUG: PATH BLOCKED (findPath")
main()
end)
task.wait()
if target == nil then
break
elseif target.Parent == nil then
break
end
until checkSight(target) == false
print("DEBUG: LOST TARGET, DESTROYING PATH (findPath)")
foundtarget = nil
path:Destroy()
break
end
if (humanoidrootpart.Position - waypoints[1].Position).Magnitude > 30 then
print("DEBUG: FINDPATH(TARGET) (findPath)")
findPath(target)
break
end
end
end
--]]
function FindTarget()
local dist = 20
local target
local players = game.Players:GetPlayers()
for i,v in ipairs(players) do
if (v.Character) then
local torso = v.Character.Torso
local human = v.Character.Humanoid
if (humanoidrootpart.Position - torso.Position).Magnitude < dist and human.Health > 0 then
if checkSight(torso) and human.Health ~= 0 then
print("DEBUG: TARGET = TORSO (FindTarget)")
print(human.Health)
target = torso
end
end
end
end
return target
end
function checkSight(target)
local ray = Ray.new(humanoidrootpart.Position, (target.Position - humanoidrootpart.Position).Unit * 50)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
local Player = game:GetService("Players"):GetPlayerFromCharacter(target.Parent)
if hit then
if hit:IsDescendantOf(target.Parent) then
if not stunned.Value then
--humanoidrootpart:SetNetworkOwner(target)
end
--[[
if not targetDebounce then
targetDebounce = true
FraudFoundPlayer:FireClient(Player)
task.wait(1)
targetDebounce = false
end
--]]
--[[]]
if (humanoidrootpart.Position - target.Position).Magnitude < MaxAttackDistance then
--print("Attack")
local RandomAttackAnim = math.random(1,2)
if RandomAttackAnim == 1 then
if Attack1Anim.IsPlaying == false and Attack2Anim.IsPlaying == false and not SwingDebounce then
SwingDebounce = true
Attack1Anim:Play()
newHitbox:HitStart()
local RandomSwingSound = SwingSounds[math.random(1, #SwingSounds)]
RandomSwingSound:Play()
task.wait(.75)
SwingDebounce = false
end
end
--[[
else
if Attack2Anim.IsPlaying == false and Attack1Anim.IsPlaying == false and not SwingDebounce then
SwingDebounce = true
Attack2Anim:Play()
print("Attack2")
if Attack1Anim.IsPlaying == true then
newHitbox:HitStart()
local RandomSwingSound = SwingSounds[math.random(1, #SwingSounds)]
RandomSwingSound:Play()
end
task.wait(.75)
SwingDebounce = false
end
end
--]]
end
--print("DEBUG: FOUND TARGET (checkSight)")
foundtarget = 1
return true
end
end
return false
end
function main()
local target = FindTarget()
if target and foundtarget == 1 then
print(target)
local Player = game.Players:GetPlayerFromCharacter(target.Parent)
humanoid.WalkSpeed = 18
findPath(target)
else
foundtarget = nil
humanoid.WalkSpeed = 7
walkRandomly()
end
end
humanoid.Running:Connect(function(speed)
if speed > 17 then
IdleAnim:Stop()
WalkAnim:Stop()
RunAnim:Play()
elseif speed > 4 and speed < 17 then
IdleAnim:Stop()
WalkAnim:Play()
RunAnim:Stop()
elseif speed <= 4 then
IdleAnim:Play()
WalkAnim:Stop()
RunAnim:Stop()
end
end)
while RunService.Heartbeat:Wait() do
main()
end