Hello Developers,
I am having issues with properly rendering the bullet on the client side, what I mean by this is the bullet is inconsistent with my movement. Here’s a video:
https://streamable.com/cpfgjf
Any help is appreciated!
Hello Developers,
I am having issues with properly rendering the bullet on the client side, what I mean by this is the bullet is inconsistent with my movement. Here’s a video:
https://streamable.com/cpfgjf
Any help is appreciated!
You’re probably doing the bullet projectile on the server. You click, network latency (ping) causes a delay, then the server finally sees you shot but by that point you already moved somewhere else on the client so it looks like the bullet is coming out the wrong place. Here’s what you’d want to be doing instead.
The common steps are the following ones:
In client side, play the shoot effects (bullet projectile + VFX) as soon as you click, and perform a raycast to check if it hit an enemy, if then call a FireServer.
In server side, when receiving the FireServer signal, do some sanity checks to ensure there is no exploits, then call a FireAllClient and change the stats that need to be changed (ammos, health…).
In client side, when receiving the FireAllClient signal, play the shoot effects for the selected player except if it is yourself, because you already played your own shoot effect on step1… it is only for the effect of others players.
I am sorry, I am a new developer and I don’t really understand how I would do this, I am using a method called fastcast and I don’t really get how I would go about firing the bullet on all the clients using fireallclient()…
Sorry, I am not that much of an experienced developer, I understand what you are trying to say in the post, however, I just don’t get how to implement it…
If I may be blunt, it feels like you’re asking for instructions on how to bake a cake without knowing how to operate the oven. You’ll be told “you need to set the temperature to 350f for 30 minutes” but you won’t know how to set the temperature or the timer.
Play around with fastcast some more before attempting to fix the quirks it can cause. You’re experiencing first hand the kind of issues using code found online without understanding them causes and if we were to write you a gun script that did everything listed for you then you’d be adding more gaps on top of a foundation filled with gaps.
Or, don’t use fastcast at all. It’s a pretty old resource that hasn’t been updated in 4 years and I’m fairly sure it uses deprecated methods which means it will break at some point.
Okay, its fine being blunt, ill try to move away from fast cast as it is causing me more issues in the future because as you said, the owner doesn’t update it anymore. The reason I am struggling is because I am trying to cast the raycast from the camera instead of the mouse (for mobile support) and most people don’t make videos or tutorials on how to do those types of guns which makes them fairly inaccurate. If you could explain to me the equations or expressions I would have to use in order to get my bullet flying that would be nice (I am not too good at math).
You should probably start simple before getting to the fancy stepped projectile logic. Try implementing a hitscan gun before moving on to projectiles with travel time.
You can generate a ray (an old instance that was used for raycasting but now exists more like a container for data about raycasting) by doing
local camera = workspace.CurrentCamera
local screenCenterCoords = camera.ViewportSize / 2
local ray = camera:ViewportPointToRay(screenCenterCoords.X, screenCenterCoords .Y)
This code generates a ray containing the data you need for raycasting from the very center of the screen.
We grab the camera’s viewport size, which is a vector2 representing the player’s screen in pixels, and divide it by 2 to get the coordinates smack dab in the middle of the screen.
Then, we feed that to ViewportPointToRay which generates a ray that, as you guessed it, is for the middle of the screen.
Then we can actually start doing proper raycasting.
local RAY_LENGTH = 300 -- if you try shooting something over 300 studs away it will not hit
local result = workspace:Raycast(ray.Origin, ray.Direction * RAY_LENGTH)
if result.Instance then
local hitPart = result.Instance
-- do your hit logic here.
end
It’s worth noting that your character will probably hit himself in the head the moment you fire. This can be fixed with raycastparams. Do you think you can figure out how to do that without being explicitly told how? One of the most important things to learn when it comes to development is how to read roblox’s official documentation for these types of things, so I’d recommend you give it a shot. (Watching youtube tutorials will not teach you how to become independent as a developer so I discourage doing so)
Thanks for the frame of my gun, ill implement this into my gun, Thanks! I already knew what raycast params are so there was no issues with that, now the hard part which is rendering the bullet which I am stuck on right now, if you mind, could you walk me through how I would render it without the bullet looking laggy?
So first of all you’d want to make sure that the code responsible for firing the hitscan gun is on the client instead of on the server. It will always be laggy otherwise since the server can’t instantly know when you fire your gun, therefore the client simply cannot rely on the server for anything at this point in the firing cycle.
If your hitscan gun hit something, you’d want to create a line (can just be a long part) and position it in-between the ray’s origin and the hit position.
If you hit nothing, you’d want to position it at origin + (direction * RAY_LENGTH / 2).
local line = LinePart:Clone()
local endPosition
local midPosition
if result.Instance then
endPosition = result.Position
midPosition = ray.Origin:Lerp(endPosition , 0.5)
else
endPosition = ray.Direction * RAY_LENGTH
midPosition = ray.Origin + (endPosition / 2)
end
-- give line length
line.Size = Vector3.new(0.1, 0.1, (ray.Origin - endPosition).Magnitude)
Next we would want to actually make it face towards where the projectile is going.
You could do this with trigonometry if you wanted, but if you don’t mind a negligible hit to performance we can let roblox do it for us.
local facingCFrame = CFrame.lookAt(ray.Origin, ray.Origin + ray.Direction)
line.CFrame = CFrame.new(midPosition) * facingCFrame * CFrame.new(-facingCFrame.Position)
-- mid pos + origin pos with facing angle - origin pos = mid pos with facing angle
line.Parent = workspace
This might seem a bit useless at the moment since it’ll be replaced once we switch to an actual projectile (assuming you’re not already happy with just using hitscan!) but this is actually very similar to what fastcast does; just in smaller steps.
Worth noting that this is a slightly naive approach as the line will come from your head instead of from the gun’s barrel and thus probably be invisible, but that’s something that can be fixed and I believe you may already have an idea as to how. Can you figure it out?
Also I did not test the code above, let me know if I overlooked anything.
Oh my bad, I used a remote event to send the information to the server to damage the player.
To damage the player is fine, but firing the actual gun (the visuals and initial check for hitting something) should be on the client. Gun shoots on client → client sees it hit something and tells server → server validates hit is the standard way of doing it. There’s also a secondary one so the server can keep track of when you use ammo and show your gun firing on other clients but that isn’t relevant for your local client.
should it look something like this?:
local camera = workspace.CurrentCamera
local gun = script.Parent
local fired = script.Parent:WaitForChild("GunFired")
local function gunActivated()
local screenCenterCoords = camera.ViewportSize / 2
local ray = camera:ViewportPointToRay(screenCenterCoords.X, screenCenterCoords.Y)
fired:FireServer(ray.Origin, ray.Direction, ray.Unit)
-- Under here is the code?
end
gun.Activated:Connect(gunActivated)
It’s kind of hard to tell what your instances are. Fired is a remote event, fair enough, but what about gun? A tool?
the local script is placed as a child inside the gun (tool) and the gun (model) is inside the gun (tool) as a child.
Okay then yeah it’s correct. You do not have to pass ray.Unit by the way, it is identical to ray.Direction.Unit and only sending direction would save bandwidth.
This is probably a dumb question, but what is bandwidth? Also, my raycast result is on the serverside, so it doesn’t work well with the if result.Instance then
statement…
Bandwidth is like internet usage. Lower = better.
You would not be raycasting on the server. Only do so on the client for the time being.
I’m heading out for the day, try seeing how far along you can get on your own.
Okay the system I have so far is pretty good, I scrapped all of the code you gave me that included math and decided to do it on my own because yours was buggy (no offense), now that the bullet is properly positioned and looks at the target AND fires at the target with ZERO LAG! However, some problems, are other people cannot see it, it doesn’t do any damage and for some reason I cannot for the life of me code a range at which the bullet must be destroyed at. This is what I got so far:
if RANGE > result.Distance then
local tweenBullet = tweenService:Create(Bullet, TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false), {Position = endPosition})
tweenBullet:Play()
tweenBullet.Completed:Wait()
Bullet:Destroy()
else
local tweenBullet = tweenService:Create(Bullet, TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false), {Position = endPosition}) -- Idk what math to do here...
tweenBullet:Play()
tweenBullet.Completed:Wait()
Bullet:Destroy()
end
The range is 300.
I am very proud of myself, I did it without an tutorials or any documentation.