godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 92 forks source link

RigidBody(2D)s body_entered function to provide collision information #848

Open jgrauman0 opened 4 years ago

jgrauman0 commented 4 years ago

Describe the project you are working on: I am designing a multiplayer 2D Space shooter which extensively uses Normal Maps and Lights to achieve 2.5D.

Describe the problem or limitation you are having in your project: For example, when RigidBody2Ds collide, there is no way (that I've discovered) to figure out the energy of the collision to be able to determine damage done. There is no way to get the speed of a body immediate before and then after the collision to calculate the kinetic energy. It seems like since the physics engine has to update the speed of the bodies, that it should be able to provide signals to send this information.

Furthermore other information like the collision point and collision normal are difficult to access. In the _on_body_entered() function, I have to do a Physics2DTestMotionResult to do a new motion and see what the collision would be. This often results in slight (or large) errors because I am testing a new motion, not actually getting the collision point and normal for the motion that already happened that caused the signal to be sent. So if the bodies were moving very rapidly, they may have turned direction and the test motion may fail.

var p = Physics2DTestMotionResult.new()
if(test_motion(last_linear/10, false, 1.0, p)):
    var normal = p.collision_normal
    var point = p.collision_point

Describe the feature / enhancement and how it helps to overcome the problem or limitation: Ideally, the body_entered(Node body) function would simply provide another class with more information about the collision that caused the signal to be sent.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: I would suggest that the body_entered(Node body) function has another argument that provides additional information about the collision such as body_entered(Node body, CollisionInformation info). That class would have CollisionInformation.collision_normal, CollisionInformation.collision_point, CollisionInformation.collision_velocity_before, CollisionInformation.collision_velocity_after, CollisionInformation.collision_energy, etc. I'm totally fine if another way is made to access the information, but the information about the collision should be about the collision that caused the signal to report and include more information than is currently available (like collision energy).

If this enhancement will not be used often, can it be worked around with a few lines of script?: No. As far as I'm aware there is no way to access this information.

Is there a reason why this should be core and not an add-on in the asset library?: I don't believe it would be possible to add this in an add-on.

madmiraal commented 4 years ago

You should be able to extract this information from Physics2DDirectBodyState, which you can get through calling RigidBody2D's _integrate_forces() function.

jgrauman0 commented 4 years ago

I had tried that method. It might be able to work in a way. For a single collision you end up basically polling when there is contact, and so end up with lots of collision data points that you have to merge together into a single collision "event." It seems like body_entered() basically filters so that there is a single signal for each collision, so it would be nice if Godot also then merges that collision data together into a single 'event'. Hope that makes sense.

jgrauman0 commented 4 years ago

Also, looking at it further, you can sort of get linear_velocity and angular_velocity before and after a collision, but you aren't able to tell what changes in velocity are due to the collision and what are due to applied forces by the user. So actually it's really hard to tell how much force is being applied just from the collision. Looking at the godot source, I can see body_pair_2d_sw.cpp is where the collision forces are applied. It seems like it would not be too hard to add the forces applied to the contact function that gets sent to the callback for the signal, but at the moment Godot compiled fine, but by compiled version isn't running properly.

adorbabble commented 1 year ago

I’m having the same problem in a game where our player characters use RigidBody2Ds, and we would really need to have access to the collision points and normal vectors in the method attached to the BodyEntered signal. I have been trying to get the information in _IntegrateForces as suggested above, but I’m afraid that it is not going to work reliably and efficiently this way

I could also try to have a look at how to add this feature, but I don’t have much experience with C++

zhagsenkk commented 8 months ago

I also have this question. Is there any progress?

WebF0x commented 7 months ago

Not mine, but this opened PR seems to address this issue