Odd bug with welds in my hitbox system

I am looking for help with a strange bug that is occuring within my hitbox system.

The Premise

I’ve been working on a side project over the last few days, set in a cave system where gunpowder is used in everyday life. I recently made another weapon, a large, slow battleaxe with a cannon on the other end. Due to the nature of the weapon, I made the hitboxes quite large.

The Problem

Large hitboxes resulted in an odd problem where the weld I use to keep the hitbox attached to the player seemed to freeze both the player and the hitbox in place. This only happens with large hitboxes, although I’m not sure of the exact dimensions required to trigger the bug.

Here is how hitboxes should act, and how they do act when they are small enough:

And here is how hitboxes act when they are large, notice the player getting stuck for a split second:

I’ve skimmed over the forums to see if anyone was having this same issue, but didn’t find a solution. I’ve also tried messing around with the dimensions of the hitboxes, and the hitbox function itself, to no avail. The hitbox is unanchored and CanCollide is set to Off.

Current Code

Here’s my current function for a hitbox. A lot of the arguments are passed through to the damage function but the main ones are rig which defines the character and the three that dictate size, width, height, length.

function module.Hitbox(rig, damage, duration, stunduration, params, width, height, length, blockable, posturedamage, attacker)
	local offset = Vector3.new(0, 0, -((length / 2) + 0.5))
	local hit = {}
	
	local hitbox = hitboxtemplate:Clone()
	hitbox.Name = rig.Name .. "Hitbox"
	hitbox.Size = Vector3.new(width, height, length)
	hitbox.CFrame = rig.HumanoidRootPart.CFrame * CFrame.new(offset)
	local weld = Instance.new("WeldConstraint")
	weld.Part0 = rig.HumanoidRootPart
	weld.Part1 = hitbox
	weld.Parent = hitbox
	weld.Enabled = true
	hitbox.Parent = workspace
	
	local connection = game:GetService("RunService").Heartbeat:Connect(function()
		for i, v in pairs(workspace:GetPartsInPart(hitbox, params)) do
			if v.Parent:FindFirstChildWhichIsA("Humanoid") and not hit[v.Parent] then
				hit[v.Parent] = true
				damagemodule.BluntDamage(v.Parent, damage, blockable, posturedamage, attacker)
				damagemodule.Stun(v.Parent, stunduration)
			end
		end
	end)
	
	task.spawn(function()
		task.wait(duration)
		connection:Disconnect()
		hitbox:Destroy()
	end)
end

Thanks to anyone who knows how to fix this!

Try setting “Massless” to true on the hitbox part, and also make sure that the character has the PrimaryPart set to a part of the character.

How about you just don’t weld the hitbox to the player, which in itself sounds unconventional. Not to mention, it’s creating a new instance for each attack, which sounds inefficient.

You already have the .Heartbeat connection set up for the hitreg, so what you can do is position the hitbox in front of the player via the LookAt vector before it does the spatial querying.

Both of these are already true.

I create a new instance for each attack so that I can have multiple people attacking at the same time, and I use a weld because it is the smoothest way to keep the hitbox in position. The .Heartbeat connection appears jumpy and a lot less smooth than welding, even with the hitbox anchored to stop constant gravity.

I’m just throwing darts at the problem here, but you could also try parenting the hitbox to the character.

Parenting the hitbox to the rig didn’t work either.

Unless each player needs to be able to attack multiple times simultaneously, you only need one hitbox for each player, for each unique attack.

I really don’t see why there would be an issue with just CFraming the hitbox. The hitbox itself should be anchored, massless, not collideable, not touchable, not queryable (IIRC CanQuery only matters for parts that are trying to be detected), and be positioned relative to the HumanoidRootPart. You can perhaps show us a video recording demonstrating the problem of “jumpy” hitboxes.

It might be worth building a simplified reproduction of the problem, see if the problem occurs when the part is welded to the player for a longer period of time. It might be a good bug to report if “Massless” is not working as expected.

Upon closer inspection of the jumpy hitboxes, it seems to be worse than I originally thought:

Can I see the code responsible for the positioning of the hitbox?

The same hitbox function as before, except I commented out the weld section and changed the .Heartbeat connection to include 1 more line at the top (Don’t mind that the damage function name changed, I made some small changes to the system)

	local connection = game:GetService("RunService").Heartbeat:Connect(function()
		hitbox.CFrame = rig.HumanoidRootPart.CFrame * CFrame.new(offset)
		for i, v in pairs(workspace:GetPartsInPart(hitbox, params)) do
			if v.Parent:FindFirstChildWhichIsA("Humanoid") and not hit[v.Parent] then
				hit[v.Parent] = true
				damagemodule.Damage(v.Parent, damage, damagetype, blockable, posturedamage, attacker)
				damagemodule.Stun(v.Parent, stunduration)
			end
		end
	end)

I’m gonna try to recreate your issue. Give me a while.

The issue seems to just be latency.

Here’s the thing: using welds appears to work better, but that’s because you’re giving the player themselves NetworkOwnership over the hitbox by welding it to their character, which in turn opens up a new door of vulnerability where the player can theoretically freely manipulate the hitbox to exploit/cheat.

There really isn’t a perfect solution to this. The only way to fix the latency is by making the client in charge of the hitreg, which is just as vulnerable as welding the hitbox to their character. But you could then implement a relatively simple anticheat where there’s a certain threshold to how far apart the player can be from its target (due to latency) and reject attacks that are unrealistically far, as well as a threshold to how fast the hitbox can move (to prevent cheats like killaura). It can still help prevent blatant cheating.

I see. This seems as close to a solution as possible, I’ll try out some stuff and see what I end up with.

Update: Welding works now. For some reason I had to toggle Massless off and then on again. (???)

1 Like

I used weldconstraint to weld a part to the player’s character bodypart from the server, and then changed the part’s position from the client, but nothing changed on the server?

WeldConstraint doesn’t care about the actual CFrame of the welded part; it overrides it because its job is to maintain a constant offset.

Also next time, please create a new thread with your issue instead of bumping a really old one.

It was a question, Besides, There wasn’t any warning for what i needed!