【问题标题】:Why does enabling a physicBody to my SKSpriteNode causes abnormalities?为什么为我的 SKSpriteNode 启用 physicBody 会导致异常?
【发布时间】:2020-09-19 05:45:54
【问题描述】:

我已经改变了这个问题不止一点,所以我把它移到了一个新的线程: How can I set a physicsbody to be properly centered?

我刚开始使用 SKPhysicsBody,我确实有 view.showsPhysics = true

下面是我创建一个简单的红色边框的代码,效果很好,正是我想要的位置。

但是,当我取消注释将physicsBody 应用于边界的两条线时,它会意外移动,甚至来自view.showsPhysics = true 的物理调试线也与边界线不同步。

下面是代码,左边提供的截图就是我想要的。右侧的屏幕截图显示了当我将physicsBody 应用于SKSpriteNode 时发生的情况。

显然我应用了一些不正确的东西,但我无法弄清楚。

func createBorder () -> SKSpriteNode
{
    let mBorder = MyBorder(color: .red, size: CGSize(
                            width: myGlobalVars.widthPoints,
    height: myGlobalVars.heightPoints * 0.01 ))

    mBorder.isHidden = true
    mBorder.anchorPoint = CGPoint(x: 0, y: 0)
    mBorder.position = CGPoint(x: 0, y: myGlobalVars.heightPoints * 0.2)
//    mBorder.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: myGlobalVars.widthPoints, height: myGlobalVars.heightPoints * 0.01))
//    mBorder.physicsBody!.affectedByGravity = false

    mBorder.zPosition = theZ.theBoarder
    mBorder.isHidden = false
    myGlobalVars.gameScene!.addChild(mBorder)

    return mBorder
}

附言请忽略第一个显示灰色条的屏幕。我刚刚改变了颜色。

【问题讨论】:

    标签: sprite-kit swift5 skphysicsbody


    【解决方案1】:

    没有看到更完整的代码示例,很难判断为什么红色矩形精灵在第二个屏幕截图中打开动态时会向下移动。

    至于 SpriteKit 动态调试可视化看起来错误,这是因为您正在更改 sprites anchorPoint 属性。此属性定义节点的 origin 点,即节点应居中的点(默认为CGPoint(x: 0.5, y: 0.5))。

    如果您查看SKPhysicsBody(rectangleOf:) 方法的文档,您会看到默认情况下物理形状是在原点创建的:

    创建一个以所属节点的原点为中心的矩形物理体。

    如果您想将精灵的anchorPoint 保持为零,您需要手动指定物理形状的中心点。在本示例中,我们假设您要查找的边框矩形大小为 600x10。您需要使用SKPhysicsBody(rectangleOf:center:) 方法来偏移物理体中心:

    let borderSize = CGSize(width: 600, height: 10)
    mBorder.physicsBody = SKPhysicsBody(rectangleOf: borderSize, center: CGPoint(x: borderSize.width / 2, y: borderSize.height / 2))
    

    【讨论】:

    • 我能够通过将锚点保持在 0.5 来修复身体部位,谢谢。 .但它仍然下降。而且我将affectedByGravity设置为false,所以边界墙不应该移动。它还在下降,我正在向 OP 添加一张新图片以显示。我会把那条线弄清楚,这样你就可以只看到物理调试线了——
    • 如果你将它的物理体“isDynamic”属性设置为false,边框将保持不动。现在边界只是忽略了场景的重力设置,但仍然会受到其他物理体的影响。我会开始在那里进行故障排除。顺便说一句,SpriteKit 的物理特性可能很古怪,有时在模拟器中测试它们会产生与在实际 iPhone 上看到的非常不同的结果。
    【解决方案2】:

    从您分享的代码来看,您可能需要设置更多物理模拟的细节。在任何情况下,如果您可以使用print 语句检查物理接触以更好地了解模拟中发生和未发生的情况,它可能会帮助您调试代码。以下是我在自己的游戏中处理物理的方式;希望这个例子会有所帮助。

    import SpriteKit
    
    class GameScene: SKScene, SKPhysicsContactDelegate {
    }
    

    我在声明GameScene 类时设置了SKPhysicsContactDelegate

    override func didMove(to view: SKView) {
        self.physicsWorld.contactDelegate = self
        self.balloon.physicsBody = SKPhysicsBody(circleOfRadius: 1.0)
        self.balloon.physicsBody?.categoryBitMask = 0
        self.balloon.physicsBody?.contactTestBitMask = 0
        self.balloon.physicsBody?.collisionBitMask = 0
    }
    

    在该类中,在didMove(to:) 方法中,我将physicsWorldcontactDelegate 设置为self,它指的是GameScene。然后我为我在场景中其他地方创建的气球对象创建physicsBody。我看到您已经在注释掉的代码部分执行此操作。我还设置了类别、联系人和碰撞位掩码,以便以后检查它们。

    func didBegin(_ contact: SKPhysicsContact) {
        if contact.bodyA.categoryBitMask == 0 {
            print("Balloon was contacted.")
        } else {
            print("No balloons hit.")
        }
    }
    

    didBegin(_:) 方法中,当引擎在每一帧调用此方法时,我会检查物理接触并采取一些行动来响应物理模拟中发生的某些接触。在这里,我选择检查categoryBitMask 中的接触对象,如果对象的位掩码为0,那么我将记录print 语句,以便我知道气球被什么东西击中。但我也可以轻松地采取其他行动。

    如果您想了解有关检查物理接触和碰撞的更多信息,请从以下几个很好的资源开始:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 2010-09-18
      • 2020-12-11
      相关资源
      最近更新 更多