Projectile using DeltaTime

I am attempting to make a flare like projectile that runs on the client. Since it’s supposed to be an effect rather than a gameplay mechanic I am not using raycasts but I still want it to move smoothly.

I couldn’t find any other topics that gave me an answer towards exactly what I am looking for.

Here’s the code I am using:

					local fire = nil
					local flare = Instance.new('Part', game.Workspace)
					flare.Anchored = true
					local speedFor = 55
					local floatiness = 8
					local speedDown = game:GetService("Workspace").Gravity / 10 / floatiness

					if game:GetService("Workspace").Gravity <= 0 then
						speedDown = 0
					end

					fire = game:GetService("RunService").RenderStepped:Connect(function(dt)
						local ford = (flare.CFrame.LookVector*speedFor)
						local down = Vector3.new(0,1)
						local poschange = (-ford+down) * dt
						local lookchange = ((ford*2)+(down*2)) * dt
						flare.CFrame = CFrame.new(flare.Position+poschange,flare.Position+lookchange)
					end)

Either way, it keeps dropping too fast at high framerates.

2 Likes

You are using the wrong timing function for a projectile. Documentation specifically states:
significant performance issues if RenderStepped is used inappropriately. To avoid this, only use RenderStepped for code that works with the camera or character. Otherwise, RunService.Heartbeat should be used.

So, use Heartbeat:

fire = game:GetService("RunService").Heartbeat:Connect(function(dt)

You might still need to tweak things a little, but it will help that variation you will get between high and low FPS devices.

2 Likes

While this is useful advice, it has not solved my problem. On higher FPS the projectile drops faster.

Can we get video example please?

I recommend looking at the implementation by egomoose:

I think the problem is with the CFrame.new “LookAt” component.

You are setting lookAt with flare.Position+lookchange. The issue with that is that it is taking flare.Position from the previous frame, and not the current frame. Which will be different, depending on the FPS.

I suggest adding poschange to the lookchange component, to make it idependent from the distance travelleds between 2 frames.

flare.CFrame = CFrame.new(flare.Position+poschange,flare.Position+poschange+lookchange)

I suppose, you may need to adjust this line too, as needed:

local lookchange = ((ford*1)+(down*1)) * dt

This part seems problematic:

If this is gravity, then it is not being adjusted to match the frametime anywhere. So regardless of your FPS the projectile will move down the same amount every frame.

A proper projectile framework implementation should look something like this:

RunService.Heartbeat:Connect(function(dt: number)

    --change in gravity
    local dg: number = Vector3.yAxis * -workspace.Gravity * dt
    --change in velocity
    local dv: number = (VELOCITY + dg) * dt
    --change in position
    PROJECTILE.CFrame = CFrame.lookAlong(PROJECTILE.Position + dv, dv)

end)

I multiply it by delta time here:

fire = game:GetService("RunService").RenderStepped:Connect(function(dt)
						local ford = (flare.CFrame.LookVector*speedFor)
						local down = Vector3.new(0,1)
						local poschange = (-ford+down) * dt -- Here

I also believe this is the problem, although I am unsure of a way to make it go in the direction in a perfect curve without going in a circle or a straight line.

What do you mean by “move smoothly”?

Is this your biggest concern? If so, do one or both of:

  • Smooth the delta time - many different ways to do this, e.g. one example found here
  • Set the maximum rate at which the projectile is updated, e.g.
local UPDATE_FREQUENCY = 1 / 60 -- i.e. 60 fps

local delta = 0
game:GetService('RunService').Stepped:Connect(function (gt, dt)
  delta += dt
  if delta < UPDATE_FREQUENCY then
    return
  end
  delta = math.fmod(delta, UPDATE_FREQUENCY)

  -- do update using some deltaTime, computed from either:
  --    - (a) a buffered delta time
  --    - OR; (b) the elapsed time from the last frame

end)
1 Like

I will try this out and get back to you, what I mean by “Move Smoothly” is that it doesn’t look choppy when moving each frame. Like for example moving using task.wait which I would never do.

This isn’t really working, it’s still dropping too quickly at high framerates.

Edit: Nevermind I played with the numbers and it now works beautifully. Thank you for the help!

No worries!

Btw, for more information, I would recommend giving this resource a read - found here

1 Like

what numbers did you end up using?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.