Skip to main content

Code to game pipeline

When you write C# in Visual Studio, GTA V knows nothing about it. The game engine is written in C++, compiled into machine code, and runs its own tight simulation loop every frame. Understanding how your code gets from a .cs file into that simulation loop is the difference between diagnosing a bug in thirty seconds or staring at an unresponsive screen for three hours.

The four layers

Your script does not talk to the engine directly. It travels through four distinct layers, each with its own job and failure mode:

  1. Your C# script: A class inheriting from Script, compiled into a .NET assembly (.dll). This is your code running inside the .NET runtime.
  2. ScriptHookVDotNet (SHVDN): A bridge written in C++/CLI. It loads your DLL into memory, manages your script lifecycle, and exposes safe C# wrappers like World, Player, and Vehicle.
  3. ScriptHookV (SHV): Alexander Blade's native hook. It attaches to the game executable, provides access to the engine's internal native tables, and pauses scripts while the game is rendering.
  4. The RAGE engine: Rockstar Advanced Game Engine. It manages physics, rendering, memory pools, and the thousands of native functions that govern Los Santos.
+------------------------------------------+
| Your C# Mod (.dll) |
+------------------------------------------+
| (calls C# API)
v
+------------------------------------------+
| ScriptHookVDotNet3.dll (bridge) |
+------------------------------------------+
| (native invocations)
v
+------------------------------------------+
| ScriptHookV.dll (runtime hook) |
+------------------------------------------+
| (engine memory/pools)
v
+------------------------------------------+
| GTA5.exe (RAGE Engine) |
+------------------------------------------+

Why the bridge exists

In the early days of modding, you had to call engine functions directly by their hexadecimal memory hashes. If you passed a float where the game expected an integer, the entire process died instantly without a message.

SHVDN acts as an interpreter and a shock absorber. When you write World.Weather = Weather.ExtraSunny;, SHVDN converts that call into the native hash SET_WEATHER_TYPE_NOW_PERSIST under the hood, checks that parameters are safe, and delivers it to the game. When something goes wrong, SHVDN catches the error and writes it to ScriptHookVDotNet.log instead of letting the game crash to desktop.

The fiber model

The game engine runs on a single main thread. It cannot wait for your script to finish a long calculation or sleep for two seconds. If your code blocks the main thread, the entire game freezes and Windows displays the spinning circle.

To solve this, SHVDN runs each script inside a fiber (a lightweight thread managed in user space). When your script finishes its Tick event or yields, execution returns immediately to the engine. The game draws the next frame, updates physics, and calls your script again on the next pass.

Where things break

Knowing the pipeline tells you where to look when something fails:

  • Compilation errors: Visual Studio catches these before the game ever runs. Syntax mistakes, missing brackets, wrong types.
  • Loading failures: SHVDN cannot find or load your DLL. Check ScriptHookVDotNet.log in your game root directory. Usually caused by targeting the wrong .NET Framework version or missing dependencies.
  • Runtime exceptions: Your code threw an unhandled error inside a Tick or KeyDown handler. SHVDN halts your script and logs the stack trace, but the game keeps running.
  • Engine pool exhaustion: Your script created hundreds of entities without cleaning them up. The game runs out of ped or vehicle slots and refuses to spawn more.

In the next lesson, we dissect the exact structure of a C# script class to see how these layers attach to your code.