Getting a sprite to issue a message when it is removed from the scene after removefromParent?

时间:2022-05-06 11:07:20

Is there some way in Swift that I can tell when an SKSpriteNode has actually been removed from the scene? I don't think it's actually done when removeFromParent is called, but instead I think it's done later, when Sprite-Kit thinks it's convenient to do so.

在Swift中有什么方法可以告诉我什么时候SKSpriteNode已经从场景中删除了吗?我不认为它实际上是在调用removeFromParent时完成的,而是我认为它是在以后完成的,当时Sprite-Kit认为这样做很方便。

I'm trying to understand the full life cycle and I've noticed that a sprite can still be involved in contact and collisions in didBeginContact even after that sprite has been removed.

我正在尝试理解整个生命周期,并且我注意到即使在删除了精灵后,精灵仍然可以参与didBeginContact中的接触和碰撞。

If I print out the contents of children (i.e. the array holding all the children of the scene) I see that the sprite is removed as soon as removeFromParent called, but the sprite is still available (at least, for this execution of the SK game loop).

如果我打印出子项的内容(即包含场景中所有子项的数组),我看到一旦removeFromParent被调用就删除了精灵,但精灵仍然可用(至少,对于SK游戏的执行)环)。

Edit: This question came out from an earlier question of mine concerning didBeginContact being called multiple times for one contact (Sprite-Kit registering multiple collisions for single contact) and discovering that removing the sprite during the first contact did not prevent the subsequent contact(s). (Because SK has 'queued' to contacts in advance.) so I was wondering when the sprite is actually removed.

编辑:这个问题来自我之前的一个问题,关于一个联系人多次调用didBeginContact(Sprite-Kit为单个联系人注册多个冲突)并发现在第一次联系期间删除精灵并没有阻止后续联系(s )。 (因为SK事先已经“联系”了联系人。)所以我想知道精灵什么时候被删除了。

3 个解决方案

#1


2  

Am I missing the obvious? So even after removeFromParent the sprite is still around. However, it might well be because I have assigned the node to a temporary SKSpriteNode variable, then as long as that variable is around, there is a strong reference to the node, so it won't be deallocated. Also the SKPhysicsContact object itself will retain a reference to the physicsBody, which has a reference to the node which I think will also prevent allocation.

我错过了明显的吗?所以即使在removeFromParent之后,精灵仍然存在。但是,它可能是因为我已将节点分配给临时SKSpriteNode变量,然后只要该变量存在,就会对该节点有强引用,因此不会释放该节点。此外,SKPhysicsContact对象本身将保留对physicsBody的引用,该对bodyBody具有对我认为也将阻止分配的节点的引用。

Update

To see when a sprite is actually released, use the deinit() method:

要查看sprite实际发布的时间,请使用deinit()方法:

deinit {
    print("Invader of type \(type) deinitialised")
}

I think this can only be added in a subclass definition, not via an extension.

我认为这只能添加到子类定义中,而不能通过扩展名添加。

Having a variable with a strong reference to the node being removed will prevent the node from being de-allocated until that variable is itself removed or changed to refer to something else.

拥有一个对要删除的节点的强引用的变量将阻止该节点被解除分配,直到该变量本身被删除或更改为引用其他内容。

#2


1  

If I've understand your question, I think it's not needed because you can always do:

如果我理解你的问题,我认为不需要,因为你可以随时做:

if let myNode = self.childNode(withName: "//myNode") {
   // ok myNode exist
}

Hope it helps you, you can write this code wherever you think is necessary.

希望它对您有所帮助,您可以在您认为必要的地方编写此代码。

Update:

About the reformulation of your question take a look below to these comments.

关于你的问题的重新制定,请看下面这些评论。

#3


1  

I have a suggestion after reading through the comments... move the node to a place outside of the playable area of your game, then remove it from parent. At this point you don't have to worry about when the physics body gets removed or when SK handles it. Or you could set the physicsBody? to nil at the same time, or use a bitmask flag as KoD suggested.

阅读评论后我有一个建议...将节点移动到游戏可玩区域之外的位置,然后将其从父级移除。此时,您不必担心物理主体何时被移除或SK何时处理它。或者你可以设置physicsBody?同时为零,或者使用像KoD建议的位掩码标志。

You can override all of the functions in the SK loop and check to see exactly when your pb is removed: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html

您可以覆盖SK循环中的所有函数,并检查您的pb被删除的确切时间:https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html

#1


2  

Am I missing the obvious? So even after removeFromParent the sprite is still around. However, it might well be because I have assigned the node to a temporary SKSpriteNode variable, then as long as that variable is around, there is a strong reference to the node, so it won't be deallocated. Also the SKPhysicsContact object itself will retain a reference to the physicsBody, which has a reference to the node which I think will also prevent allocation.

我错过了明显的吗?所以即使在removeFromParent之后,精灵仍然存在。但是,它可能是因为我已将节点分配给临时SKSpriteNode变量,然后只要该变量存在,就会对该节点有强引用,因此不会释放该节点。此外,SKPhysicsContact对象本身将保留对physicsBody的引用,该对bodyBody具有对我认为也将阻止分配的节点的引用。

Update

To see when a sprite is actually released, use the deinit() method:

要查看sprite实际发布的时间,请使用deinit()方法:

deinit {
    print("Invader of type \(type) deinitialised")
}

I think this can only be added in a subclass definition, not via an extension.

我认为这只能添加到子类定义中,而不能通过扩展名添加。

Having a variable with a strong reference to the node being removed will prevent the node from being de-allocated until that variable is itself removed or changed to refer to something else.

拥有一个对要删除的节点的强引用的变量将阻止该节点被解除分配,直到该变量本身被删除或更改为引用其他内容。

#2


1  

If I've understand your question, I think it's not needed because you can always do:

如果我理解你的问题,我认为不需要,因为你可以随时做:

if let myNode = self.childNode(withName: "//myNode") {
   // ok myNode exist
}

Hope it helps you, you can write this code wherever you think is necessary.

希望它对您有所帮助,您可以在您认为必要的地方编写此代码。

Update:

About the reformulation of your question take a look below to these comments.

关于你的问题的重新制定,请看下面这些评论。

#3


1  

I have a suggestion after reading through the comments... move the node to a place outside of the playable area of your game, then remove it from parent. At this point you don't have to worry about when the physics body gets removed or when SK handles it. Or you could set the physicsBody? to nil at the same time, or use a bitmask flag as KoD suggested.

阅读评论后我有一个建议...将节点移动到游戏可玩区域之外的位置,然后将其从父级移除。此时,您不必担心物理主体何时被移除或SK何时处理它。或者你可以设置physicsBody?同时为零,或者使用像KoD建议的位掩码标志。

You can override all of the functions in the SK loop and check to see exactly when your pb is removed: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html

您可以覆盖SK循环中的所有函数,并检查您的pb被删除的确切时间:https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html