Skip to content

[Bullet] Wrong contact count from PhysicsDirectBodyState which is provided by _integrate_forces #66968

Description

@kubecz3k

Godot version

3.5 stable

System information

Ubuntu 22.04

Issue description

This is related to Bullet physics
Having problem with porting project from Godot 3.3.2 to Godot 3.5, the PhysicsDirectBodyState that is provided by RigidBody._integrate_forces() is unable to correctly determine collision count anymore.
It's working fine for most of the time, but the problem is it's not really consistent, and not having collision information where in reality the collision clearly happens makes this method quite unhelpful.

Steps to reproduce

The best to use reproduction sample but will describe steps that were made in order to prepare it

  1. Create a static body for a floor, it should be concave polygon with ramps as well as flat surfaces
  2. Create RigidBody for the character, set "Custom integrator" to true and Contacts Reported to 2
  3. Use this script for the RigidBody
const MAX_SPEED = 2.0
const ACCELERATION = 15.0
var steering_force: Vector3 = Vector3()

var nmbOfCollisions: int = 0 


func _integrate_forces(state):
	nmbOfCollisions = state.get_contact_count();
	print("Collisions count: ", nmbOfCollisions)
	
	var normalizedSteeringForce = steering_force.normalized();
	var delta = state.get_step();
	var lv = state.get_linear_velocity();
	var velV = Vector3(0,lv.y,0);
	var velH = Vector3(lv.x, 0, lv.z)
	
	# workaround since state.get_total_gravity() returns 0,0,0
	var gravity : Vector3 = Vector3(0, -9.8, 0) * delta 
	
	
	var canSteer = nmbOfCollisions > 0 and steering_force.length_squared() > 0.0
	if canSteer:
		velH += normalizedSteeringForce * ACCELERATION * delta
		if velH.length() > MAX_SPEED:
			velH = velH.normalized() * MAX_SPEED
	
	velV += gravity
	state.set_linear_velocity(velH + velV);


func _process(delta: float) -> void:
	steering_force = Vector3()
	if Input.is_action_pressed("forward"):
		steering_force.z = 1.0
	if Input.is_action_pressed("backward"):
		steering_force.z = -1.0
	if Input.is_action_pressed("left"):
		steering_force.x = 1.0
	if Input.is_action_pressed("right"):
		steering_force.x = -1.0
	if nmbOfCollisions > 0:
		if Input.is_action_just_pressed("jump"):
			apply_central_impulse(Vector3(0,3.5,0))
  1. Ensure you have proper input mapping in project setting
  2. Put the character on the level, try to move and jump, at some point you should see you wont be able to move since collision with ground is not detected

With reproduction sample

  1. It's enough to start it
  2. there are also two buttons in top left that can be used to play with it more
    • one position player in position where he is able to move again
    • the other puts him above flat surface - but after the fall collision is not detected

collision-count

Minimal reproduction project

collisionissue35.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions