SpriteKit:无法在联系回调中更改节点位置

时间:2014-04-02 11:38:52

标签: sprite-kit

我有一个带动态物理体的节点。而且我想让它静止,并在与另一个身体接触时改变它的位置。

我设法使用此问题中提供的解决方案使身体保持静止:Sprite Kit failing assertion: (typeA == b2_dynamicBody || typeB == b2_dynamicBody)

但是,如果我在其中一个联系人回调方法中更改节点的position属性(例如didBeginContact),则不会考虑新位置。

我怎么能实现这个目标?

3 个答案:

答案 0 :(得分:6)

我相信这是SpriteKit中的一个错误。 (我能用SpriteKit 7.1重现这个问题。)

以下是一个快速解决方法:

- (void) didBeginContact:(SKPhysicsContact *)contact
{
     contact.bodyB.node.position = CGPointMake(newX, newY);
     contact.bodyB.node.physicsBody = contact.bodyB.node.physicsBody; // <-- Add this line
}

答案 1 :(得分:0)

JKallio的解决方案对我不起作用(OS X 10.10.5上的Xcode 7.2.1,针对iOS 8.1)。我发现我能够在update:方法中更改位置,因此我通过在didBeginContact中设置标记并更改update:中的位置来解决错误。

@implementation GameScene {
    SKNode *_victim;
    CGPoint _target;
}

- (void)didMoveToView:(SKView *)view {
    _victim = nil;
}

- (void)didBeginContact:(SKPhysicsContact *)contact {
    _victim = contact.bodyB.node;
    _target = CGPointMake(newX, newY);
}

- (void)update:(CFTimeInterval)currentTime {
    if (_victim != nil) {
        _victim.position = _target;
        _victim = nil;
    }
}

@end

请注意,_victim同时充当节点和标志。

我的解决方案比JKallio更复杂;在来之前尝试那个。

答案 2 :(得分:0)

作为变通方法的另一个选项,我改为在SKSpriteNode子类中为我想要移动的对象调用一个方法,并传入该主体。该职位设置正确。

/* In GameScene.swift */

func didBegin(_ contact: SKPhysicsContact) {
    let dotBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask == 0b1 {
        dotBody = contact.bodyB
    } else {
        dotBody = contact.bodyA
    }

    if let dot = dotBody.node as? Dot {
        dot.move()
    }        
}

这是Dot类:

import SpriteKit
class Dot : SKSpriteNode {
    let dotTex = SKTexture(imageNamed: "dot")
    init() {
        super.init(texture: dotTex, color: .clear, size: dotTex.size())
        self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
        self.physicsBody?.categoryBitMask = 0b1 << 1
        self.physicsBody?.contactTestBitMask = 0b1
    }

    func move() {
        let reset = SKAction.run {
            self.position.x = 10000
        }
        self.run(reset)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}