Network Efficient and Safe Practices with Projectiles

Sorry to bump this topic, but I was using this method for a projectile and came into an issue for myself.
How would I synchronize the clean up of the fireball?

I tried this: When a hit occurred around the beginning of the code, I fire to all clients telling them to clean up using something like Debris or something but I keep running into a synchronization issue. I have this fireball in a tool, so when I spam click on the tool, it cleans up prematurely.

1 Like

What I’ve done is add a time value to the name of the projectile.

So for instance, I’ll get the time when the move is used and store it into a variable, then I’ll use that for all my synchronization for that specific use of the move.

So I would do something like this:

-- server code
local moveTick = workspace:GetServerTimeNow()

-- assume you have a remote called ClientEffect for effects
remotes.ClientEffect:FireAllClients("Fireball", character, moveTick)

local exploded = false

-- handle raycasting code here if you do wall impacts

task.delay(4, function()
     if not exploded then
          exploded = true
          remotes.ClientEffect:FireAllClients("FireballExplode", character, moveTick)
          -- end fireball raycasts here
     end
end)

--////client code

--// fireball code

--clone fireball
fireball.Parent = workspace.Projectiles
fireball.Name = "Fireball"..character.Name..moveTick

-- do the rest of your fireball code

--// explosion code
local fireball = workspace.Projectiles:FindFirstChild("Fireball"..character.Name..moveTick)

-- destroy the fireball however you want

Basically I name the client-sided fireball to the name of the character that used it as well as the time value of that move. Then since I know that’s what it’ll be named, when it’s time for the fireball to explode I give the client the same values as before so it can find the right fireball to handle.

Not sure about the cleaning up prematurely issue without some code to see. Make sure that each subsequent use of the tool doesn’t affect the previous use.

2 Likes

ahh okay, cheers. I fixed the issue using the unique identifiers. I just had to specify which spells to destroy, thanks!

Hello i just wanted to add that changing the speed from 45 to a greater number like 60, will have a tendency of not registering hits and completely pass through some npcs without dealing damage.

Another issue ive faced is when i use it on an npc thats rotated sideways, it also doesnt register them and passes right through.

If you have any solutions please let me know!

Make sure you’re giving the result sent back from the client enough leeway! How much leeway are you giving it? Print out the result of the part where you check the distance between what the server calculated as the position of the projectile to the NPC. See if it’s greater than the leeway you’re giving it and consider increasing your leeway.

Faster projectiles can be an issue due to the travel-time the packet takes to reach the server/client. That added extra bit of time can add distance to the projectile on the server and make the server think the projectile is farther than it really was on the client!

That 2nd issue sounds strange, as the projectile should be registering if it touches any BasePart. I can’t exactly point it out without some code or an example place, but try figuring out where it’s not registering. Is it not registering on the client? Is the server getting the result but not allowing the hit to occur?

1 Like

Wow you were completely right lol. I forgot to change the distance on the server script. Sorry for the confusion! Thank you

For the second error i am still unable to find a solution. It appears to damage up close to the target, but when applying some distance it passes straight through them. Heres a video example. It could just be my rigs somehow, but im not too sure tbh.

https://gyazo.com/5ed9f780ac30bd5279f7c2d5630a1310
https://gyazo.com/4d04a1045938d2c0bf5605d8f031fb2e

Glad to know that helped.

I would try and figure out where it’s going wrong, that is a weird issue that I’ve never had, I even tried replicating it by increasing the speed of my fireball in the test place that’s shown and I have 0 issues with speeds of 100+, as long as I give it a little extra leeway.

If it’s losing it on the client, you might be filtering it out somehow before sending it off. Also try printing out the results of the PartsInRadius function or whatever you’re using to check if somehow the function/module isn’t picking up the NPC.

If it’s recieved on the server, then try and figure out where the server is dropping the result, and modify from there.

What’s weird is the fact that at the end there it is hitting that further away NPC, so I’d like to guess that it’s just being filtered out somewhere.

1 Like

I think i found the source. It prints the npc out in the GetPartsBoundInRadius script, and on the client and server script. But when it gets to the magnitude script:

if (v.HumanoidRootPart.Position - positionCFrame.Position).magnitude > 7 then print("MAGNITUDE") return end -- added print to test results

it prints back magnitude. Testing it out a bit, it turns out i just had to increase the magnitude value. Still weird it happened though, but im glad i found a fix. Thanks again

edit: still encounter it sometimes. very strange. ill try to look into it some more

1 Like

Okay i figured out it’s registering the magnitude between the projectile and the NPCs as a lot larger than it should be. For instance, i have the radius of the attack set to 10, because thats the approximate size of the particle. But even when the projectile is right next to the enemy, it will print out saying the magnitude is above that radius.
https://gyazo.com/773bb60ce6461528bf972055ded9f8d9

I assume this is due to the server approximating where the projectile will be, and getting it wrong. Whats a good way i can get around this to more accurately determine where the projectile could be? Thank you.

You could try to visualize where it’s hitting by making parts on the client and server at where they see it, that’d give a better idea maybe of what’s going on.

Also, the system assumes that packet travel is instant, when in reality it isn’t. You can try and subtract the overall travel time (server → client → server) from the time it took to respond. That would likely give a more accurate result.

Would it be more efficient to have the server call some sort of :FireOtherClients() to handle the destruction of the projectile when hit, or have all clients run the Hitbox detection and handle destruction on the client?

This would mean more instant destruction/clean up but at the cost of potentially worse performance on the client. And of course, only the firing player would send the Hitbox results to the server.

1 Like

So what if we did want to make homing projectiles? Would we just make the projectile on the server?

Homing projectiles with a guaranteed target can work if you have a certain time you need it to reach their destination so it coincides with everyone. However, if the homing projectile can change targets mid-flight, since positions can be different for each client, you have to handle that on the server.

1 Like

Would this mean also having a hitbox on the server? I’m making a game with multiple weapons, and I initially planned to make a hitbox module that’s based on the client to overhaul the current system I have. The problem with that is that there will be a homing rocket, and so since I’d have to base that on the server.

I’m thinking that I could just have two separate functions that dictate whether the hitbox will be preformed on the client or the server, but in my mind this just complicates things a lot and I would like to keep the system for hitboxes simple and easy to manage.

Then there’s the amount of remotes that may possibly come from this…

I actually do have a hitbox module, HitboxClass, that can easily handle client or server sides hitboxes, you can maybe check to see if that’ll fit your needs. Other than that, yeah, if you want a rocket that can dynamically respond to things like player movements so it can accurately change targets in a fair way, server-sided is the way to go.

1 Like

Is there something I’m doing wrong? It was just working a couple of minutes ago but when I tried backtracking using ctrl + z it didn’t let me go all the way back and now nothing is being detected.

The alive and projectile object values are set by the way, this code is inside of a module script. Absolutely no errors by the way.

image

@VulkanAPI ?

Sorry!

HitObject only works with parts, so use the InBox or InRadius SpatialOption, or just pass in a part, you can read about the SpatialOption param here.

Reason why this is the case is because if magnitude were to be used, the script would be looping through the entire workspace to figure out the distance of every BasePart in there, and that wouldn’t be too good.

Granted, later on I could add some way to only look through certain folders so it’ll only search in that if Magnitude has to be used.

I have NO clue what happened, but annoyingly the version I was working on disappeared even tho I published it? I can’t find it in the version history at all either, so I guess I’m going to have to restart everything and see if it’s working.

Not all, I still seem to have some stuff but I’ll see what I can do and if what you said works or not.

Ok so:

bombData.range was an integer, I removed it and just passed an integer instead of indexing it, and although the hitbox appeared, nothing was printed.

Although, when I passed a Vector3 instead, it functioned regularly and I was blown away by the bomb.