2016-05-01 3 views
2

Я пытаюсь обнаружить столкновения между узлами, которые раньше не сталкивались в моей игре SpriteKit, вызывая node.hash и сохраняя новые узлы в наборе. Я вижу, что через некоторое время новые узлы имеют тот же хеш, что и узлы, которые я ранее называл node.removeFromParent() on.SpriteKit: Хеширование переработанного SKShapeNode

Я предполагаю, что, поскольку я удаляюсь из родителя и снова создаю очень похожие узлы снова и снова, SK автоматически перерабатывает некоторые узлы.

Как я могу получить по-настоящему уникальный хэш из узлов в SpriteKit?

Пожалуйста, дайте мне знать, если потребуется дополнительное разъяснение. Я чувствую, что размещение моего кода не будет слишком актуальным для этого сообщения.

Кроме того, я не могу воспроизвести эту проблему, когда я отлаживаю свой телефон, подключенный к xcode, но я добавил журнал, который показывает, что node.hash не уникален для вновь созданных узлов. Кто-нибудь знает, почему поведение по переработке будет отличаться от моего телефона, подключенного к Xcode?

+0

Одним из решений может быть расширение SKShapeNode и добавление переменной hasCollided, но я чувствую, что это чрезмерное проектирование, что можно сделать проще с помощью правильного метода хэширования. – shivsta

+0

Когда вы говорите «по-настоящему уникальный», вы имеете в виду содержание (что представляют узлы) или вы можете просто использовать указатели экземпляра как значение хэширования? Извинения за незнание SpriteKit. – xtravar

+0

Я тоже не слишком знаком с SK. Содержимое каждого из узлов является таким же. Я считаю, что хеш-функция просто возвращает пятно узла в памяти, которое используется повторно. Я работал вокруг этого за раз, удаляя хэш узла из набора непосредственно перед его уничтожением. Но мне все же хотелось бы знать, есть ли способ получить другое значение хэша для каждого экземпляра SKShapeNode. – shivsta

ответ

3

Я думаю, вы можете не понимать, что такое хэш и что делает.

Хэш не обязательно является уникальным значением. Это односторонняя функция (не обязательно криптографическая), которая принимает произвольные данные и дает значение. Если одни и те же данные хэшируются более одного раза, он будет выдавать одно и то же значение хэша, а не другое значение.

Работа против вас, однако, является тот факт, что значение .hash является не криптографический хэш (который несколько интенсивных вычислений). Качество хэш-функции, криптографической или нет, основано на том, как часто встречаются столкновение хешей . Столкновение хэшей возникает, когда два значения различают значения, выдает тот же хэш.

Криптографические функции хэширования, среди прочего, выбираются из-за низкой скорости столкновения хэшей. Функция .hash может иметь высокую скорость столкновения, даже если ваши данные различны, в зависимости от ваших конкретных данных.

Гораздо лучшим решением является добавить свойство для ваших узлов, которые могут быть легко проверены:

class MyNodeClass: SkShapeNode { 
    var hasCollided = false // Publicly accessible property 
} 

Я заметил, что в других комментариях вы говорите, «Я интересно найти правильный хэш.» Я бы настоятельно рекомендовал против этого подхода, так как, опять же, функции хэша определенно будут иметь вычислительную нагрузку. Чем лучше функция, тем выше такая нагрузка.

Если вы действительно ищете уникальный идентификатор для каждого узла (а не отслеживания конфликтов), то почему бы не реализовать внутреннее свойство, которое инициализируется из инициализатора на основе значения класса, которое просто создает уникальный, увеличивающий Я БЫ?

0

Если вы правильно поняли, вы пытаетесь определить, столкнулись ли вы с новыми объектами. Вы можете просто создать собственный объект SKShapeNode с помощью свойства boolean. Это избавит вас от необходимости сталкиваться с сталкивающимися хэшами и вместо этого даст надежный метод проверки того, был ли обработан узел.

class CustomShapeNode: SKShapeNode { 
    var hasAlreadyCollided = false 

    // Any required overidden methods 
} 
+0

Да, я пытаюсь столкнуться с новыми объектами. Как я уже сказал выше, это вариант для обойти это, но я решил пойти с другим обходом: я удаляю узел из набора прямо перед его удалением. Мне все еще интересно, почему метод .hash не работает, и мне интересно найти правильный хеш. – shivsta

1

SKNode использует реализацию по умолчанию NSObject «s из hash который просто возвращает адрес памяти

import Foundation 
import SpriteKit 

let node = SKNode() 
let hex = String(node.hash, radix:16) 
let addr = unsafeAddressOf(node) 

print(hex) // 7f9a21d080a0 
print(addr) // 0x00007f9a21d080a0 

Так в основном, один раз в ячейку памяти используется повторно, значение хеш-функции не собирается быть уникальным. Вероятно, разница между поведением в отладке связана с оптимизацией компилятора.

Чтобы получить уникальный хеш, вам необходимо переопределить метод hash вашего SKNode и вернуть ему что-то действительно уникальное. Простая стратегия будет назначить каждый узел в id свойство при создании чего-то вроде

class MyNode : SKNode { 
    var uid:Int 

    init(uid:Int) { 
     self.uid = uid 
     super.init() 
    } 

    override var hash:Int { get { 
     return self.uid 
    }} 

    required init(coder aDecoder: NSCoder) { 
     fatalError("not implemented, required to compile") 
    } 
} 

Если начать счетчик выключены на Int.min и увеличить его в стороне Int.max вам придется создать 18,446,744,073,709,551,613 узлов, прежде чем запускать из единственности ,

+1

Педантичность: Swift.Int изменяет размеры на разных платформах. :) Но да, возможно, не будет создано даже 2 триллиона объектов. – xtravar

+0

+1 @xtravar Хорошая уловка, да. Это предполагает 2^64-1 возможных значений, тогда как на некоторых аппаратных средствах это действительно будет 2^32-1 –

Смежные вопросы