What would be the best way to implement hitboxes for a competitive fighting game?

Hey everyone! I want to know what you would think the best way of implementing hitboxes are, specifically for high-ceiling competitive fighting games (i.e Street Fighters or Smash Brothers).

The methods of making hitboxes that I am currently aware of are :
Raycasted hitboxes. This provides maximum accuracy but is reliant on the animations. This is therefore not ideal for the kind of game I am going for, and will not be used.

Part hitboxes with :GetTouchingParts(). This can work well, but I do not believe it’s meant to be used for this kind of job. It’s reliant on the roblox engine being accurate, which isn’t always the case.

RotatedRegion3. Like the part but far more complicated. I don’t know if it’s a good idea to use these for hitboxes.

Magnitude checks. I believe this is what smash bros uses. They have a few “circles” forming a line for an attack. I believe this wouldn’t carry over to 3D games as well, however.

Sight check. Far more limiting than the previous options, but the most straight forward to set up.

Which one would you recommend? Any methods I haven’t considered?

1 Like

It all depends on what exactly type of fighting your game is going to have like if its gonna be hand to hand combat then I dont think magnitude would be the best for that if its gonna be sword fighting then get touching parts and region3 would work the best

Ah, let me clarify: This would be the main hitbox used for everything that doesn’t require more specific use cases. If I were to make an aoe move for instance, I would probably use a magnitude check instead.
However, concerning your sword example, both would end up using the same method. I am also not looking to get accurate hitboxes for the sake of being accurate to the animation, but hitboxes that feel right. This means even if your sword whiffs the opponent it should still be able to hit if it got reasonably close.

Edit: I am truly trying to make this side project like a fighting game. This means fist attacks will probably be able to reach reasonably far (i.e mario’s fists getting big in smash whenever he attacks)

1 Like

Sorry to bump, but have you found a solution to this? I’ve been thinking about hitbox creation for a while, but the main issue is that all measures that I’ve come up with to make accurate hitboxes fall flat due to client-server delay. Is there any way that I could circumvent this delay without sacrificing safety?

There isn’t a good way of mitigating client-server delay with hitboxes that doesn’t sacrifice at least a little bit of safety. That being said, the game I’m working on right now runs hitboxes on the client and server at the same time. If the client detects a hit, it sends the hit to the server’s hitbox, and the server does a few sanity checks like checking magnitude and such. (I also check ping and only accept client hits from low ping players, but that’s optional)

2 Likes

Hmm, interesting. How do you manage that? VFX have to be played on the server and so does damage calculation, so do you have something that handles delay? Or do you just play animations and everything except hitbox creation on the server?

I’ve tried this method earlier and had to ditch it because at high ping you could visibly confirm a hit, but because I played animations on the client (to know when to cast hitboxes), when the ping started to get into the 100s, there was a notable delay between hitting an opponent on a client and then actually getting hit. Do you have that issue as well?

Sadly there isn’t really any super elegant solution to this, way later I ended up implementing a system where I would store a list of player positions every few frame, up to roughly ~300 location snapshots per player, and then I’d take into account the ping of the player attacking to “rewind” the player’s location and create a hitbox in that position, same with the attacking player.
It still ended up very occasionally making the player miss but I disguised these as “Misses!” so that the player would still get feedback for their attack & they wouldn’t be able to tell that it was just a hitbox issue.

This solution allowed me to have client-sided hitboxes that are hard to exploit nonetheless.

As for a simpler solution, while this is a bit of a cheat, you can have the “damaged flinch” and/or damage numbers pop up instantly on the client instantly upon hitting a player, EVEN if the attack didn’t connect on the server. The player would think that the attack landed without even knowing that it dealt no damage, as long as health bars aren’t visible to other players. It’s not a perfect solution but 99% of players won’t even notice it.

1 Like

I really like this idea, but I’m a little bit confused about how this would operate.

How would you handle cooldowns and stun? If you create client-sided hitboxes, then that means whatever you’re using to determine when that hitbox would activate would also be on the client, and all the server would receive is a potentially hit humanoid.

Exploiters would be able to fire this event however many times they want, and apart from magnitude checks, I wouldn’t be able to properly verify if the attack is valid. For example, I wouldn’t be able to account for cooldowns because all you get on the client is a humanoid that could have been hit.

Until now, I’ve been using a server-sided hitbox system, where the player sends the attack they’ve used, and the server goes into a bunch of information modules to get the info for that attack, plays the animation, creates a hitbox, and wait for a result. However, as you can probably guess, this causes a lot of lag and makes the game nigh unplayable at pings higher than 150ms, as hitboxes appear quite far behind the player’s client position. Because of this, I want to switch to a client-sided hitbox system, but I’m stuck at how sanity checks would account for cooldowns.

How would I drop a ‘potential hit’ if they shouldn’t be able to use the move? For example, if they’re already using a move, if they’re stunned, or if the move’s on cooldown?

Additionally, for your method, how do you communicate the “snap-shots” you take to the server? Assuming you take them on the client, once communicated to the server, wouldn’t the client have moved?

Sorry if these questions are a bit off-topic.

You wouldn’t make the combat entirely client-sided, you would still keep a chunk of the higher-level functionality on the server. What I usually do is have both the client and the server run the same weapon code as the client, or at least very similar code.
I’d then communicate to the server whenever the client attacks (you would need to do this anyways if you want client-sided vfx to replicate for everyone), and note down when the player clicked. Using this variable, I can tell if the weapon was used in too quick of a succession and drop inputs, or when the client tells the server that they’ve hit a player you can also use that variable to tell if the player is plausibly in the middle of the attack state.

Say the cooldown is 2 seconds, the valid attack window is 1.5 seconds. If I click, I set the attack var to the current time. If I try clicking again 0.5 seconds later, the server will see that the attack is still on cooldown and will not overwrite the last attack time. If the server is told that someone hit a player 1 second after they previously clicked, it will allow the hitbox to get created and do checks for whether or not they truly got hit.

Dropping potential hits is done the in the same place.
I personally have a table for each player that represents all sources of “interruption” and add a string to this table when a source of “interruption” is added. That way multiple interruptions can stack at the same time and remove themselves without getting in the way of other stun sources. If some sources of interruption are whitelisted for the attack I’m doing, I can just loop through the list of stun sources looking specifically for entries that don’t have one of the whitelisted string names.

A good example for this is not dropping input if someone’s trying to jump while dashing.

As for the snapshots, that’s purely done on the server. Knowing both players ping allows you to revert both of their hitboxes to match up roughly what the attacking player was seeing on their screen when they claim to have hit someone.

Here is with 500 ping, no rewind. The red box represents where the server sees the dummy, and the blue box represents where the client saw the dummy. By the time the server gets the message that the client thinks they’ve hit the dummy, the dummy has already walked far far away. (please note that the red square is in response to the blue square at the right, not the left)

Now here’s what it looks like with hitbox rewinding.
BrQzj722GW

4 Likes