Is this a good way to do hitboxes in combat games?

So basically, this is how it would work in my head even though I’ve never really tried making one of those types of games before:

  • Make a part in studio called “HitBox” and proportion it to be around the same size as your average player, then parent that part to replicatedstorage.
  • Then in a client script parented to startercharacterscripts, do this:
-- Local script
local part = game.ReplicatedStorage:WaitForChild("Hitbox"):Clone()
local RE = game.ReplicatedStorage:WaitForChild("RemoteEvent")
while true do
local hitbox = workspace:GetPartBoundsInBox(character.CFrame, part.Size)
for i, part in hitbox do
if part.Parent:FindFirstChild("Humanoid") then
local tracks = part.Parent.Humanoid.Animator:GetPlayingAnimationTracks()
for i, track in tracks do
if track.Animation.AnimationId = "blahblahblah" and track.IsPlaying then
RE:FireServer(part)
end
end
end
end
task.wait()
-- Server Script
local RE = game.ReplicatedStorage.RemoteEvent
RE.OnServerEvent:Connect(function(Player, part)
if part.Parent:FindFirstChild("Humanoid") then -- Verifying info on the server
local tracks = part.Parent.Humanoid.Animator:GetPlayingAnimationTracks()
for i, track in tracks do
if track.Animation.AnimationId = "blahblahblah" and track.IsPlaying then
Player.Character.Humanoid.Health -= 20
end
end
end)

By the way guys I wrote this script in the devforum it’s not in my actual game so some things may be written incorrectly but you get the idea.

Any help is much obliged guys.

Ok just figured out I can use an event when the player clicks a button instead of while loop silly chicken, then just raycast from all players. and check if like the distance between em is like less than 2 studs and do my stuff.

i mean it’s a great way ngl, but here’s a revised version

  1. *** Local Script (StarterCharacterScripts)***
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local part = game.ReplicatedStorage:WaitForChild("HitBox"):Clone()
local RE = game.ReplicatedStorage:WaitForChild("RemoteEvent")

-- Ensure hitbox part is not collidable and is invisible
part.CanCollide = false
part.Transparency = 1
part.Parent = workspace

while true do
    part.CFrame = character.HumanoidRootPart.CFrame -- Align hitbox with the character
    local hitbox = workspace:GetPartBoundsInBox(part.CFrame, part.Size)

    for _, hitPart in pairs(hitbox) do
        if hitPart.Parent:FindFirstChild("Humanoid") then
            local humanoid = hitPart.Parent.Humanoid
            local tracks = humanoid.Animator:GetPlayingAnimationTracks()

            for _, track in pairs(tracks) do
                if track.Animation.AnimationId == "blahblahblah" and track.IsPlaying then
                    RE:FireServer(hitPart)
                end
            end
        end
    end

    task.wait(0.1) -- Wait for a short period to prevent performance issues
end

and for the

1. Server Script (ServerScriptService)

local RE = game.ReplicatedStorage:WaitForChild("RemoteEvent")

RE.OnServerEvent:Connect(function(player, hitPart)
    if hitPart.Parent:FindFirstChild("Humanoid") then -- Verifying info on the server
        local humanoid = hitPart.Parent.Humanoid
        local tracks = humanoid.Animator:GetPlayingAnimationTracks()

        for _, track in pairs(tracks) do
            if track.Animation.AnimationId == "blahblahblah" and track.IsPlaying then
                player.Character.Humanoid.Health -= 20
            end
        end
    end
end)

Explanation of Improvements:

  1. Align Hitbox to Character:
  • The hitbox part is aligned with the character’s HumanoidRootPart each loop iteration.
  1. Prevent Performance Issues:
  • A short wait period (task.wait(0.1)) is added to prevent performance issues due to the infinite loop running without any delay.
  1. Ensure Hitbox Part is Non-collidable and Invisible:
  • The hitbox part is set to non-collidable and fully transparent to ensure it doesn’t interfere with gameplay.
  1. Consistent Naming and Pairs Iteration:
  • Used pairs for iterating through arrays to ensure consistency and avoid potential issues with unexpected key values.
  1. Correct Animation ID Check:
  • Fixed the conditional check to == for comparing the animation ID instead of = which is used for assignment.

Make sure the HitBox part exists in ReplicatedStorage and the RemoteEvent is also set up properly in ReplicatedStorage. This setup should work better for detecting hitboxes and handling the hit detection logic. goodluck making ur game :wink:

if u want more improvements, i can help

Thanks for that, I appreciate you took tons of time to do that just to help me! But I realised I don’t need to use a while loop at all. As for a combat game I can just detect when the player uses the tool such as a punch tool. Then just raycast and check if the distance between the player and other players is 2 studs. If it is? Boom, do my stuff. Which is way better for performance and above everything else.

Thanks aswell, but that was just because this script isn’t one I put in my actual game. I just typed it up on the devforum topic and didn’t see the errors as they aren’t highlighted lol.

1 Like

i don’t have anything to do anyway lol, but, you’re welcome,so uhm here’s the scripts:

Local Script (inside the Tool):

local tool = script.Parent
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local RE = game.ReplicatedStorage:WaitForChild("RemoteEvent")

local function onActivated()
    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
    if humanoidRootPart then
        -- Define the ray
        local rayOrigin = humanoidRootPart.Position
        local rayDirection = humanoidRootPart.CFrame.LookVector * 2 -- 2 studs ahead

        local raycastParams = RaycastParams.new()
        raycastParams.FilterDescendantsInstances = {character}
        raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

        local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

        if raycastResult then
            local hitPart = raycastResult.Instance
            if hitPart and hitPart.Parent:FindFirstChild("Humanoid") then
                local humanoid = hitPart.Parent.Humanoid
                local tracks = humanoid.Animator:GetPlayingAnimationTracks()

                for _, track in pairs(tracks) do
                    if track.Animation.AnimationId == "blahblahblah" and track.IsPlaying then
                        RE:FireServer(hitPart)
                    end
                end
            end
        end
    end
end

tool.Activated:Connect(onActivated)

Server Script (ServerScriptService)

The server script remains largely unchanged but ensures validation when the event is fired from the client.

local RE = game.ReplicatedStorage:WaitForChild("RemoteEvent")

RE.OnServerEvent:Connect(function(player, hitPart)
    if hitPart.Parent:FindFirstChild("Humanoid") then -- Verifying info on the server
        local humanoid = hitPart.Parent.Humanoid
        local tracks = humanoid.Animator:GetPlayingAnimationTracks()

        for _, track in pairs(tracks) do
            if track.Animation.AnimationId == "blahblahblah" and track.IsPlaying then
                player.Character.Humanoid.Health -= 20
            end
        end
    end
end)

Explanation:

  1. Raycasting:
  • When the tool is activated (tool.Activated:Connect(onActivated)), a ray is cast from the player’s HumanoidRootPart in the direction the character is facing.
  • The ray has a length of 2 studs (humanoidRootPart.CFrame.LookVector * 2).
  1. Raycast Parameters:
  • We use RaycastParams to ignore the character casting the ray.
  1. Hit Detection:
  • If the ray hits a part and the part’s parent has a Humanoid, it checks if the specified animation is playing and then fires the remote event to the server.
  1. Server Validation:
  • The server script validates the hit to ensure it’s legitimate before applying damage.
    plus that was a really good choice for using a tool

Nah man you didn’t have to do that for me, I would’ve been able to do that myself lol. I’m not gonna take your script as I usually prefer to do things myself instead of stealing whole systems but I appreciate the help and I’ll mark you as the solution anyway for anyone else who is thinking about a combat game and hitbox detection stuff as it’s pretty detailed.

1 Like

not stealing, its called “help” lol, np btw

Well technically yeah I guess but yk. I usually like to accomplish things myself unless they’re way too difficult. Anyways thanks.

bro litrally using ai LOOOOOOOOOOOOOOOL

1 Like

Actually yeah now that I think about it he may’ve been using AI lol.

AI, more like actually knowing english? or, if that was ai, i don’t know what to say to my grammar, tbh, don’t blame anything to ai.

Edit: i just like to comment my code more often so people could understand it.

1 Like

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