I'm not that great of a programmer, and I'd followed a tutorial and made my own edits to make an AI. It worked perfectly until I starting cloning it for minigames where it would fail to target the player when they got in range or touched the "detector". Attached the entire script below.
local Goblin = script.Parent:WaitForChild("Humanoid")
local Root = script.Parent:WaitForChild("HumanoidRootPart")
local Head = script.Parent:WaitForChild("Head")
local lowerTorso = script.Parent:WaitForChild("LowerTorso")
local runservice = game:GetService("RunService")
local AttackAnim = script:WaitForChild("SlashAnim")
local Attack = Goblin:LoadAnimation(AttackAnim)
local BlockAnim = script:WaitForChild("BlockAnim")
local Block = Goblin:LoadAnimation(BlockAnim)
Attack.Priority = Enum.AnimationPriority.Action
local Blocking = script.Parent.Blocking
local AttackSound = script:WaitForChild("Slash")
local RoarSound = script:WaitForChild("Roar")
local clone = script.Parent:Clone()
function walkRandomly()
local xRand = math.random(-50,50)
local zRand = math.random(-50,50)
local goal = Root.Position + Vector3.new(xRand,0,zRand)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(Root.Position, goal)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
Goblin.Jump = true
end
Goblin:MoveTo(waypoint.Position)
local timeOut = Goblin.MoveToFinished:Wait(1)
if not timeOut then
Goblin.Jump = true
walkRandomly()
end
end
else
wait(1)
walkRandomly()
end
end
function findPath(target)
runservice.Heartbeat:Connect(function()
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(Root.Position, target.Position)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
Goblin.Jump = true
end
Goblin:MoveTo(waypoint.Position)
local timeOut = Goblin.MoveToFinished:Wait(1)
if not timeOut then
Goblin.Jump = true
findPath(target)
break
end
if checkSight(target) then
repeat
Goblin:MoveTo(target.Position)
attack(target)
wait(0.1)
if target == nil then
break
elseif target.Parent == nil then
break
end
until checkSight(target) == false or Goblin.Health < 1 or target.Parent.Humanoid.Health < 1
break
end
if (Root.Position - waypoints[1].Position).Magnitude > 20 then
findPath(target)
break
end
end
end
end)
end
function checkSight(target)
local ray = Ray.new(Root.Position, (target.Position - Root.Position).Unit * 40)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
if hit then
runservice.Heartbeat:Connect(function()
if hit:IsDescendantOf(target.Parent) and math.abs(hit.Position.Y - Root.Position.Y) < 3 then
return true
end
end)
end
return false
end
function findTarget()
local dist = 50
local target = nil
local potentialTargets = {}
local seeTargets = {}
for i,v in ipairs(workspace:GetChildren()) do
runservice.Heartbeat:Connect(function()
local human = v:FindFirstChild("Humanoid")
local torso = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
if human and torso and v.Name ~= script.Parent.Name then
if (Root.Position - torso.Position).Magnitude < dist and human.Health > 0 then
table.insert(potentialTargets,torso)
end
end
end)
end
if #potentialTargets > 0 then
for i,v in ipairs(potentialTargets) do
if checkSight(v) then
table.insert(seeTargets, v)
elseif #seeTargets == 0 and (Root.Position - v.Position).Magnitude < dist then
target = v
dist = (Root.Position - v.Position).Magnitude
end
end
end
if #seeTargets > 0 then
dist = 200
for i,v in ipairs(seeTargets) do
if (Root.Position - v.Position).Magnitude < dist then
target = v
dist = (Root.Position - v.Position).Magnitude
end
end
end
if target then
if math.random(20) == 3 then
RoarSound:play()
end
end
return target
end
function attack(target)
if (Root.Position - target.Position).Magnitude < 7 then
Attack:Play()
wait(0.3)
AttackSound:Play()
if target.Parent ~= nil then
if math.random(5) == 3 then
Blocking.Value = true
Block:Play()
wait(2)
Block:Stop()
Blocking.Value = false
else
if target.Parent.Blocking.Value == false then
target.Parent.Humanoid:TakeDamage(15)
elseif target.Parent.Blocking.Value == true then
script.Clang:Play()
end
end
end
wait(1)
end
end
function died()
wait(5)
script.Parent:Destroy()
end
Goblin.Died:Connect(died)
function main()
local target = findTarget()
if target then
Goblin.WalkSpeed = 16
findPath(target)
else
Goblin.WalkSpeed = 12
walkRandomly()
end
end
while wait(0.1) do
if Goblin.Health < 1 then
break
end
main()
end
script.Parent.Detector.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= "Goblin" then
local target = findTarget()
checkSight(target)
end
end)

4 comments
You could probably put a lot of goblins in a model in ReplicatedStorage and put that model in the Workspace when the minigame starts.
What I am doing is putting the amount I want in every wave in folders in the ReplicatedStorage, then cloning each wave's folder which contains the goblins and it still breaks.
Dude, I've never written a script that long before and your calling yourself "not a great programmer"?, Btw I've also been working on an AI recently without using pathfinding which I can explain the whole process of it if you want the script.
Well I followed a tutorial for practically all of it, but I need the pathfinding because the AI needs to be able to chase the player and attack them.