You need to show the code for the physicsbody for the player as well as your didBegin(contact:)
. From what you're saying, it seems as though the player is colliding with the bullet, which it will do unless you take specific action to prevent it.
The bullet is created with the player's position so they are trying to occupy the same space. If you haven't switched off collisions between the player and the bullet then the player will collide with the bullet and be 'pushed' away - 'knocked back' as you put it. The bullet is unaffected because you have set the bullet's collisionBitMask
to only be the enemy.
To switch off collision between the player and the bullet without affecting anything else the player might collide it, you can use:
player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue
Edit:
(You're right - didBegin
not necessary for collisions)
You have an issue I think in defining the physicsBody for the bullet:
bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
bullet.size = CGSize(width: 40, height: 30)
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width / 2)
For the first 3 references to the bullet's physicsBody, you are using an optional (bullet.physicsBody?) which says "If the physicsBody isn't null, then do this... Except it will be null. You need the line that creates the physicsBody (the last line of the block above) to be the first line to actually create the physicsBody. Currently your categoryBitMask, collisionBitMask and contactTestBitMask aren't getting set for the bullet. although that should make the bullet 'collide' with and bounce off the player too.
Are you doing something similar for the player, as it certainly sounds as though collision detection is causing it to bounce off the bullet.
This might help - apologies if you know this stuff. : How to Detect collision in Swift, Sprite kit
and here's a small sample project with collisions: https://stackoverflow.com/a/43605825/1430420
Both answers are a few years old, so I hope they still work with the latest versions of iOS, SpriteKit and Swift.
Edit2:
Also I just noticed this :
bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
You are trying to give the bullet a category of enemy. Did you mean to? Although as the physicsBody for the bullet hasn't been set yet, this line of code has no effect.
What actually happens is that when you create the bullet's actual physicsBody, the default for the categoryBitMask is set to all 1s. (https://developer.apple.com/documentation/spritekit/skphysicsbody/1519869-categorybitmask) meaning it collides with everything. Then when you turn off collisions between the player and the bullet category:
player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue
the player and the bullet still collide because you've switch off collisions between player and physicsBodies with a category of only bullet, but bullet's physicsBody has a category of eveything i.e. player's collisionBitMask is:
11111111111111111111111111111101 (assuming the enemy category is 2)
and bullet's bitMask is:
11111111111111111111111111111111 because you haven't changed it after creating the physicsBody.
When you moved the definition of bullet's physicsBody to before the bitMask settings, then you have the situation where player's collisionBitMask is still:
11111111111111111111111111111101 (assuming the enemy category is 2)
but bullet's collisionBitMask is now:
00000000000000000000000000000100 (assuming your enemy category is 4), because you gave bullet's physicsBody category BitMask enemy's category, and they still collide because bit 2 is 1 in both bitmasks.