Dear community,
I am migrating a Godot 3 project. I am adding KinematicBodys programmatically and I want to react on user clicks on it. In Godot 3, I connected the object to the click handler as follows:
my_object.connect("clicked",self,"on_object_clicked")
So far I found no way how to do this in Godot 4 where I use MeshInstance3D (hope this is correct?) and I found no way to install a click handler programmatically.
Any hints?
Thanks in advance!
#React on clicks on 3d object
51 messages · Page 1 of 1 (latest)
my_object.connect("clicked", on_object_clicked)
should do the trick
I just tested it and it doesn't work (I added a breakpoint to the function called). If I read the docs correctly neither MeshInstance3D nor one of the base classes emits the "clicked" signal.
I see that CollisionObject3D has a input_event signal, but I am not sure how to use CollisionObject3D instead of MeshInstance3D.
MeshInstance3D is the visual mesh of the model and the CollisionObject3D must be its child to collide with other objects.
Ah, so I need to create a CollisionObject3D for each MeshInstance3D, add it and add the listener to the first one. Thanks, I will try that!
Let me see, I don't remember well, but when I created an object, I had an alert to add a Collision
It says that CollistionObject3D is abstract ... hm ...
Ok, I was wrong. You have to use StaticBody3D for input
And then you add CollisionShape3D
Your method must be so _on_static_body_input_event(camera: Node, event: InputEvent, click_position: Vector3, normal: Vector3, shape_idx: int)
Use click_position to get the position on the mesh surface
I only need the object clicked, is it in event?
I have this node tree
I think you can change CSGBox3D to your MeshInstance3D
Yes, when you click the object, then input_event signal is emitted. You have to connect this signal with your method
yes, but inside the method, how can I find out which object has been clicked?
The first object on the front
Every object you want to click, you have to connect input_event signal. If you want to connect the same method with some objects, then add an extra arg, and you do object.connect(_on_static_body_input_event.bind(object))
After you do your conditionals
just reading about bind() ... seems to be what I need ... testing ...,
When you connect a signal which has some args, then the bind args are set after.
yes. Still, my function is not called. Do I need to call the .connect on the StaticBody3D or on the CollisionShape3D?
And do I need to set any properties in the CollisionShape3D?
like shape opr make_convex:from_siblings()? But my mesh is not a sibling ...
oh, i forgot object.input_event, sorry
You have to connect static_body.input_event.connect(...
Always connect signals. If you connect an object, then you type the signal as the first string arg
ok, like so?
var coll: StaticBody3D = StaticBody3D.new()
coll.add_child(CollisionShape3D.new())
hex_placeholder.add_child(coll)
coll.input_event.connect(on_placeholder_clicked.bind(hex_placeholder))
The hex_placeholder is what the user clicks.
yes, that's this line:
coll.add_child(CollisionShape3D.new())
Also the collision shape needs to have the same shape to your object
yes
If you doesnt modify the shape, then has no shape
aaah, look:
void create_convex_collision(clean: bool = true, simplify: bool = false)
This helper creates a StaticBody3D child node with a ConvexPolygonShape3D collision shape calculated from the mesh geometry. It's mainly used for testing.
could create_trimesh_collision be better?
yes, I can try that, but then I need to find the created staticBody3D to connect my function to ...
unfortunately it does not return it
I think that staticbody3d is a new child. You can try print(your_mesh_object.get_children()) after calling the method
well it is the only child, so get_child(0) does the trick
Yes, that works
Turns out I need to check for the event type
because my function now reacts on mouse touch, not click...
okay it basically works now, but the trimesh seems to be inappropriate, because my "placeholder" object is "hollow". So if I click the empty space within, I don't get my event.
turns out the create_convex_collision is what I need
Thanks, this really helpoed!
It worries me "It's mainly used for testing." in the descriptions of both methods to create the staticbody
I always create it on the scene
Hope the developers don't remove it 
I think it is because of the cost