#React on clicks on 3d object

51 messages · Page 1 of 1 (latest)

snow coyote
#

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!

brazen gull
#

my_object.connect("clicked", on_object_clicked)

should do the trick

snow coyote
#

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.

brittle thunder
#

MeshInstance3D is the visual mesh of the model and the CollisionObject3D must be its child to collide with other objects.

snow coyote
#

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!

brittle thunder
#

Let me see, I don't remember well, but when I created an object, I had an alert to add a Collision

snow coyote
#

It says that CollistionObject3D is abstract ... hm ...

brittle thunder
#

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

snow coyote
#

I only need the object clicked, is it in event?

brittle thunder
#

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

snow coyote
#

yes, but inside the method, how can I find out which object has been clicked?

brittle thunder
#

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

snow coyote
#

just reading about bind() ... seems to be what I need ... testing ...,

brittle thunder
#

When you connect a signal which has some args, then the bind args are set after.

snow coyote
#

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 ...

brittle thunder
#

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

snow coyote
#

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.

brittle thunder
#

The static body needs a collision shape...

#

Look my screenshot up

snow coyote
#

yes, that's this line:
coll.add_child(CollisionShape3D.new())

brittle thunder
#

Also the collision shape needs to have the same shape to your object

snow coyote
#

yes

brittle thunder
#

If you doesnt modify the shape, then has no shape

snow coyote
#

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.

brittle thunder
#

could create_trimesh_collision be better?

snow coyote
#

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

brittle thunder
#

I think that staticbody3d is a new child. You can try print(your_mesh_object.get_children()) after calling the method

snow coyote
#

well it is the only child, so get_child(0) does the trick

brittle thunder
#

Yes, that works

snow coyote
#

Turns out I need to check for the event type

#

because my function now reacts on mouse touch, not click...

brittle thunder
#

Use conditionals with event arg

#

event is InputEventMouseButton...

snow coyote
#

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!

brittle thunder
#

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

snow coyote
#

Hope the developers don't remove it gdhalo

brittle thunder
#

I think it is because of the cost