Hi, i’ve been trying to make a football system (similar to the game Rematch) where you choose where your ball curves, I did it with bezier curves, but when the ball reaches the last point of the bezier curve it suddenly stops and falls straight down instead of continuing it’s trajectory (first video). The problem has something to do with physics, so i thought of some solutions. Do I make custom physics for the ball (calculating where the ball will bounce and stuff) ? Or just fix the bug (somehow idk) and keep the roblox physics ? (both of the methods are in combination with bezier curves) or I just make it full custom physics without bezier curves (I tried this and it didn’t work very well it’s like the ball would curve based off the world origin, also the green points don’t go through the red circle which is also a problem (2nd video), for this i followed this 1st part of a tutorial https://www.youtube.com/watch?v=279r8beQPeE&t=1002s)? I would like to be able to predict where the ball will end up being or landing, at all times (Because I want to make an indicator where the ball will land, like in Rematch) so what method would you recommend me using in order to achieve this ? Do I stop using bezier curves ? Maybe try with vector forces ? Also feel free recommend some tutorials that I could follow.
Script where I calculate the bezier and where I apply the custom physics module script
local CurvePoints = {}
local Ball = script.Parent
local function CreateKeyPart(Part: Part, Pos, Player: Player)
Part.Shape = "Ball"
Part.Size = Vector3.new(1.25, 1.25, 1.25)
Part.Anchored = true
Part.CanCollide = false
Part.Material = Enum.Material.Neon
Part.Color = Color3.fromRGB(255, 0, 0)
Part.Transparency = 0.5
Part.Parent = game.Workspace.Map
Part.Position = Pos
end
local function lerp(t,a,b)
return a+(b-a)*t
end
local function quadBezier(t,p0,p1,p2)
local l1 = lerp(t,p0,p1)
local l2 = lerp(t,p1,p2)
local quad = lerp(t,l1,l2)
return quad
end
local function CreateCurve(p0: BasePart, p1: BasePart, p2: BasePart)
for i = 0, 1, 0.1 do
local Part = Instance.new("Part")
Part.Color = Color3.new(0, 1, 0)
Part.CanCollide = false
Part.Size = Vector3.new(0.25,0.25,0.25)
Part.Anchored = true
Part.Shape = "Ball"
Part.CFrame = CFrame.new(quadBezier(i,p0.Position, p1.Position, p2.Position))
Part.Parent = TrashFolder
Debris:AddItem(Part, 0.25)
table.insert(CurvePoints, Part.Position)
end
return CurvePoints
end
local BallPhysics = require(game.ServerScriptService.Modules.BallPhysics).new(true) --Physics Without Bezier
function BallMotion(Attachment, CenterPart, CursorPart, Ball)
BallPhysics:Cast(Attachment.Position, CursorPart.Position, Ball) -- Without Bezier
--CurvePoints = CreateCurve(Attachment, CenterPart, CursorPart) -- With Bezier
--for i = 1, #CurvePoints do
-- Ball.CFrame = CFrame.new(CurvePoints[i])
-- wait()
--end
--CurvePoints = {}
end
ShootRemote.OnServerEvent:Connect(function(Player, CenterPos, CursorPos)
if Ball:GetAttribute("Possesion") == false then return end
local Attachment = Character:WaitForChild("Attachment")
local CenterPart = Instance.new("Part")
local CursorPart = Instance.new("Part")
CenterPart.Name = "CenterPart"
CursorPart.Name = "CursorPart"
CreateKeyPart(CenterPart, CenterPos, Player)
if CursorPos then
CreateKeyPart(CursorPart, CursorPos, Player)
end
Weld:Destroy()
Ball.CanCollide = true
Ball:SetAttribute("Possesion", false)
Debaunce = false
BallMotion(Attachment, CenterPart, CursorPart, Ball)
task.wait(0.5)
Debaunce = true
CenterPart:Destroy()
CursorPart:Destroy()
end)
custom physics module script (the script from the video)
local RunService = game:GetService("RunService")
local Debris = game:GetService("Debris")
local BallPhysics = {}
function BallPhysics.new(Visualize)
local NewPhysics = {}
NewPhysics.Params = RaycastParams.new()
NewPhysics.Params.FilterType = Enum.RaycastFilterType.Include
NewPhysics.Params.FilterDescendantsInstances = workspace.Map:GetChildren()
function NewPhysics:Cast(Start, Dest, Ball)
--t = time
--a = acceleration
local VForce = (Dest-Start).Unit * 200
local t = 0
local CurrentPos = Start
local RayResult = nil
local Found = false
local a = Vector3.new(-workspace.Gravity, -workspace.Gravity, -workspace.Gravity)
local Connection = RunService.Heartbeat:Connect(function(dt)
if not Found then
t += dt
local ProjectPos = Vector3.new(
Start.X + VForce.X*t + 0.5*a.X*t*t,
Start.Y + VForce.Y*t + 0.5*a.Y*t*t,
Start.Z + VForce.Z*t + 0.5*a.Z*t*t
)
RayResult = workspace:Raycast(CurrentPos, ProjectPos - CurrentPos, self.Params)
CurrentPos = ProjectPos
if Visualize then
local Part = Instance.new("Part")
Part.Size = Vector3.new(0.25,0.25,0.25)
Part.Position = ProjectPos
Ball.Position = ProjectPos
Part.Anchored = true
Part.CanCollide = false
Part.Material = Enum.Material.Neon
Part.Color = Color3.fromRGB(0, 255, 0)
Part.Shape = "Ball"
Part.Parent = game.Workspace.TrashFolder
--Debris:AddItem(Part, 0.2)
end
if RayResult or t > 1 then
Found = true
end
end
end)
while not Found do
task.wait()
end
Connection:Disconnect()
end
return NewPhysics
end
return BallPhysics
video with bezier
video without bezier
