Hello! I am currently attempting to create realistic ODM gear based on the show Attack on Titan. The mechanics consist of a movement system where players can move their mouse over a wall or object and press Q / E on their keyboard to initiate a grapple onto the object. I already have the movement working so far, but I’ve run into a road block. I wanted to incorporate an orbiting-like mechanic to the system that slowly orbits a player around the object they’ve grappled on, in a circle. I’ve tried several methods of doing this, like using AngularVelocity, BodyAngularVelocity, CylindricalConstraints, and simply editing my BodyVelocity (the main character mover) to move the character in a circle around the object, which didn’t work. At this point, I have no idea what to do. Here’s a portion of my current code that handles movement with the ODM gear:
ReplicatedStorage.Assets.Remotes.GrappleBegin.OnServerEvent:Connect(function(Player, HP)
local Character = Player.Character or Player.CharacterAdded:Wait()
local Root = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local ODM = Character:FindFirstChild("ODM")
if HP and ODM then
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = { Character; ODM }
Params.FilterType = Enum.RaycastFilterType.Exclude
local Dir = (HP - Root.Position).Unit
local _Filter = workspace:Raycast(Root.Position, Dir * 400, Params)
if _Filter then
if _Filter.Instance then
if _Filter.Instance.Name ~= "Baseplate" then
ReplicatedStorage.Assets.Remotes.CLIENT_2:FireClient(Player)
local AttchHolder = Instance.new("Part", workspace)
AttchHolder.Transparency = 1
AttchHolder.CanCollide = false
AttchHolder.Anchored = true
AttchHolder.Position = _Filter.Position
AttchHolder.Name = Player.Name.."_ODM_GRAPPLE_POS"
local Identifier = Instance.new("BoolValue", Character)
Identifier.Name = "IsGrappling"
ReplicatedStorage.Assets.Remotes.CreateClientBillboard:FireClient(Player, AttchHolder)
ReplicatedStorage.Assets.Remotes.FOV_Out:FireClient(Player)
ODM.Root.Shot:Play()
ODM.Gas.Emitter.Boost.Enabled = true
ODM.Gas.Emitter.Trail.Enabled = true
task.delay(ODM.Root.Shot.TimeLength / 2, function()
ODM.Gas.Burst:Play()
ODM.Gas.Emit:Play()
end)
Root.CFrame = CFrame.lookAt(Root.Position, AttchHolder.Position)
local Attch0 = Instance.new("Attachment", Root)
Attch0.Name = "ODM_ATTACHMENT"
local Attch1 = Instance.new("Attachment", AttchHolder)
local RightBeam = ODM.LeftGrapple3.Beam
local LeftBeam = ODM.RightGrapple3.Beam
RightBeam.Attachment1 = Attch1
LeftBeam.Attachment1 = Attch1
local BodyVelocity = Instance.new("BodyVelocity", Root)
BodyVelocity.MaxForce = Vector3.new(5000, 5000, 5000)
BodyVelocity.P = 25
local Direction = (AttchHolder.Position - Root.Position).Unit
local Rotation = CFrame.lookAt(Vector3.new(0, 0, 0), Vector3.new(Direction.X, 0, Direction.Z))
local BodyGyro = Instance.new("BodyGyro", Root)
BodyGyro.D = 100
BodyGyro.P = 5000
BodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
BodyGyro.CFrame = Rotation
local Connection
local Connection2
task.delay(1, function()
for i, x in pairs(Character:GetDescendants()) do
if x:IsA("BasePart") then
local __Connection
__Connection = x.Touched:Connect(function(Hit)
if not game.Players:GetPlayerFromCharacter(Hit.Parent) and Hit ~= _Filter.Instance or Hit.Name == "Baseplate" and ReplicatedStorage.Assets.Remotes.CollisionCheckRunner:FireClient(Player) == true then
if Character:FindFirstChild("IsGrappling") then
Identifier:Destroy()
BodyGyro:Destroy()
BodyVelocity:Destroy()
AttchHolder:Destroy()
ODM.Gas.Emitter.Boost.Enabled = false
ODM.Gas.Emitter.Trail.Enabled = false
ReplicatedStorage.Assets.Remotes.FOV_In:FireClient(Player)
ODM.Gas.Emit:Stop()
if not ODM.Root.Retract:FindFirstChild("Cooldown") then
ODM.Root.Retract:Play()
end
Connection:Disconnect()
end
end
end)
Identifier.Destroying:Connect(function()
__Connection:Disconnect()
end)
end
end
end)
Connection2 = _Filter.Instance.Touched:Connect(function(Hit)
if Hit then
if game.Players:GetPlayerFromCharacter(Hit.Parent) == Player then
if BodyVelocity and AttchHolder and BodyGyro then
BodyGyro:Destroy()
BodyVelocity:Destroy()
AttchHolder:Destroy()
ODM.Gas.Emitter.Boost.Enabled = false
ODM.Gas.Emitter.Trail.Enabled = false
ReplicatedStorage.Assets.Remotes.FOV_In:FireClient(Player)
ODM.Gas.Emit:Stop()
if not ODM.Root.Retract:FindFirstChild("Cooldown") then
ODM.Root.Retract:Play()
end
Identifier:Destroy()
Connection2:Disconnect()
Connection:Disconnect()
end
end
end
end)
Connection = RunService.Heartbeat:Connect(function(DT)
if AttchHolder then
local UpdatedDir = (AttchHolder.Position - Root.Position).Unit
local UpdatedRotation = CFrame.lookAt(Vector3.new(0, 0, 0), Vector3.new(UpdatedDir.X, 0, UpdatedDir.Z))
BodyVelocity.Velocity = (AttchHolder.Position - Root.Position).Unit * 100
BodyGyro.CFrame = UpdatedRotation
end
end)
end
end
end
end
end)
I’ve been trying to implement this mechanic for multiple days with no successful results, so if anyone has a potential solution, please let me know. Thanks!