The zombie always stops chasing/moving after it either,
Reaches the player
The player dies
Code
local SearchDistance = 100000
local aiDamage = 5
local canWander = false
local WanderX, WanderZ = 30, 30
function getHumanoid(model)
for _, v in pairs(model:GetChildren()) do
if v:IsA'Humanoid' then
return v
end
end
end
local ai = script.Parent
local human = getHumanoid(ai)
local hroot = ai.HumanoidRootPart
local zspeed = hroot.Velocity.magnitude
local pfs = game:GetService("PathfindingService")
function GetPlayerNames()
local players = game:GetService('Players'):GetChildren()
local name = nil
for _, v in pairs(players) do
if v:IsA'Player' then
name = tostring(v.Name)
end
end
return name
end
function GetPlayersBodyParts(t)
local torso = t
if torso then
local figure = torso.Parent
for _, v in pairs(figure:GetChildren()) do
if v:IsA'Part' then
return v.Name
end
end
else
return "HumanoidRootPart"
end
end
function GetTorso(part)
local chars = game.Workspace:GetChildren()
local torso = nil
for _, v in pairs(chars) do
if v:IsA'Model' and v ~= script.Parent and v.Name == GetPlayerNames() then
local charRoot = v:FindFirstChild'HumanoidRootPart'
if (charRoot.Position - part).magnitude < SearchDistance then
torso = charRoot
end
end
end
return torso
end
deb = false
for _, zambieparts in pairs(ai:GetChildren()) do
if zambieparts:IsA("Part") then
zambieparts.Touched:connect(function(p)
if deb == false and p.Parent:FindFirstChild("Torso") and p.Parent.Name ~= ai.Name then -- damage
deb = true
local animation = script:WaitForChild('Animation')
local humanoid = script.Parent:WaitForChild('Humanoid')
local attack = humanoid:LoadAnimation(animation)
attack:Play()
local enemy = p.Parent
local enemyhuman = getHumanoid(enemy)
enemyhuman:TakeDamage(aiDamage)
task.wait(0.35)
deb = false
end
end)
end
end
local path
local waypoint
local oldpoints
local isWandering = 0
if canWander then
spawn(function()
while isWandering == 0 do
isWandering = 1
local desgx, desgz = hroot.Position.x + math.random(-WanderX, WanderX), hroot.Position.z + math.random(-WanderZ, WanderZ)
human:MoveTo( Vector3.new(desgx, 0, desgz) )
wait(math.random(4, 6))
isWandering = 0
end
end)
end
while task.wait() do
if script.Parent.Humanoid.Health <= 0 then
script:Destroy()
end
local enemytorso = GetTorso(hroot.Position)
if enemytorso ~= nil then -- if player detected
isWandering = 1
local function checkw(t)
local ci = 3
if ci > #t then
ci = 3
end
if t[ci] == nil and ci < #t then
repeat
ci = ci + 1
wait()
until t[ci] ~= nil
return Vector3.new(1, 0, 0) + t[ci]
else
ci = 3
return t[ci]
end
end
path = pfs:FindPathAsync(hroot.Position, enemytorso.Position)
waypoint = path:GetWaypoints()
oldpoints = waypoint
local connection;
local direct = Vector3.FromNormalId(Enum.NormalId.Front)
local ncf = hroot.CFrame * CFrame.new(direct)
direct = ncf.p.unit
local rootr = Ray.new(hroot.Position, direct)
local phit, ppos = game.Workspace:FindPartOnRay(rootr, hroot)
if path and waypoint or checkw(waypoint) then
if checkw(waypoint) ~= nil and checkw(waypoint).Action == Enum.PathWaypointAction.Walk then
human:MoveTo( checkw(waypoint).Position )
human.Jump = false
end
if connection then
connection:Disconnect()
end
else
for i = 3, #oldpoints do
human:MoveTo( oldpoints[i].Position )
end
end
elseif enemytorso == nil and canWander then -- if player not detected
isWandering = 0
path = nil
waypoint = nil
human.MoveToFinished:Wait()
end
end
Try this code i used for an old game of mine, it doesn’t have the issues you mentioned
task.wait(5)
local PathfindingService = game:GetService("PathfindingService")
local AI = script.Parent
local RP = script.Parent.HumanoidRootPart
local Hum = script.Parent.Humanoid
Hum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
local Waypoints = game.Workspace:WaitForChild("Waypoints"):GetChildren()
RP:SetNetworkOwner(nil)
local attackAnim = Hum.Animator:LoadAnimation(script.Attack)
local walkAnim = Hum.Animator:LoadAnimation(script.Walk)
local runAnim = Hum.Animator:LoadAnimation(script.Run)
local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {Hum}
local Damage = 25
local AttackRange = 5
walkAnim.Looped = true
runAnim.Looped = true
walkAnim:Play()
local LastSeenPos
local RayParams = RaycastParams.new()
RayParams.FilterType = Enum.RaycastFilterType.Exclude
local pathParams = {
AgentHeight = 5,
AgentRadius = 3,
AgentCanJump = true,
}
local function getPath(destination)
local path = PathfindingService:CreatePath(pathParams)
path:ComputeAsync(RP.Position, destination)
return path
end
function lineOfSight(target)
local rayDirection = target.Position - RP.Position
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {RP.Parent}
local RayResult = workspace:Raycast(RP.Position, rayDirection, rayParams)
if RayResult and RayResult.Instance then
if RayResult.Instance:IsDescendantOf(target.Parent) then
return true
else
return false
end
end
end
function getTarget()
local closestTarget
local distanceFromClosestTarget = 1000000000
for i, player in pairs(game.Players:GetChildren()) do
local distance = (player.Character.HumanoidRootPart.Position - RP.Position).Magnitude
if distance < distanceFromClosestTarget then
distanceFromClosestTarget = distance
closestTarget = player
end
end
return(closestTarget)
end
local db = false
local runAnimPlayingStatus = false
local walkAnimPlayingStatus = false
function chaseTarget(target)
print('chasing')
if runAnimPlayingStatus == false then
walkAnim:Stop()
runAnim:Play()
runAnimPlayingStatus = true
walkAnimPlayingStatus = false
end
local path
path = getPath(target.Character.HumanoidRootPart.Position)
local waypoints = path:GetWaypoints()
local humTarget = getTarget()
local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)
if waypoints[2] then
Hum:MoveTo(waypoints[2].Position)
LastSeenPos = humTarget.Character.HumanoidRootPart.Position
if (humTarget.Character.HumanoidRootPart.Position - RP.Position).Magnitude <= 5 and db == false then
db = true
attackAnim:Play()
humTarget.Character.Humanoid:TakeDamage(Damage)
attackAnim.Ended:Wait()
db = false
end
if humTarget and LineOfSight then
chaseTarget(humTarget)
else
moveToLastSeen(LastSeenPos)
end
else
warn("checkpoint 2 does not exist, falling back to patrol")
patrol()
end
end
function moveToLastSeen(location)
print('fired')
local path = getPath(location)
for i, waypoint in pairs(path:GetWaypoints()) do
local humTarget = getTarget()
local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)
if humTarget and LineOfSight then
path:Destroy()
chaseTarget(humTarget)
break
else
if walkAnimPlayingStatus == false then
walkAnim:Play()
walkAnimPlayingStatus = true
end
runAnimPlayingStatus = false
runAnim:Stop()
Hum:MoveTo(waypoint.Position)
Hum.MoveToFinished:Wait()
if i == #path:GetWaypoints() then
patrol()
end
end
end
end
function moveTo(target)
local humTarget = getTarget()
local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)
if humTarget and LineOfSight then
chaseTarget(humTarget)
else
local path = getPath(target)
if path.Status == Enum.PathStatus.Success then
for i, waypoint in pairs(path:GetWaypoints()) do
local humTarget = getTarget()
local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)
if humTarget and LineOfSight then
path:Destroy()
chaseTarget(humTarget)
break
else
if walkAnimPlayingStatus == false then
walkAnim:Play()
walkAnimPlayingStatus = true
end
runAnimPlayingStatus = false
runAnim:Stop()
Hum:MoveTo(waypoint.Position)
Hum.MoveToFinished:Wait()
if i == #path:GetWaypoints() then
patrol()
end
end
end
end
end
end
function patrol()
local ChosenWapoint = math.random(1, #Waypoints)
moveTo(game.Workspace.Waypoints:FindFirstChild(ChosenWapoint).Position)
end
patrol()
It has some functionality where it requires line of sight to attack and if it losses sight when chasing it goes to the last known position of the player, however if you want to simplify it you can remove those aspects and just keep the core