void Start()
    {
        rig       = GetComponent <XRRig>();
        footsteps = GetComponent <AudioSource>();

        // Vector *pointing* towards origin. We remove the z axis because we
        // don't want to be pushed from the origin in the z axis, only in x/y.
        upAxis = (new Vector3(0, 0, 0) - rig.transform.position).normalized;
        upAxis = new Vector3(upAxis.x, upAxis.y, 0);

        rig.MatchRigUp(upAxis);
    }
    private void FixedUpdate()
    {
        upAxis = (new Vector3(0, 0, 0) - rig.transform.position).normalized;
        upAxis = new Vector3(upAxis.x, upAxis.y, 0);
        rig.MatchRigUp(upAxis);

        // Movement relative to the local forward direction of the camera
        Quaternion headYaw   = Quaternion.Euler(0, rig.cameraGameObject.transform.localEulerAngles.y, 0);
        Vector3    direction = headYaw * new Vector3(inputAxis.x, 0, inputAxis.y);

        if (movementAllowed)
        {
            if (Mathf.Abs(inputAxis.x) > 0.001 || Mathf.Abs(inputAxis.y) > 0.001)
            {
                if (fallingSpeed > -1)
                {
                    if (!footsteps.isPlaying)
                    {
                        footsteps.Play();
                    }
                }
                else
                {
                    if (footsteps.isPlaying)
                    {
                        footsteps.Stop();
                    }
                }

                transform.Translate(direction * Time.fixedDeltaTime * speed);
            }
            else
            {
                if (footsteps.isPlaying)
                {
                    footsteps.Stop();
                }
            }
        }
        else
        {
            if (footsteps.isPlaying)
            {
                footsteps.Stop();
            }
        }

        bool isGrounded = DetermineIfGrounded();

        // v(t) = 0 if grounded, else v(t) = v0 + at.
        if (isGrounded)
        {
            fallingSpeed = 0;
        }
        else
        {
            fallingSpeed += Physics.gravity.y * Time.fixedDeltaTime;
        }

        // since up is a vector in world space, gravity needs to be applied in world space
        transform.Translate(rig.transform.up * fallingSpeed * Time.fixedDeltaTime, Space.World);

        MaintainAboveGround();
    }