Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do SKPhysicsContactDelegate on a separate class is not being called

I have been trying to add a contact delegate to my GameScene:

self.physicsWorld.contactDelegate = ContactManager()

However, I am doing this by having the contact delegate (ContactManager class) on a separate class, to avoid having that much code on my GameScene. This is my contact delegate:

class ContactManager : NSObject, SKPhysicsContactDelegate {

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

}

The problem is that when object 1 collides with object 2 it does not run the method didBegin(). However, I know the problem is not the bitmasks because I made the GameScene inherit the SKPhysicsContactDelete and set the delegate to self and the method didBegin() worked. So the issue is that the class ContactManager() is not linking up correctly, how can I make sure the a contact manager on a separate class from the GameScene works?

like image 976
Pablo Avatar asked Jan 31 '26 14:01

Pablo


2 Answers

contactDelegate on SKPhysicsWorld is unowned(unsafe), which means that it will not increase the retain counter, and will not be treated as an optional.

This means that you are responsible for retaining whatever object you place into this variable.

In your code self.physicsWorld.contactDelegate = ContactManager() You are setting the contact delegate to be a local copy of ContactManager. Since nothing is retaining this, it will immediately be discarded because the retain count is set to 0.

This is the reason why in most cases, people use self as the delegate, because you are guaranteed that self exists.

To remedy this situation, make sure you have a property that retains your ContactManger so that you do not lose it upon creation.

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

Source: https://developer.apple.com/reference/spritekit/skphysicsworld/1449602-contactdelegate

like image 184
Knight0fDragon Avatar answered Feb 03 '26 06:02

Knight0fDragon


As per Whirlwind:

Only one object can be set as a delegate of a physics world. So if you set self.physicsWorld.contactDelegate = contactManagerInstance, and later in your code you set it again to self (where self is a scene), only the scene will receive contact notifications. So you can either have a scene listening for the contacts or the ContactManager. So basically do what Knight0fDragon said, make a property and set it to be a contact delegate.

like image 37
Fluidity Avatar answered Feb 03 '26 05:02

Fluidity