Hello,
I’ve been trying to make a client sided projectile, but I got stuck. So how can I do this? I tried remote events and bindable events and none of them worked in my favor. So what should I do? I also know this is a basic question, but any help is appreciated.
I would use FastCast. It’s a very good module. He also has a video using it to do client replication. Although it’s outdated, it will give you a general idea of how client-sided projectiles are programmed.
Is there another way to this? I have never touched modules before, and even with the youtube video I doubt I would be able to understand or use it. But, thank you for the response!
I would recommend that if you want to script anything remotely advanced, module scripts are imperative for you to learn, but this can be done without the module.
I would have the hit-scan be on the server, and the visual projectile be on the client. It would go something like this:
The server fires a ray projectile for hitscan, and every time the ray is updated, you would fire a RemoteEvent to the client sending information about the position and the direction. The client would then create a part and move the part every time it received more information about the server-sided array.
You would want the remote event firing pretty frequently for smooth effects, so I’d suggest using RunService.
Instance.new("Part") in a local script, you can handle its movement locally as well (providing the part is left unanchored) as movement of unanchored parts replicates to the server.
If I were you, I would create the projectile on the server, and then do the visuals on the client. Then you compare the two to make sure there isn’t anyone exploiting it badly.
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.
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.