The issue with bezier curves is that they need points and say you point at a player and that player moves out the way once you fired the projectile and it will end up stuck at target’s previous position
The tracer should be bound to the time that it was fired so that it appears accurately positioned on each client. So for this scenario, you may want to use RunService.Stepped, it passes a time & deltaTime value.
This is actually not called a bezier curve, it is known as a simple alternating curve. To apply it to 3d you’ll for a given time step, t, notice that if you just wanted it to go striaght you could just do player.Position + target.Position*t. We’ll call this reference value straight. If we just wanted it to go right towards the target we could just do something like
local vectorBasis = Instance.new("Vector3Value")
vectorBasis.Value = player.Position
local tweenService = game:GetService("TweenService")
local tween = tweenService:Create(vectorBasis, TweenInfo.new(1), {Value = target.Position})
tween:Play()
vectorBasis.Changed:Connect(function()
projectile.Position = vectorBasis.Value
end)
What we need to do now is modify that second to last line. We’ll first create a coordinate space so we can define “flat”. We need to create a constant reference point to avoid distortion. We can do this by using the built-in lookAt matrix constructor.
local coordinateSpace = CFrame.lookAt(player.Position, target.Position, Vector3.new(0,1,0))
We can then multiply the rightVector by a oscillating value and apply that as an offset
local vectorBasis = Instance.new("Vector3Value")
vectorBasis.Value = player.Position
local tweenService = game:GetService("TweenService")
local tween = tweenService:Create(vectorBasis, TweenInfo.new(1), {Value = target.Position})
tween:Play()
local coordinateSpace = CFrame.lookAt(player.Position, target.Position, Vector3.new(0,1,0))
vectorBasis.Changed:Connect(function()
local t = inverseLerp(player.Position, target.Position, vectorBasis.Value)
projectile.Position = vectorBasis.Value + coordinateSpace.RightVector * (15*math.cos(t)
end)