NPC Walking In Place?

So the npc is meant to randomly wonder until the player enters it’s radius. But for some reason it just stays in one spot, walking in place, until the player enters it’s radius. Anyone know why this is?

Script:

local npc = script.Parent
local humanoid = npc:FindFirstChild("Humanoid")
if not humanoid then return end
if not npc.PrimaryPart then
	npc.PrimaryPart = npc:FindFirstChild("HumanoidRootPart")
	if not npc.PrimaryPart then return end
end

local followRadius = 50
local wanderRadius = 5
local forwardDistance = 2
local downwardDistance = 10
local safeDropThreshold = 2

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {npc}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude

local walkAnim = Instance.new("Animation")
walkAnim.AnimationId = "rbxassetid://90572220017959"
local walkAnimTrack = humanoid:LoadAnimation(walkAnim)

local homePos = npc.PrimaryPart.Position
local wanderDestination = nil
local isFollowing = false

local function getSafeWanderDestination()
	for i = 1, 10 do
		local offsetX = (math.random() * 2 - 1) * wanderRadius
		local offsetZ = (math.random() * 2 - 1) * wanderRadius
		local candidate = homePos + Vector3.new(offsetX, 0, offsetZ)
		local rayOrigin = candidate + Vector3.new(0, 5, 0)
		local ray = workspace:Raycast(rayOrigin, Vector3.new(0, -10, 0), raycastParams)
		if ray then
			candidate = Vector3.new(candidate.X, ray.Position.Y, candidate.Z)
			return candidate
		end
	end
	return nil
end

local prevPos = npc.PrimaryPart.Position

while true do
	wait(0.1)
	local targetPlayer = nil
	local closestDistance = math.huge
	for _, player in pairs(game.Players:GetPlayers()) do
		if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
			local dist = (npc.PrimaryPart.Position - player.Character.HumanoidRootPart.Position).Magnitude
			if dist < closestDistance then
				closestDistance = dist
				targetPlayer = player
			end
		end
	end

	local npcPos = npc.PrimaryPart.Position
	local destination = npcPos

	if targetPlayer and targetPlayer.Character and targetPlayer.Character:FindFirstChild("HumanoidRootPart") then
		if closestDistance <= followRadius then
			isFollowing = true
			wanderDestination = nil
			local targetPos = targetPlayer.Character.HumanoidRootPart.Position
			if (npcPos.Y - targetPos.Y) >= 5 then
				destination = npcPos
			else
				local forwardDir = (targetPos - npcPos).Unit
				local checkPos = npcPos + forwardDir * forwardDistance
				local groundRay = workspace:Raycast(npcPos, Vector3.new(0, -downwardDistance, 0), raycastParams)
				local forwardRay = workspace:Raycast(checkPos, Vector3.new(0, -downwardDistance, 0), raycastParams)
				local dropOff = false
				if not forwardRay then
					dropOff = true
				elseif groundRay then
					local dropHeight = groundRay.Position.Y - forwardRay.Position.Y
					if dropHeight > safeDropThreshold then
						dropOff = true
					end
				end
				if dropOff then
					destination = npcPos
				else
					destination = targetPos
				end
			end
		else
			isFollowing = false
		end
	else
		isFollowing = false
	end

	if not isFollowing then
		if wanderDestination == nil or (npcPos - wanderDestination).Magnitude < 1 then
			wanderDestination = getSafeWanderDestination()
		end
		destination = wanderDestination or npcPos
	end

	humanoid:MoveTo(destination)

	local currentPos = npc.PrimaryPart.Position
	local movedDistance = (currentPos - prevPos).Magnitude
	if movedDistance > 0.05 then
		if not walkAnimTrack.IsPlaying then
			walkAnimTrack:Play()
		end
	else
		if walkAnimTrack.IsPlaying then
			walkAnimTrack:Stop()
		end
	end
	prevPos = currentPos
end

Thanks!

image

1 Like