In the past two days, I’ve been trying to achieve the Magnus effect for my soccer game. When I finally managed to get it working, I ran into problems caused by the structure of my own code.
Basically, I’m using a VectorForce in a loop to create a nice curve, but the issue is that I don’t really know how to implement it so that the ball doesn’t keep curving after it lands or something like that.
I’ve tried using the built-in physics friction, but it somehow doesn’t work as expected. I also experimented with some damping, but it doesn’t behave the way I want it to.
(Code is a mess because its intented for tests!)
local RepStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Debris = game:GetService("Debris")
local part: Part = script.Parent
local _coefficent = .04
local Balls = {}
local cd = false
local _angle = math.rad(35)
local _power = 150
local _curveDir = 1
local _curveStrength = math.clamp(_power / 50, 0, 3.2)
local _velocity = Vector3.new(-math.cos(_angle), math.sin(_angle), 0) * _power
part.Touched:Connect(function(Part: Part)
local Player: Player = game.Players:GetPlayerFromCharacter(Part.Parent)
if not Player then end
if cd then return end
task.delay(1,function()
cd = false
end)
cd = true
local Ball = RepStorage.Ball:Clone()
Ball.Parent = workspace
Ball:PivotTo(Part.CFrame + Vector3.new(-5, 0, 0))
Ball.PrimaryPart.AssemblyLinearVelocity = _velocity
table.insert(Balls, Ball)
task.delay(3, function()
table.remove(Balls, table.find(Balls, Ball))
Ball:Destroy()
end)
end)
RunService.Heartbeat:Connect(function(Delta: number)
for _, Ball in pairs(Balls) do
local p: Part = Ball.PrimaryPart
if not p or not p.Parent then continue end
local vf = p.Parent:FindFirstChildOfClass("VectorForce")
if not vf then continue end
local LinearVel = p.AssemblyLinearVelocity
local Speed = LinearVel.Magnitude
local CurveDirection = LinearVel:Cross(Vector3.new(0, -workspace.Gravity, 0)).Unit * _curveDir
local Force = CurveDirection * _curveStrength * Speed
vf.Force = Force
end
end)