Is it possible to make a "smart" zombie?

So I’m currently making a testing game and making fun things but I want to make a zombie that jumps and moves toward the player, this can be done with Path finding service but how?

--Zombie Move
local zombieTorso = script.Parent.Torso
local zombieHumanoid = script.Parent.Humanoid

local function findTarget()
local agroDistance = 100
local target = nil
for i, v in pairs(game.Workspace:GetChildren()) do
local human = v:FindFirstChild("Humanoid")
local torso = v:FindFirstChild("HumanoidRootPart")
if human and torso and  v ~= script.Parent then
-- Check distance
if (zombieTorso.Position - torso.Position).magnitude < agroDistance then
agroDistance = (zombieTorso.Position - torso.Position).magnitude
target = torso
end
end
end
return target
end

while wait(1) do
local torso = findTarget()
if torso then
zombieHumanoid:MoveTo(torso.Position)
else
zombieHumanoid:MoveTo(zombieTorso.Position + Vector3.new(math.random(-50,50), 
0,math.random(-50,50), 0))
end
end

--Zombie Kill
local zombieTorso = script.Parent.Torso

local function PlayerTouched(Part)
local Parent = Part.Parent
if game.Players:GetPlayerFromCharacter(Parent) then
Parent.Humanoid.Health = 0
end
end

zombieTorso.Touched:connect(PlayerTouched)
1 Like

Use “PathFindingService”
it is hard to explain so you can search a video up about it.

Yeah, I know how to use PathFindingService, but how would I do it?

Well just make “Waypoints” and then make the zombie follow them, also you will have to make the waypoints go to the nearest player, similar to your script.

This article from the Roblox Wiki breaks down how to utilize PathFindingService to generate a navigation mesh, and then fine-tune the different ways to reach specific waypoints. I’d recommend you take a look.

I got it, I did it but it moves to my previous point, how do I fix this…do I make a while true do?

local zombieTorso = script.Parent.Torso
local zombieHumanoid = script.Parent.Humanoid
local PathFindingService = game:GetService("PathfindingService")

local function findTarget()
local agroDistance = 100
local target = nil
for i, v in pairs(game.Workspace:GetChildren()) do
	local human = v:FindFirstChild("Humanoid")
	local torso = v:FindFirstChild("HumanoidRootPart")
	if human and torso and  v ~= script.Parent then
		-- Check distance
		if (zombieTorso.Position - torso.Position).magnitude < agroDistance then
			agroDistance = (zombieTorso.Position - torso.Position).magnitude
			-- Path Finding (Smart Zombie)
			local path = PathFindingService:CreatePath()
			path:ComputeAsync(zombieTorso.Position, torso.Position) -- 1 = Start, 2 = End
			local waypoints = path:GetWaypoints()

			for i, waypoint in pairs(waypoints) do
				-- Action
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					zombieHumanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				end
				zombieHumanoid:MoveTo(waypoint.Position)
				zombieHumanoid.MoveToFinished:Wait(2)
			end

			zombieHumanoid:MoveTo(game.Workspace.torso.Position)
		end
	end
end
return target
end

while wait(1) do
local torso = findTarget()
if torso then
	zombieHumanoid:MoveTo(torso.Position)
else
	zombieHumanoid:MoveTo(zombieTorso.Position + Vector3.new(math.random(-50,50), 0,math.random(-50,50), 0))
end
end

If it moves to your previous point, chances are that you mislabeled your points.

If it moved to the point you wanted then went backwards, the while wait(1) code in the original script might be making the zombie move more times than you want, which is why it goes back.

It might also be something to do with PathfindingService, but I’m not too familiar with the service myself so I don’t know of anything in there that you need to do otherwise it breaks.

Its doing this: (it moves to where i previously were)

Looking through the code, there are several things that seem to be acting weird:

  • game.Workspace.torso.Position isn’t (or at least shouldn’t) be a valid position - there’s no part named “torso” in the workspace itself, but there is one for your character.
  • MoveToFinished:Wait() seems to add additional delay to the movement, not sure why they decided to add that.
  • You don’t need the torso if/else statement at the end, now that all your pathfinding and moving is dealt with in the findTarget() function.
  • There’s no need to set agroDistance again - and actually this would change the agroDistance permanently, for no apparent reason.
  • We don’t need two :MoveTo() functions unless we want to add back in the random wandering from the now-removed if/else statement.