Creating a Battlegrounds-like Hitbox

INTRODUCTION

You might have played top battlegrounds games, most notably The Strongest Battlegrounds. As a programmer, you may be wondering how they created their hitboxes, especially if you are an inspiring developer planning on creating something similar. In this tutorial, I will guide you on how to create a professional punch hitbox. Keep in mind that this will not carry you. To create a worthy punching system, you need to address the following:

  1. Sound Effects. You need to have good sound effects to really feel the kick in your punches.
  2. Animations. Very important. Without good animations, your punches will feel stale.
  3. Visual Effects. This contributes to your overall game design. Your punches must not feel bland.

Keep in mind that I will not be addressing these key details because this is a tutorial for your hitboxes.

MAIN IDEA

First of all, we need to figure out the way we will be creating the hitbox. This is the bread and butter.
If you are a beginner developer, you may suggest Touched Events. Please for the love of everyone in the Devforum, do not use Touched Events. They take up more resources than necessary, and is more complicated than the solution, which I will get into later.

If you are an intermediate developer, you might suggest Raycasting. This is a more viable option than Touched Events and you may use this, but I wouldn’t recommend, since you need several Raycasts to cover a larger area.

Spatial Queries

However, there exists Spatial Queries. There are several of them, but most notably, there are 3 main options. The following all are built-in roblox functions used on workspace.

  1. GetPartsInPart() is more accurate but takes up more resources because you need to have a part in workspace

  2. GetPartsBoundInRadius() is reliable, but is only used for spherical hitboxes

  3. GetPartsBoundInBox() is also reliable, but instead is used for cubical hitboxes, and doesn’t take up many resources.

These options may vary depending on what hitbox you are going for, but I highly recommend GetPartsBoundInBox(). For this tutorial, I will be using GetPartsBoundInBox() because of its utility in our scenario.

SCRIPTING

Now we get to the sauce of making your hitbox. Many people will recommend using a ServerScript but this is super unreliable. Using this will make everything happen Server-sided, so if you have high ping, it will feel very unfair because it looks like you hit your victim, when you didn’t.

However, using a LocalScript instead of a ServerScript is like switching out airpods for headphones. Everything now happens on your client which as a result, you actually hit the victim when you are supposed to. Beginner programmers will often look over Remote Events, which you can use to send a signal for the player who got hit to the server, which will then do the extra damage, stun, etc.

Here’s how you put it into action:

local plr = game.Players.LocalPlayer
local char = plr.Character

local HBsize = Vector3.new(4.6, 4, 5.75) -- change to your hitbox size
local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
overlapParams.FilterDescendantsInstances = {char}

local parts = workspace:GetPartBoundsInBox(hrp.CFrame * CFrame.new(0, 0.25, -HBsize.Z/2), HBsize, overlapParams)
local plrsHit = {} -- table for all the players who were caught in the hitbox

for _, v in pairs(parts) do
	if v.Parent and v.Parent:FindFirstChild("Humanoid") and v.Parent:FindFirstChild("HumanoidRootPart") then

		local EChar = v.Parent

		if not table.find(plrsHit, EChar) then table.insert(plrsHit, EChar) end

	end
end

After, you then just send a signal through a RemoteEvent.
Now, here’s a step-by-step explanation on what the code does:

  1. First, we create our basic variables for the player who will create the hitbox.
  2. Then, we configure the settings our hitbox by listing the size of our hitbox, and by create parameters. FilterType = Enum.RaycastFilterType.Exclude will make everything in the FilterDescendantsInstances table be excluded for the hitbox, and FilterDescendantsInstances = {char} will make our character be excluded.
  3. Afterwards, we create another variable. It is what makes the hitbox. The first parameter is the CFrame of where our hitbox will be created, the second parameter is the size of our hitbox, then the third parameter is our Overlap Parameters, where we excluded us from being in the hitbox.

However, the variable will actually only return us a table full of parts which were caught in the hitbox. Instead, we would like to know the players caught in it. To do that, we create an empty table, then we execute a for loop for the parts variable, where we creating the hitbox. Remember, that variable is only full of parts that was in the hitbox.

Using the for loop, we check if the part has a parent, and if the parent has a Humanoid and a HumanoidRootPart. By doing that, we know if we detected a player, and from there we create a variable for the enemy character and insert it into the empty table that we had.

So, by doing that, we now have a table with the players caught in the hitbox!

EXTRA INFO

  • To get the amount of players caught, you would just to #plrsHit which will return a number of how many objects (or how many players) were in the table.
  • To actually damage the players or configure the players, you would create a for loop for the plrsHit table, where v is the character of the player. Then you would do something like
v.Humanoid:TakeDamage(number)

If you have any questions, do not hesitate to ask. Have a great day!

6 Likes