When one body orbits another, its movement at any given time is perpendicular to the translation between the bodies.
[image]
This script will make two parts, one of which is unanchored and orbits another.
local part1 = Instance.new("Part")
part1.Position = Vector3.new(20, 5, 0)
part1.Parent = workspace
local part2 = Instance.new("Part")
part2.Position = Vector3.new(0, 5, 0)
part2.Anchored = true
part2.Parent = workspace
-- BodyVelocity is used to counteract gravity
-- Setting Velocity of part1 every Stepped works too, but lets the part drop down slowly
local force = Instance.new("BodyVelocity", part1)
force.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
-- force.P = math.huge
local axis = Vector3.new(0, 1, 0) -- Axis that the part is spinning around
local speed = 50
game["Run Service"].Stepped:Connect(function()
force.Velocity = (part1.Position - part2.Position):Cross(axis).Unit * speed
-- (part1.Position - part2.Position): vector pointing from part2 to part1 whose magnitude is the distance between them
-- :Cross(axis): vector that is perpendicular to both the rotation axis and the translation
-- .Unit * speed: force magnitude to be 20
print((part1.Position - part2.Position).Magnitude) -- watch the distance between them grow slowly :(
end)
I’m using Velocity here (instead of CFraming like the script you found does) because it generally keeps physics correct. Things that you hit while orbiting will be knocked away etc.
Say a character was falling and they wanted to swing, they would press a button while falling and they would swing based on that speed and direction.
Let’s see… we have the original Velocity of the player and we want to keep going that way.
Modify the variables in the above script thus:
local velocity -- velocity of the player, find it however you like
local posPlayer
local posTarget
local speed = velocity.Magnitude -- retain current speed
local axis = (posTarget - posPlayer):Cross(velocity).Unit -- vector that has length of 1 and is perpendicular to both direction of movement and translation between player and target
-- watch the distance between them grow slowly :(
I put this comment in the code because that happens. You might want to connect the player and the target with a RodConstraint.
If the player (or part, in the test script) collides with something, it won’t bounce back. This is because the BodyVelocity is very stubborn. Setting Velocity and removing gravity from the player would help here, as would updating speed
based on the current velocity every step, so that it can change on collision.
All of this is best done in a local script. No server script involvement or remote events are needed, just set the character’s velocity/position/whatever. The BodyVelocity will work even if it doesn’t exist on the server, because it does exist for the client, and the client tells the server where the character is anyway.