How do I create basic punching combat?

I’ve already looked on the forum for this and looked up a youtube tutorial but there wasn’t anything here and the yt video wasted an hour of my life and the script did nothing.

How would I even start? From hitboxes, to playing animations, to the script itself. I don’t know what I’m doing. Literally anything is appreciated.

I want the end result to be something similar to fighting games like the strongest battlegrounds and similar stuff.

  1. Animation
  2. Fire remote event
  3. Receive remote event
  4. Do damage checking, i use workspace:GetPartBoundsInBox() for that
  5. Combat
1 Like

Thanks! Do you know a good place to learn how to do all of these steps?

probably roblox studio, using a local and server script

1 Like

A good place to learn the basics is this tutorial:

Of course you will have to replace .Touched with GetPartBoundsInBox() as @notsad2 said. If your wondering why it is because it is a lot more accurate.

1 Like

Thank you! This video helped a lot. However I keep getting an error that says “Cframe is not a valid member of Part “Workspace.(username).HumanoidRootPart”” Which is causing the hitbox to not appear. How can I fix this?

Can you show me the line of code that has the error?

It must be CFrame, not Cframe. If the spelling wasn’t the issue, then I don’t know until we see more code.

1 Like

I fixed the error however I’m now having problems with using GetPartBoundsInBox(). Just replacing Touched didn’t work so I tried following the documentation and now the hitbox isn’t showing up. Here’s my code:

game.ReplicatedStorage.CombatHit.OnServerEvent:Connect(function(plr)
	print(plr)
	
local hitbox = Instance.new("Part")
	hitbox.Parent = workspace
	hitbox.Anchored = true
	hitbox. CanCollide = false
	hitbox.Transparency = 0.5
	hitbox.Size = Vector3.new(5,5,5)
	hitbox.CFrame = plr.Character.HumanoidRootPart.CFrame *CFrame.new(0,0,-5)
	game.Debris:AddItem(hitbox, 2)
	local hits = {}
	local hitItems = workspace:GetPartBoundsInBox(hitbox.CFrame, hitbox.Size)
		if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= plr.Name then
			if not hit.Parent.Humanoid:FindFirstChild(plr.Name) then
				if Hits[hit.Parent.Name] then
					return
				end
				Hits[hit.Parent.Name] = true
				local snd = script.hit_punch_l:Clone()
				snd .Parent = hit.Parent:FindFirstChild("Humanoid")
				snd.Play()
				game.Debris:AddItem(snd,2)
				hit.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
				wait(4)
				Hits[hit.Parent.Name] = false
				end
		end
	end)
	
end)

Another idea is to use hit-checking on the client and then sanity checking on the server, this will make the gameplay smoother for the puncher but may cause the person receiving the attack’s perspective to feel unsynchronized. The main issue for all of these methods is client to server transmission latency. If you do decide to go this way, they are a variety of hit-checking systems such as clientcast that can handle hitboxes.

1 Like

Glad you got the bug fixed. This guy explains how to use get GetPartInBoundBox() very well.

Funnily enough this video is the reason I can use GetPartInBoundBox()

1 Like
game.ReplicatedStorage.PunchRemote.OnServerEvent:Connect(function(plr)
	if not plr or not plr.Character then return end
	
	local playerHand = plr.Character:FindFirstChild("RightHand")
	if not playerHand then return end
	
	--/ Make Hitbox
	
	local hitbox = Instance.new("Part")
	hitbox.Position = playerHand.Position
	hitbox.Size = Vector3.new(3, 3, 3)
	hitbox.Transparency = 0.5
	hitbox.BrickColor = BrickColor.new("Really red")
	hitbox.CanCollide = false
	
	local weldc = Instance.new("WeldConstraint", hitbox)
	weldc.Part0 = hitbox
	weldc.Part1 = playerHand
	
	hitbox.Parent = workspace
	game.Debris:AddItem(hitbox, 1)
	
	
	--/ Get Parts inside the hitbox      
	
	task.wait(.5)	
	local params = OverlapParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {plr.Character}
	params.MaxParts = 30
	--params.POTENTIAL_OTHER_PARAMETERS...(...)	
	local hitItems = workspace:GetPartBoundsInBox(hitbox.CFrame, hitbox.Size, params)
	
	
	--/ Loop over the hit parts and detect a potential enemy - and damage them	
	
	local hitEnemies = {}	
	for i, v in pairs(hitItems) do
		local taggedEnemy = v.Parent:FindFirstChild("Humanoid")
		if taggedEnemy and taggedEnemy.Health > 0 and not hitEnemies[taggedEnemy] then
			hitEnemies[taggedEnemy] = true
			taggedEnemy:TakeDamage(20)
			-- hitSound?
		end
	end
	table.clear(hitEnemies)
end)

image


This creates a Hitbox around the hand you’re punching with and after x seconds, it detects the parts inside. It then loops over these parts and sees if they’re from an enemy.

Alternatively, you could use .Touched for as long as CanHit = true to catch anything that starts touching the Hitbox during the time it’s there:

local canHit = true
local hitEnemies = {}	

hitbox.Touched:Connect(function(hit)
	if canHit == true then		
		local taggedEnemy = hit.Parent:FindFirstChild("Humanoid")
		if taggedEnemy and taggedEnemy.Health > 0 and not hitEnemies[taggedEnemy] then
			hitEnemies[taggedEnemy] = true
			taggedEnemy:TakeDamage(20)
			-- hitSound?
		end		
	end
end)
-- I believe this Connected .Touched function automatically disconnects when the Hitbox is destroyed

task.wait(1)
canHit = false

Hopefully this helps :`)

2 Likes

Having the hitbox around the hand is pretty cool ngl.

2 Likes