Head bobbing consists of transformations to the camera to imply human movements of the player. The player would be using his/her feet to step from one foot to the other. This causes all sorts of changes to the viewpoint of the player but we're just going to look at a few.
Let's define a function to call with some time value which we can then plug into an oscillator to then apply the bobbing. I'm using Unity3D and C# as an example but the concepts apply to anything. For those unfamiliar
Transform holds object transform data (position, rotation) and
Rigidbody holds physics information (velocity).
void ApplyBob(float time, GameObject playerObj, GameObject camObj)
Transform t = camObj.GetComponent<Transform>(); //Position and rotation of camera
Rigidbody rb = playerObj.GetComponent<RigidBody>(); //Velocity of player
We want the head bob to be based both on time and the player's velocity so let's calculate the velocity as well.
Vector3 vel = rb.velocity;
vel.y = 0; //0 out y (up) component for xz velocity only
float velocity = vel.magnitude;
Obviously if the player isn't moving, we don't need to apply any head bob (We check it against a threshold instead of 0)
if(Mathf.Abs(velocity) <= 0.0001f)
Now we need to plug it into some sort of oscillating function, we'll stick with sine.
float bobOscillate = Mathf.Sin(time * velocity * (2 * Mathf.PI));
So now we have an oscillating function from -1 to 1 which completes one cycle every at the same rate as the velocity (1 unit/second in velocity would give 1 Hz in bobbing).
What we do now is take this and apply it to all the values we want to bob.
t.position.y += bobOscillate; //Oscillate the position in y (up) axis)
t.rotation.x += bobOscillate * 5; //Oscillates 5 degrees in each direction around x axis, presented this way for clarity (if using Unity3D, use Transform.Rotate)
This is the most basic setup you'd need for head bobbing. To perfect it for your specific game you'd want to do with following.
- Replace the sine function with a different or transformed function. Sine is a very smooth, ideal function which probably doesn't best represent the jerkiness and subtleties of human motion. Using a different oscillating function (or even one that draws on a custom data set and interpolates between the values similar to what might happen with motion capture data) would be much better.
- Changing the oscillator frequency to better match your players velocity for your given engine and player walking animation. This would require adding some constant multiplier into the
time * velocity * 2*pi portion of the line of code with the sine function.
- Adding more values to oscillate instead of just the height of the camera and the rotation to better simulate head bobbing.
All of these things would require more research into how humans actually walk and move or just playing around with things until they seem realistic enough / desirable.