I have made a Zombie Artificial Intelligence script that chases the nearest player to the zombie using a mixture of pathfinding, raycasting and the MoveTo() function. The overall gist of the code works, however the zombie keeps pausing after each waypoint and this is just not practical.
Heres the code I wrote:
local pathfindingservice = game:GetService("PathfindingService")
local db = false
local torso = nil
local torsochar = nil
local zombie = script.Parent:WaitForChild("Zombie")
local me = script.Parent:WaitForChild("Head")
script.Parent.PrimaryPart:SetNetworkOwner(nil)
local target = nil
local aim
local path
local a = 1
local movetotimeout = 0
local movementdone = false
local chooserdb = false
function FindNearest(position)
local lowest = math.huge -- infinity
local NearestPlayer = nil
for i,v in pairs(game.Players:GetPlayers())do
if v and v.Character then
local distance = v:DistanceFromCharacter(position)
if distance < lowest then
lowest = distance
NearestPlayer = v
end
end
end
return NearestPlayer
end
function targetposition()
torso = FindNearest(me.Position)
if torso ~= nil then
torsochar = game.Workspace:FindFirstChild(torso.Name)
-- print("torsochar"..tostring(torsochar.HumanoidRootPart.Position))
target = torsochar.HumanoidRootPart.Position
end
return target
end
-- if target is within a radius and raycasting shows that there is nothing in the way,
-- use MoveTo (on loop) but if ray casting shows something in the way then use pathfinder.
function movementchooser()
if chooserdb == false then
chooserdb = true
local barrierfinder = Ray.new(me.Position, (targetposition() - me.Position).Unit * 500)
local hit, position = game.Workspace:FindPartOnRayWithIgnoreList(barrierfinder, script.Parent:GetChildren())
if hit == torsochar:WaitForChild("RayHitbox") then
print("MoveTo selected")
chooserdb = false
return "MoveTo"
else
print("PathFind Selected")
chooserdb = false
return "Pathfind"
end
end
end
function Pathfinding()
aim = targetposition()
path = pathfindingservice:CreatePath()
path:ComputeAsync(me.Position, aim)
local waypoints = path:GetWaypoints()
for i, waypoint in pairs(waypoints)do
if waypoint.Action == Enum.PathWaypointAction.Jump then
zombie:ChangeState(Enum.HumanoidStateType.Jumping)
end
zombie:MoveTo(waypoint.Position)
zombie.MoveToFinished:Wait()
end
return "done"
end
function MoveTo()
print("MoveTo Activated")
movementdone = false
movetotimeout = 0
zombie:MoveTo(targetposition())
while movetotimeout < 1 do
wait(0.1)
movetotimeout = movetotimeout + 0.1
print("MoveTo Check", movetotimeout)
end
if movetotimeout >= 1 then
print("timed out")
movementchooser()
if movementchooser() == "Pathfind" then
Pathfinding()
repeat
wait()
until Pathfinding() == "done"
end
else
if zombie.MoveToFinished == true then
print("MoveTo Finished")
movementdone = true
return "Done"
end
end
movementdone = true
return "Done"
end
wait(15)
while true do
MoveTo()
repeat
wait()
until movementdone == true
wait()
end
I would prefer to only use pathfinding service however I have found that it won't change target position when the nearest player moves.
Any suggestions will be very much appreciated, Thanks.
