ios – 奇怪的SpriteKit For Loop Bug

我遇到了一个我无法弄清楚的非常奇怪的错误.在我的游戏中,你驾驶一辆2D飞机上的汽车试图避开障碍物(如岩石或汽车).障碍可以出现在3条不同的路径上.有时在任何路径上只有一个障碍物,或者有时在三条路径中的两条路径上存在两个障碍物.

我遇到的问题是,当两个障碍出现然后当它们离开屏幕时被删除时,屏幕上当前移动的障碍之一也被“删除”(我知道这是因为控制台打印“已删除的对象”3次).但是,随机“删除”的障碍不会从视图中删除.相反,它冻结了以前的地方,永远不会消失.

这是我遇到问题的代码块:

var canGetScore = true
for (num,obj) in enumerate(obstaclesToMove) {
    obj.position.y -= CGFloat(gameSpeed)
    if obj.position.y <= userCar.position.y && obj.name == "NotPassed" {
        obj.name = "Passed"
        if canGetScore {
            canGetScore = false
            score += 1
            scoreLabel.text = "\(score)"
        }
    }
    if obj.position.y <= -CGRectGetMidY(self.frame) {
        obj.removeFromParent()
        obstaclesToMove.removeAtIndex(num)
        println("deleted object")
    }
}

变量键:

>“barriersToMove”是一系列障碍物(SKSpriteNodes),应该向下移动到屏幕上.
>“gameSpeed”是屏幕每帧移动多少像素的整数(在此实例中值为5).
>“userCar”是用户控制的字符(SKSpriteNode).

“canGetScore”的目的是消除我之前遇到的另一个错误.我知道这不是导致我当前的错误.

有没有人知道为什么会这样?如果您需要更多解释,请询问.

额外注意:用户的汽车技术上从不移动,但背景和障碍物移动.

最佳答案 在我看来,问题在于如何从obstoToMove中删除你的对象

想象一下,你的数组中有三个对象:

obstaclesToMove = [object1, object2, object3]

你必须删除对象1& 2,因为它们必须离开屏幕,所以你在代码中做的是首先删除对象1然后删除对象2,除了在你的代码中它转换为:

obstaclesToMove.removeAtIndex(0)
obstaclesToMove.removeAtIndex(1)

您会认为这不是问题,除非您在执行此操作时查看阵列会发生什么:

obstaclesToMove = [object1, object2, object3]
obstaclesToMove.removeAtIndex(0)
// obstaclesToMove = [object2, object3]
obstaclesToMove.removeAtIndex(1)
// obstaclesToMove = [object2]

通常,从正在循环的数组中删除对象是个坏主意.你可以做些什么让它更安全:

>收集数组中需要删除的所有索引
>按相反顺序对它们进行排序
>从数组中删除项目

你可以这样做:

var indexToDelete: [MyObstacleObject] = []
var canGetScore = true
for (num,obj) in enumerate(obstaclesToMove) {
    obj.position.y -= CGFloat(gameSpeed)
    if obj.position.y <= userCar.position.y && obj.name == "NotPassed" {
        obj.name = "Passed"
        if canGetScore {
            canGetScore = false
            score += 1
            scoreLabel.text = "\(score)"
        }
    }
    if obj.position.y <= -CGRectGetMidY(self.frame) {
        indexToDelete.append(num)
    }
}

indexToDelete.sort({ $0 > $1 })

for item in indexToDelete {
    obstaclesToMove[item].removeFromParent()
    obstaclesToMove.removeAtIndex(item)
    println("deleted object")
}

这样,当您从阵列中删除项目时,您可以确保它们仍然具有正确的索引,因为您将首先删除具有更高索引的项目.

点赞