Source Surfing Phyiscs?

Obviously I don’t expect exact code on how this works, but I was wondering if anyone understood how it’s done in source, and possibly a general idea of how you’d duplicate that in Unity? Mostly out of general curiosity, although I might try to make something out of it if I have the patience :stuck_out_tongue:

Please elaborate as to the definition of “source surfing physics”. You mean wave surfing?

1 Like

Try Googling ‘physics source code’, download and study it.

Here is an article on it with some code and references
http://flafla2.github.io/2015/02/14/bunnyhop.html

Ill post the code from one of those sites here with a small edit.
Keep in mind that since the code uses Time.fixedDeltaTime, it probably expects to be ran in FixedUpdate
Click for code

// accelDir: normalized direction that the player has requested to move (taking into account the movement keys and look direction)
// prevVelocity: The current velocity of the player, before any additional calculations
// accelerate: The server-defined player acceleration value
// max_velocity: The server-defined maximum player velocity (this is not strictly adhered to due to strafejumping)
private Vector3 Accelerate(Vector3 accelDir, Vector3 prevVelocity, float accelerate, float max_velocity)
{
    float projVel = Vector3.Dot(prevVelocity, accelDir); // Vector projection of Current velocity onto accelDir.
    float accelVel = accelerate * Time.fixedDeltaTime; // Accelerated velocity in direction of movment

    // If necessary, truncate the accelerated velocity so the vector projection does not exceed max_velocity
    if(projVel + accelVel > max_velocity)
    {
        //accelVel = max_velocity - projVel;
        accelVel = Mathf.Max(0f, max_velocity - projVel); //I found this to be better
    }

    return prevVelocity + accelDir * accelVel;
}

private Vector3 MoveGround(Vector3 accelDir, Vector3 prevVelocity)
{
    // Apply Friction
    float speed = prevVelocity.magnitude;
    if (speed != 0) // To avoid divide by zero errors
    {
        float drop = speed * friction * Time.fixedDeltaTime;
        prevVelocity *= Mathf.Max(speed - drop, 0) / speed; // Scale the velocity based on friction.
    }

    // ground_accelerate and max_velocity_ground are server-defined movement variables
    return Accelerate(accelDir, prevVelocity, ground_accelerate, max_velocity_ground);
}

private Vector3 MoveAir(Vector3 accelDir, Vector3 prevVelocity)
{
    // air_accelerate and max_velocity_air are server-defined movement variables
    return Accelerate(accelDir, prevVelocity, air_accelerate, max_velocity_air);
}

A few things…
I think some base testing values can be…
max_velocity_air = .3f
air_accelerate = 100

Edit-
I am not sure about this part, but I am assuming you will also need to make sure your character controller system has a “slope limit” of which if the angle of the surface you are standing on is too steep, then isGrounded will be false and no friction should be applied.
Air strafing should handle the rest.

I am also assuming by surfing you mean this
Click for video

1 Like

Making some experiment in the past for surfing and windsurfing simulation, my conclusion was:

  • Make a collider wave mesh is GPU expensive but there is some asset in the asset store.

  • Add some kind of mesh deformation when the surf is passing.

  • Put a low CG on the surfboard RB to stabilise it.

  • Make a tail tween fin of the surfboard that produces side lift and drag (vertical stabiliser as rubber).
    If is arcade, then only drag and angle control direction.

  • Add lift to the surfboard when is moving, perpendicular to the board and square the velocity.

  • The surfer animation use inverse kinematic or “Final Ik” to be on board.

  • Push the CG and surfer back when is increasing in speed.