How do I go about making a weapon system?

So I want to make a weapon system, however I am unsure how to go about it.
The plan is for 3 base weapon types: hitscan, projectile and hitbox (or otherwise melee).
Hitscan fires one or more rays from the weapon to detect hits, projectile fires one or more projectile parts from the weapon and hitbox creates one or more boxes in the direction the weapon is facing.
I don’t particularly want tutorials (especially video tutorials), as I want to figure out things along the way (I learn better like that), nor do I want existing weapon systems (although if you have an open source one feel free to share might be useful as a reference if I get stuck), rather I want a list of things I’ll need to do in order.
Thanks in advance!

1 Like

Hello, for a projectile weapon there are many ways to do it. For example you can rely on roblox’s physcis engine and then use the .Touched event to see when the projectile hits something. You should read up on vector forces if your interested in this approach. Additionally, I would recommend creating the projectile on the server and client. On the client immediatly spawn the projectile, this projectile is just for visuals. On the server you can make a projectile and adjust it based on the ping amount of the player, make it transparent and use it for detecting the collisions and doing the damage.

.Touched can get get bad for high speed projectiles however this is less of an issue then people make it to be.

However the main problem I would say with the above approach is making a projectile on server and client is hard to sync accuratly using roblox’s physcis.

An other way, is to use raycasting and not use roblox physcis at all. You would simulate the projectile each frame and raycast to the new position to figure out any collisions, you don’t have to use raycasting, you could implement custom sweeping but I would say raycasting is the easiest solution and works for most small projectiles, for bigger onces you could even shoot multiple rays

Here is a simple example to get you started

local Speed = 100

local Params = OverlapParams.new()
local PART = workspace.projectile
Params.FilterDescendantsInstances = {PART}

game:GetService('RunService').Heartbeat:Connect(function(TimeFromPreviousFrame)
	local NewPosition = Part.Position + Vector3.yAxis * TimeFromPreviousFrame * Speed
	local Hit = workspace:Raycast(OldPosition, (NewPosition - OldPosition), Part)
	
	if Hit then
		-- do something
	else
		PART.Position = NewPosition
	end
end)

Hitscan is really simple, just shoot a ray where the the mouse is hitting, you can use mouse.Hit.Position, ect. Send this hit position to the server and the client shoot position, make sure the server does some validation to see if the hit position and client shoot position is plausaible to prevent exploiters, and shoot a ray on the server from the Player start position to the hit position to see what what was hit.

1 Like

Last time I tried to make projectiles my biggest difficulty was actually figuring out the point from where to fire without giving the client full control
How do i go about doing that without making it feel incredibly inaccurate or trusting the client way too much?

1 Like

One of the ways to do this is buffer the player position or the weapon position every frame in a range of 500 miliseconds let’s say. What we can do is rewind back in the buffer when the player shoots by the ping time. This we can get an accurate starting position. However, I actually would reccomond allowing the client to send their projectile starting position while using the buffer concept, on the server you would check if this starting position is close to the value of the buffer during ping miliseconds ago. This allows some flexbility as ping timings won’t always exactly match up, ect.

This is the first step, now after you find the starting position you can accelrate the projectile until it catches up to what we think it should it be at currently, in your script account that you projectile is ping seconds behind. So make the projectile move faster till it catches up (make sure this looks realistic though). I think this is better then just spawning the projectile offsetted. When your spawning local projectiles for the rest of the clients to render it also make sure to employ this. (An other way could be simulating the projectile seperatly only on the shooter side, but all the other clients request the server every x miliseconds for an update)

(Player:GetNetworkPing() is not a measurement of a roundtrip I believe, just a aproximation one way trip which is why we rewind by ping seconds ago)