I’m trying to create a basic raycast weapon system and I want to generate a bullet client-side for visuals. The bullet spawns properly, with the right position and rotation, but it just stays there floating in the air without moving or disappearing, which is what a LocalScript in the bullet itself is meant for.
This is the bit of code that spawns the bullet from a LocalScript, which again, seems to be working fine:
-- perform client-side visuals
local hit = raycast.CalculateRay(client, tool, hitPos)
local bullet = RepStorage:WaitForChild("Weapons"):WaitForChild("Bullets"):WaitForChild("Bullet"):Clone()
bullet.CFrame = CFrame.lookAt(shootPart.Position, hitPos)
bullet.Parent = workspace
And here’s the LocalScript that’s parented to the bullet:
local bullet = script.Parent
local speed = 50
local deleteTime = 2
local Run = game:GetService("RunService")
local timer = 0
Run.RenderStepped:Connect(function(delta)
bullet.Position = bullet.Position + (bullet.CFrame.LookVector * speed * delta)
timer = timer + delta
if timer > deleteTime then
bullet:Destroy()
end
end)
What’s strange to me is that the game seems to simply ignore the RenderStepped event; I also tried doing a while loop to see if it was an issue with RunService, but that didn’t help. It’s as if the script didn’t exist at all. Is there a different way I should be approaching this?
Thanks, this code does seem way better than what I had, although it still doesn’t execute when I spawn the bullet itself. It just looks like the LocalScript doesn’t initialize for some reason.
Relying on the physics engine means the bullet can physically slow down due to throttling, causing it to desync.
Using the Debris service means that the bullets are immutable; once they’re set to be deleted, there’s nothing you can do to cancel that. Their original method of accumulating a number is a better solution.
This is from my own bullet handler module:
(it’s quite old, but it’s proof that it’s possible)
t.v += t.gv * dt --add gravity (t.gv) to the current velocity
local ch = t.v * dt --the change in position of the bullet
local nx = t.p.CFrame + ch
t.p.CFrame = CFrame.lookAt(nx.Position, (nx + ch).Position) --position and orientate the bullet
Well, it’s parented to the bullet itself, which I guess does count
I got it working by changing the velocity of the bullet from the LocalScript in the weapon, but I’m not too happy with it since the bullet falls too fast; however, I don’t want to change the game’s gravity just for this one purpose, so I need to find a way to use the CFrame method that’s being talked about instead.
Refer to what I posted.
Basically, you have a velocity value attributed to each bullet that can change independently. Gravity (a Vector3) gets added to the velocity on every frame. Then the velocity is applied to the position of the bullet itself. You’ll have to use the deltatime of the RenderStepped event for the math.
Here’s a pseudocode in case you didn’t understand the first sample I posted:
--this is a constant. It should be updated when the workspace gravity itself updates.
local gravityVector = Vector3.new(0, -workspace.Gravity, 0) --note the negative sign!
--[inside the RenderStepped loop]--
--bulletVelocity is a Vector3 in worldspace, just like the actual .Velocity property of parts.
--multiply the gravity vector3 by the deltatime and add it to the velocity.
bulletVelocity += gravityVector * deltatime
--Distance is just speed multiplied by time. This would be the change-in-position of the bullet.
local displacement = bulletVelocity * deltatime
--add the displacement to the bullet's position to move it by a single frame.
bulletPosition += displacement
--now would be the time to use Raycast for hit registration. The "displacement" variable can be reused here as the direction component.
--rinse and repeat for each bullet on each RenderStepped.