如何安全地从 NSMutableSet 中删除对象 (cocos2d-iphone)

发布于 2024-09-12 17:22:48 字数 948 浏览 6 评论 0原文

我对严肃的编程相当陌生,所以请原谅我的愚蠢,但我自己没能弄清楚这一点。

我正在用 cocos2d-iphone 编写一个游戏。我有一个场景对象,其 ivars 中有多个 NSMutableSets - 单位、建筑物、火箭等。我在从这些 NSMutableSets 中删除对象时遇到问题。当子弹对象被初始化时,它会像这样搜索应该损坏的目标:

...
for ( RXUnit * unit in targetSet ) {
    if ( ccpDistance( unit.position, rayPoint ) < 20 ) {
    ... 
    [unit damageSelfBy:damage];
    ...
    }
}
...

如果单位没有足够的 HP 来维持,则 [unit DamageSelfBy:damage] 方法会杀死该单位损害。除其他外,它还执行以下操作:

[scene.units removeObject:self];

(scene.units 与上面循环中的 targetSet 是相同的 NSMutableSet)

每当使用此行时,从集合中删除单位时发射的子弹无法正确初始化。项目符号 init 方法执行到上面所示的 for 循环(是的,该单元确实被前一个项目符号损坏并移除),但 init 方法中此循环之后的任何其他内容都不会执行。

令人惊讶的是,应用程序继续正常运行,除了卡住的子弹之外没有任何可见的影响。控制台不显示任何警告/错误,编译时也没有警告。

我还尝试通过将实际的删除代码放入场景的更新方法中来延迟单元从集合中删除的时间,但这没有帮助。

我想我可以做一些丑陋的黑客来隐藏这个问题,但我相信它稍后会咬我的屁股。好吧,我真的很想了解发生了什么以及如何正确解决它。

非常感谢任何帮助/想法。也许我什至不应该将游戏对象存储在 NSMutableSets 中?

I'm rather new to serious programming, so please forgive my dumbness, but I've failed to figure this out by myself.

I am writing a game with cocos2d-iphone. I have a scene object with several NSMutableSets in its ivars - units, buildings, rockets, etc. I have a problem removing objects from these NSMutableSets. When a bullet object is init-ed it among other things searches for a target that it should damage like this:

...
for ( RXUnit * unit in targetSet ) {
    if ( ccpDistance( unit.position, rayPoint ) < 20 ) {
    ... 
    [unit damageSelfBy:damage];
    ...
    }
}
...

The [unit damageSelfBy:damage] method kills the unit if it does not have enough HP to sustain damage. Among other things it does this:

[scene.units removeObject:self];

(scene.units is the same NSMutableSet as targetSet in the loop above)

Whenever this line is used, the bullet that was shot at the time the unit is being removed from the set fails to init properly. The bullet init method executes up to the for loop shown above (yes, the unit does get damaged and removed by previous bullet), but anything else that goes after this loop in the init method is just not executed.

Surprisingly, the application continues to run normally with no visible effects apart from that stuck bullet. Console does not show any warnings/errors, there are no warnings when compiling either.

I also tried delaying the time the unit is removed from the set by putting the actual removal code in the scene's update method, but that does not help.

I think I can make some ugly hacks to hide this problem, but I'm sure it will bite me in the ass later. And well, I would really like to understand what is going on and how to properly address it.

Any help/ideas are much appreciated. Maybe I shouldn't even store game objects in NSMutableSets?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独夜无伴 2024-09-19 17:22:48

set 容器是对象的唯一引用吗?如果您在运行对象的方法时释放对象,我不确定是否存在已定义的行为。您可能需要将其标记为“死亡”,然后执行清理步骤。

Is the set container the only reference to the object? I'm not sure that there is a defined behavior if you dealloc an object while you're running its methods. You may need to mark it as "dead" and then do a cleanup step afterward.

未蓝澄海的烟 2024-09-19 17:22:48

如果您从集合中删除该对象,并且该集合是对该对象的唯一引用,则该对象可以立即被释放。想一想:您正在运行其方法的对象可能立即消失。这很糟糕™。

这就是为什么你的延迟删除有效;这不是一个诡计。您需要等待,直到使用完该对象,然后删除它。不过,有一个比您的 objectsToRemove 技巧更好的方法:

[self retain];
[self autorelease];
[scene.units removeObject:self];

autorelease 将导致在运行循环时将延迟的 release 消息发送到您的对象完成,因此通过使用 retain,然后使用 autorelease,可以防止对象在从 scene.units 中删除后消失。

If you remove the object from the set, and that set is the only reference to the object, then the object could be deallocated right then. Think for a second: the object whose methods you're running could disappear right now. That's Bad™.

That's why your delayed removal works; it's not a trick. You're waiting until you've finished using the object, then you're deleting it. There's a better way, though, than your objectsToRemove trick:

[self retain];
[self autorelease];
[scene.units removeObject:self];

autorelease will cause a delayed release message to be sent to your object when the run loop finishes, so by using retain, then autorelease, you prevent the object from disappearing the second it's removed from scene.units.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文