I am working on a game where you cut trees with an axe and I was wondering if anyone had a good way to make a hitbox for the axe and the tree? Just wondering because I am trying to find the best method to make this work efficiently
Raycasts are not ideal for this as they stop as soon as they hit something instead of getting all the parts in a hitbox, they are more of a hit-line instead of a hitbox.
The most straightforward way of creating hitboxes is through one of the these methods:
- For box-shaped hitboxes:
Workspace:GetPartBoundsInBox(cframe: CFrame, size: Vector3, overlapParams: OverlapParams)
- For sphere-shaped hitboxes:
Workspace:GetPartBoundsInRadius(position: Vector3, radius: number, overlapParams: OverlapParams)
Here’s an example of how you do box-shaped hitboxes
Hitbox.server.luau (a server script parented to the axe Tool
):
local Workspace = game:GetService("Workspace")
local HITBOX_SIZE = Vector3.new(4, 4, 4) -- This will be the size of your hitbox
local DISTANCE_FROM_CHARACTER = 4 -- This is how far in front of your character the hitbox will be centered
local TREE_PARTS = Workspace:WaitForChild("Trees") -- Parent of all the trees
local axe = script.Parent
assert(axe:IsA("Tool"), "Make sure the script is parented to a tool")
local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Include
overlapParams.FilterDescendantsInstances = { TREE_PARTS }
local function onAxeActivated()
local character = axe:FindFirstAncestorOfClass("Model")
assert(character, "Character not found")
local cframe = character:GetPivot() + (character:GetPivot().LookVector * DISTANCE_FROM_CHARACTER)
local partBoundsInBox = Workspace:GetPartBoundsInBox(cframe, HITBOX_SIZE, overlapParams)
print("Parts in hitbox", partBoundsInBox)
--[[ If you only want to handle one part in the hitbox we can use
if #partBoundsInBox < 1 return end
handlePartInHitbox(partBoundsInBox[1])
]]
end
local function initialize()
axe.Activated:Connect(onAxeActivated)
end
initialize()
They both return an array of BasePart
that you can iterate through to deal with any part that was caught in the query.
Creator Docs Pages:
hello, Elaugh14
You’ll want to use collision-based hitboxes or raycasting to detect when the axe hits a tree.
- Attach a small invisible part** to the axe head (call it “HitPoint”)
- On swing (click or animation trigger)
local tool = script.Parent
local hitPoint = tool:WaitForChild("HitPoint")
tool.Activated:Connect(function()
local rayOrigin = hitPoint.Position
local rayDirection = hitPoint.CFrame.LookVector * 3
local params = RaycastParams.new()
params.FilterDescendantsInstances = {tool}
params.FilterType = Enum.RaycastFilterType.Blacklist
local result = workspace:Raycast(rayOrigin, rayDirection, params)
if result and result.Instance then
if result.Instance:IsDescendantOf(workspace.Trees) then
print("Hit tree!")
-- Add chop logic here
end
end
end)
That’s a good way to make a hitbox but I think I would prefer GetPartsBounds since it is more of a hitbox like @yieldlua said
GetPartsInPart
or GetPartsBoundInBox
is definitely more hitbox-like, especially if you want physical overlap rather than just ray detection. I suggested raycasting since it’s fast and precise, but if you’re going for more of a swing zone feel, bounding box hit detection is a solid pick too.