2017-01-31 2 views
3

Я пытался добавить контакт делегата на мой GameScene:Почему SKPhysicsContactDelegate на отдельный класс не вызывается

self.physicsWorld.contactDelegate = ContactManager() 

Однако, я делаю это, имея контакт делегата (ContactManager класс) на отдельный класс, чтобы не иметь столько кода на моей GameScene. Это мой контакт делегат:

class ContactManager : NSObject, SKPhysicsContactDelegate { 

    func didBegin(_ contact: SKPhysicsContact) { 
     print("they touched!") 
    } 

} 

Проблема заключается в том, что, когда объект 1 сталкивается с объектом 2 не запускается метод didBegin(). Однако я знаю, что проблема не в битах, потому что я сделал GameScene наследованием SKPhysicsContactDelete и установил делегат для себя, а метод didBegin() работал. Поэтому проблема заключается в том, что класс ContactManager() не правильно связывается, как я могу убедиться, что менеджер контактов в отдельном классе из GameScene работает?

+1

ничего не сохраняет 'ContactManager' так, как только вы выходите из функции, становится нулевой – Knight0fDragon

+1

вам нужна глобальная переменная в вашей сцене:' частный пусть ContactManager = ContactManager() ' , затем установите 'self.physicsWorld.contactDelegate = contactManager' – Knight0fDragon

+1

Только один объект может быть установлен как делегат мира физики. Поэтому, если вы установите self.physicsWorld.contactDelegate = contactManagerInstance, а позже в своем коде вы снова установите его на себя (где self - это сцена), только сцена получит оповещения о контактах. Таким образом, вы можете либо прослушивать сцену для контактов, либо ContactManager. Так что в основном делайте то, что сказал Knight0fDragon, создайте свойство и назначьте его делегатом-контактом. – Whirlwind

ответ

2

contactDelegate на SKPhysicsWorld является unowned(unsafe), что означает, что она не будет увеличивать счетчик сохранить, и не будут рассматриваться в качестве опции.

Это означает, что вы несете ответственность за сохранение любого объекта, который вы помещаете в эту переменную.

В вашем коде self.physicsWorld.contactDelegate = ContactManager() Вы устанавливаете делегат контакта как локальную копию ContactManager. Так как ничего не удерживает это, он будет немедленно отброшен, потому что счет сохранения установлен в 0.

Именно по этой причине в большинстве случаев люди используют self в качестве делегата, потому что вам гарантировано, что существует self.

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

class Example : SKScene 
{ 
    let contactManager = ContactManager() 
    func someKindOfSetup() 
    { 
    self.physicsWorld.contactDelegate = contactManager 
    } 
} 

Источник: https://developer.apple.com/reference/spritekit/skphysicsworld/1449602-contactdelegate

+0

И в этом случае было бы полезно упомянуть, что пример должен быть подклассом SKScene. @ Knight0fDragon, вы знали, что мы * можем * подкласс SKPhysicsWorld? Я не знаю, может ли быть какое-то использование этого факта ... Кроме того, в документах нет упоминания о том, что этот класс не должен быть подклассом (например, он указан для классов SKTexture или SKAction). Или, может быть, я не заметил эту часть в docs ... – Whirlwind

+0

@Whirlwind они говорят, что не подкласс SKView тоже, но я делаю это так или иначе – Knight0fDragon

1

По Вихрь:

только один объект может быть установлен в качестве делегата от мира физики. Поэтому, если вы установили self.physicsWorld.contactDelegate = contactManagerInstance, а затем в свой код, вы снова установите его на себя (где self - это сцена), только сцена получит оповещения о контактах. Таким образом, вы можете либо прослушивать сцену для контактов, либо ContactManager. Поэтому в основном делайте то, что сказал Knight0fDragon, создайте свойство и назначьте его делегатом-контактом.

+0

Не знаю, я только установил контактDelegate один раз. Я упомянул оба сценария, но они оба происходят независимо. Я устанавливаю self.physicsWorld.contactDelegate один раз, независимо от того, является ли он сам или классом ContactManager, он выполняется один раз. Я сделал это ради тестирования. – Pablo