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)