Setup:


Everything seen on the image above can be found in the studio file at the bottom
As you can see on the image above I want to fire a part (representing my fishing hook) from the start to the end. The rope constraint is just for the visuals. For whatever reason the part does not stop where it is supposed to but flies further. For bigger distances the deviation increases.
Let me explain what I did. The movement of the part is the same as a projectile motion. Using the physical equations shown below, the following equation for velocity is obtained by transformation:

equation for velocity

standard equation for projectile motion taken from wikipedia. Please ignore the fact that it says ß instead of α
For my calculation α, x, g and y are given. After calculating the velocity, I divide it into x, y and z axis. My corresponding code looks like this:
function GetVelocity()
local X = GetDistance(Bullet,Border) -- Bullet = Projectile // Border = vertical part
local Y = (Border.Position.Y - Border.Size.Y / 2) - Bullet.Position.Y -- distance on y-axis
local Beta = GetBeta() -- angle between z-axis and projectile direction in 2D space (x-axis and z-axis)
local Velocity = math.sqrt((math.pow(X,2) * workspace.Gravity)/(2 * math.cos(Angle) * math.sin(Angle) * X - 2 * math.pow(math.cos(Angle),2) * Y))
local XVelocity = math.sin(math.rad(90) - Angle) * Velocity * math.cos(Beta)
local YVelocity = math.cos(math.rad(90) - Angle) * Velocity
local ZVelocity = math.sin(math.rad(90) - Angle) * Velocity * math.sin(Beta)
local TravelTime = X/(math.sin(math.rad(90) - Angle) * Velocity)
return Vector3.new(-XVelocity,YVelocity,-ZVelocity),TravelTime
end
I have calculated the whole thing several times and can’t figure out why it doesn’t land where it is supposed to. Any ideas why?
Appendix:
Whole Code
local RService = game:GetService("RunService")local Bullet = workspace.Bullet
local Border = workspace.Border
local Anchor = workspace.Anchor
local Rope = Anchor.RopeConstraint
local Angle = math.rad(70)
local Connection
function GetDistance(PartA,PartB)
local X = PartA.Position.X - PartB.Position.X
local Y = PartA.Position.Y - PartB.Position.Y
local Z = PartA.Position.Z - PartB.Position.Z
return math.sqrt(math.pow(X,2) + math.pow(Y,2) + math.pow(Z,2))
end
function GetBeta()
local Beta = math.rad(90) - math.atan((Bullet.Position.X - Border.Position.X) / (Bullet.Position.Z - Border.Position.Z))
if Bullet.Position.Z <= Border.Position.Z then
Beta = -(math.rad(180) - Beta)
end
return Beta
end
function GetVelocity()
local X = GetDistance(Bullet,Border) -- Bullet = Projectile // Border = vertical part
local Y = (Border.Position.Y - Border.Size.Y / 2) - Bullet.Position.Y -- distance on y-axis
local Beta = GetBeta() -- angle between z-axis and projectile direction in 2D space (x-axis and z-axis)
local Velocity = math.sqrt((math.pow(X,2) * workspace.Gravity)/(2 * math.cos(Angle) * math.sin(Angle) * X - 2 * math.pow(math.cos(Angle),2) * Y))
local XVelocity = math.sin(math.rad(90) - Angle) * Velocity * math.cos(Beta)
local YVelocity = math.cos(math.rad(90) - Angle) * Velocity
local ZVelocity = math.sin(math.rad(90) - Angle) * Velocity * math.sin(Beta)
local TravelTime = X/(math.sin(math.rad(90) - Angle) * Velocity)
return Vector3.new(-XVelocity,YVelocity,-ZVelocity),TravelTime
end
function CalculateRopeLength()
Rope.Length = 1 + 20/GetDistance(Anchor,Bullet) + GetDistance(Anchor,Bullet) -- Increase 1 for bigger distances
end
function Shoot()
local TravelTime
Bullet.AssemblyLinearVelocity,TravelTime = GetVelocity()
Bullet.Anchored = false
Connection = RService.Heartbeat:Connect(CalculateRopeLength)
wait(TravelTime)
Connection:Disconnect()
Bullet.Anchored = true
end
GetVelocity()
for i = 5,1,-1 do
print("Shooting in "..i.." seconds")
wait(1)
end
Shoot()
Place file: Fishing physics.rbxl (25.0 KB)