当shouldEnableLimits为true,且设置了lowerAngleLimit和upperAngleLimit时,SKPhysicsJointPin出现不正确的行为。

7

我目前有一个布娃娃的图形,它由一个父节点(没有附加物理体)和许多子节点组成,每个子节点都包含一个圆形物体。这些圆形物体使用SKPhysicsJointPin相互连接,如下所示:

Ragdoll figure

每个SKPhysicsJointPin都有shouldEnableLimits = true,我目前为lowerAngleLimitupperAngleLimit分别使用-0.05和0.05的值。
这很有效地防止形状过度变形,除非整个图形倒置,此时所有关节突然试图收缩,如下所示:

Broken ragdoll figure

当人物完全倒立时,关节会非常快地收缩。当他再次旋转时,所有关节都恢复正常。为什么会这样?我如何保持关节的正确角度?

编辑1:

我刚试着用Objective-C重新编写了项目,以防它是由于某些奇怪的Swift错误导致的;结果发现这个问题在Objective-C中仍然存在,所以我已经移除了Swift标签。

目前我的最佳猜测是,当附加到它们的主体向左或向右旋转超过180°时,SpriteKit计算关节相对于世界的角度不正确,因此错误的角度被传递给底层的Box2D关节。

我不确定是否应该不断更新下限和上限角度以匹配它们的主体世界角度,但似乎当身体非常接近倒立时,关节停止正常工作。无论如何,我将继续尝试实验...

编辑2:

我现在相当确定问题的发生是因为SpriteKit(我猜有充分的理由)修改了zRotation值,使其保持在-180°和180°之间。例如,如果节点顺时针旋转并达到-180°,SpriteKit会自动将其值包装回+180°。我相当自信这种包装会导致关节表现不稳定,只需要找出如何抵消它... 编辑3: 我已经上传了演示此问题的示例应用程序(包括视频),正如Apple最初要求的那样:Xcode项目 / 视频

你需要使用更长的物理体而不是圆形。每个物理体应该代表一个手臂、腿、脚、躯干等。你自己的身体是由你在这里创建的骨骼结构吗? - ZeMoon
你尝试过为单个物体禁用重力吗? - CodeSmile
你是如何将字符翻转过来的? - 0x141E
我对头节点施加力,有效地拖动了身体的其余部分。如果头部向一侧移动,然后向下移动,身体就会倒置。 - Robert
我已经在我的问题中添加了一些进一步的发现。 - Robert
显示剩余8条评论
2个回答

0

目前我的lowerAngleLimit和upperAngleLimit的值分别为-0.05和0.05。

根据文档...

upperAngleLimit - 夹爪关节所允许的最大角度,以弧度表示

...这些极限值是以弧度为单位的。

0.05 radians = 2.86478898 degrees

所以,你只允许身体总共移动约5度。这是一个非常小的范围。根据我的经验,当物体被迫超出范围时,SpriteKit会开始出现奇怪的弹跳行为。

我认为这种行为不仅限于倒置的身体。我最好的猜测是,物理引擎没有帧率来在一帧中施加重力,并在下一帧中捕捉到物体在移动出范围之前。

你应该增加范围。我更喜欢用角度来指定它。例如...

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)

你需要调整角度、质量和重力,直到找到一个合适的位置,使物体能够以真实的方式移动。

如果你真的想要如此小的运动范围,我建议你干脆将其完全禁用。

circle.physicsBody?.allowsRotation = false

谢谢你的回答,但我已经尝试了很多不同的角度;一个小角度并不是问题的原因。我相当确定问题是由于SpriteKit在超过其限制时规范化身体旋转角度而混淆了基础Box2D关节所致。无论如何,我认为一个约5º的角度对于物理引擎来计算并不是特别小,它可以很好地处理它们,直到角色翻转! - Robert
我能告诉你的是,我已经在SpriteKit中实现了一个布娃娃,并且当它倒立时我没有遇到任何问题。你想做的事情是完全可能的。 - Charlie Martin
当我提交了错误报告后,苹果要求提供一个样例应用程序/视频。我已经将其修复为现代Swift并重新上传(仍然以相同的方式失败),请随意查看(添加到原始帖子的链接);如果您有任何见解,我会很感兴趣! - Robert
我会在有空的时候看看能否让它正常工作。如果不行,我很感兴趣追踪这个错误,谢谢。 - Charlie Martin
我无法使用您设置的身体大小和角度使其正常工作。我注意到,身体和角度越大,发生这种情况的频率就越来越低,直到完全没有发生。我还注意到,它似乎只会在“链式”身体中发生,这导致我提出了一个新的理论:在将约束应用于身体的第一个关节的过程中,它正在将同一身体上的其他关节拉出范围。听起来像是个漏洞。一个有趣的实验是看看在没有SpriteKit的情况下,在box2d中是否会出现此问题。如果是,那么它可能是引擎的限制。如果不是,那么这是一个Spritekit的错误。 - Charlie Martin
有趣,谢谢 - 我相信我之前在Box2D中看到过类似的链和物体运动。我可能需要在其中实现类似的东西来找出答案! - Robert

0

我可以确认,这是SpriteKit中的一个bug。在我的情况下,我使用了最简单的场景,即通过销钉连接的两个精灵。不幸的是,在iOS 9上仍然会发生这种情况 :(


这也是我在项目中不得不使用chipmunk的原因。 - JakubKnejzlik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接