Note : Blender 2.82, Godot 3.2.1.
I'm sure there's no connection, but ever since the lockdown started I've been feeling
tired again. My brain is sluggish and my body feels exhausted.
Probably not a good time to try and implement doors in my game ...
Anyway. I forced myself to do a little bit of work each day (30 minutes or so),
and it seems I have now made 'ALL THE MISTAKES' !
So. Read, and learn (or laugh) (or weep).
I started by modeling a couple of doors based on the size of real doors (I actually made them a bit bigger because it's a castle) and I also textured them (because ... why not ? In hindsight, not one of my better ideas). My player model is smallish, compared to the doors ... so, everything seemed fine to me.
Next, I added collision shapes to the walls, floor, and doors, and exported everything to Godot. However, when I tried walking through an open door (in game), the player character got stuck ! The doorway also looked unexpectedly narrow ...
So, I ended up having to make the doors (and door frames and wall entrances) 0.05 Blender units (meters) wider (yes, I found that quite funny too), and I also changed the camera fov from 70 to 45 (gasp !). I'll just have to wait and see if that's an ok thing to do ; the doorways definitely look better ...
Doors are 'interactables', so, in theory, they should be quick to implement since I already figured out how to do that. And more importantly, I wrote it up in a blog post, so I don't even have to remember how I did that (and I don't) !
The reality :
I'm not going to talk about all the things I tried that failed, but, at one point I seriously considered replacing all hinge doors in the game with sliding doors :
There's a good reason 'door tutorials' only talk about sliding doors ...
This is my player character standing too close to an opening/closing door :
In the end, I did find a tutorial on hinge doors.
But alas ... It was a tutorial about hinge doors that always swing open -away- from the player ( as you see in shooters). And that's not what I want for my game.
Back to creating my own 'hacky solution' ...
So, this is the door structure I'm currently using in Godot :
If you have read my previous posts, you'll recognize the 'interactable' (IA) setup ... with some tweaks.
First, you may wonder why I haven't made the door frame (I called it 'arch') part of the wall
rather than the 'door interactable'.
Well, there's a good reason for that ! Godot doesn't seem to have a 'snap' functionality for precisely placing 2 models relatively to one another. And, as I found out, if a door isn't in exactly the right place inside the door frame, light from the room behind the door comes through ... This looks quite bad in a game.
The 'wrapper' node contains all nodes that require the rotation animations (door, key, ...).
The 'push zone' (pz_1) is meant to solve the problem of the player character standing too
close to a door. It consists of an Area node and a Position3d node.
When the player interacts with a door while he's standing inside a push zone area, he will be transported to the 'new_pos' before the door opens or closes.
A problem I had, was that I wanted this solution to work no matter what direction the player character was facing when he interacted with a door. He should always end up looking at the door :
I have to admit I was struggling quite a bit with the math for this.
But then, I discovered that gdscript has a function called 'angle_to()' that returns the minimum angle between 2 vectors ! This makes it very easy to find out by how much the player character has to be rotated when he's transported to his new position.
The only problem with this function is, that it always returns a positive number, so I still don't know if I have to rotate the player clockwise or counter clockwise ...
There's probably an easy way to find out ... but, it just didn't 'come to me'.
Fortunately, the 2d version of 'angle_to()' -does- return the rotation direction ! So, I converted the 2 relevant Vector3's into Vector2's by getting rid of the Y axis info (the Y axis is the axis around which the player needs to be rotated) :
The function update_player_tf() is called from within do_hsl_click(), which handles clicks on doors :
Both functions are part of the script attached to the iad_x root node (see first image under 'Hacky Solution').
Note : I use this 'hack' with 2 conditions :
1) the player rotates in increments of 90 degrees (might change in the future)
2) player and door are horizontal and at the same height (meaning : I don't know what happens when a player that is on the stairs or a slope tries to open a door that opens towards him).
The last bit of code is attached to the push zone 'pz_1' node :