Im doing a new combat system with a hitbox function using “:GetPartsInPart()” but [i think the loop] works really bad
The function never ends so the game starts lagging as hell
function Hitbox(Character,DMG,STUN,Duration,WeldedPart,Distance,Knockback,Knockback2,Transparency)
local debounce = false
print("HITBOX START")
local HITBOX = script.SWORDHITBOX:Clone()
HITBOX.Anchored = false
HITBOX.Parent = Character
HITBOX.CFrame = Distance --EXAMPLE: Character.HumanoidRootPart.CFrame + Character.HumanoidRootPart.CFrame.LookVector*4
HITBOX.Orientation = Character.HumanoidRootPart.Orientation + Vector3.new(0,-90,0)
HITBOX.Transparency = Transparency
local weld = Instance.new("WeldConstraint")
weld.Part0 = WeldedPart
weld.Part1 = HITBOX
weld.Parent = weld.Part0
function Damage(hit) --ingore this, this is only effects + dmg
end
local parts = workspace:GetPartsInPart(HITBOX)
game:GetService("RunService").Stepped:Connect(function(step)
wait(0.01)
for _, v in pairs(parts) do
print("HITBOX ACTIVE")
Damage(v)
end
end)
wait(Duration)
game.Debris:AddItem(HITBOX,0)
print("HITBOX END")
debounce = false
end
i try changing the detection part to this:
while HITBOX and task.wait(0.01) do
for _, v in pairs(parts) do
print("HITBOX ACTIVE")
Damage(v)
end
end
but didnt work
Oh and there is no chance i change this to raycast or region3 or touched,
raycast module depends on the animation, touched is bad and idk how region3 works
For the hitbox though, you can just make it have a table of the things it hit and if an enemy got caught in it you add it to the table and say that if not table.find(table,enemy). You could also make the RunService disconnect when the hitbox ended.
local parts = workspace:GetPartsInPart(HITBOX)
game:GetService("RunService").Stepped:Connect(function(step)
wait(0.01)
for _, v in pairs(parts) do
print("HITBOX ACTIVE")
Damage(v)
end
end)
You check just once what’s inside the hitbox, and then starts a loop that keeps rechecking what was already checked. Apparently you don’t have any way to recognize if you’ve already damaged a character before too, which means if this hitbox touches a character, the character will keep getting damaged forever. What you should is:
First move the parts variable that stores the parts that are inside the hitbox to inside the loop, so if the hitbox stops touching someone, it won’t keep hitting them anymore.
You need a way to recognize if you’re hitting the same character again the you can’t just hit a same character more than once. To do this, create a table before starting the loop and store the Humanoid’s parent inside the table. Before damaging a Humanoid, you should check if they’re inside the table, and if not, then damage it.
Also, the reason you’re having lag is because you’re not stopping the loop, so Roblox Studio keeps running the loop forever, causing lag eventually. To fix this, you should use the .Destroyed event to check when the hitbox is destroyed (and apparently your hitbox is not even destroyed, so I recommend using the Debris service ato destroy the hitbox after some seconds or miliseconds), and once the hitbox is destroyed, you have to stop the loop you’ve started. To stop the loop you’ve started, put the loop inside a table:
local loop = game:GetService("RunService").Stepped:Connect(function(step)
[...]
After putting the loop inside a table, inside the function the .Destroyed event will run, you have to type:
loop:Disconnect()
Which will disconnect the loop, therefore preventing your game from lagging.
Sorry for the late response, I did that system a while ago and it had a lot of errors… Right now my hitbox module looks like this:
function CombatHandler.Hitbox(Player,Size,Position,Weld,Duration)
local Character = Player.Character or workspace.PlayerCharacters:FindFirstChild(Player.Name)
local hitbox = Instance.new("Part", Character)
hitbox.Name = "Hitbox"
hitbox.CanCollide = false
hitbox.CanQuery = false
hitbox.Massless = true
hitbox.Transparency = 1
hitbox.Size = Size
hitbox.CFrame = Position
if Weld ~= nil then
local weld = Instance.new("WeldConstraint")
weld.Part0 = Weld
weld.Part1 = hitbox
weld.Parent = weld.Part0
end
game.Debris:AddItem(hitbox,Duration)
return hitbox
end
function CombatHandler.HitDetection(Player,Hitbox)
local Character = Player.Character or workspace.PlayerCharacters:FindFirstChild(Player.Name)
local OP = OverlapParams.new()
OP.FilterType = Enum.RaycastFilterType.Exclude
OP.FilterDescendantsInstances = {Character}
local DebounceTable = {}
local Loop
local RemovingLoop
print("Starting HitDetection loop")
Loop = game:GetService("RunService").Stepped:Connect(function(step)
for _,HitPart in pairs(workspace:GetPartsInPart(Hitbox,OP)) do
if DebounceTable[HitPart] then
return
end
DebounceTable[HitPart] = true
print(HitPart.Name)
if HitPart.Name == "CharHitbox" or HitPart.Name == "WeaponClashHitbox" then
print("Sucesfully Detected Hit on Part: "..HitPart.Name)
return HitPart
end
end
end)
RemovingLoop = workspace.DescendantRemoving:Connect(function(part)
if part == Hitbox then
print("Hitbox Destroyed Detected on HitDetection fuction")
Loop:Disconnect()
DebounceTable = nil
print("HitDetection loop Disconected and DebounceTable Cleaned")
RemovingLoop:Disconnect()
end
end)
end
I dont have any errors or lag whatsoever but I dont think this is the best way I could be doing this and I dont really know if im doing something wrong so please help me and tell me if you find anything wrong.
I think you’re just using workspace.DescendantRemoving unecessarily. As I’ve said in my previous response, you can use the .Destroying event that every part has to detect when the part is getting destroyed (and also wouldn’t need to save the event connection in a variable to disconnect it).