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

Posted

技术标签:

【中文标题】SpriteKit:无法在联系人回调中更改节点位置【英文标题】:SpriteKit: cannot change node position in contact callback 【发布时间】:2014-04-02 11:38:52 【问题描述】:

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

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

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

我怎样才能做到这一点?

【问题讨论】:

能否贴出无法更新位置的代码,以及您如何实现链接到的解决方案? @LearnCocos2D JKallio 给出的解决方案工作正常(将physicsBody 重新分配给它的节点) 【参考方案1】:

我相信这是 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

【讨论】:

它工作正常。我只是稍微改变了最后一行:contact.bodyB.node.physicsBody = contact.bodyB.node.physicsBody;【参考方案2】:

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 的更复杂;在来之前试试那个。

【讨论】:

【参考方案3】:

作为解决方法的另一个选项,我改为在 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)
    

【讨论】:

以上是关于SpriteKit:无法在联系人回调中更改节点位置的主要内容,如果未能解决你的问题,请参考以下文章

复制 SpriteKit 节点位置

删除联系人 spritekit 上的节点

无法修改 didBeginContact 中的contact.bodyA

带有 AVAudioPlayerNode 的 SpriteKit 位置音频

iOS7 Sprite Kit如何在更改锚点时计算节点位置?

无法使应用程序进入主菜单(Swift 4 SpriteKit)