Help with collisions in space

Godot Version

4.5

Question

I am making a space game with momentum based movement and I am trying to make collisions where you bounce off of things. Right now, when I hit something light, I think it mostly works, but when I hit a planet(20000kg), I just stop.
Here’s my movement and collision code:

    var target_acceleration = Vector3.ZERO
	var relative_acceleration = Vector3.ZERO
	if Input.is_key_pressed(KEY_W):
		target_acceleration.z += (-acceleration*delta) #Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_S):
		target_acceleration.z += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_A):
		target_acceleration.x += (-acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_D):
		target_acceleration.x += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_CTRL):
		target_acceleration.y += (-acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_SPACE):
		target_acceleration.y += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	
	relative_acceleration = transform.basis * target_acceleration #Rotate movement to be relative to ship's orientation
	target_velocity += relative_acceleration #Apply acceleration
	
	target_velocity *= natural_deceleration #Natural deceleration
	
	velocity = target_velocity
	velocity += get_gravity() #Apply gravity

	bounces = 0
	remaining = velocity * delta
	
	impact = move_and_collide(remaining) #Built in function to have nice movement, velocity, and collision
	
	if impact != null:
		velocity = velocity.bounce(impact.get_normal())
		remaining = impact.get_remainder()
		
		impact = null
		impact = move_and_collide(remaining)

Thanks to pizza_delivery_man and hyvernox, here is fixed code:

	var target_acceleration = Vector3.ZERO
	var relative_acceleration = Vector3.ZERO
	if Input.is_key_pressed(KEY_W):
		target_acceleration.z += (-acceleration*delta) #Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_S):
		target_acceleration.z += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_A):
		target_acceleration.x += (-acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_D):
		target_acceleration.x += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_CTRL):
		target_acceleration.y += (-acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	if Input.is_key_pressed(KEY_SPACE):
		target_acceleration.y += (acceleration*delta)#Applying axial acceleration, compensated for time since last tick
	
	relative_acceleration = transform.basis * target_acceleration #Rotate movement to be relative to ship's orientation
	target_velocity += relative_acceleration #Apply acceleration
	
	target_velocity *= natural_deceleration #Natural deceleration
	
	velocity = target_velocity
	velocity += get_gravity() * delta #Apply gravity

	
	impact = move_and_collide(velocity*delta) #Built in function to have nice movement, velocity, and collision
	
	if impact != null:
		var collider = impact.get_collider()
		var bounce = collider.physics_material_override.bounce
		
		var impact_normal = impact.get_normal()
		#impact_normal *= bounce
		#impact_normal = impact_normal.normalized()
				
		velocity = velocity.bounce(impact_normal)
		velocity *= bounce
		target_velocity = velocity
		
		impact = null
		impact = move_and_collide(velocity*delta)

Are you sure the remainder goes into move_and_collide() ?
I would expect the velocity should.
Also with momentum transfer all momentum is conserved … m1v1 + m2v2 =[const] and its the same before and after the collision.

its possible that the spaceship would not bounce much. (Especially if theres no angle). The planet should weigh (edit: have greater mass than…) more than 20 metric tons.

If we are talking cartoon physics, then im not sure … if that isnt cartoony anyway. In real life there could be energy dissipated as heat, dust, derbris taking some energy as momentum etc.

1 Like

I’ve got the bounce actually working, the trouble I have now is that when I pull the bounce from the RididBody(planet) I bounce with more velocity than I started. What did I do wrong?

	if impact != null:
		var collider = impact.get_collider()
		var bounce = collider.physics_material_override.bounce
		
		var impact_normal = impact.get_normal()
		impact_normal *= bounce
		impact_normal = impact_normal.normalized()
				
		velocity = velocity.bounce(impact_normal)
		target_velocity = velocity
		
		impact = null
		impact = move_and_collide(velocity*delta)

The planet is moving? I cant tell without running the code to be honest.

The planets momentum m2×v2 is greater … so when the objects collide the [const] is preserved and the ships momentum m1×v1 grabs some velocity (or energy) from the planet in the collision, so the planet slows and the ship goes much faster …

v1 =( [const] - m2× v2)/m1

So you would have to replace [const] with initial momentum of the system and compute the new v1 if you knew v2 … or the change in v2 … then it would make sense.

First you take the collision normal, then you multiply it by bounce just to normalize it afterwards?

Shouldn’t you mutliply the velocity by bounce instead?

Yes that was me being stupid. That seems to work as intended now, thanks for the help.

No, I just worded poorly. Sorry!
Thanks for the help, I think I’ve got it solved now.