How to make rigidbody2D physics work in top-down game?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Dayls

Hello. In my top down 2D project when I create logs that player can shift(something like in Zelda 2D), I make Gravity Scale to 0. In order for gravity to “pull” the log to the surface, as if along the Z axis, which is not in Rigidbody2D. That is, when I set the GravityScale to 0 so that the log does not roll from top to bottom across the screen, it turns out that with this parameter, the mass and weight do not affect anything and the log is in zero gravity. Therefore, I had a question, how to make the gravity of Rigidbody2D work in the TopDown project?

:bust_in_silhouette: Reply From: darkshadow

Your halfway there with the zero g but you’ll need to code in thr friction of the “floor” yourself.

Friction is a force proportional to velocity and in the opposite direction, the scale depends if the log is on ice low friction or mud high friction.

EDIT: see an example implentation below:

Thank you. I will try to find a way to do this

Dayls | 2021-06-10 10:08

Sorry for second question. But could you suggest me how to make this (if you know) please. Because I just haven’t really figured out Godot yet, and how to do things like that

Dayls | 2021-06-11 14:37

Add this script to your rigid body, it would be even simplier but add_central_force() behaves in an unusual manner and previous forces need clearing on the next frame. This acts like the damper (I just came across) but in your own script you could tweak the friction depending on what your object is on top of:

 extends RigidBody2D

export(float) var mu_static = 0.8  # friction coefficients
export(float) var mu_moving = 0.5  # pushing something moving is easier
# mu depends on what material the object is on, so use area detectors and change
# this values depending on ice or mud

export(float) var move_strength = 50

var applied_forces: Vector2 = Vector2(0, 0)

func add_force_for_frame(force: Vector2):
	# add_force adds a permanent force, for a temporary one we need to wipe it
	# by undo the force next frame, just keep track of forces applied
	applied_forces += force

func _ready() -> void:
	# no world gravity pushing the object down (in the +y) direction
	# we are top down so gravity is acting into the screen (in +z) but the
	# "ground" normal force is canceling it out
	self.gravity_scale = 0

func _physics_process(delta: float) -> void:
	add_force_for_frame(-applied_forces) # wipe out previous forces

	# arrows keys apply force to move it
	# could equally have a different body which pushes it
	if Input.is_action_pressed("ui_right"):
		self.add_force_for_frame(move_strength * Vector2(1, 0))
	if Input.is_action_pressed("ui_left"):
		self.add_force_for_frame(move_strength * Vector2(-1, 0))
	if Input.is_action_pressed("ui_up"):
		self.add_force_for_frame(move_strength * Vector2(0, -1))
	if Input.is_action_pressed("ui_down"):
		self.add_force_for_frame(move_strength * Vector2(0, 1))

	# this bit applies the damping force
	# minus is there because friction resists the direction of motion
	# friction depends on the m * g of the object (in this case the weight)
	if self.linear_velocity.length() == 0:
		self.add_force_for_frame(- self.weight * mu_static * self.linear_velocity.normalized())
		self.add_force_for_frame(- self.weight * mu_moving * self.linear_velocity.normalized())
	# no worries about collisions as they add their own forces in opposition to these ones

darkshadow | 2021-06-13 12:55

Thank you! It works perfectly !

Dayls | 2021-06-15 11:20

Hello! I need your help. The script works well and everything, but I have a problem. I want to simulate a tank ~45T. and I want it to stop fast when I release the button. But I can only achieve that with friction coefficient around 20, but that’s not really correct cause it can’t be greater that 1. Could you advice something?

llem00n | 2022-11-05 10:56

:bust_in_silhouette: Reply From: Dayls

I solved this problem by switching RigidBody2D’s mode to Character and then changing angular damp and linear damp parameters to 100