Setting up C# and creating a basic resource
FiveM runs C# resources, not just Lua. Here's the deal: C# catches your mistakes before the server ever starts, your editor autocompletes everything, and you get the whole .NET toolbox for hard stuff like external API calls. This lesson builds a C# resource from nothing - the project files, the BaseScript class (the base class FiveM looks for to run your code), and how you call FiveM's built-in functions from C#.
Build it
Create the C# project
In your resources folder:
mkdir resources/qu_csharp_demo
cd resources/qu_csharp_demo
dotnet new classlib --framework netstandard2.1
dotnet add package CitizenFX.Core --version 1.0.*
Rename Class1.cs to ServerMain.cs, then add a second file ClientMain.cs for the client-side code. You will compile these into a server assembly and a client assembly.
Write the server script
Server-side code runs on the machine hosting the game. Put your commands, database calls, and player events here. What you can't do here is read the keyboard or anything from Game.* - those only exist on each player's computer, so the key-press loop waits for the client file in the next step.
using CitizenFX.Core;
namespace QuCsharpDemo
{
public class ServerMain : BaseScript
{
public ServerMain()
{
Debug.WriteLine("C# resource started!");
// Register a chat command (server-side)
API.RegisterCommand("csharp_hello", new Action<int, List<object>, string>((source, args, raw) =>
{
Debug.WriteLine($"Player {source} said: {string.Join(" ", args)}");
}), false);
}
}
}
Write the client script
Anything that watches the keyboard belongs on the client. A Tick is code FiveM runs once every frame, on each player's computer, and that's the only place Game.* and Control.* (the keypress functions) actually exist.
using CitizenFX.Core;
namespace QuCsharpDemo
{
public class ClientMain : BaseScript
{
// Tick runs every frame - like CreateThread with Wait(0)
[Tick]
public async Task OnTick()
{
if (Game.IsControlJustPressed(0, Control.Pickup))
{
Debug.WriteLine("E key pressed in C#!");
}
await Task.FromResult(0);
}
}
}
Create the fxmanifest
The manifest is the file FiveM reads to know what to load. Building gives you two .dll files (an assembly is just your compiled code in one file). Hand the server one to server_script and the client one to client_script so each lands on the right side.
fx_version 'cerulean'
game 'gta5'
server_script 'qu_csharp_demo.Server.net.dll'
client_script 'qu_csharp_demo.Client.net.dll'
You don't register your classes anywhere. FiveM cracks open each .net.dll, finds every class that inherits from BaseScript, and runs it. The server file runs ServerMain, the client file runs ClientMain.
Test the command and key press
In-game: type /csharp_hello testing C# → server console prints the message (from the server assembly). Press E → client console (F8) prints "E key pressed in C#!" (from the client assembly).
Keep reading the full lesson
Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.
- Common failures
The remainder of Setting up C# for FiveM resources is available to FiveM School members.