What is a good method for hit detection on my sword?

Hello! I was wondering what will be a good way to use hit detection on my sword. I tried detecting when it hits a certain keyframe then running :GetTouchingParts() but most of the time it doesn’t register a hit. Somebody on Discord told me to use a .Touched event, but I don’t know if you use the tool but don’t hit someone, next time it touches a player it will damage them (even if you didn’t activate it).

Here is the LocalScript:

local tool = script.Parent
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local folder = script.Parent.Animations
local idle = humanoid:LoadAnimation(folder.Idle)
local canAttack = true
local place = 1
local remote = game.ReplicatedStorage:WaitForChild("SwordEvent")

tool.Activated:Connect(function()
	if canAttack then
		canAttack = false
		local swings = folder:GetChildren()
		table.remove(swings, table.find(swings, folder.Idle))
		table.remove(swings, table.find(swings, folder.Block))
		
		local swing = humanoid:LoadAnimation(swings[place])
		
		swing.KeyframeReached:Connect(function(keyframe)
			if keyframe == "Attack" then
				print("Keyframe Attack Reached!")
				remote:FireServer(script.Parent)
			end
		end)
		
		swing:Play()
		place += 1
		if place >= 3 then
			place = 1
		end
		swing.Stopped:Wait()
		wait(3)
		canAttack = true
	end
end)

tool.Equipped:Connect(function()
	idle:Play()
end)

tool.Unequipped:Connect(function()
	idle:Stop()
end)

And here is the ServerScript:

local remote = game.ReplicatedStorage:WaitForChild("SwordEvent")
local canAttack = true

local function sword(player, sword)
	if canAttack then
		canAttack = false
		print("Fired")
		local hitbox = sword.Hitbox
		local parts = hitbox:GetTouchingParts()
		
		for _, part in pairs(parts) do
			print(part.Name)
			local hitPlayer = game.Players:GetPlayerFromCharacter(part.Parent)
			if hitPlayer then
				print("Player was hit")
				local hitHumanoid = part.Parent.Humanoid
				hitHumanoid:TakeDamage(20)
				print("Player was damaged")
				break
			end
		end
		wait(3)
		canAttack = true
	end
end

remote.OnServerEvent:Connect(sword)

Thanks for reading!

1 Like

I would recommend raycasting for detecting hits from the sword. Here is a great module you can use: Raycast Hitbox 4.01: For all your melee needs!

Wouldn’t recommend that module tbh because performance wise it’s not good at all. If you look in the main handler script you can see swordphin use a pairs loop inside a heartbeat connection which runs on frame and inside that pairs loop, there is a whole bunch of code calling multiple functions in that for loop. Basically a whole inefficient mess.

2 Likes

Raycasting or region 3 or magnitude + dot product are good hit boxes but performance wise raycasting is the way to go because region3 and magnitude loop through everything inside the region unlike raycasting which casts a ray. If u are planning on using raycasting I would cast more than 2 rays for a good hit box.

Okay, I’ll try it out, thanks!

How would I implement raycasting? Maybe check the closest player with magnitude and cast a ray to see if they are near the player to damage them?

You don’t have to use both. For raycasting you can just cast a ray from each limb to a point a few studs infront of the player like:

local ray = Ray.new(limb.Position, limb.CFrame.lookVector * 10) – This should be in a ipairs or numeric loop when looping through the children of a character and checking if the limb:IsA(“BasePart”)

Note: Im pretty sure Ray.new() is deprecated and therefore should learn workspace:Raycast() method. I didn’t look into it so I apologize for not giving a proper example. Hope I helped!

Alright I’ll try something out, thanks!

Hey also, should I cast the ray as soon as they attack, or cast it when they hit the Attack keyframe?

thats ur choice for when u wanna cast the ray but I honestly think there should be a slight delay after the player slashes.

Alright thanks for your help, when I get the time I’ll see if I can make it work.

That’s not true at all, I am not sure where you’re getting your information from, but just because it runs on Heartbeat it doesn’t make it “inefficient”.

Looking at the MainHandler, it’s pretty efficient and it’s just a bunch of raycasts, nothing out of the ordinary or performance heavy (as rays were designed to be light weight and using them for this is probably the best approach).
You could get up to hundreds of raycasts per frame and still run on smooth 60 FPS without any performance issues. (Client that is, I’ve tested it myself)

To OP: The reason that resource exists (Resource being: Raycast Hitbox 4.01: For all your melee needs!) is because it’s one of the best methods for hit detection when it comes to the server & melee, I have actually implemented it for my projectiles and it worked quite well and probably better than most. If you’re planning to use anything then you should use that module. From what I could see, it only starts raycasting while hitting and catches all objects depending on the attachments you provide, that’s what makes it better than most, it uses the fact that raycasting is light weight and does it pretty well.

No no… If u saw the heartbeat connection you can see a for loop inside a for loop. Now imagine, how many hitboxes and points are being looped through? A for loop inside a for loop inside a heartbeat calling like 3 functions in that loop. (Basically like 4000 + per second) At this point, its a lot worse performance wise than a region3 or magnitude hitbox and therefore being inefficient and costly on performance. This is not based on anyone else’s opinion. It should be clear to anyone that can visualize whats going on.

Edit: Also yes you are correct, its the most accurate hitbox, but if you care about performance running with multiple players in game I wouldn’t recommend it for the reasons I gave above.

2 Likes

I tested it and it works great for what I need, and also my game doesn’t lag or anything so I’ll just use that, thanks for all your help though!