How can I make by bézier curves "faster"?

Hello! I made one of my skills use bézier curves to make my projectiles curve more to the right or left when shooting them towards the target. However, it’s very slow! I need to make it faster but I have no clue how! I figured the only way to make it faster would be replacing my RunService.Heartbeat:Wait() with something faster but there really is nothing faster than it on the server. And making the index add more than 0.01 makes the curve incomplete so my projectiles end up in the wrong spot.
Here’s a clip of my current skill:
https://gyazo.com/57937fa6fa3b955c437ecdb40bcef4b2
You can see that my projectiles are pretty slow. The code I use is the basic quadratic bézier curve formula combined with a while loop:

local function QuadraticBezier(Index, CurrentPosition, CurvePos, Destination)
	return ((1 - Index)^2 * CurrentPosition) + (2 * (1 - Index) * Index * CurvePos) + (Index^2 * Destination);
end;
local index = 0;
while true do
	if Blast.Parent == nil or Blast:FindFirstChild("BodyPosition") == nil then
		return;
	end;
	index += 0.01;
	local TargetPosition = QuadraticBezier(index , StartPoint, RandomCurve.Position, CurrentLast);
	Blast.BodyPosition.Position = TargetPosition;
	game:GetService("RunService").Heartbeat:Wait();
end;

Increase index by a higher amount, for example, 0.1 instead of 0.01 (also, ; aren’t required in Lua).

I mentioned here that if I try making index increase more, the projectiles don’t follow the right direction and end up in the wrong spot.

Try adding

if index > 1 then
    break
end

to the end of the loop

	index += 0.01;
	local TargetPosition = QuadraticBezier(index , StartPoint, RandomCurve.Position, CurrentLast);
	Blast.BodyPosition.Position = TargetPosition;
	game:GetService("RunService").Heartbeat:Wait();
	
	if index > 1 then
		break
	end

You should probably use the delta time returned by Heartbeat:Wait() so it accounts for when the server slows down.

local function QuadraticBezier(Index, CurrentPosition, CurvePos, Destination)
	return ((1 - Index)^2 * CurrentPosition) + (2 * (1 - Index) * Index * CurvePos) + (Index^2 * Destination);
end;
local index = 0;
local dt = 1/60
while true do
	if Blast.Parent == nil or Blast:FindFirstChild("BodyPosition") == nil then
		return;
	end;
	index += dt * 2; -- increase the constant until it's fast enough
    -- I'm not sure how the projectile could go to the wrong spot with this, 
    -- maybe send a video of what it looks like with high speed?
	local TargetPosition = QuadraticBezier(index , StartPoint, RandomCurve.Position, CurrentLast);
	Blast.BodyPosition.Position = TargetPosition;
	dt = game:GetService("RunService").Heartbeat:Wait();
end;
1 Like

What about .stepped? I believe it’s faster than heartbeat.

Let me show you what I mean. Here are two different clips.
This one shows you what happens if I set index to increase at a 0.05 rate:
https://gyazo.com/76605956ca0bdd74ef02c50f33f3fee6

As you can see, the projectiles are faster but don’t get the exact position of the target but end up near them of some studs.
While with index increasing at a rate of 0.1 this happens:
https://gyazo.com/c214f097048900a247b57742839ebdf5

You can clearly see they mess up badly here. They almost don’t even get near the target. I will try with your method but not sure if anything is going to change.

Stepped isn’t faster than heartbeat, it just runs before it every frame, additionally running before physics

Projectiles should be simulated on the client using RenderStepped. However if you insist on doing this on the Server you need to update it every RunService.Stepped, do not use a while loop.

RunService.Stepped:Connect(function()
    -- code here
end)
5 Likes

So you are suggesting, the best alternative would be giving the player the control of the projectiles and manipulating their position directly from the client? I’ll try with using Stepped too instead of Heartbeat, without using a while loop.

Everything related to visual stuff should be done on client side, and server should only take care of numbers if you know what I mean. You could make one calculation on server that would be a lot less expensive than going through all of the steps and calculating them. Something like this:

Server: I know that the visual effect will hit at x: 0, y: 2, z: 4 in 10s and after that I can do all the damage and stuff.
Client: I will calculate through each step to create smooth visual effect for the player!

2 Likes

On my game my effects are mostly made on the client so that they are smooth (and don’t end up making the server laggy), however I never really thought of making projectiles on the client too. I guess I could give it a try.

The hit detection should be handled on the server, the client should render the projectile itself. The projectile should not exist on the server at all. Modules like FastCast offer this functionality already.

1 Like