RayCast2D won't detect collision with TileMap (GDScript)

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

I’m trying to make a weighted graph for path-finding with A* and want to create a vertex where an agent can fall to off a ledge. However the raycast shown in this code below won’t detect a collision with my TileMap. All tiles in the set are on physics layer 0. The function shown takes a tiles coordinate on the map, as well as which side we want to cast the ray from as the offset, I want it to return the ground position beneath, but so far I haven’t had any luck.

func find_landing(start_pos: Vector2i, offset: int):
start_pos = tile_map.map_to_local(Vector2i(start_pos.x + offset, start_pos.y))
var final_pos = Vector2i(start_pos.x, start_pos.y + 1000)
var ray = PhysicsRayQueryParameters2D.create(start_pos, final_pos, 1)
var result = get_world_2d().direct_space_state.intersect_ray(ray)
if result != {}:
	return ray['position']
return null

Maybe as a quick test, you could put an object with a CollisionShape2D where you expect the raycast to see if the function is behaving as you expect, or if it’s specific to the tilemap. Also, are there other objects like the player that could be colliding with the ray first, or just nothing is detecting?

Tom Mertz | 2023-05-23 01:08

That is a great problem solving step that I hadn’t though of, thank you. Unfortunately the RayCast does collide with a StaticBody2D, so now I’m questioning why the tilemap isn’t detecting in the collision. Perhaps I do not fully understand what determines the collision layer of a TileMap, I was under the impression that the physics layer that each tiles collision is made on determines that, but I may be mistaken.

Leo Knight | 2023-05-23 08:35

:bust_in_silhouette: Reply From: Tom Mertz

Just tested this and it seems to be working. Here’s a couple things I set up in my test project, maybe it might help you:

enter image description here

  1. Check the tile set has a physics layer added and that it has a collision layer set (you’ve said you have a physics layer, so collision layer/mask probably defaulted to 1).
  2. Next, check that items on the tile set have collision boxes defined. You can make sure of this by clicking on the “Select” tab under TileSet and clicking on the tile and it should have a polygon under it’s physics tab that matches the physics layer 0 you are trying to Raycast to. It’ll look slightly orange, and in the tileset it might give you a blue preview of the collider. You can mess with the collider size/shape (you might know this).

Then I ran a simple script to test collisions:

extends Node2D
@onready var tile_map = $TileMap

var previous_mouse_pos: Vector2
# Called when the node enters the scene tree for the first time.
func _ready():
	var mask: int = tile_map.tile_set.get_physics_layer_collision_layer(0)
	print(mask)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	var mouse_pos: Vector2 = get_global_mouse_position()
		
	if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
		var space = get_world_2d().direct_space_state
		
		var query = PhysicsRayQueryParameters2D.create(previous_mouse_pos, mouse_pos, 2)
		var result = space.intersect_ray(query)
		if result != {}:
			print(result)

	previous_mouse_pos = mouse_pos

I tested this with collision layer 1 and 2 for the tile set physics layer 0 and changed the mask value the script was looking for from 1 and 2 and it correct did and didn’t detect the collisions. So, it seems like it’s working.

It might help to also isolate your tilemap into its own scene and run the above script to validate the collisions in isolation. You just click and drag over objects and it should show you the raycast collisions in the debug output when the script mask and tileset layers are set correctly.

One last thing, under the Debug menu at the top there is an option “Visible Collision Shapes” which helps you see all of the collision shapes at runtime to make sure they are where you think they are.

Hope some of this helps, let us know what you find!