queue_free(), so the object finishes it's own processing. But you also need to work the other way around—objects referencing other objects should check that the object still exists before trying to do things with it. If you get crashes, try checking if the
object != null, or if
object.is_inside_tree() before using it.
I've also had issues with collisions and different scripts running on process and fixed process. Apparently objects queue freed during process can still register a collision in the next fixed process, but by that time the object is already gone, so any attempt to, say,
get_contact_collider_object() will cause a crash. Not sure how that's possible, but fortunately it was easy enough to fix by running both scripts on fixed_process.