Note : Godot 3.2.3, Blender 2.83.
I spent a fair amount of time creating rooms and adding doors to one of the levels
in the castle. This involved quite a bit of going back and forth between Blender and Godot
to check room sizes as well as game logic (the fun part !).
Since it's been a LONG time since I did any coding, I also spent half a day trying to figure out why
mouse_over() wasn't working on the new doors. 😐
As it turned out, my younger self had decided on 'raycasting' (out of necessity - and yes,
I completely forgot about that) rather than my goto 'mouse_entered' and 'mouse_exited' methods ...
And that brings me to another important point : CollisionObject (Area and StaticBody) layer and mask settings !
Up until now, I hadn't been paying much attention to these settings. Mostly because I had no idea what
they did, or why I would want to use them.
This is what the
Godot documentation has to say :
. collision_layer : where -this- object is in
. collision_mask : what layers this object will scan for -other- objects to interact with
Note : I think the decimal calculations on that page are wrong. If you convert 0b1101
to decimal, you get 13, not 26 (the 1st bit is pow(2,0) !). Also, if you hold the mouse over one of the little squares in the editor, it will show
you a 'value'. This is the value specific for that particular layer. So, layers 1, 3, and 4 give us : 1 + 4 + 8 = 13.
So. Why is this important ?
Well, if you leave everything at the default values of layer=1 and mask=1, then, everything will
interact with everything. For instance, the collisionshapes for the walls will register a
collision with other walls (if they intersect), with doors, and even with area nodes that I use for mouse interactions.
The floor will pick up a huge number of collisions if walls, doors, player, pickups, etc intersect even a little
bit with the floor.
Probably not what you want.
Also, if you're using raycasting for all interactions of the player with his environment, these settings are important :
Raycasting returns a Dictionary with information about the first object the ray (going from the mouse
position to a certain distance inside the game world) detects.
So, sometimes, overlapping StaticBodies and Areas can make things a bit complicated (see
below) ...
Some important parameters are :
1) 'collide_with_bodies' and 'collide_with_areas' : you can specify if you want to detect only Area nodes, only
PhysicsBody nodes (eg. StaticBody), or both.
2) 'exclude' : you can exclude a list of specific objects from being detected.
3) 'collision_mask' : speficy the layers that should be scanned by the ray.
Before I started using layers and masks, my code looked like this (see my earlier post for more info) :
I speficied that I'm only interested in Area nodes (and not eg. the StaticBody of a door) and that the ray should ignore the player. Further down the code, I then specified what I wanted to do with each of the Area nodes detected (eg. the door 'hotspot' node for detecting mouse clicks, and the door 'push zone' that prevents the player from being in the way of a door opening).
But this approach gave me some trouble when I was trying to change the mouse cursor to indicate that the player could interact with the door :
As you can see, the door collisionshape is filtered out, but the push zone is blocking (in front of) the door hotspot node.
I fixed this problem by using masks and layers.
I have placed the player in layer 32, and for now, he is not scanning for anything (mask=64, but
no objects will be placed in that layer).
The push zone ('Z_DOOR') is present in layer 2 and scans for the player. The hotspot area
('DOOR_HSL') is placed in layer 4 and doesn't scan for anything (it only interacts with the mouse).
I can now adjust the raycast code to only scan layer 4 :
The result :
There is something else that I may need to investigate, and that's the 'monitoring' and
'monitarable' settings, also for CollisionObjects. But that will be something for
the future. =)