Wrong behavior with SKPhysicsJointPin when shouldEnableLimits are true and lowerAngleLimit and upperAngleLimit set

Currently, I have a ragdoll figure, which consists of a parent node (without attached physical bodies) and many child nodes, each of which consists of a circle body. Circles are connected to each other using SKPhysicsJointPin between each circle:

Ragdoll figure

Each SKPhysicsJointPin has shouldEnableLimits = true , and currently I'm using the values ​​-0.05 and 0.05 for lowerAngleLimit and upperAngleLimit respectively.

This works very well and does not allow the deformation to deform too much, unless the figure goes upside down as a whole, in which case all the joints suddenly try to compress, for example:

Broken ragdoll figure

The joints conclude very quickly when the figure is completely upside down. When he turns again, all joints return to normal. Why is this happening? How to maintain proper joint angles?

Change 1:

I just tried to rewrite the project in Objective-C if this happened due to some strange Swift error; this problem still shows up in Objective-C, so I removed the Swift tag.

My best guess at the moment is that the angle of the joints relative to the world is incorrectly calculated by SpriteKit, when the bodies to which they are attached rotate more than 180 Β° in any direction, and therefore the wrong angles are transferred to the Box2D base joints.

I was not sure whether I should constantly update the limits of the lower and upper corners to match the world angles of their bodies, but it does not seem to be the same as when the body is very close to the -DD joints stop working properly. Anyway, I will continue to experiment ...

Edit 2:

Now I am sure that the problem arises because SpriteKit (I think, not without reason) changes the value of zRotation to keep it between -180 Β° and 180 Β°. If, for example, the node rotates clockwise and reaches -180 Β°, SpriteKit automatically wraps its value back to + 180 Β°. I'm pretty sure this wrap makes the joints behave erratically, I just need to figure out how to counteract this ...

Edit 3:

I downloaded an example application (including video) that demonstrates this problem as originally requested by Apple: Xcode Project / Video

+6
source share
2 answers

"I am currently using the values ​​-0.05 and 0.05 for lowerAngleLimit and upperAngleLimit, respectively.

According to the docs ...

upperAngleLimit is the largest angle allowed for a pin connection, in radians .

... the limits are in radians.

 0.05 radians = 2.86478898 degrees 

So, you allow bodies to move only 5 degrees. This is a very small range. In my experience, SpriteKit starts this weird binding when the body is pushed out of range.

I do not think that this behavior is characteristic of inverted bodies. My best guess is that the physics engine has no frame rate to apply gravity in one frame and catch the body before it goes out of range in the next.

You must increase the range. I prefer to indicate it in degrees. For instance...

 func degreesToRadians(degrees: CGFloat) -> CGFloat { return CGFloat(M_PI) * degrees / 180.0 } pinJoint.shouldEnableLimits = true pinJoint.lowerAngleLimit = degreesToRadians(-30.0) pinJoint.upperAngleLimit = degreesToRadians(180.0) 

You will have to bother with angles, mass and gravity until you find a sweet spot where things will move realistically.

If you really want a small number of movements to be small, I would just turn it off altogether.

 circle.physicsBody?.allowsRotation = false 
0
source

I can confirm that this is a bug in SpriteKit. In my case, I use the simplest scenario of two sprites connected by a pin joint. Unfortunately, this is still happening on iOS 9 :(

0
source

Source: https://habr.com/ru/post/974507/


All Articles