How to get a realistic rim hang effect?

I’m trying to suspend / hang the player by their hands as if they were grabbing and holding onto the rim of a basketball hoop. It works somewhat, but they keep leaning to the side and it all around doesn’t look so good.

Video of the issue ^

Current code for making them hang from the rim:

-- make attachments
			for i = 1,2 do
				local rightHand = i == 1 and true or false
				local hand = rightHand and char:WaitForChild("RightHand") or char:WaitForChild("LeftHand")

				local direction = CFrame.lookAt(goalPos, Vector3.new(hand.Position.X, goalPos.Y - 0.25, hand.Position.Z)).LookVector * 1.25
				local a1, a2 = Instance.new("Attachment"), Instance.new("Attachment")

				a1.Parent = rim
				a2.Parent = hand
				a1.WorldPosition = goalPos + direction

				local constraint = Instance.new("BallSocketConstraint")
				constraint.Attachment0 = a1
				constraint.Attachment1 = a2
				constraint.Parent = hand

				game.Debris:AddItem(a1, rimHangTime)
				game.Debris:AddItem(a2, rimHangTime)
				game.Debris:AddItem(constraint, rimHangTime)
			end

The end result I’m trying to get should look something along the lines of this:

(I asked the creator of this game how they did it and they said ball and socket constraints in each hand attached to points around the rim.)

Pretty sure that’s because of the default falling animation, enable platform stand during the hang time.

Tried platform stand already and I got the same result. The animation you see is just the dunk animation. However it doesn’t swing or tilt to the side so I don’t know what is causing it to appear as if one hand is disconnected.

Because you’ve only attached one hand to it not two?

I am using a for loop to attach both. Specifically, right here:


I have also made it so the attachments are visible for debugging; There is one each hand and two are created on the rim. So it would appear that the attachments are working fine

Perhaps you have the attachments at strange positions.

Nope, they generate them around the rim fine as I stated above.

You shouldn’t have to WaitForChild in the loop.

You could try defining this already where you already defined your character as it spawns.
There’s a few things I can recommend trying…

See if something like this could work

local player = game:GetService("Players").LocalPlayer
local char = player.Character

Local rightHand = char:WaitForChild("RightHand")
Local leftHand = char:WaitForChild("LeftHand ")

for i = 1,2 do
   local handVar == 1 and true or false
   local hand = handVar and rightHand or leftHand 

--- rest of your code
end

Send a screenshot of the attachment positions that you said you have made visible.

Try this coroutine.wrap

It runs past the loop and should run rightHand and leftHand functions at the same time

				local direction = CFrame.lookAt(goalPos, Vector3.new(hand.Position.X, goalPos.Y - 0.25, hand.Position.Z)).LookVector * 1.25
				local a1, a2 = Instance.new("Attachment"), Instance.new("Attachment")
				local constraint = Instance.new("BallSocketConstraint")
local function rightHand()

				local Rhand = char:WaitForChild("RightHand") 

				a1.Parent = rim
				a2.Parent = Rhand 
				a1.WorldPosition = goalPos + direction

				constraint.Attachment0 = a1
				constraint.Attachment1 = a2
				constraint.Parent = Rhand 

				game.Debris:AddItem(a1, rimHangTime)
				game.Debris:AddItem(a2, rimHangTime)
				game.Debris:AddItem(constraint, rimHangTime)
end

local function leftHand()
                coroutine.wrap(rightHand)() -- The () at the end is required for the coroutined function to run
				local Lhand= char:WaitForChild("LeftHand") 

				a1.Parent = rim
				a2.Parent = Lhand
				a1.WorldPosition = goalPos + direction

				constraint.Attachment0 = a1
				constraint.Attachment1 = a2
				constraint.Parent = Lhand

				game.Debris:AddItem(a1, rimHangTime)
				game.Debris:AddItem(a2, rimHangTime)
				game.Debris:AddItem(constraint, rimHangTime)
end

leftHand()

Thats actually a really good idea, I didn’t think about the fact that one hand could be created before the other

The main problem you have to keep in mind when running this loop you have a few Instance.new() statements which takes some time in itself.

Not much but in your case enough for it take enough time before the loop runs a second time to get undesired results in your case.

I unfortunately still get the same result, it doesn’t appear to have done anything

Even after the loop has been removed? And the coroutine.wrap ran the same time?

between print statements see the time between

in the rightHand function
print("rightHand")

in the leftHand function
print("leftHand")

Because it should both run instantly?

The attachments visibly appear all at the same time, I’m beginning to think that the cause might be one of the constraints just stops working or its my animation not being suitable for the rim hangs.

After doing some testing both constraints are indeed working. I left one hand out from being connected as a test and I actually got better-ish results. Could it be that the ball and socket constraints are fighting each other?

I edited the original courtine.wrap and cleaned it up alittle and changed hand to Lhand and Rhand to their own variables

That method won’t work because you defined where the rim attachments go outside of the hand functions. You also only added 1 constraint and 2 attachments rather than 2 constraints and 4 attachments.

Honestly, the best solution I could come up with (with minimal code that is) is to manually animate it. Have several animations where the player slam-dunks from several angles.

I usually use tools like Blender for more realistic animations since they can be simulated and baked.