GBare Engine is a lightweight, modular 2D game engine written in C# using the Raylib-cs library. Its goal is to provide developers with a flexible, minimalistic framework for creating 2D games with full control over components and behavior. GBare does not enforce a specific architecture – instead, it allows you to build GameObject
s by attaching individual Component
s (e.g., Transform
, Rigidbody
, Collider
, Animator
) and defining behavior in code.
.NET 6 or newer
IDE like Visual Studio
Raylib-cs (installed via NuGet)
Operating system: Windows, Linux, or macOS (any platform supported by .NET 6+ and Raylib)
At least 2 GB RAM and a GPU with OpenGL or DirectX support
Download GBare.dll
Reference the DLL in Your Game Project
In Visual Studio:
Right-click project → Add → Reference → Browse → Select GBareEngine.dll
Install Raylib-cs via NuGet
Your game project still needs to include Raylib:
Create your first GameObject
for example
public class Player : GameObject { //Declaration of GameObject
public void Update(){
Console.WriteLine("Frame update");
}
}
This GameObject outputs “Frame update” every frame to the Console.
Register your GameObject and run it
In void Main()
{
Engine.RegisterNew(new Player()); //Registers Player GameObject
Engine.LoadAndRun(new Player()); // Starts your game without scene file
}
If you want to use Scene file (.GBS)
Engine.RegisterNew(new Player()); //Registers Player GameObject
Engine.LoadAndRun(Scene scene);
A GameObject
is the base unit in the engine. It represents anything in the game: a player, an enemy, a UI element, etc. A GameObject by itself holds no logic – it’s simply a container for Component
s.
A list of components (List<Component> Components
)
Lifecycle methods:
Start()
– called once after being added to a scene
Update()
– called every frame, contains logic
Draw()
– called every frame to render the object
SceneLoaded()
– called once after the entire scene is loaded
Destroy()
– called before the object is removed
public class Player : GameObject {
public override void Start()
{
AddComponent(new Transform()); // Adds Transform component, stores position
AddComponent(new Collider()); // Adds Collider
AddComponent(new Rigidbody()); // Adds Rigidbody. Always add Rigidbody after Transform and Collider
}
public override void Update()
{
// Movement logic
}
public override void Draw()
{
// Render logic
}
}
A Component
adds data or behavior to a GameObject
. All components inherit from the abstract Component
class and have:
Parent
(reference to the GameObject
)Transform
Holds position in Vector2
.
Rigidbody
Handles basic physics:
Force AddForce(Vector2 force)
Velocity, acceleration, drag
Physics integration with ApplyPhysics()
Rigidbody requires Collider and Transform to work
Collider
Adds collision detection. Contains width, height, and bounding box.
IsColliding(Collider other)
and debug drawing support.Animator
Stores a dictionary of animations and updates frames over time.
AudioSource
Loads and plays sound effects via Raylib.
UIElementButton, UIElementDrag, etc.
GUI components. Use Collider
for mouse detection and expose events like OnClick()
.
WebSocketComponent
Provides native ClientWebSocket
support. Handles sending and receiving messages in real-time.
Timer
Calls a delegate after a set number of seconds – useful for timeouts and delays.
A Scene
stores all active GameObject
s and manages their lifecycles.
Key responsibilities:
AddObject(GameObject)
– calls Start()
and updates global lists
RemoveObject(GameObject)
– schedules destruction for after the current frame
Loaded()
– called after all objects are created
Update()
– runs each object’s Update()
every frame
Draw()
– renders all objects in draw order
There is not need to do Update()
or Draw()
manually , because Engine
already manages that.
A Scene
can be saved to .GBS file. File structure is written in Json.
Example of .GBS file:
{
"Objects": [
{
"Name": "Player",
"Components": [
{ "Type": "Transform", "X": 400, "Y": 20 },
{ "Type": "Collider", "Width": 32, "Height": 32 },
{ "Type": "Rigidbody", "Mass": 1.0 }
]
}
]
}
The static Engine
class runs the game loop and handles scene loading.
Key methods:
RegisterNew(GameObject)
– adds a GameObject
type to the registry (used when loading from JSON)
SceneIO.GetSceneData(string path)
– loads raw scene data from a .GBS
file
SceneIO.GetSceneFromData(...)
– parses scene data into a runtime Scene
LoadAndRun(Scene scene)
– opens the Raylib window and begins the game loop. Can be used with no scene file too LoadAndRun(GameObjects[])
A basic game project using the GBare Engine should follow a clean and modular directory layout. Here’s a recommended structure:
/MyGameProject
│
├── /Scenes
│ │
│ └── Default.GBS // Serialized scene data
├── /GameObjects
│ │
│ ├── Player.cs // Your custom GameObject subclass
│ │
│ └── Enemy.cs
├── Program.cs // Main entry point
├── MyGameProject.csproj // Your game project file
│
├── /bin / /obj // Compiled output (auto-generated)
Program.cs
This file contains your game’s main entry point. Typically it:
Registers all custom GameObject
s
Loads a .GBS
scene
Starts the engine runtime
Example:
Engine.RegisterNew(new Player()); //Registering GameObjects
var data = Engine.SceneIO.GetSceneData("./Scenes/Default.GBS"); //Loading scene
var scene = Engine.SceneIO.GetSceneFromData(data);
Engine.LoadAndRun(scene);
The GBare Engine includes a basic but expandable error-handling system through custom exception classes. These exceptions help you identify issues at different stages of engine usage, such as scene loading, component instantiation, and more.
Below are the custom exceptions included in the engine:
EngineException
Namespace: GBare_Engine
Thrown when a generic engine-level failure occurs. Most commonly used as a fallback when deserialization or internal state validation fails.
RigidBodyException
Namespace: GBare_Engine
Thrown when Rigidbody
tries to perform a calculation with invalid data
(e.g. Mass = 0
).
Typical cause: Invalid RigidbodyData
settings or invalid Rigidbody
properties.
Vector2Exception
Namespace: GBare_Engine
Thrown when Vector2
data does not meet expectations.
Typical cause: Vector2
argument is null
RequiredComponentException
Namespace: GBare_Engine
Thrown when Component
or GameObject
require Component
that does not exists or had not been registered.
Typical cause: Component
has not been registered.
FieldAccessException
Namespace: System
Thrown when Gamestore
is required to save data when Gamestore
hadn’t been Initialized.
Typical cause: Gamestore
not initialized.
ComponentKeyNotFoundException
Namespace: GBare_Engine
Thrown when the engine attempts to instantiate a component with a type string that doesn’t match any known type in ComponentFactory
.
Typical cause: A typo in the .GBS
file’s Type
field, or an unregistered custom component.
GameObjectInstantiationException
Namespace: GBare_Engine
Thrown when the engine tries to instantiate a GameObject
that has not been registered using Engine.RegisterNew(...)
.
Typical cause: Forgetting to register a GameObject
before loading a .GBS
scene that refers to it.
Congratulations! You’ve now been introduced to the core structure and functionality of the GBare Engine. In this Getting Started guide, you’ve learned how to:
Understand the engine’s basic structure and file layout
Create and register custom GameObject
classes
Load and save scenes using the .GBS
format
Handle common errors and exceptions in your project
This foundation is designed to help you quickly get up and running with 2D game development using GBare, while leaving room for advanced customization and expansion.