RopeConstraints and RodConstraints being too laggy when connected between two Players

I’ve made a script that connects player1’s (senders) and player2’s (receivers) hands (bottom attachments on arms) with RopeConstraint. Another thing I did is disable Motor6D connecting the shoulders for both players and connected them with RodConstraint so they the arms would be jiggly instead of being anchored to the player. This does work fine but the receiver player receives extreme input lag and choppiness when trying to move around. I’ve already tried using BasePart:SetNetworkOwner() but it didn’t fully fix the problem, as the input lag and mild choppiness was still present. Do I have to write my own system instead of using Constraints? If so, how should I implement it?

Heres my current code:

PromptResponse.OnServerEvent:Connect(function(_, receiver:Player, sender:Player, response)
    local receiverChr = receiver.Character
    local senderChr = sender.Character

    if not response then
        receiverChr.IsPaired.Value = false
        senderChr.IsPaired.Value = false
        receiverChr.ProximityPrompt.Enabled = true
        senderChr.ProximityPrompt.Enabled = true
        PromptSender:FireClient(sender, true)
        return
    end
    
    PromptSender:FireClient(sender, "accepted")
    
    
    local attachmentS = Instance.new("Attachment", senderChr["Left Arm"])
    attachmentS.Name = "AttachmentS"
    attachmentS.Position = Vector3.new(0, -1, 0)
    
    local attachmentR = attachmentS:Clone()
    attachmentR.Name = "AttachmentR"
    attachmentR.Parent = receiverChr["Right Arm"]


    local rope = Instance.new("RopeConstraint", senderChr["Left Arm"])
    local rodS = Instance.new("RodConstraint", senderChr["Left Arm"])

    rodS.Length = 0.3
    
    local rodR = rodS:Clone()
    rodR.Parent = receiverChr["Right Arm"]

    rope.Length = 0.3


    rodS.Attachment0 = senderChr["Left Arm"].LeftShoulderAttachment
    rodS.Attachment1 = senderChr["Torso"].LeftCollarAttachment
    rodR.Attachment0 = receiverChr["Right Arm"].RightShoulderAttachment
    rodR.Attachment1 = receiverChr["Torso"].RightCollarAttachment

    rope.Attachment0 = senderChr["Left Arm"].AttachmentS
    rope.Attachment1 = receiverChr["Right Arm"].AttachmentR

    senderChr.Torso["Left Shoulder"].Enabled = false
    receiverChr.Torso["Right Shoulder"].Enabled = false
    
end)
1 Like

It could be that it is like this in Roblox Studio, have you tried with 2 accounts and 2 different devices?

I have, it didn’t fix the issue.

Make sure each player controls their own character’s parts. Use SetNetworkOwner() to give control of Player1’s arm to Player1, and Player2’s arm to Player2. This helps reduce lag.

Simplify Constraints: Try using fewer constraints, like just a RopeConstraint or HingeConstraint. Having too many constraints (like RodConstraint) can slow things down.

-- network ownership on both players arms
local senderArm = senderChr["Left Arm"]
local receiverArm = receiverChr["Right Arm"]

-- set the network ownership to the respective players
senderArm:SetNetworkOwner(sender)
receiverArm:SetNetworkOwner(receiver)

Using SetNetworkOwner() doesn’t fix the issue entirely. It does make the player a little less laggy, but the input delay still persists. As for simplifying constraints, how can I then make the arm attached to the player and be affected by physics?

Address the player so it doesn’t lag.

-- Example, set arm's network ownership to the local player
arm:SetNetworkOwner(player) 
-- 

Use a WeldConstraint to attach the arm to the player: The WeldConstraint can be used to physically connect the arm to the player’s body part , while still allowing the physics engine to affect the arm’s movements.

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

-- Create a new Part (arm)
local arm = Instance.new("Part")
arm.Size = Vector3.new(1, 2, 1)  -- Example size of an arm
arm.Position = character.Torso.Position + Vector3.new(1, 0, 0)  -- Attach near torso
arm.Parent = workspace

-- Create a WeldConstraint to attach the arm to the torso
local weld = Instance.new("WeldConstraint")
weld.Part0 = arm
weld.Part1 = character.Torso  -- Assuming the torso is the base part
weld.Parent = arm

If you want the arm to have rotation (like a ragdoll), you can use a BallSocketConstraint to attach the arm with some flexibility then:

local ballSocket = Instance.new("BallSocketConstraint")
ballSocket.Parent = arm
ballSocket.Attachment0 = armAttachment  -- Create an attachment on the arm
ballSocket.Attachment1 = torsoAttachment  -- Create an attachment on the torso
ballSocket.LimitsEnabled = true
ballSocket.TwistLimitsEnabled = true
ballSocket.TwistLowerAngle = -45
ballSocket.TwistUpperAngle = 45
ballSocket.Parent = arm

-- Let me know if you have any problems! :)

I rewrote your script, and I see a few issues, like: having both a RopeConstraint and RodConstraint applied at once on the players’ arms is unnecessary.

PromptResponse.OnServerEvent:Connect(function(_, receiver:Player, sender:Player, response)
    local receiverChr = receiver.Character
    local senderChr = sender.Character

    if not response then
        receiverChr.IsPaired.Value = false
        senderChr.IsPaired.Value = false
        receiverChr.ProximityPrompt.Enabled = true
        senderChr.ProximityPrompt.Enabled = true
        PromptSender:FireClient(sender, true)
        return
    end
    
    PromptSender:FireClient(sender, "accepted")
    
    local attachmentS = Instance.new("Attachment", senderChr["Left Arm"])
    attachmentS.Name = "AttachmentS"
    attachmentS.Position = Vector3.new(0, -1, 0)
    
    local attachmentR = attachmentS:Clone()
    attachmentR.Name = "AttachmentR"
    attachmentR.Parent = receiverChr["Right Arm"]

    local rope = Instance.new("RopeConstraint", senderChr["Left Arm"])
    rope.Length = 0.3
    rope.Attachment0 = senderChr["Left Arm"].AttachmentS
    rope.Attachment1 = receiverChr["Right Arm"].AttachmentR

    senderChr.Torso["Left Shoulder"].Enabled = false
    receiverChr.Torso["Right Shoulder"].Enabled = false
    
    local senderArm = senderChr["Left Arm"]
    local receiverArm = receiverChr["Right Arm"]

    senderArm:SetNetworkOwner(sender)
    receiverArm:SetNetworkOwner(receiver)
end)
-- Let me know if this works! :)

You have to implement your functionality on the client side

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.