How do I accomplish an NPC that chases every player?

  1. What do I want to achieve?

It’s easiest for me to give an example: On Player1’s screen, the enemy is chasing him, and on Player2’s screen it shows that the enemy is chasing him instead of Player1.

  1. What is the issue?

I’m having trouble understanding how I can achieve my goal.

  1. What solutions have you tried so far?

I’ve tried typing it just like a normal AI script but it was a local script, obviously, that didn’t work.

local aiModel = script.Parent
local Humanoid = aiModel:FindFirstChild("Humanoid")

local sightRange = 50
local killDistance = 3

local function findPlayer()
	
	local Players = game.Players:GetPlayers()
	
	for i, Player in pairs(Players) do
		if Player.Character then
			if Player.Character:FindFirstChild("Humanoid").Health > 0 then
				local Target = Player.Character
				local Distance = (aiModel.RootPart.Position - Target.HumanoidRootPart.Position.Magnitude)
				
				if Distance < sightRange then
					Humanoid:MoveTo(Target.HumanoidRootPart.Position)
				end
				
				if Distance < killDistance then
					if Target.Humanoid then
						Target.Humanoid:TakeDamage(100)
					end
				end
			end
		end
	end
end

while wait() do
	findPlayer()
end
1 Like

For each client have the server spawn a NPC, handle SFX/VFX on client side and make all baseparts/meshparts of npc Transparency 0 on Client, Otherwise on server It’s Transparency 1. Then have an object value/or table which specifies a link of which npc is set to which player, now you have 1:1 looking npcs chasing each player and to each player visually it looks like the npc is only chasing them and they wouldn’t know that theirs actually multiple.

Could you help me script that? Not a full script, just a basic example script that I could work off.

@Velliaan has a good concept. However, have you considered how to resolve issues of obstacle avoidance? Have you looked into the pathfinding service? If each NPC is going to follow a player 1:1 then you need a pathing system so the NPC can get to the player.

To all parts of an NPC to transparent or opaque, you would do this:

local model = script.Parent
for _, part in pairs(model:GetChildren()) do
	if part:IsA("BasePart") or part:IsA("MeshPart") then
		part.Transparency = 1 -- To make transparent.
	end
end

Put that in a server script inside the NPC’s model at the same location where Humanoid, Head, HumanoidRootPart, etc… are located.

On the client, you would have to use a remote event when the NPC spawns. In the event, the client will have to know which NPC to set the transparency to 0 on. You can send the model to the client.

local replicatedStorage = game:GetService("ReplicatedStorage")

replicatedStorage.makeVisible.OnClientEvent:Connect(function(model)
	for _, part in pairs(model:GetChildren()) do
		if part:IsA("BasePart") or part:IsA("MeshPart") then
			part.Transparency = 0 -- To make opaque
		end
	end
end

Make sure you create the event and place it in replicated storage.

Thank you for your comment, but it has been deemed too laggy for some devices, and I’ve found a way to do it.

I made a LocalScript in StarterPlayer >> StarterPlayerScripts:

local Clone = NPC:clone()

Clone.Parent = game.Workspace.NPC

And then I made another one for the AI:

local hrpOfNPC = npc:WaitForChild("HumanoidRootPart")

local plrsHit = {}

local maxDistance = math.huge


npc.Humanoid.Touched:Connect(function(touch)

	if game.Players:GetPlayerFromCharacter(touch.Parent) and not plrsHit[game.Players:GetPlayerFromCharacter(touch.Parent)] then

		plrsHit[game.Players:GetPlayerFromCharacter(touch.Parent)] = true
		
		touch.Parent.Humanoid.Health = 0
		
		wait(1)

		plrsHit[game.Players:GetPlayerFromCharacter(touch.Parent)] = false	
	end
end)


while wait() do
	
	local plrs = game.Players:GetPlayers()
	
	local closestHRP
	
	for i, plr in pairs(plrs) do
		
		if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") and plr.Character.Humanoid.Health > 0 then
			
			local hrp = plr.Character.HumanoidRootPart
			
			local distanceBetween = (hrpOfNPC.Position - hrp.Position).Magnitude
			
			
			if not closestHRP then closestHRP = hrp end
			
			if (hrpOfNPC.Position - closestHRP.Position).Magnitude > distanceBetween then
				
				closestHRP = hrp
				
			end
		end
	end
	
	if closestHRP and (hrpOfNPC.Position - closestHRP.Position).Magnitude <= maxDistance then npc.Humanoid:MoveTo(closestHRP.Position) end
end

Later, I’m going to rescript the AI for it to work with PathfindingService