NPC's walking past targets

It don’t know if studio can’t handle 50 NPC’s but for some reason, my NPC’s are walking past their target. I added a print when the NPC reached the position. The print works but the NPC just keeps going.

It only works properly if I only spawn 20 total NPC’s.

AI Script:

local RunService = game:GetService("RunService")

local character = script.Parent.Parent
local humanoid = character:WaitForChild("Humanoid")
local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")

local Animator = humanoid:WaitForChild("Animator")

local Enemies = workspace:WaitForChild("Enemies")

local AttackAnimations = script:WaitForChild("AttackAnimations")
local attackCombo = 0
local maxAttackAnims = #AttackAnimations:GetChildren()

local TargetValue = character:WaitForChild("TargetValue")
local attacking = false

local AIRunning = true
local attackAnimConnection

local seeDistance = 1000
local findDistance = seeDistance

local damage = 3

local attackCooldown = 0.5
local attackCurrentTime = attackCooldown

local function CanSee(target, distance)
	task.desynchronize()

	if target and target.PrimaryPart then
		local origin = HumanoidRootPart.Position

		local targetRoot = target.PrimaryPart
		local targetPos = targetRoot.Position

		local targetToChar = (targetPos - origin).Unit
		local targetLookVector = HumanoidRootPart.CFrame.LookVector

		local dot = targetToChar:Dot(targetLookVector)

		if dot >= 0.5 or distance > findDistance then
			return true
		end
	end
end

local function GetNearestTarget()
	task.desynchronize()

	local nearestDistance = seeDistance
	local nearestTarget = nil

	for i,v in Enemies:GetChildren() do
		if v:IsA("Model") and v.PrimaryPart then
			local targetRoot = v.PrimaryPart
			local targetHumanoid = v:FindFirstChildOfClass("Humanoid")

			local distance = (HumanoidRootPart.Position - targetRoot.Position)

			if targetHumanoid and targetHumanoid.Health > 0 and distance < nearestDistance then
				local canSee = CanSee(v, distance)

				if canSee then
					nearestDistance = distance
					nearestTarget = v
				end
			end
		end
	end

	task.synchronize()
	TargetValue.Value = nearestTarget
end

local function StopAttackAnimConnection()
	if attackAnimConnection then
		attackAnimConnection:Disconnect()
		attackAnimConnection = nil
	end
end

local function DamageTarget()
	if TargetValue.Value then
		local targetHumanoid = TargetValue.Value:FindFirstChildOfClass("Humanoid")

		if targetHumanoid and targetHumanoid.Health > 0 then
			targetHumanoid:TakeDamage(damage)
		end
	end
end

local function PlayAttackAnimation()
	task.synchronize()

	attackCombo += 1

	local attackAnim = AttackAnimations[attackCombo]

	if attackAnim then
		local track = Animator:LoadAnimation(attackAnim)
		track:Play()

		track.Stopped:Connect(function()
			DamageTarget()
		end)
	end

	if attackCombo >= maxAttackAnims then
		attackCombo = 0
	end
end

local function Attack()
	local attackDistance = 8

	if TargetValue.Value and TargetValue.Value.PrimaryPart and tick() - attackCurrentTime >= attackCooldown then
		local targetRoot = TargetValue.Value.PrimaryPart
		local distance = (HumanoidRootPart.Position - targetRoot.Position)

		if distance <= attackDistance then
			attackCurrentTime = tick()

			PlayAttackAnimation()
			attacking = true
		else
			attacking = false
		end
	end
end

local function IsAlive()
	if TargetValue.Value then
		local targetHumanoid = TargetValue.Value:FindFirstChildOfClass("Humanoid")

		if targetHumanoid and targetHumanoid.Health > 0 then
			return true
		end
	end
end

coroutine.wrap(function()
	while AIRunning do
		coroutine.wrap(function()
			if not attacking then
				GetNearestTarget()
			end

			local isAlive = IsAlive()

			if isAlive then
				Attack()
			else
				attacking = false
			end
		end)()

		task.wait(0.1)
	end
end)()

Movement Script:

local RunService = game:GetService("RunService")

local character = script.Parent.Parent.Parent
local humanoid = character:WaitForChild("Humanoid")
local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")

local TargetValue = character:WaitForChild("TargetValue")

local function GoToTarget()
	local stopDistance = 6

	if TargetValue.Value and TargetValue.Value.PrimaryPart then
		local origin = HumanoidRootPart.Position

		local targetRoot = TargetValue.Value.PrimaryPart
		local targetPos = targetRoot.Position

		local distance = (HumanoidRootPart.Position - targetRoot.Position)

		if distance > stopDistance then
			local direction = (targetPos - origin).Unit
			local position = targetPos - direction * stopDistance

			humanoid:MoveTo(position)
		end
	end
end

RunService.PostSimulation:Connect(function()
	GoToTarget()
end)

Video:

With only 2 NPC’s:

It seems like they are going to the same position.

I fixed it by pasting the Movement Code inside the AI Handler code.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.