Hello, so I was testing my code, when I runned into a massive lag spike with over 3k pings, obviously you can’t play, like that.
But I think I know it’s origin, even though I can’t find a “real” solution to it.
Here’s the script:
local function search(tbl)
table.sort(tbl, function(a,b)
return (killer.PrimaryPart.Position - a.Character.PrimaryPart.Position).Magnitude < (killer.PrimaryPart.Position - b.Character.PrimaryPart.Position).Magnitude
end)
self.currentTarget = tbl[1]
RunService.Heartbeat:Connect(function()
if self.currentTarget == nil then return end
local NewPath = Path.new(killer)
NewPath:Run(self.currentTarget.Character.PrimaryPart.Position)
NewPath._events.WaypointReached.Event:Connect(function()
zoneParameters1.Position = killer.PrimaryPart.Position - Vector3.one
zoneParameters2.Position = killer.PrimaryPart.Position - Vector3.one
zone1 = Zone.new(zoneParameters1)
zone2 = Zone.new(zoneParameters2)
end)
end)
return tbl
end
I use ZonePlus and SimplePath in this module. Thanks in advance to everyone who’s going to help!
function Killer.new(killer, maxDistance)
killer.PrimaryPart.Anchored = false
killer.PrimaryPart.CanCollide = false
local self = {}
self.maxDistance = maxDistance or 100
self.currentTarget = nil
self.cooldownInSeconds = 5
self.zoneParams = {}
function self:MoveTo(pos1,pos2)
local Distance = (pos1 - pos2).Magnitude
if Distance > self.maxDistance then
return warn("pos1 is more than "..tostring(self.maxDistance).." studs away, and it's over the max, please, change the max distance or use 2 fewer distances")
else
local NewPath = Path.new(killer)
if killer.PrimaryPart.Position ~= pos1 then
killer.PrimaryPart.Position = pos1
end
NewPath:Run(pos2)
end
end
function self:FindNearestTarget(zoneParameters1, zoneParameters2)
local zone1 = Zone.new(zoneParameters1)
local zone2 = Zone.new(zoneParameters2)
local function search(tbl)
table.sort(tbl, function(a,b)
return (killer.PrimaryPart.Position - a.Character.PrimaryPart.Position).Magnitude < (killer.PrimaryPart.Position - b.Character.PrimaryPart.Position).Magnitude
end)
self.currentTarget = tbl[1]
RunService.Heartbeat:Connect(function()
if self.currentTarget == nil then return end
local NewPath = Path.new(killer)
NewPath:Run(self.currentTarget.Character.PrimaryPart.Position)
NewPath._events.WaypointReached.Event:Connect(function()
zoneParameters1.Position = killer.PrimaryPart.Position - Vector3.one
zoneParameters2.Position = killer.PrimaryPart.Position - Vector3.one
zone1 = Zone.new(zoneParameters1)
zone2 = Zone.new(zoneParameters2)
end)
end)
return tbl
end
local playersInZone = {}
zone1.playerEntered:Connect(function(player)
if table.find(playersInZone, player) == nil then
table.insert(playersInZone, player)
task.spawn(search, playersInZone)
end
end)
zone1.playerExited:Connect(function(player)
if table.find(playersInZone, player) then
table.remove(playersInZone, table.find(playersInZone, player))
if self.currentTarget == player then
self.currentTarget = nil
end
end
end)
zone2.playerEntered:Connect(function(player)
player.Character.Humanoid:TakeDamage(100)
player.Character.Humanoid.Died:Connect(function()
self.currentTarget = nil
end)
end)
task.spawn(function()
while task.wait(self.cooldownInSeconds) do
if self.currentTarget == nil then
local randomPosition = Vector3.new(math.random(5,100), 0, math.random(5,100))
local NewPath = Path.new(killer)
NewPath:Run(randomPosition)
NewPath._events.WaypointReached.Event:Connect(function()
zoneParameters1.Position = killer.PrimaryPart.Position
zoneParameters2.Position = killer.PrimaryPart.Position
zone1 = Zone.new(zoneParameters1)
zone2 = Zone.new(zoneParameters2)
end)
else
return
end
end
end)
end
return self
end
It’s risky to create a connection within an infinite loop, you’ll need to be very careful about controlling the rate that they’re created when doing so
If self.currentTarget says nil for even 1 second, 60 WaypointReached.Event connections will be created (assuming you have 60 fps)
The answer would depend on why are you creating it within a loop in the first place
If you want to create a connection whenever currentTarget is not nil, then you can use a value instance to detect when it changes and run the code inside the value instance’s Changed connection
What’s the type of the currentTarget value? I can write example code if you wish
Oh, sorry I forgot to mention that I tried with :GetProperyChangedSignal("Position") (for the primarypart), and it didn’t fire, same for the .Changed, and about the example, well, sure! Thanks alot @JohhnyLegoKing
Disconnecting the connection if currentTarget is not nil could also work to fix the problem:
function Killer.new(killer, maxDistance)
killer.PrimaryPart.Anchored = false
killer.PrimaryPart.CanCollide = false
local self = {}
self.maxDistance = maxDistance or 100
self.currentTarget = nil
self.cooldownInSeconds = 5
self.zoneParams = {}
function self:MoveTo(pos1,pos2)
local Distance = (pos1 - pos2).Magnitude
if Distance > self.maxDistance then
return warn("pos1 is more than "..tostring(self.maxDistance).." studs away, and it's over the max, please, change the max distance or use 2 fewer distances")
else
local NewPath = Path.new(killer)
if killer.PrimaryPart.Position ~= pos1 then
killer.PrimaryPart.Position = pos1
end
NewPath:Run(pos2)
end
end
function self:FindNearestTarget(zoneParameters1, zoneParameters2)
local zone1 = Zone.new(zoneParameters1)
local zone2 = Zone.new(zoneParameters2)
local function search(tbl)
table.sort(tbl, function(a,b)
return (killer.PrimaryPart.Position - a.Character.PrimaryPart.Position).Magnitude < (killer.PrimaryPart.Position - b.Character.PrimaryPart.Position).Magnitude
end)
self.currentTarget = tbl[1]
local connection
connection = RunService.Heartbeat:Connect(function()
if self.currentTarget == nil then return end
connection:Disconnect()
local NewPath = Path.new(killer)
NewPath:Run(self.currentTarget.Character.PrimaryPart.Position)
NewPath._events.WaypointReached.Event:Connect(function()
zoneParameters1.Position = killer.PrimaryPart.Position - Vector3.one
zoneParameters2.Position = killer.PrimaryPart.Position - Vector3.one
zone1 = Zone.new(zoneParameters1)
zone2 = Zone.new(zoneParameters2)
end)
end)
return tbl
end
local playersInZone = {}
zone1.playerEntered:Connect(function(player)
if table.find(playersInZone, player) == nil then
table.insert(playersInZone, player)
task.spawn(search, playersInZone)
end
end)
zone1.playerExited:Connect(function(player)
if table.find(playersInZone, player) then
table.remove(playersInZone, table.find(playersInZone, player))
if self.currentTarget == player then
self.currentTarget = nil
end
end
end)
zone2.playerEntered:Connect(function(player)
player.Character.Humanoid:TakeDamage(100)
player.Character.Humanoid.Died:Connect(function()
self.currentTarget = nil
end)
end)
task.spawn(function()
while task.wait(self.cooldownInSeconds) do
if self.currentTarget == nil then
local randomPosition = Vector3.new(math.random(5,100), 0, math.random(5,100))
local NewPath = Path.new(killer)
NewPath:Run(randomPosition)
NewPath._events.WaypointReached.Event:Connect(function()
zoneParameters1.Position = killer.PrimaryPart.Position
zoneParameters2.Position = killer.PrimaryPart.Position
zone1 = Zone.new(zoneParameters1)
zone2 = Zone.new(zoneParameters2)
end)
else
return
end
end
end)
end
return self
end
Thanks alot! This works, could explain me, why RunService.Stepped works and RunService.Heartbeat no? Really, I don’t know much about RunService (only Heartbeat and Renderstepped which are kinda the same).