I have been making a top down shooter for a few days but have been plagued with weird collisions on these fast moving bullets. sometimes bullets will just go through something but will still collide, just after it's fully inside of the hitbox. I set the hitbox of the bullets to be slightly in front of the bullet sprite itself but that has only slightly helped. any methods for better collisions? the bullet itself is just a character body 2d with an area 2d attached that deletes itself when it enters a hitbox or some other collision body.
#better collisions for fast moving projectiles?
1 messages · Page 1 of 1 (latest)
"bullet through paper" problems like these are unavoidable with raw physics and very fast-moving-objects. One solution would to shoot a raycast (or shapecast if your bullets are very big) forward from the bullet every physics step, check if there's anything the bullet would collide with next frame, and then move the bullet to the collision spot that physics step instead of fully inside the hitbox
Godot Engine documentation
Hereda: Node2D< CanvasItem< Node< Object A ray in 2D space, used to find the first collision object it intersects. Descripción: A raycast represents a ray from its origin to its target_pos...
okay, got it. in my code, if I want to set the velocity to make sure that it will stop ahead of the raycast's collider, how would I code that? this is what I have so far.
actually made a mistake in the target pos code, meant to make it just change the x value not the whole vector
Idk if a 2D raycast's target position is global, but if it isn't you should change it to:
raycast.target_position = to_local(global_position) + velocity * delta
updated my code again, here's what I have so far. the reason for the abs() was because the raycast was only ever pointing in the +x direction for some reason. it kind of works, but for some reason you can still see the bullet entering the object and not stopping in front of it.
Do you still have tunneling issues?
here's it now
after I changed the code
also I didn't show it but it's a lot more apparent when shooting at actual enemies
I realize you aren't calling on_hit() when the raycast is colliding, how is the hit detection working right now?
Oh you are using an area hitbox
You can just call on_hit() and pass in the collider when the raycast is colliding
true
i tested that and it works but the bullet looks like it's stopping way before whatever it's hitting
which isn't a huge deal since ill probably add impact effects later but still
So i actually do my project's projectiles differently; they hold a prev_pos variable, and instead of raycasting ahead, it raycasts from the prev_pos to the current_pos
prev_pos just being the position the bullet was the previous frame
I think that would get rid of the bullets looking like they collide early
okay, ill try that
You can make sure prev_pos holds the last frame's position by updating it last in physics_process, and having your functions run before it
yes but i realize you can get rid of current_pos as a variable and just use global_position
and make sure to use to_local() for the target_position
now it just wont collide with anything
try making the raycast top_level
still nothing
kinda weird, can't even see the raycast even though I have visible collision shapes enabled
probably just cause it's too small or something
scratching my head rn
i feel like it has something to do with the raycast's local position and converting its global_position locally
maybe
just tried "raycast.to_local" but still nothing
weidly it looked like the raycast was just firing up for a second
i'll send you my projectile script, it's 3D but you should be able to convert it
somehow prev pos and global position are the same
just did some print statements and both are the exact same
doesn't look like it changed anything
looking and comparing both scripts i'm not sure why prev_pos is not updating late for you
yeah idk
i understand ur code and it honestly looks like it would have the exact same functionality
try storing all the raycast related code into a single function, like handle_ray()
okay
did that and it looks like the positions are different
however still not colliding with anything somehow
you could try using the physics server instead of a raycast
i suspect it's some jank with the raycast's position inheriting the projectile's and how it's being updated constantly in physics_process
using the physics server would mean just checking between two positions
how big is the difference between prev_pos and global_position?
the positions with no name are the global
yea that seems like its working wtf
is the ray being blocked by the projectile's body? since its a characterbody
nah, it doesnt have a collision shape
okay then
im gonna leave this here for now and just set up the old system again
i feel like im losing my mind
i was literally watching other top down shooters have fast moving projectiles with collisions that dont suck
it feels like it should be pretty easy but whatever
Rigidbody2D has continuous collision detection support that should handle this out of the box. However, I don't see an option for that on CharacterBody2D. Is there a reason you require that particular class for your projectiles?
The docs for the continuous CD are here:
Godot Engine documentation
Inherits: PhysicsBody2D< CollisionObject2D< Node2D< CanvasItem< Node< Object Inherited By: PhysicalBone2D A 2D physics body that is moved by a physics simulation. Description: RigidBody2D implement...
@inner lantern @sterile wolf just wanted to update this to say I have found an okay solution right now. I used the raycasting method to get more accurate collisions however visually the bullet stops much before whatever it's going to hit. To answer your question, the reason it was a character body was because I was originially using the move and slide function to move the bullet, although now I don't use that for movement. I would use rigid bodies, but arent they expensive to instantiate / have lots of in the scene?
Yea, there will be a cost to using rigidbodies. If they are set to collide with nothing, (just relying on raycasting for collisions) you can avoid the cost of physics calculations, but if each projectile is a node you'll only be able to handle id say 50-200 projectiles at once at an acceptable framerate
If you're going for a bullet hell style amount of projectiles, (1000+) id make a ProjectileManager class that will make each projectile just some data (position, velocity, transform) and update them in a for loop
Im not super sure if it's gonna be a bullet hell kind of game, was more aiming for something like hotline miami or otxo
If there won't be many projectiles at once, your implementation will work just fine💯
Alr