How to handle projectiles client/server

heya quick one, you know how we say to not depend on the client when sending a packet or remote from client to server. How would you setup visuals for a projectile that causes damage? Let’s say you have a kunai or a fireball how would you handle impact of such a projectile? In my mind I can imagine, I don’t understand how you would handle damage from the impact or handle hitboxes related to that.

1 Like

You should just handle it all on the server. No matter what, the projectile won’t be 100% accurate across all clients, so your best bet is to just handle both visuals and hitboxes on the server. For handling the actual projectile hitboxes, you can use a hitbox module lor write your own, and while the projectile is in motion, you’d update the hitboxes CFrame to the projectiles CFrame. You’ll probably have to implement your own things into this, but this is just how i’d personally do it.

but what if i want visuals on client, velocity as well.

You definitely could, but you still need to hitbox to run on the server, and at that point the visuals and hitbox will have some sort of desync which will be more noticeable for people with high ping. I wouldn’t recommend it, but its doable.

No offense but this advice isn’t great.

There are two main benefits to running hitboxes on the client, the first being it offloads the workload to the client. The other is that it means that what the client sees is what the hitboxes are. With server-sided hitboxes you need to aim where your target is on the server, not where they are on your screen.

For visuals, it should always be done on the client. There is no need to stress out the server. Usually you’ll want to send a remote event that sends instructions to a client script full of visual functions that then executes them.

Anyways, here’s the basics of the a client-based projectile system:

  • Client: Handles input, launches projectile, simulates hitbox, tells server when attack was launched and when attack hits.
  • Server: Recieves and tells other clients to replicate projectile, handles damage, does sanity checks.
  • Other clients: Replicates projectiles, doesn’t simulate hitboxes for non-owned projectiles.
3 Likes

So you recommend depending on the client to know when the impact happens and on server you wait for the impact signal from the client?

end goal being everything is client expect damage

Actually how about this,

Let’s say the situation starts from server, from server > fire all clients > setup projectile and everything for all clients > but only the local player that is the same name as the caster of the projectile (provided from the server) will send hitbox detection information to the server > on server handle damage.

running hitboxes on the client allows exploiters to easily destroy your game. rule #1 of any multiplayer game is to never trust the client

Doesn’t mean they fully have to run on the server, the server has latency between client and server events like movement of the player for example. So while doing it on the server is the safest option, it’s the slowest one of all.

Another option is to run everything on client, it’s the fastest, but like you said, is exploitable, though though this doesn’t matter for single player games.

The best option is registering the hit on the client, and sending over the hit to the server which from there deals damage and fires additional VFX/events onwards.

Adding checks and a rate limiter on remote events will stop any invalid checks sent to the server.

This method combines both of the 2 methods above into one, so it’s safe and fast and the same time, though its more of a 50/50 rather than a 0/100.

But this is actual bad advice.

1 Like

Running a projectile on each separate client is going to cause desync due to latency. Rather you use the server to control the projectile or not, there’s going to be latency. Not only that, but because 1 client is controlling the hitbox, the position it appears to hit at will be different and innacurate across clients. Theres also the issue of a client lagging out, and specifically the one controlling the hitbox. Lets say they lag out. That means the hitbox wont register any hits until they come back. By that time, the projectile is already long gone on other clients, but the hitbox is probably in the same position, and if someone happens to touch it, then they get ‘hit’ even though the projectile is far away

If you mean serversided checks, they’re useless unless the server has something it can compare the clients values with, like its own server only projectile position. But if you did that, then you might as well run hitboxes on the server too. You can obviously do whatever you want, its individual preference, but if you want a somewhat secure game, then dont do this.

That’s basically it.

Though whether or not you want it to start from the server depends on if you want the attack to feel responsive. So for something like a gun, starting from the client is a better option.

The only desync that can happen is the projectile’s time-distance offset since all clients recieve the
same direction, starting position, and literally everything to recreate the projectile. I suppose for something like a grenade that bounces and rolls you might want to make that server-sided, but there’s arguments to make even that client-sided.

Now you could send your perferred method of benchmarking to reference where they technically should be, but you also have to consider that there will be a delay between when the server informs the attacked client that they’ve been hit. So in other words, while all the projectiles are synced in real time using benchmarking, the machines still have a delay between communicating.

How do you think the projectile is moving? It’ll be using renderstepped, and determining distance to move with deltatime (time since last frame) so FPS doesn’t matter. Also, there can be a client-sided check to stop a check if it’s been a while since the last frame.

“Server-sided checks are useless unless you do them.”

Let me go into detail WHY server-sided hitboxes are bad.

There are two players, Alpha and Beta. Player Alpha is attempting to attack player Beta in a game with server-sided hitboxes. Currently, player Beta is strafing right. Due to client-server delay, the position of Beta’s character is desynced across both clients and the server.

On Beta’s screen, he is where he is. However, it takes one latency unit (LU) - the time it takes for a signal from a client to reach the server - for Beta’s computer to replicate this to the server. So the server is one LU behind on where Beta’s character is on his screen. It also takes an additional LU for the server to replicate where it has Beta’s character to Alpha’s computer, so now Alpha is 2 whole LU behind.

Alpha goes in to attack, striking where he sees Beta’s character on his screen… and he misses. Why? Because what he sees on his screen is basically outdated to the server’s “screen”. What Alpha actually needs to do is attack where Beta is going to be in one LU to hit him, which is counterintuitive to the game’s visuals.

Beta isn’t much happier either, as when he gets hit he only sees Alpha attack the air next to him, not his character.

Now let’s use client-sided hitboxes. Alpha attacks where he sees Beta on his screen and lands a hit. Beta is probably less happy than getting hit by server-sided hitboxes, but the client-side hitboxes also allow him to hit his target by aiming where his character is on screen.

security > whatever ur talking about imo, but do whatever you want bro

@TheCraftNCreator destroyed you in every argument, yet you are still in denial, lmao.

1 Like

Fantastic advice throughout the post. This is precisely how I handled my projectile pipeline:


I have a document containing a series of sanity checking procedures as well

1 Like

For handling projectiles (in the good way according to me), I do structure so:

  • Shared (ModuleScript): Write the function that creates and simulates the bullet, and create a folder where you put your events. Make sure it returns the bullet so you can know if it hits somebody.
  • Client: Handles the input, and when you attack, call the function in shared to create and simulate the bullet and fire an event to the server script. Use Touched or any other function that fires an event to the server to inflict damages.
  • Server: Once the fire event gets fired/invoked (it depends on you if you want to add extra security in major detriment of speed), fire another event to all clients in ReplicatedStorage. Also host damages via this script when the damage event is triggered in the client.

In StarterPlayerScripts:

  • Create a client script that, when the ReplicatedStorage event is fired, also create and simulate the bullet from the shared module script to ensure a butter-smooth result.

I actually use this a lot in my new projects, even for non-firearm stuff like bloxy colas like here:

Knowing those tricks can really be a great step for a smooth experience. And, if you can use Zap, it’s even better since it can handle more events at the same time.

Imo player experience should always be a first rather than security. Any game should feels smooth and satisfying to play to an extend, and we know smooth and satisfying don’t go well together with serverside.
Ofc, one may argue that if there is exploiters, there won’t be a good player experience, but the reality is that exploiters, at least for less popular games, are very few and far between, unless your game has a critical flaw that allow script kids to run rampant. Most of the time it’s just player vs player, so it’s best to cater for them.

tldr; security means very little if your game feels bad to play

3 Likes

Precisely. I’ve played way too many games where I have to walk in front of my opponent and swing ahead of them to actually hit them because the developer decided to handle hitboxes on the server. Is this really what I have to deal with just because I want to play with my friend who happens to live in a region quite far away? It’s not fun at all. Its absurd. People will not want to play your game if you have to predict every movement to land hits at all.

If you want security, handle hitboxes on the client, but check on the server if the person hit is actually close to the person who hit him. Sure, now people can have slightly extended reach if they really want to cheat, but your game is actually fun to play and you won’t have people hitting melee attacks from 2000 studs away.

Even then, the suggested approach isn’t requesting that the client’s reported collisions are accepted by the server without question. Should the server decline the client’s claim, that’s that. Local VFX/SFX responsiveness is preserved, and other clients are unaffected. Look at any large-scale FPS game on Roblox. For example, Phantom Forces. When your ping spikes through the roof, the only thing that stops are the other players. You can move freely, your weapons still work, rounds still fire, and they strike their targets with the appropriate SFX and VFX without delay