SpriteKit iOS 7 Sknode 没有被删除

Posted

技术标签:

【中文标题】SpriteKit iOS 7 Sknode 没有被删除【英文标题】:SpriteKit iOS 7 Sknode not being removed 【发布时间】:2014-03-20 19:34:31 【问题描述】:

我正在为 ios 7 开发一款游戏,它使用 Spritekit。

主要的 skspritenode 是一架直升机,当这架直升机接触到收缩奖励拾取器时,直升机会收缩以使用户更容易导航。以下是按预期工作的缩小直升机的代码(self 指的是直升机 skspritenode):

SKAction *scaleHeli = [SKAction scaleBy:.70 duration:1];
SKAction *setPhysicsBody = [SKAction runBlock:^
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
self.physicsBody.mass = 0.080944441;
self.physicsBody.restitution = 1.0f;
self.physicsBody.allowsRotation = FALSE;
self.physicsBody.categoryBitMask = APAColliderTypeShip;
self.physicsBody.collisionBitMask = APAColliderTypeCavePiece;
self.physicsBody.contactTestBitMask = APAColliderTypeCavePiece | APAColliderTypeBonusPickup;
];

SKAction *seq = [SKAction sequence:@[scaleHeli, setPhysicsBody]];

[self runAction:seq];
_shrinkEnabled = true;

我有一个持续预定时间的收缩奖励的计时器设置:

-(void)startShrinkTimer

    //Creating the timer for the shield
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self    selector:@selector(countDownShrinkDuration) userInfo:Nil repeats:true];
    _timerSeconds = 15;


-(void)countDownShrinkDuration

    if(_timerSeconds > 0)
    
        --_timerSeconds;
    
    else if(_timerSeconds == 0)
    
        [_sceneRef disableShrinkBonus];
        [_timer invalidate];
    

    if(_timerSeconds < 5)
    
        [_sceneRef shrinkWearingOut];
    

如果计时器小于 5 秒,则调用 shrinkWearingOut 函数,该函数将标签添加到淡入淡出的节点(self 指的是直升机 skspritenode):

SKLabelNode *downLbl = [[SKLabelNode alloc] init];
downLbl.text = @"↓";
downLbl.fontColor = [UIColor whiteColor];
downLbl.fontSize = 9.0f;
downLbl.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
downLbl.position = CGPointMake(0,-30);
downLbl.zPosition = 5;

SKAction *fadeOut = [SKAction fadeOutWithDuration: .2];
SKAction *fadeIn = [SKAction fadeInWithDuration: .2];
SKAction *pulse = [SKAction sequence:@[fadeOut,fadeIn]];

SKAction *pulseForever = [SKAction repeatActionForever:pulse];

SKSpriteNode *wearingOut = [[SKSpriteNode alloc] init];
wearingOut.name = @"wearingOut";

[wearingOut addChild:downLbl];

[wearingOut runAction:pulseForever];

[self addChild:wearingOut];

一旦计时器归零,就会调用 disableShrink 函数,它会尝试移除脉动节点并将直升机缩放到其原始大小(self 指的是直升机 skspritenode):

[[self childNodeWithName:@"wearingOut"] removeFromParent];

SKAction *scaleHeli = [SKAction scaleBy:1.3 duration:1];
SKAction *setPhysicsBody = [SKAction runBlock:^
    self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
    self.physicsBody.mass = 0.080944441;
    self.physicsBody.restitution = 0.0f;
    self.physicsBody.allowsRotation = FALSE;
    self.physicsBody.categoryBitMask = APAColliderTypeShip;
    self.physicsBody.collisionBitMask = APAColliderTypeCavePiece;
    self.physicsBody.contactTestBitMask = APAColliderTypeCavePiece | APAColliderTypeBonusPickup;

    _shrinkEnabled = false;
];

SKAction *seq = [SKAction sequence:@[scaleHeli, setPhysicsBody]];

[self runAction:seq];

问题#1:这行代码: [[self childNodeWithName:@"wearingOut"] removeFromParent]; 实际上并没有从直升机节点中删除脉动节点,我在这里设置了一个断点并验证了该节点不是零,但它似乎仍然没有删除该节点。非常令人沮丧,因为我使用了完全相同的代码行和不同名称的不同奖励拾取,它工作得很好。唯一的区别是另一个奖励拾取是使用 skshapenode,无论哪种方式它们都从 sknode 继承,所以它们的功能应该相同。

问题 #2:脉动节点已成功添加,但仅脉冲几次,我觉得这很奇怪,因为我使用了不同奖励的确切 skaction 集,并且该奖励脉冲直到它从直升机节点中删除.

【问题讨论】:

【参考方案1】:

观察:

你不应该使用 NSTimer。而是使用 SKScene 的 update: 方法执行定时操作,如果需要,将其转发给需要它的子节点。或使用 SKAction runBlockwaitForDuration 排序。 NSTimer 可能不会与 Sprite Kit 更新/渲染循环同步运行,如果节点或场景暂停,它们也不会停止触发。

检查您没有多个名为“wearingOut”的子节点。听起来你可能添加了不止一个。使用 NSTimer 实际上可能会导致奇怪的行为,因为 Sprite Kit 可能会延迟从场景中添加/删除节点,因此添加/删除节点的时间可能是一个问题。这是一个疯狂的猜测。

脉动问题也可能表明多个精灵,也许它们是异步脉动的,因此它们看起来没有脉动。或者尝试fadeAlphaTo: 操作。

通常尝试使用记录在案的初始化程序。如果您只使用[[SKLabelNode alloc] init],可能会出现问题。我遇到了[SKSpriteNode node] 的一些问题,例如即使在设置纹理后也无法绘制。取而代之的是 [SKLabelNode labelNodeWithFontNamed:@"Arial"] 或任何其他指定的初始化程序。参考Sprite Kit Framework reference。

【讨论】:

很高兴您能回复我,我希望您能回复。哈哈。你马上解决了我的问题。如果计时器小于 5 秒,它会调用 shrinkwearingoff,应该等于 5,这样它只会被调用一次。但现在这并不重要,因为无论如何我都不应该使用计时器。谢谢一百万。

以上是关于SpriteKit iOS 7 Sknode 没有被删除的主要内容,如果未能解决你的问题,请参考以下文章

Spritekit 无尽的跑步者父 SKNode

子类化使用 SpriteKit .sks 场景文件创建的 SKNode

swift SpriteKit SKNode 类

在 SpriteKit 中禁用 SKNode 的旋转

SpriteKit: NSInvalidArgumentException - 试图添加一个已经有父节点的 SKNode

SpriteKit addChild(node: SKNode) 复数?