God am I happy to write this post. I've been working extremely hard for the past two days polishing the player controller, bringing it a little closer to something you could get from a AAA first person experience. I did a lot of trial and error so I didn't feel like posting half done work in here. Most of the changes are cosmetic ones or "feel" oriented, but are crucial (in my opinion) to make a video game feel comfortable and immersive.
Here are the high concept of this scripting bit... (I'll maybe do a detailed tutorial).
As I previously mentioned in one of my post, I did the head bob with the camera shake function. It felt good at first until I started to notice an annoying problem. When the head bobbing motion is over the camera doesn't smoothly goes back to 0,0,0 rotation from it's relative position. It abruptly goes back to its initial position. I did played around with the "Oscillation Blend In/Out Time" without really finding a sweet spot. There was still that abruptness that bothered me. My instinct told me to use a Timeline to recreate the head bob and affect the camera's relative rotation over time. That didn't work either (on both the "camera boom" and the "follow camera"... note that I'm using the Third Person Template). The closest I got to change the relative rotation of the camera was using the node Add Local Rotation which didn't yield the results I was looking for (i.e. it was changing the rotation on input but not with the Tick Event... strange). Found online someone who did the motion by using the Set Relative Location node (moving it vertically up and down). That worked pretty well (using a timeline and updating the current location of the camera through a variable called "last cam location"). The next part was making the camera smoothly go back to it's initial position after the player stops walking. This part was easy. I took the variable that was being updated by the timeline for the head bob movement and used another timeline to smoothly blend between the "last cam location" (whatever it was when you stopped moving) and the "default location" (which is right in front of the eyes of the character mesh). The timeline simply goes from 0 to 1 in 0.2 seconds and feeds a "lerp function" that takes care of blending between the two values. All of this makes for a seamless head bob that smoothly goes back to it initial position after stopping the movement.
For research purposes, I decided to go back to Dishonored and analyze how the character was moving. I noticed that when the character is falling and reaches the ground the camera moves down a bit (or a lot) to simulate the impact. I said "oh yeah that's cool. That seems like something that would be easy to implement". Erhm... no. But... after a few iteration I finally found a solid way of doing it that works right after you jump and land and when you fall from a ledge.
Here are the high concept of this scripting bit... (I'll maybe do a detailed tutorial).
As I previously mentioned in one of my post, I did the head bob with the camera shake function. It felt good at first until I started to notice an annoying problem. When the head bobbing motion is over the camera doesn't smoothly goes back to 0,0,0 rotation from it's relative position. It abruptly goes back to its initial position. I did played around with the "Oscillation Blend In/Out Time" without really finding a sweet spot. There was still that abruptness that bothered me. My instinct told me to use a Timeline to recreate the head bob and affect the camera's relative rotation over time. That didn't work either (on both the "camera boom" and the "follow camera"... note that I'm using the Third Person Template). The closest I got to change the relative rotation of the camera was using the node Add Local Rotation which didn't yield the results I was looking for (i.e. it was changing the rotation on input but not with the Tick Event... strange). Found online someone who did the motion by using the Set Relative Location node (moving it vertically up and down). That worked pretty well (using a timeline and updating the current location of the camera through a variable called "last cam location"). The next part was making the camera smoothly go back to it's initial position after the player stops walking. This part was easy. I took the variable that was being updated by the timeline for the head bob movement and used another timeline to smoothly blend between the "last cam location" (whatever it was when you stopped moving) and the "default location" (which is right in front of the eyes of the character mesh). The timeline simply goes from 0 to 1 in 0.2 seconds and feeds a "lerp function" that takes care of blending between the two values. All of this makes for a seamless head bob that smoothly goes back to it initial position after stopping the movement.
For research purposes, I decided to go back to Dishonored and analyze how the character was moving. I noticed that when the character is falling and reaches the ground the camera moves down a bit (or a lot) to simulate the impact. I said "oh yeah that's cool. That seems like something that would be easy to implement". Erhm... no. But... after a few iteration I finally found a solid way of doing it that works right after you jump and land and when you fall from a ledge.
My first try at it was "on input" (checking after the player pressed jump) and using the "isFalling" variable integrated into the player controller by default. That didn't worked so well. I still wanted that motion on the camera when the player was landing from falling of a ledge. I was also still trying to find a way not to use an indefinite check... I had to. I also found a variable named "isMovingOnGround" that was probably a bit more precise than the "isFalling" one (after monitoring its with Print functions).
The final iteration includes a little bit of black magic. I added a box component inside the player capsule that is being translated down with a quick delay once the character has left the ground. When the box hits something it fires up a collision event that triggers the downward camera motion. This just creates an event for me to continue the flow of the logic without cluttering the graph. I also added a few boolean checks on the head bob motion to make sure that it wouldn't interfere with the landing animation. You can check the result of all this below.
The final iteration includes a little bit of black magic. I added a box component inside the player capsule that is being translated down with a quick delay once the character has left the ground. When the box hits something it fires up a collision event that triggers the downward camera motion. This just creates an event for me to continue the flow of the logic without cluttering the graph. I also added a few boolean checks on the head bob motion to make sure that it wouldn't interfere with the landing animation. You can check the result of all this below.