我正在玩一些SpriteKit的东西。我对SpriteKit
很新,所以我的技术可能不好,我不知道。这就是我正在做的事情:
它基本上是一个带盾牌的宇宙飞船(2D,从上方看)。有几个“盾牌段”(左,右,上,下,每一个是SKShapeNode
),然后有“移相器”node
s,这些是从边框到中心的线条。装置(宇宙飞船在中心)。我想检测相位器何时击中其中一个屏蔽段。我尝试使用collisionMasks,但它根本不起作用。所以我尝试了自己的检测方式。
接下来,我绘制相位器的方法可能看起来很奇怪。我在网上搜索但是没找到任何东西,真的。因此,我绘制移相器的方法是不断地用每个帧的稍长路径替换phaser node
(一条直线)的路径。
这是执行此操作的方法,也会导致应用崩溃:
incomingPhasers
是一个包含场景中当前所有Phaser
个对象的数组。 Phaser
类主要包含名为SKShapeNode
的{{1}}和其他一些元信息。
通过稍微增加node
属性来完成移相器进度的推进。 delta是自上一帧以来的时间差(因为此方法是从progress
update(_:)
是用于线条绘制的位移矢量。
let vector
当我向阵列添加许多移相器时, private func advancePhasers(_ delta: TimeInterval) {
for phaser in incomingPhasers where !phaser.targetHit {
// advance progress of phaser
phaser.progress = min(phaser.progress + CGFloat(delta) * phaser.progressRate, 1)
let vector = phaser.origin.vector(toPoint: phaser.target, fraction: phaser.progress)
// create new path
let path = UIBezierPath()
path.move(to: phaser.origin)
path.addLine(to: phaser.origin + vector)
phaser.node.path = path.cgPath
// check collision
let phaserPoint = path.currentPoint
enumerateChildNodes(withName: "shieldSegment", using: { (node, stop) in
if let node = node as? ShieldSegmentNode {
if node.contains(phaserPoint) {
// collision
phaser.targetHit = true
}
}
})
}
}
会导致应用崩溃:
*由于未捕获的异常'NSGenericException'而终止应用程序,原因:'* 集合< __ NSArrayM:0x17404ce40>在被列举时被突变。'
我不知道我能在这做什么。我必须循环屏蔽段节点,但这会不断崩溃。
这是否与线程安全有关?我需要让它安全吗?如果是这样,怎么样?
谢谢!
如果您需要更多信息或代码,请告诉我。我不能在这里发布所有内容,代码太多了。
答案 0 :(得分:2)
在枚举时,您不能在集合中变异(更改,添加或删除项目)。很难通过代码中的更多细节告诉您如何修复它的更多信息。有些事情是在这里改变集合:
enumerateChildNodes(withName: "shieldSegment", using: { (node, stop) in
if let node = node as? ShieldSegmentNode {
if node.contains(phaserPoint) {
// collision
phaser.targetHit = true
}
}
})
我解决这些问题的一种方法是我有第二个用于将项目放入符合我所需标准的集合,然后在第一次枚举之后,我可以枚举第二个集合并对第一个集合执行必要的变异