Unreal Engine Fundamentals
Everything in Unreal Engine is built from two core classes: UObject and AActor. Inheritance is the key to understanding how the engine structures its data. Whether you are targeting Unreal Engine 4 (UE4) or Unreal Engine 5 (UE5), the architecture remains remarkably similar.
Essential Global Offsets
To begin interacting with the game's memory, you need two specific entry points (global offsets):
- GWorld: A pointer to the
UWorldobject. This object represents the entire game world state. - GNames: A pointer to the global array of FName objects. This is used to resolve the human-readable names of objects.
GObjects is another global array, but it's less critical for external hacks unless you are dealing with weak pointers or need to iterate every object in memory (which is slow).
Key Tools
Before we write code, you need the right tools to inspect the game's memory structure:
- Dumper-7: https://github.com/Encryqed/Dumper-7
- Dumpspace: https://dumpspace.spuckwaffel.com/
The World-to-Screen Chain
To create visual hacks like ESP (Extra Sensory Perception) or Aimbots, you need to convert a 3D location in the game world to a 2D coordinate on your screen. This requires the "View Projection Matrix" or camera data.
Here is the chain of pointers you must follow to find the camera:
- UWorld: Read
GWorld. - GameInstance:
UWorld->GameInstance - LocalPlayer:
GameInstance->LocalPlayers(TArray) ->LocalPlayer[0] - PlayerController:
LocalPlayer->PlayerController - PlayerCameraManager:
PlayerController->PlayerCameraManager - CameraCachePrivate:
PlayerCameraManager->CameraCachePrivate->POV
Which object holds the most up-to-date camera location?
Player ESP: Finding Enemies
Most games store players in an array. Depending on the game, this might be in GameState or ULevel.
Method 1: APlayerState (The Standard Way)
The GameState contains a PlayerArray, which is a list of APlayerState objects. This is often the most reliable way to get player information.
Note: Games often extend this class (e.g., ADBDPlayerState). You can still read the base APlayerState members at the standard offsets, but game-specific data will be further down.
Method 2: Actor Array (The Universal Way)
If GameState is encrypted or unavailable, you can iterate the "Actor Array" in the PersistentLevel. This finds everything in the world, not just players, so you'll need to filter by name or type.
The actor array is located inside UNetConnection or directly on ULevel depending on the game version.
Practical Exercise: Reading the Pawn
You have found the APlayerState. Now you need to get the 3D position of the player.
- Read
PawnPrivatefromAPlayerState(offset0x320). - Read RootComponent from the Pawn (offset
0x1A8onAActor). - Read
RelativeLocationfrom the RootComponent (offset0x150onUSceneComponent).
Validate your understanding by writing the Lua code to perform this read chain.
Rendering Skeletons (Bone ESP)
Boxes are boring. We want skeletons. This requires two things:
- BoneArray: A
TArrayof FTransforms (local bone positions). - ComponentToWorld: An
FTransformthat converts local space to world space.
These are found on the USkeletalMeshComponent, which is usually at offset 0x328 (Mesh) on the ACharacter class.
To get the world position of a bone:
BoneWorldPos = BoneLocalPos * ComponentToWorld
This is a matrix multiplication. If you are using an external cheat, you'll need to implement the math for FTransform multiplication.