Surfing a like game

Hello!

I’m trying to create a game where the player can surf, just like in CSS or CSGO if you’re familiar.

If not, here’s some gameplay.

What should I follow to create my own prototype? I can’t seem to find anything on the internet that can answer my question.

Thank you!

This is a script i modified it has bhoping and surfing

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Contains the command the user wishes upon the character
struct Cmd
{
public float forwardMove;
public float rightMove;
public float upMove;
}

public class GMSPlayer : MonoBehaviour
{
public Transform playerView; // Camera
public float playerViewYOffset = 0.6f; // The height at which the camera is bound to
public float xMouseSensitivity = 30.0f;
public float yMouseSensitivity = 30.0f;
//
/Frame occuring factors/
public float gravity = 20.0f;

public float friction = 6; //Ground friction

/* Movement stuff */
public float moveSpeed = 7.0f;                // Ground move speed
public float runAcceleration = 14.0f;         // Ground accel
public float runDeacceleration = 10.0f;       // Deacceleration that occurs when running on the ground
public float airAcceleration = 2.0f;          // Air accel
public float airDecceleration = 2.0f;         // Deacceleration experienced when ooposite strafing
public float airControl = 0.3f;               // How precise air control is
public float sideStrafeAcceleration = 50.0f;  // How fast acceleration occurs to get up to sideStrafeSpeed when
public float sideStrafeSpeed = 1.0f;          // What the max speed to generate when side strafing
public float jumpSpeed = 8.0f;                // The speed at which the character's up axis gains when hitting jump
public float moveScale = 1.0f;

/*print() style */
public GUIStyle style;

/* Sound stuff */
public AudioClip[] jumpSounds;

/*FPS Stuff */
public float fpsDisplayRate = 4.0f; // 4 updates per sec

private int frameCount = 0;
private float dt = 0.0f;
private float fps = 0.0f;

private CharacterController _controller;

// Camera rotations
private float rotX = 0.0f;
private float rotY = 0.0f;

private Vector3 moveDirectionNorm = Vector3.zero;
private Vector3 playerVelocity = Vector3.zero;
private float playerTopVelocity = 0.0f;

// Q3: players can queue the next jump just before he hits the ground
private bool wishJump = false;

// Used to display real time fricton values
private float playerFriction = 0.0f;

// Player commands, stores wish commands that the player asks for (Forward, back, jump, etc)
private Cmd _cmd;

private void Start()
{
	// Hide the cursor
	Cursor.visible = false;
	Screen.lockCursor = true;

	// Put the camera inside the capsule collider
	playerView.position = new Vector3(
		transform.position.x,
		transform.position.y + playerViewYOffset,
		transform.position.z);

	_controller = GetComponent<CharacterController>();
}

private void Update()
{
	// Do FPS calculation
	frameCount++;
	dt += Time.deltaTime;
	if (dt > 1.0 / fpsDisplayRate)
	{
		fps = Mathf.Round(frameCount / dt);
		frameCount = 0;
		dt -= 1.0f / fpsDisplayRate;
	}
	/* Ensure that the cursor is locked into the screen */
	if(Screen.lockCursor == false)
	{
		if(Input.GetMouseButtonDown(0))
			Screen.lockCursor = true;
	}

	if (Cursor.visible == true) {

		if (Input.GetKeyUp (KeyCode.Escape)) {

			Cursor.visible = false;
		}

	}

	/* Camera rotation stuff, mouse controls this shit */
	rotX -= Input.GetAxis("Mouse Y") * xMouseSensitivity * 0.02f;
	rotY += Input.GetAxis("Mouse X") * yMouseSensitivity * 0.02f;

	// Clamp the X rotation
	if(rotX < -90)
		rotX = -90;
	else if(rotX > 90)
		rotX = 90;

	this.transform.rotation = Quaternion.Euler(0, rotY, 0); // Rotates the collider
	playerView.rotation     = Quaternion.Euler(rotX, rotY, 0); // Rotates the camera

	// Set the camera's position to the transform
	playerView.position = new Vector3(
		transform.position.x,
		transform.position.y + playerViewYOffset,
		transform.position.z);

	/* Movement, here's the important part */
	QueueJump();
	if(_controller.isGrounded)
		GroundMove();
	else if(!_controller.isGrounded)
		AirMove();

	// Move the controller
	_controller.Move(playerVelocity * Time.deltaTime);

	/* Calculate top velocity */
	Vector3 udp = playerVelocity;
	udp.y = 0.0f;
	if(playerVelocity.magnitude > playerTopVelocity)
		playerTopVelocity = playerVelocity.magnitude;
}

/*******************************************************************************************************\
|* MOVEMENT
\*******************************************************************************************************/

/**
* Sets the movement direction based on player input
*/
private void SetMovementDir()
{
	_cmd.forwardMove = Input.GetAxis("Vertical");
	_cmd.rightMove   = Input.GetAxis("Horizontal");
}

/**
 * Queues the next jump just like in Q3
 */
private void QueueJump()
{
	if(Input.GetKeyDown(KeyCode.Space) && !wishJump)
		wishJump = true;
	if(Input.GetKeyUp(KeyCode.Space))
		wishJump = false;
}

/**
 * Execs when the player is in the air
*/
private void AirMove()
{
	Vector3 wishdir;
	float wishvel = airAcceleration;
	float accel;

	float scale = CmdScale();

	SetMovementDir();

	wishdir =  new Vector3(_cmd.rightMove, 0, _cmd.forwardMove);
	wishdir = transform.TransformDirection(wishdir);

	float wishspeed = wishdir.magnitude;
	wishspeed *= moveSpeed;

	wishdir.Normalize();
	moveDirectionNorm = wishdir;
	wishspeed *= scale;

	// CPM: Aircontrol
	float wishspeed2 = wishspeed;
	if (Vector3.Dot(playerVelocity, wishdir) < 0)
		accel = airDecceleration;
	else
		accel = airAcceleration;
	// If the player is ONLY strafing left or right
	if(_cmd.forwardMove == 0 && _cmd.rightMove != 0)
	{
		if(wishspeed > sideStrafeSpeed)
			wishspeed = sideStrafeSpeed;
		accel = sideStrafeAcceleration;
	}

	Accelerate(wishdir, wishspeed, accel);
	if(airControl > 0)
		AirControl(wishdir, wishspeed2);
	// !CPM: Aircontrol

	// Apply gravity
	playerVelocity.y -= gravity * Time.deltaTime;
}

/**
 * Air control occurs when the player is in the air, it allows
 * players to move side to side much faster rather than being
 * 'sluggish' when it comes to cornering.
 */
private void AirControl(Vector3 wishdir, float wishspeed)
{
	float zspeed;
	float speed;
	float dot;
	float k;
	int i;

	// Can't control movement if not moving forward or backward
	if(Mathf.Abs(_cmd.forwardMove) < 0.001 || Mathf.Abs(wishspeed) < 0.001)
		return;
	zspeed = playerVelocity.y;
	playerVelocity.y = 0;
	/* Next two lines are equivalent to idTech's VectorNormalize() */
	speed = playerVelocity.magnitude;
	playerVelocity.Normalize();

	dot = Vector3.Dot(playerVelocity, wishdir);
	k = 32;
	k *= airControl * dot * dot * Time.deltaTime;

	// Change direction while slowing down
	if (dot > 0)
	{
		playerVelocity.x = playerVelocity.x * speed + wishdir.x * k;
		playerVelocity.y = playerVelocity.y * speed + wishdir.y * k;
		playerVelocity.z = playerVelocity.z * speed + wishdir.z * k;

		playerVelocity.Normalize();
		moveDirectionNorm = playerVelocity;
	}

	playerVelocity.x *= speed;
	playerVelocity.y = zspeed; // Note this line
	playerVelocity.z *= speed;
}

/**
 * Called every frame when the engine detects that the player is on the ground
 */
private void GroundMove()
{
	Vector3 wishdir;
	Vector3 wishvel;

	// Do not apply friction if the player is queueing up the next jump
	if (!wishJump)
		ApplyFriction(1.0f);
	else
		ApplyFriction(0);

	float scale = CmdScale();

	wishdir = new Vector3(_cmd.rightMove, 0, _cmd.forwardMove);
	wishdir = transform.TransformDirection(wishdir);
	wishdir.Normalize();
	moveDirectionNorm = wishdir;

	var wishspeed = wishdir.magnitude;
	wishspeed *= moveSpeed;

	Accelerate(wishdir, wishspeed, runAcceleration);

	// Reset the gravity velocity
	playerVelocity.y = 0;

	if(wishJump)
	{
		playerVelocity.y = jumpSpeed;
		wishJump = false;
		PlayJumpSound();
	}
}

/**
 * Applies friction to the player, called in both the air and on the ground
 */
private void ApplyFriction(float t)
{
	Vector3 vec = playerVelocity; // Equivalent to: VectorCopy();
	float vel;
	float speed;
	float newspeed;
	float control;
	float drop;

	vec.y = 0.0f;
	speed = vec.magnitude;
	drop = 0.0f;

	/* Only if the player is on the ground then apply friction */
	if(_controller.isGrounded)
	{
		control = speed < runDeacceleration ? runDeacceleration : speed;
		drop = control * friction * Time.deltaTime * t;
	}

	newspeed = speed - drop;
	playerFriction = newspeed;
	if(newspeed < 0)
		newspeed = 0;
	if(speed > 0)
		newspeed /= speed;

	playerVelocity.x *= newspeed;
	// playerVelocity.y *= newspeed;
	playerVelocity.z *= newspeed;
}

private void Accelerate(Vector3 wishdir, float wishspeed, float accel)
{
	float addspeed;
	float accelspeed;
	float currentspeed;

	currentspeed = Vector3.Dot(playerVelocity, wishdir);
	addspeed = wishspeed - currentspeed;
	if(addspeed <= 0)
		return;
	accelspeed = accel * Time.deltaTime * wishspeed;
	if(accelspeed > addspeed)
		accelspeed = addspeed;

	playerVelocity.x += accelspeed * wishdir.x;
	playerVelocity.z += accelspeed * wishdir.z;
}

private void OnGUI()
{
	GUI.Label(new Rect(0, 0, 400, 100), "FPS: " + fps, style);
	var ups = _controller.velocity;
	ups.y = 0;
	GUI.Label(new Rect(0, 15, 400, 100), "Speed: " + Mathf.Round(ups.magnitude * 100) / 100 + "ups", style);
	GUI.Label(new Rect(0, 30, 400, 100), "Top Speed: " + Mathf.Round(playerTopVelocity * 100) / 100 + "ups", style);
}

/*
============
PM_CmdScale

Returns the scale factor to apply to cmd movements
This allows the clients to use axial -127 to 127 values for all directions
without getting a sqrt(2) distortion in speed.
============
*/
private float CmdScale()
{
	int max;
	float total;
	float scale;

	max = (int)Mathf.Abs(_cmd.forwardMove);
	if(Mathf.Abs(_cmd.rightMove) > max)
		max = (int)Mathf.Abs(_cmd.forwardMove);
	if(max <= 0)
		return 0;

	total = Mathf.Sqrt(_cmd.forwardMove * _cmd.forwardMove + _cmd.rightMove * _cmd.rightMove);
	scale = moveSpeed * max / (moveScale * total);

	return scale;
}
/**
 * Plays a random jump sound
 */
private void PlayJumpSound()
{
	// Don't play a new sound while the last hasn't finished
	if(GetComponent<AudioSource>().isPlaying)
		return;
	GetComponent<AudioSource>().clip = jumpSounds[Random.Range(0, jumpSounds.Length)];
	GetComponent<AudioSource>().Play();
}

}