godot-proposals icon indicating copy to clipboard operation
godot-proposals copied to clipboard

Get impact force when a RigidBody hits another body

Open Wapit1 opened this issue 5 years ago • 9 comments

Describe the project you are working on: I have been working with physic game where the player hits a lot of body with held rigidbody and can't get more progress on the physic side of thing because of the lack of a consistant lightweight way of getting the impact force

Describe the problem or limitation you are having in your project: getting the impact force requires to constantly calculate the previous velocity, else you can't tell how fast the object hit one a other: the force is already reduce before you receive the signal and you thus get a very small number which isn't representative of the linear velocity before impact (due note that it 2D you have still a bit more force during the impact tick, but it is not that consistant, has it already lost a bit force )

Describe the feature / enhancement and how it helps to overcome the problem or limitation: having a consistant Vector of the impact strength will allow programmer to create easily system like sound of impact, realistic breakable object, multiplied knockback on rigidbody and other Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: having a parameter with the signal on_body_entered would allow the user to use it easily and should be , too my understanding of physics engine, not too hard to get has the physics engine already calculates the force being transferred to the other object so the number would only need to be exposed (and while your at it why not expose a few more value like the force lost in friction, the average of point of impact and the force a joint is applying to the rigidbody)

If this enhancement will not be used often, can it be worked around with a few lines of script?: It would be used often and can get worked around with a few line of code (keeping in a var the linear_velocity every tick), but it is required to be put on every rigidbody (has you want the force difference on impact for realistic result) and its is not that consistant, has the body might go through the object and then get pulled back

Is there a reason why this should be core and not an add-on in the asset library?: because having it has an add-on would be harder to implement and most developer would like the idea of easily have the possibility to have different impact sound based on impact strength, have damage dealt based on the force of the swinging weapon and thus be allowed to create loads of physic based emergent gameplay

Wapit1 avatar Feb 16 '20 14:02 Wapit1

I have yet to see the

the body might go through the object and then get pulled back

case, but having a built in function would definitely make having various impact related systems much easier (e.g. deforming a visual mesh on impact like I do in my little car game)

Zireael07 avatar Feb 16 '20 16:02 Zireael07

Is this related to https://github.com/godotengine/godot/pull/36008 ?

fire avatar Feb 24 '20 22:02 fire

Is this related to godotengine/godot#36008 ?

no, but I am always happy to see more physics control (I am personally waiting for active ragdoll - currently working with joint and ragdoll)

Wapit1 avatar Feb 24 '20 22:02 Wapit1

I linked the wrong pr. This is active ragdolls. https://github.com/godotengine/godot/pull/28909

fire avatar Feb 24 '20 22:02 fire

yes I am waiting for this PR (although it is a separate issue) my current project is so because of the lack of physics data and reliable active ragdoll having the player smash stuff with is floppy arms

Wapit1 avatar Feb 25 '20 01:02 Wapit1

Is this the same as #409? That feature request describes the ability to use RigidBody2D contact monitoring to get the collision impulse. *Edit: This FR appears to be for 3D, the one I linked is for 2D.

briansemrau avatar Feb 25 '20 03:02 briansemrau

If anyone else encounters this, I worked around this limitation by keeping track of the previous velocity, and on body_entered signal, using the difference between the previous _physics_process' velocity and the current one as a way to determine "force" (at least well enough to make hit sounds work) as it seems to run the signal after taking account for the hit

Jimmio92 avatar Jan 25 '21 05:01 Jimmio92

If anyone else encounters this, I worked around this limitation by keeping track of the previous velocity, and on body_entered signal, using the difference between the previous _physics_process' velocity and the current one as a way to determine "force" (at least well enough to make hit sounds work) as it seems to run the signal after taking account for the hit

That doesn't work for rotating objects. Their impace force can be multiple times the force of just the velocity difference. Still a very valdid proposal.

MrMinimal avatar Jan 31 '24 20:01 MrMinimal

That doesn't work for rotating objects. Their impace force can be multiple times the force of just the velocity difference. Still a very valdid proposal.

Could also keep track of angular velocity but...

I haven't tried but getting the body state and then do the dot product between collision normal and collision velocity multiplied by the other collider mass might give better results.

graphnode avatar Apr 30 '24 14:04 graphnode

Here's how I approached it:

# On the rigid body:
func _integrate_forces(state : PhysicsDirectBodyState3D):
	for contact_index in state.get_contact_count():
		var object_hit := state.get_contact_collider_object(contact_index)
		if (is_instance_valid(object_hit)): # To fix a case where an object hits the player as player is deleted during level transition (intermission)
			Physics.handle_rigid_body_collision(self, object_hit, state.get_contact_collider_position(contact_index), state.get_contact_local_velocity_at_position(contact_index), state.get_contact_impulse(contact_index))

# And in my physics Autoload:
static func handle_rigid_body_collision(object : PhysicsProp, object_hit : Node3D, position : Vector3, velocity : Vector3, impulse : Vector3):
	# TODO: Sometimes impulse is 0, 0, 0, even though there is a solid impact.  Jolt bug?
	if (impulse.length_squared() > MIN_IMPULSE_RESPONSE_SQUARED):
		Combat.handle_rigid_body_hit(object, object_hit, velocity, impulse)
		var speed_change := impulse.length() / object.mass
		SoundSystem.play_physics_impact_sound(object, position, speed_change)

Still, it would be great to have a general purpose callback with the impulse whenever a collision happened so things like impact sounds and such could be implemented without having a ton of extra script in performance-critical areas like physics.

jitspoe avatar Jun 25 '24 00:06 jitspoe