How does collision work with physicsServer2D objects?

Godot Version

Hi, I am using a PhysicsServer2D on a bullet hell project that I’m working to improve performance, and I managed to spawn bullets in the server, but I’m still very new to this and I have no idea how to make collision work.

  • How would I be able to detect when the bullet collides with a non-physicsserver object (for example, a bullet getting queue_free() after colliding with a bullet_killzone area2d)
  • How would I be able to detect when something collides with a bullet? (for example, the player losing HP after a bullet collided with it)

Here is the current code for my bullets :

extends Node2D

var object
var image

@onready var shape = RectangleShape2D.new()
@export var texture : Texture2D

var bulletPosition
var bulletRotation
var bulletSize
var bulletSpeed

var physicsServer
var renderServer

var direction



func _ready():
	
	direction = Vector2.RIGHT.rotated(deg_to_rad(bulletRotation))
	
	shape.size = Vector2(64, 64)
	physicsServer = PhysicsServer2D
	object = physicsServer.body_create()
	physicsServer.body_set_space(object, get_world_2d().space)
	physicsServer.body_add_shape(object, shape)
	
	var objectTransform = Transform2D(0, Vector2(bulletSize, bulletSize), 0, bulletPosition)
	physicsServer.body_set_state(object, PhysicsServer2D.BODY_STATE_TRANSFORM, objectTransform)
	
	physicsServer.body_set_mode(object, PhysicsServer2D.BODY_MODE_KINEMATIC)
	
	physicsServer.body_set_collision_layer(object, 2)
	
	renderServer = RenderingServer
	image = renderServer.canvas_item_create()
	renderServer.canvas_item_set_parent(image, get_canvas_item())
	renderServer.canvas_item_add_texture_rect(image, Rect2(-32, -32, 64, 64), texture)
	renderServer.canvas_item_set_transform(image, objectTransform)

func _physics_process(delta):
	
	bulletPosition += direction * bulletSpeed * delta
	
	var objectTransform = Transform2D(0, Vector2(bulletSize, bulletSize), 0, bulletPosition)
	physicsServer.body_set_state(object, PhysicsServer2D.BODY_STATE_TRANSFORM, objectTransform)
	renderServer.canvas_item_set_transform(image, objectTransform)

func _exit_tree():
	PhysicsServer2D.free_rid(object)
	RenderingServer.free_rid(image)

Thanks a lot in advance!!

I’m curious to why spawning physics bodies and canvas items manually, in GD script, is going to improve performance? Traditional scene spawning will do this all for you in native code.

If you want to improve performance you need to use a GPUparticle node with collision detection enabled and a sub_emitter for collision effects.

Anyway to answer your question _body_set_sync_state_callback

This will notify you when there is a change and will return a physicsDirectBodyState2d to the callback function. This will allow you to manage all the collision information manually.

1 Like

Thank you so much! As to why I’m using a physics server, I don’t really know tbh I thought it improved performance for the bullets to be managed by it?? Idk I’ll have to do more research

The only thing I think it would avoid is having nodes in the scene tree. Which I’m not sure is that much of a save compared to the number of interactions in GD script here.

I was thinking about GPUparticles and I’m not sure how to get the collision info back. There other option is a compute shader. But that would require you to develop your own physical checks.

Anyway I watched this a while back can’t remember what they did.

So I really wish I could get more into what is the best approach to improve performance, and I will definitely do so later, but this project is for a game jam that ends monday, so I dont really have time to learn and implement a new method that I currently know nothing about.
In the meantime, im unsure what to do with _body_set_sync_state_callback? Ive done a bit of research but couldnt find anything that was talking about it in the godot documentation, and i dont really know how to implement it into my code?

I was looking at the source code on it. It is basically a signal connecting function. Pass it an rid and a callable func. The callable requires one parameter. (Which is a physicsdirectbodystate.)

If you watch the video he uses a resource pooling technique and he turns off collisions for the bullets and uses a raycast quarry to do bullet collision.

I think you could just set a collision layer on the bullet and turn off the mask to get a similar efficiency. Then just have objects that are collidable mask the bullet layer. (Untested, but it seems that is what the physics quarry is all about.)

Oh my bad that function is in the PhysicsServer2d Extension API only

Oh god now im even more confused. I think ill look into queries because like you said, that seems to be what they used in the 10000 bullets video