Problem with "intersect_ray" method, this method seems doesn't work correctly when the ray cast is emitted from inside an object

Godot Version

4.2.1 stable

Question

func ray_create(mousePos: Vector2) -> Dictionary:
	var space = get_world_2d().direct_space_state
	var parameter = PhysicsRayQueryParameters2D.create(mousePos, mousePos + Vector2(15, 0), 64)
	parameter.collide_with_areas = true
	parameter.collide_with_bodies = false
	var collision_results = space.intersect_ray(parameter)
	return collision_results

I use this code to detect what item the mouse is pointed in backpack, and the UI of my backpack is like:
图片

Here is the problem, every time I click an item in the backpack (Green Box, and green point means where I clicked), the collision result return by the “intersect_ray” method is actually pointed to others (Red Box).

图片

It seems that “intersect_ray” doesn’t work correctly when the ray cast is to emitted from inside an object

What should I do to detect the item that I actually click?

For UI stuff it’s better to use Controls as they are specific for UI and handle all the input interactions you need natively.

If you still want to use an Area2D it’s better to use the CollisionObject2D._input_event() method or connect to its CollisionObject2D.input_event signal to code your input interactions. You’ll need to enable CollisionObject2D.input_pickable for the method and signal to work.

If you still want to use a ray cast then you’ll need to add the Area2Ds RIDs you don’t want to hit in the PhysicsRayQueryParameters2D.exclude array. You can get the RID of the Area2D with CollisionObject2D.get_rid()

1 Like

Set PhysicsRayQueryParameters2D.hit_from_inside to true, it’s false by default.

1 Like

I really appreciate your help, the Control Nodes is my first option, however, I couldn’t use them to achieve drag and put items in the backpack grid, then I tried to use ray cast. I might try Controls again to see if I can achieve the same function with Controls. Anyway, thanks again!!~

Thank you very much, I didn’t see this parameter before. Really appreciate!!~

Here’s a demo that shows how to setup the Control nodes drag and drop functionality godot-demo-projects/gui/drag_and_drop at master · godotengine/godot-demo-projects · GitHub

Wow!! It really helps, thank you very much!!!~

I just want to thank you again, that demo is really useful, and now I have reconstructed my code, which is much simpler than what I did before…

Sorry to bother you, but I have one question about that demo.

I just wonder, how can I get the reference of the dragged object?

My understanding is that, I can use two signals to achieve this, one is emitted when an object is dragged, then I record this object. When I successfully drop this object on something, I emit another signal to change the object I recorded before.

I don’t know if I did the right thing

What do you mean? In the Control._get_drag_data() function you can return whatever you need. If you need to pass the object that’s been dragged then just pass it in a Dictionary like:

func _get_drag_data(at_position:Vector2) -> Variant:
	return {
		"source_object": self,
		"other_data": other_data,
	}

Then in the Control._drop_data() function you can do whatever you need with that object like:

func _drop_data(at_position:Vector2, data:Variant) -> void:
	if data is Dictionary:
		var source_object = data.get("source_object", null)
		if source_object:
			print("Dropped data from object %s to object %s" % [source_object.name, name])
			# Do stuff with the source object
1 Like

How stupid I am, thank you very much, you really help me a lot!!!~

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