How do you make drag hitboxes?

I’m making a dbd inspired game sort of like Forsaken and TR:UD, based around 2009 - 2013 roblox, and i’m trying to find how to make the cool dragging hitboxes you see in games.

What i mean by this is, have you ever been in a game with show hitboxes on, and the attack has multiple hitboxes that drags along with you? If not, join Item Asylum or Forsaken, turning show hitboxes on and look at an attack.

I’m not the best at explaining, though I hope you can SOMEWHAT understand what i’m talking about. I’ve looked online to try and find a tutorial on how to get this type of hitbox, but I can’t find any.

If anybody on the forums know how to make the multi-hitbox thingy, PLEASE tell me how, bc i dont want those bad, janky 1 hitbox attack systems

Like one of those curved red ones that go with the weapon?

(image taken from google, raycast hitbox 4.01 post on devforum)

No, like the ones where each frame a new square-hitbox is made, gimmie a second i’ll get a photo



these types of hitboxes

Oh, alright.

Im guessing you can make a point on your weapon and weld it to your handle/blade so when the animation plays the part goes with it, that’s going to the the centre/origin of all the parts, then through out the duration of the animation, make these boxes and check if something got hit with workspace:GetPartBoundsInBox() or with workspace:GetPartsInPart(), though I would go with the first option, then combine every hit from those boxes into one mega table. Then remove duplicate hits, check if a humanoid was hit, if hit then deal damage.

3 Likes

Depends on how detailed you want to do it. A good place to start is distance check each enemy to create a table of potential hits.
Afterwards you would want to perform raycast/overlap queries and maybe angle checks.

Based on your video, it looks like he’s doing box checks in front of the character for X amount of seconds every frame. That’s really not that complicated.
I’ll give you an example of how to do that.

local RS = game:GetService("RunService")
local Players = game:GetService("Players")


local function Hitbox(HRP : BasePart, Duration : number, Size : Vector3, Offset : CFrame, OnHit)
	local OParams = OverlapParams.new()
	OParams.FilterType = Enum.RaycastFilterType.Include
	OParams.MaxParts = 100
	OParams.CollisionGroup = "Default"
	OParams.RespectCanCollide = false

	local minRadius = Offset.Position.X+Offset.Position.Y+Offset.Position.Z
		+ (Size.X+Size.Y+Size.Z)/2 + 2.5 -- 2.5 for character radius

	local already_hit = {[HRP.Parent]=true} -- that way self is already excluded

	local Connection = RS.PostSimulation:Connect(function(dt)
		local instances = {}
		for _,plr in Players:GetPlayers() do
			if plr.Character and not already_hit[plr.Character] then
				local xHRP = plr.Character.HumanoidRootPart
				if (xHRP.Position-HRP.Position).Magnitude <= minRadius then
					table.insert(instances, plr.Character)
				end
			end
		end
		OParams.FilterDescendantsInstances = instances
		local partHits = workspace:GetPartBoundsInBox(HRP.CFrame * Offset, Size, OParams)
		for _,part in partHits do
			local xChar = part.Parent -- the char of the part should be the direct parent
			if not already_hit[xChar] then
				already_hit[xChar] = true
				task.defer(OnHit, xChar)
			end
		end
	end)

	task.delay(Duration, Connection.Disconnect, Connection)

	return Connection
end

See RunService, GetPartBoundsInBox
The testing place I made for this since it was a lot of complicated code:
overlap hitbox.rbxl (89.7 KB)

2 Likes

Hey, I was working on doing what you said (really good btw), and I ran into a small issue that probably has a really easy quick fix but I’m having trouble finding it.

when I activate the attack i get the error message “invalid argument #2 to ‘remove’ (number expected, got Instance)”

if part:GetAttribute(“Hitbox”) then table.remove(touchedParts, part) end – removes hitboxes

I know that the issue is me using an object in table.remove, but how do i find the index of the object in the table so I can use the index of the object instead?

Sorry for the late reply.

I guess you can do:

table.remove(touchedParts, touchedParts[part])
1 Like

Thanks to everyone for your help! Due to the support, I was able to make and debug the hitbox system, and it’s now fully functional

If anyone in like 10 years wants to know how to make drag hitboxes, heres the code I used:

-- needs a part called "playerHitbox" inside of the character to detect a hit

local function createHitbox(damage, size, offset, hrp, hitboxes, touchedTable)
	local hitbox = Instance.new("Part")
	hitbox.CanCollide = false
	hitbox.Transparency = 0.75
	hitbox.Size = size
	hitbox.Parent = workspace
	hitbox.CFrame = hrp.CFrame * CFrame.new(offset)
	hitbox.Anchored = true
	
	table.insert(hitboxes, hitbox)
	
	local touchedParts = workspace:GetPartBoundsInBox(hitbox.CFrame, hitbox.Size)
	for i, part in touchedParts do
		table.insert(touchedTable, part)
	end
end

m1Event.OnServerEvent:Connect(function(player, damage, size, offset, startup, Time, increment)
	task.wait(startup) -- startup time
	
	local hitboxes = {}
	local touchedParts = {}
	local damagedPlayers = {}
	
	local character = player.Character or player.CharacterAdded:Wait()
	local hrp = character:WaitForChild("HumanoidRootPart")
	local humanoid = character:WaitForChild("Humanoid")
	
	local breakLoop = false
	
	for i = 1, math.floor(Time / increment), 1 do
		createHitbox(damage, size, offset, hrp, hitboxes, touchedParts)
		
		for i, part in touchedParts do
			if table.find(hitboxes, hitboxes[part]) or table.find(damagedPlayers, damagedPlayers[part.Parent.Name]) or not part.Parent:FindFirstChild("Humanoid") then 
				table.remove(touchedParts, touchedParts[part]) -- removes hitboxes, non-charcater objects, and anything already damaged
			else
				if part.Name == "playerHitbox" and part.Parent.Name ~= character.Name then
					table.insert(damagedPlayers, part.Parent.Name)
					part.Parent:FindFirstChild("Humanoid"):TakeDamage(damage)
					breakLoop = true -- once hit it will stop casting the hitboxes
				end
			end
		end
		
		table.clear(touchedParts)
		
		task.wait(increment)
		
		if breakLoop then break end
	end
	
	for i, hitbox in hitboxes do
		hitbox:Destroy()
	end
end)

Thanks everybody! I can now continue development! :hammer:

3 Likes

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