Making a melee combat system. I am using this script to detect when the opponent is blocking, so the attacker cancels his animation and doesn’t do damage.
hitbox.OnHit:Connect(function(hit)
if state == 2 then
if hit.Name == "BlockPart" then
stunned = true
hitbox:HitStop()
stopAnims()
blockSound:Play()
I am using raycast hitbox, for those who don’t know what it is, it’s really irrelevant, you can imagine this as a basic touch event.
As You can see in this video, blocking sometimes doesn’t work and the opponent gets damaged. This happens because sometimes the ray (hitpart) hits the opponent’s body first, and only then blockpart (miliseconds difference). This mostly happens when the attack starts when the sword is already touching the body. I don’t want to make sword cancollide, because it brings other issues + it doesn’t solve this problem, I already tried.
I would much appreciate if you could explain how you handle blocking in your games, or offer solution on how to fix it in my case^
I guess what the solution could be is instead of using a part make some sort of a custom made state, like a set attribute and if the NPC/player has the attribute the attack gets redirected to the block effects instead of damaging
That won’t work, because I want the attacker to be blocked only if he’s attacking from front. So for example you block, but someone attacks you from behind, you should still take damage
I’ll try to experiment with this tomorrow, but I’d like to achieve something more precise to the sword movement. Watch this video starting from 5:33.
[Video deleted]
As you can see, if the sword hits directly the shield, the attack gets blocked, in all other cases it doesn’t, which allows for players to bypass blocks by clever sword movement.
If it hits the body instead of the blockpart first, something is probably wrong with your raycast.
I would check what’s going on with the rays but if you don’t feel like so, you can wait with damaging the player and then check if the attack was blocked.
local lastBlock = {}
hitbox.OnHit:Connect(function(hit)
if hit.Name == 'Body' then
task.wait(.2)
if lastBlock[attacker] and tick() - lastBlock[attacker] < .4 then return end
-- damage handling
elseif hit.Name == 'Blockpart' then
lastBlock[attacker] = tick()
end
end
Remember about initializing lastBlock in PlayerAdded and removing player key in PlayerRemoving.
Here’s how RayCast Hitbox works. The green circles you see are attachments. Every frame a ray is fired from all of the attachments. Once one of the rays hits something with a humanoid, none of the rays will hit anymore (to avoid doing multiple damages on one hit).
This is not so different to the regular .Touched Event, as if any pixel of the part touches another part, the event will fire.
There is nothing wrong with a ray, I see no other way of firing a ray and hit being accurate. If for example I fire a ray only from the middle of the sword, nothing will happen if the tip of the sword touches.
I can’t use your method, because if it hits the body, it won’t detect hits with the blockpart anymore, as the rays will stop firing on body hit.
why don’t you get rid of the blockpart and just set an attribute on the enemy or other players model like Character:SetAttribute('Blocking', true) when they are blocking and when they stop or not blocking Character:SetAttribute('Blocking', nil)
check it with
if Character:GetAttribute('Blocking') then
-- currently blocking
else
-- not blocking
end
on and you will want to do this from a server script on set and unset that way all clients can see and also the server can see the attribute
Because as explained above, I want the attack to be blocked only if the sword hits the blocker’s sword or shield at the time of blocking. If I do it your way the attack will be blocked even when attacking from behind or any direction
Oh, alright.
This part of your thread confused me: This happens because sometimes the ray (hitpart) hits the opponent’s body first, and only then blockpart (miliseconds difference)