Constant Control: Air Movement in Reboot
Giving the player better control of their skating television when airborne has been on our team's to do list for a long while at this point. And now it can finally be checked off. Giving the player air control allows for the player to have constant control over the character at all times during gameplay. We wanted to ensure that the player never felt like the movement of their character was outside of their control.
Weeks prior, I attempted to come up with a solution that never made much headway. Back then, the code for movement and turning was much more tangled. This meant that applying even a small change to turning could cause the player to spiral out of control or jump into the sky. Before Champlain Games Festival, Jacob and I made a pretty extensive rework of the physics-based movement system to pivot more strongly towards a more arcade-y, non-realistic physics style. One of the smallest, and most impactful changes came from altering the way turning was calculated.
Originally, turning manipulated Euler angles directly (a no no in Unity, I learned later), setting the y value of the objects Euler angles to a factor of input and turn speed. This worked initially, but this method of turning presented a problem. The solution to that problem turned out to be a significant impediment in build air turning. Manipulation the Euler angles directly meant that there was a bit of a delay between the player model's rotation and the direction force of the player's velocity. To compensate for this delay, the player's rigidbody was snapped to the forward value calculated by turning within the same frame. I talked about this topic a few weeks ago.
It turned out that this turning solution was overly complicated and treacherous when it came time to attempt adding in air movement. The rework?
The rework required a single function call made directly to the player object's transform. This call replaced all my bad practice usage of Euler angles. "turnFactor" in the code above is simply input multiplied by a rotation speed variable. The turning code above decouples physics and rotation. This solution removed the need to manipulate the player's rigidbody entirely, and opened the door for a new air turning solution.
So with that new movement style implemented, and the removal of some problematic elements of the code, I was able to take another crack at giving the player control when coming off of ramps or jumps. I decided to rework the turning aspect in-air movement first.
I had discussed air turning with designers weeks before so I knew that we wanted turning in the air to feel a little bit less responsive than grounded turning. The solution here was simply to scale down the speed of the player's rotation when they're airborne. The scaling is controlled by "airTurnFactor" which is a value clamped between 0 and 1.
The solution for air movement when it came to physics movement turned out to be a relatively painless to implement as well. The air movement code's execution is dictated by a few boolean flags that check if the player is airborne and attempting to accelerate. The air movement code itself is not that dissimilar from grounded movement. The key for air movement was to continue to apply gravity, even as the player has control over the direction the player character is falling. This meant applying velocity in the direction the player was facing and then reapplying the original rigidbody y value.
This allows for the player to accelerate somewhat while in the air, while preventing them from skating across the sky in a straight line.
This solution was functional, but it wasn't producing the desired gameplay effect; the fall off effect of gravity on the player was too low. To solve for this, I increased Unity's gravity scale to -15 from the real-world -9.81. This allows for a better feeling fall while also giving the player control over their trajectory.