How to connect a joint to a tile?

Godot Version

4.1.2

Question

Hello, could anybody tell me how to connect a spring joint (or any other joint) to a tile?
A screenshot just in case:


Sorry for non-english sometimes

It’s not possible as the Joint2D expects a PhysicsBody2D and TileMap is not a PhysicsBody2D. It creates and manages those bodies directly in the PhysicsServer2D.

The easiest solution is to create a StaticBody2D or RigidBody2D where you want the Joint2D to be pinned and use that.

Another option, if you intend to create the joint via code, is to use the PhysicsServer2D directly and create the joint from there.

Also, take into account that a CharacterBody2D is moved via code and won’t be affected by physics so connecting it to a joint will probably not work as you expect.

Example using the PhysicsServer2D directly using a RigidBody2D:

extends RigidBody2D


@onready var ray_cast_2d: RayCast2D = $RayCast2D

var joint_rid:RID
var connected:bool = false
var collision_point:Vector2


func _ready() -> void:
	lock_rotation = true
	joint_rid = PhysicsServer2D.joint_create()


func _draw() -> void:
	if connected:
		draw_line(Vector2.ZERO, collision_point - global_position, Color.RED, 2, true)


func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("click"):
		if connected:
			# Disconnect the joint by creating a new one
			PhysicsServer2D.joint_clear(joint_rid)
			connected = false
			queue_redraw()
		else:
			# throw raycast and connect if possible
			var mouse = get_local_mouse_position()
			ray_cast_2d.enabled = true
			ray_cast_2d.target_position = mouse
			ray_cast_2d.force_raycast_update()
			# if colliding and the collision is to a tile on top of the character
			if ray_cast_2d.is_colliding() and ray_cast_2d.get_collision_normal().is_equal_approx(Vector2.DOWN):
				# Wake up the body
				sleeping = false
				# Get the rid of the collider and collision point
				var collider_rid = ray_cast_2d.get_collider_rid()
				collision_point = ray_cast_2d.get_collision_point()
				# Create a damped spring joint and set its params
				PhysicsServer2D.joint_make_damped_spring(joint_rid, global_position, collision_point, get_rid(), collider_rid)
				PhysicsServer2D.damped_spring_joint_set_param(joint_rid, PhysicsServer2D.DAMPED_SPRING_DAMPING, 1)
				PhysicsServer2D.damped_spring_joint_set_param(joint_rid, PhysicsServer2D.DAMPED_SPRING_REST_LENGTH, 10)
				PhysicsServer2D.damped_spring_joint_set_param(joint_rid, PhysicsServer2D.DAMPED_SPRING_STIFFNESS, 50)
				queue_redraw()
				connected = true
			ray_cast_2d.enabled = false

	if connected:
		queue_redraw()

Result:

I’ve not tried this but if you want to use it with a CharacterBody2D then I guess you could create a RigidBody2D, use that for the joint and set the velocity of the CharacterBody2D to the direction of the RigidBody2D when it connects.

2 Likes

I didn’t expect such a detailed explanation, thank you so much!

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