How can I make a client-sided projectile?

How should I go about testing the input?

The input of the user? If so use inputservice

This only works locally not on the server even if I unanchored the part.

Should I use a bindable event, remote event, or remote function?

For sending information about the projectile remote events.

1 Like

I just learned user input service can’t be used on a script. :confused: So how should I go about testing detection now?

Ok so I’ve managed to work something up, but it still works only on the local script maybe you can edit it to make it work on server. Here’s what I have
(In Order)
Local Script:

local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()
local UserInputService = game:GetService("UserInputService")
local RemoteEvent = script:WaitForChild("RemoteEvent")

local Holding = false
local debounce = false

if not UserInputService.KeyboardEnabled and not UserInputService.MouseEnabled then
	script.Parent:Destroy()
elseif UserInputService.KeyboardEnabled and UserInputService.MouseEnabled then

	mouse.Button1Down:Connect(function()
		Holding = true	
		repeat wait(0.25)
			if not debounce then
				debounce = true
				RemoteEvent:FireServer()
				wait(0.25)
				debounce = false
			end
		until Holding == false
	end)

	mouse.Button1Up:Connect(function()
		Holding = false
	end)
end

Script:

local RemoteEvent = script.Parent:WaitForChild("RemoteEvent")

local Event = script:WaitForChild("Event")

RemoteEvent.OnServerEvent:Connect(function(player)

Event:FireAllClients(player)

end)

Local Script:

local Event = script.Parent:WaitForChild("Event")
Event.OnClientEvent:Connect(function(player)
	local character = player.Character
	
	local Projectile = game:GetService("ReplicatedStorage").Objects:WaitForChild("Projectile"):Clone()
	Projectile.Parent = workspace
	Projectile.Position = character.Direction.Position
	local Fire = Instance.new("Sound")
	Fire.SoundId = "http://www.roblox.com/asset?id=130113322"
	Fire.Volume = 0.25
	Fire.Parent = Projectile
	Fire:Play()

	--Body Velocity

	local BodyVelocity = Instance.new("BodyVelocity")
	BodyVelocity.Parent = Projectile
	BodyVelocity.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	BodyVelocity.Velocity = character.Direction.CFrame.LookVector * 150

	wait(0.4)
	Projectile:Destroy()
end)

if you have the projectile being fired in a local script, and it does not get replicated ( check roblox documentation ) it will be clientside. it all depends on what exactly you want, if i knew more i could give more guidance

You want to use a RemoteEvent. RemoteEvents and functions are meant to communicate server to client, and Functions will yield the code who fired it until the function bound ends, returning the parameters you want to. I am not experienced on FPS games, but I think it might be good to follow these steps:

  • First, create a local script, with an event to shoot the projectile (mouse click, bind a key, etc);
  • Second, get the parameters that will be used for the projectile (aim direction, weapon used);
  • Make a check on that local script to see if the player can shoot the bullet, and if it’s allowed, FireServer the remoteevent, passing the parameters used (aim direction, weapon used);
  • On the server script, bind the remoteevent.OnServerEvent to the function that will check the bullet collision. The first parameter on that function is always the player who fired the event, and the rest are the parameters you passed (aim, weapon used);
  • On the function you bound to the event, check again if the player can shoot (enough ammo, cooldown), in order to prevent exploiters;
  • If the player can shoot, raycast the trajectory from the player position to the aim direction, and apply damage if it hits a player; If the bullet is visibly slow, you can use spawn() (as not to yield the function) to make a small loop of raycasts, that stops either when it hits something or the maximum range is reached. You can simulate gravity on these multiple raycasts, and even check headshots for more damage;
  • FireAllClients the remoteevent, and bind a function on the local script to receive the direction the bullet travelled and the type of bullet and who shot. On this function, do the visual effects you want to add to the bullet, like particle emission, tweening the visual projectile, light emission.
  • You might want to bind another event for the server to fire when the player hits an enemy, as to show if it hit someone. You can also use RemoteFunction to InvokeServer instead of FireServer, so you can return the player who was hit back to the player. You will still have to use remotevent to FireAllClients the visual bullet you want to create.
2 Likes

Okay. In summary I want a client sided projectile which is a projectile on the client side. To make it have very fast response time instead of it being in a server script which has a delay.
Here’s a topic relating to something of what I’m trying to achieve.

So in summary it goes like:
Local Script(Fire) —> Script(Fires Client) —> Local Script(Shows on screen)
right? Also thank you for putting a lot of effort in your writing.

In that case you can do what I said, but check only on the local script if someone was hit. It will be lagless for the shooters perspective, but you are open for exploits. In that case, you can make the server apply damage no matter what the client sent, and make a server check only to see if the client is being too unconsistent (shooting too fast for the weapon that is being used for example) and procceed to kick the probable exploiter.

1 Like

Would something like this work? Also it’s not really for a fps game. It’s a blaster that’s like a magic spell.

Make so when you shoot the Projectile, you fireserver to fireallclients (except the player who cast the spell) to replicate a fake projectile, only for visuals.
Still on the local script, make so when the Projectile touches an enemy, it fireServer another remoteevent that will be used to apply damage and replicate the hit visual effect to other players via FireAllClients.

If you’re interested in how multiplayer FPS guns work, this video is pretty good:

Basically:

  • Where the bullet comes from (barrel or camera)
  • What is replicated to other players (damage or new bullets (aka hitscan or projectile weapons))
  • How all of these are processed (effects, anti cheat)
1 Like

But, you can’t use fire all client on a normal script? It’s a local script to normal script so shouldn’t it be fire server?

yo i usually do show a visual before firing a remote to the server so the client sees no delay then do fireallclients, on mobile so can’t explain further rn but reply if u need more help

yea, just fire the hitscan on the server and instead of sending events with position and direction information you just fire the remote event once and that would send a part, with a bodyvelocity in just the direction.

How do I use fire all clients from the local script?
AstronautGFX

You don’t seem to have a great understanding of the roblox engine or lua in general so I would advise you to learn remotes better. But I’ll give you the general idea and you can try work it out yourself as it’s the best way to learn.

So I usually have a local script where I have a Mouse.Button1Down:Connect() function where I’ll detect if a player has fired a projectile, then I like to have a module script so I can easily fire projectiles and I’ll call a function in the module script to fire a projectile on the client so they don’t experience delay. Then I fire an event to the server to preform hit detection and in the script I’ll have a FireAllClients() which will make a visual for the rest of the players.

If you didn’t understand all of that then you’re clearly not ready for this type of system and I strongly advise you to learn some more otherwise you will have an extremely hard time doing it.

This code doesn’t work btw, it just shows the basic idea.

Client:

local function Proj(origin,topos)
	--//make projectile here
end

Mouse.Button1Down:Connect(function()
	Proj(origin,topos) --//Make projectile for client 

	game.ReplicatedStorage.RemoteEvent:FireServer(origin,topos)
end)

game.ReplicatedStorage.Visuals.OnClientEvent:Connect(function(plr,origin,topos)
	if localplayer ~= plr then --//make sure were not making two projectiles for the client
		Proj(origin,topos) --//Make projectile for client 
	end
end)

Server:

game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(plr,origin,topos)
	--//do raycasting hitdetection
	
	game.ReplicatedStorage.Visuals:FireAllClients() --//make projectile for all players
end)
6 Likes