2017-06-13 8 views
0

私はいくつかのSpriteKitのことを考えています。私はかなりSpriteKitに新しいですので、私の技術が悪いかもしれない、私は知らない。ここに私が取り組んでいることがあります:SpriteKit - enumerateChildNodeにより、 "配列が列挙されている間に配列が変更されました"というクラッシュが発生します。

基本的にシールド付きの宇宙船(2D、上から見た)です。いくつかの "シールドセグメント"(左、右、上、下、それぞれがSKShapeNodeです)があり、次に "phaser" nodeが境界線からデバイスの中心まで描かれた線です(宇宙船はセンター)。フェイザーがシールドセグメントの1つに当たったときを検出したい。私はcollisionMasksを使ってこれを試しましたが、まったく動作しませんでした。だから私は自分自身の検出方法を試みた。

次に、フェーザーを描く私の方法は奇妙に思えるかもしれません。私はオンラインで検索しましたが、何も見つかりませんでした。ですから、私がフェイザーを描画する方法は、各フレームより少し長いパスを使って、常にphaser node(直線)のパスを置き換えることです。

これを行い、また、クラッシュへのアプリの原因となる方法です。

incomingPhasersは、現在、シーン内のすべてのPhaserのオブジェクトを含む配列です。 Phaserクラスには、主にというnodeとその他のメタ情報が含まれています。

位相器の進歩は、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 

       } 
      } 
     }) 
    } 
} 

enumerateChildNodes Iは多くを追加するときにアプリケーションがクラッシュするので、デルタ時間差であります配列へのフェイザー:

* 'NSGenericException' キャッチされない例外によりにアプリを終了、理由:「*コレクション< __NSArrayM:0x17404c e40>を列挙しながら突然変異させた。 '

私はここで何ができるのか分かりません。シールドセグメントノードを循環させる必要がありますが、これはクラッシュし続けます。

これはスレッドの安全性と関係がありますか?それをスレッドセーフにする必要がありますか?もしそうなら、どうですか?

ありがとうございました!

これ以上の情報やコードが必要な場合は教えてください。私はここにすべてを投稿することはできません、あまりにも多くのコードです。

答えて

1

コレクションが列挙されている間、コレクション内のアイテムを変更(変更、追加または削除)することはできません。あなたのコードの詳細を修正する方法についてもっと詳しく教えてください。いくつかの事はここにコレクションを突然変異されています。私はこれらの問題を解決

enumerateChildNodes(withName: "shieldSegment", using: { (node, stop) in 
    if let node = node as? ShieldSegmentNode { 
     if node.contains(phaserPoint) { 

      // collision 
      phaser.targetHit = true 

     } 
    } 
}) 

一つの方法は、私は私の希望の条件に合うようにアイテムを入れるための第二のコレクションを持っているし、最初の列挙した後、私は上で列挙することができます2番目のコレクションと最初に必要な突然変異を実行

+0

ええ、何?これらは単に読み込みであり、唯一の書き込み操作は 'phaser.targetHit = true'です。しかし、私がそれを取り除いても、それはクラッシュします。私は見つけようとします。編集:それが空である場合でも、それはクラッシュします。それは変です – Quantm

+0

おそらく別のスレッドで別の場所に変異しているはずです –

+0

ええと、 'enumerateChildNodes'を使う場所は2つあります。しかし、私は別のスレッドでそれらを呼び出すことはありません。それらはすべて 'update(_ :)'の中から呼び出されます。これはメインのキューにありませんか? – Quantm

関連する問題