Scale is not working properly (RigidBody2D)

Hi,

I’m desperate.

I built a scale with

  • a beam (RigidBody2D) and
  • a Static Body (without sprite) as pivot.
  • Both are connected with a PinJoint2D.

Now, I would like to achieve the following: when the player runs on the beam, I want the scale to tilt accordingly. I have already used Area2D to detect when the body is on it, but how can I exert force on the beam?

Here is the test code I cobbled together from the internet, but it doesn’t work properly. The scale only tilts to one side, and walking on it has no effect. The only thing that works in the code is that the scale realigns itself when the player steps off.

extends RigidBody2D


@export var return_speed = 6.0

@export var player_weight = 80.0
@export var gravity = 980.0

var players_on_scale = []

func _physics_process(delta):
	angular_velocity += (-rotation * return_speed) * delta
	
	for player in players_on_scale:
		var force = Vector2.DOWN * player_weight * gravity
		apply_central_force(-force)


func _on_area_2d_body_entered(body: Node2D) -> void:
	if body.is_in_group("Player"):
		players_on_scale.append(body)
	


func _on_area_2d_body_exited(body: Node2D) -> void:
	if body.is_in_group("Player"):
		players_on_scale.erase(body)

Can anyone help? I’m feeling a bit overwhelmed at the moment.

Finally, I can contribute a solution and a recipe to the community!

I have found two solutions that work. Both can be found in the script. For my purposes, exerting force and exerting torque achieve the same effect.

This may be useful for anyone who needs something like this.

extends RigidBody2D

# Attach this script inside the Beam/Bar node (RigidBody2D):

# SCALE (Node2D)

# ---- Bar (RigidBody2D)         <---- attach here
# ---------- Sprite2D
# ---------- CollisionShape2D

# ---- Area2D
# ---------- CollisionShape2D

# ---- Pivot (StaticBody2D)

# ---- PinJoint2D


#--------------------------------------------------------------------------------
# GLOBALS
#--------------------------------------------------------------------------------
@export var return_speed 	= 10.0
@export var player_weight 	= 2000
var player: Node2D = null
#--------------------------------------------------------------------------------



#--------------------------------------------------------------------------------
# PHY STUFF
#--------------------------------------------------------------------------------
func _physics_process(delta):	
	# Balance beam if no force applied
	angular_velocity += (-rotation * return_speed) * delta
	
	# When Body enters the Area2D, apply force
	if player:
		apply_player_torque()
#--------------------------------------------------------------------------------



#--------------------------------------------------------------------------------
# Alternative 1: Apply force
#--------------------------------------------------------------------------------
func apply_player_force():
	var local_pos := to_local(player.global_position)
	var force := Vector2(0, player_weight)
	apply_force(force, local_pos)	
#--------------------------------------------------------------------------------



#--------------------------------------------------------------------------------
# Alternative 2: Apply torque
#--------------------------------------------------------------------------------
func apply_player_torque():
	var local_x := to_local(player.global_position).x
	apply_torque(local_x * player_weight)
#--------------------------------------------------------------------------------



#--------------------------------------------------------------------------------
# Enter: Collision with Area2D inside Beam/Bar (RigidBody2D)
#--------------------------------------------------------------------------------
func _on_area_2d_body_entered(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player = body
#--------------------------------------------------------------------------------



#--------------------------------------------------------------------------------
# Exit: Collision with Area2D inside Beam/Bar (RigidBody2D)
#--------------------------------------------------------------------------------
func _on_area_2d_body_exited(body: Node2D) -> void:
	if body.is_in_group("Player"):
		player = null
#--------------------------------------------------------------------------------

Jeff

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.