Hello! Basically, I have a script that’s inside the character when they join, however, it uses a TouchEvent, basically detecting if one of the body parts is hit, it does a function.
My Question
Is there a better way to basically check if a player’s body part is hit than the code below?
I’m using a RayCast module for my weapons, how would I apply it to the code below in terms of constantly checking if a body part gets hit? (I’m using RaycastHitboxV3)
for i, x in pairs(character:GetChildren()) do
if x:IsA("BasePart") or x:IsA("MeshPart") then
x.Touched:Connect(function(hit)
if hit:FindFirstChild("IsASword") and hit:FindFirstChild("IsSwinging").Value == true and cooldown == false then
cooldown = true
--//Now we check if are hitting the player's back
if character:FindFirstChild("Block") and character:FindFirstChild("Block"):IsA("Animation") then
local maxHitAngle = 45
local isFacingBack = false
local humnCF= character.HumanoidRootPart.CFrame
local left = (humnCF*CFrame.Angles(0, math.rad(maxHitAngle ), 0)) * CFrame.new(0, 0, -0.1)
local right = (humnCF*CFrame.Angles(0, math.rad(-maxHitAngle ), 0)) * CFrame.new(0, 0, -0.1)
local fartherLeft = (humnCF*CFrame.Angles(0, math.rad(maxHitAngle + 0.1), 0)) * CFrame.new(0, 0, -0.1)
local fartherRight = (humnCF*CFrame.Angles(0, math.rad(-maxHitAngle - 0.1), 0)) * CFrame.new(0, 0, -0.1)
local headPos = hit.Parent.Head.Position
local isInsideAngle = (headPos - left.p).Magnitude < (headPos - fartherLeft.p).Magnitude and (headPos - right.p).Magnitude < (headPos - fartherRight.p).Magnitude
if isInsideAngle then -- the angle might be negative instead of positive depending on what you want, so just put "not isInsideAngle" if you need it reversed
isFacingBack = false
else
isFacingBack = true
end
local isBlocking = false
for i, sword in pairs(character:GetChildren()) do
if sword:FindFirstChild("IsASword") then
if sword:FindFirstChild("IsBlocking").Value == true then
isBlocking = true
end
end
end
if isBlocking == true and isFacingBack == false then
Blocked(character)
else
cooldown = false
end
else -- Not in guarding state
DamagedEnemyHit(character)
end
else
-- No attacking happening
end
end)
end
end
You could use :GetPartsInPart (more accurate but more expensive) or :GetPartBoundsInBox (for simple brick-like hitboxes)
:GetPartsInPart
local lp = game:GetService('Players').LocalPlayer
local char = workspace:WaitForChild(lp.Name)
local param = OverlapParams.new()
param.FilterDescendantsInstances = {char}
param.FilterType = Enum.RaycastFilterType.Blacklist
param.MaxParts = 1
local parts = {}
for _, v in ipairs(char:GetChildren()) do
if v:IsA('MeshPart') then
table.insert(parts, v)
print(v)
end
end
while char do
for _, v in ipairs(parts) do
char:SetAttribute(v.Name, #workspace:GetPartsInPart(v, param) > 0)
end
task.wait()
end
:GetPartBoundsInBox (extended hitbox)
local lp = game:GetService('Players').LocalPlayer
local char = workspace:WaitForChild(lp.Name)
local param = OverlapParams.new()
param.FilterDescendantsInstances = {char}
param.FilterType = Enum.RaycastFilterType.Blacklist
param.MaxParts = 1
local parts = {}
for _, v in ipairs(char:GetChildren()) do
if v:IsA('MeshPart') then
table.insert(parts, v)
print(v)
end
end
local extension = Vector3.new(.1, .1, .1)
while char do
for _, v in ipairs(parts) do
char:SetAttribute(v.Name, #workspace:GetPartBoundsInBox(v.CFrame, v.Size + extension, param) > 0)
end
task.wait()
end
Here’s a demo of the :GetPartBoundsInBox method that you can try yourself: touchedAlternative.rbxl (34.8 KB)
local Part = workspace.Part
RunService.Heartbeat:Connect(function()
local PartRegionMin = Vector3.new(Part.Position.X-Part.Size.X/2, Part.Position.Y-Part.Size.Y/2, Part.Position.Z-Part.Size.Z/2)
local PartRegionMax = Vector3.new(Part.Position.X+Part.Size.X/2, Part.Position.Y+Part.Size.Y/2, Part.Position.Z+Part.Size.Z/2)
local CreatedRegion = Region3.new(PartRegionMin, PartRegionMax)
local PartsInRegion = workspace:FindPartsInRegion3WithWhiteList(CreatedRegion, {Put ignore list}, 25)
for IndexPart, PartInRegion in pairs(PartsInRegion) do
...
end
end)