# LimonEngine: a small C++ engine aimed at first person games

> LimonEngine is a multi-platform 3D engine in C++ that focuses on first person games and on being easy to study, with a node-based render pipeline editor, a built-in map editor, rigid body physics and extensions written in C++ or Python. It is LGPL-3.0, its last tagged release was 0.6 in 2019, and the master branch is still moving.

**enginmanap/limonEngine** — 3D FPS game engine with full dynamic lighting and shadows

- Repository: https://github.com/enginmanap/limonEngine
- Website: http://www.limonengine.com
- Stars: 716 · Forks: 72
- Language: C++
- License: LGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/enginmanap-limonengine

## An engine whose stated goal is being readable

Limon is a multi-platform 3D game engine mainly focusing on first person games, and the focus of its development is stated as two things: ease of use and ease of study.

That framing explains the shape of the whole project. It is not a general purpose engine trying to serve a studio, it is one aiming at a first person game, and it is built so that a person can read it.

The feature list is long enough to be a real engine and specific enough to show the emphasis. On the rendering side there is a configurable node-based render pipeline editor that automatically scans shaders and creates nodes using reflection, a CPU side extension endpoint for stage setup, frame render and cleanup, tag based filtering for targeting specific stages for specific objects, and multithreaded four stage filtering including frustum and occlusion culling for the world per camera, with all rendering done by the same system.

The shipping features are dynamic lighting work. There are cascaded shadowmaps with optional staggering, point shadow mapping, and SSAO with a sample render method on the CPU side. There is a custom camera extension supporting both perspective and orthogonal projection, with samples for an object attached camera and an orthogonal player camera. And there is software occlusion culling for both camera types.

Around that sits rigid body physics, 3D spatial sound with music and audio channels, a built-in editor with an animation sequencer, a fully customizable input system with gamepad support, a shading editor, and automatic navigation grid generation with multi-threaded pathfinding.

The project is LGPL-3.0 licensed, the primary language is C++, the default branch is master, and the last push was on 2026-10-20. The tagged releases stop at 0.6 from 2019-02-12, with 0.5.1 and 0.5.2 in 2018, so the branch is where the work is.

## Building it on Ubuntu, which is four steps

The build instructions are written for Ubuntu 26.04 and they are unusually complete, which is the point of a project meant to be followed.

Step one is the dependency install, a single apt command covering cmake, git, the assimp, bullet, SDL3, SDL3 image, freetype, tinyxml2, glew and glm development packages plus build-essential.

Step two is the clone, and it carries a note that matters. Because GitHub is limiting LFS bandwidth, it is removed, and cloning the LimonEngine repository should also include all data needed:

```
$ git clone https://github.com/enginmanap/limonEngine.git && cd limonEngine && git submodule update --init
```

The submodule update is not optional, since the third party libraries live in those submodules and the Data directory is part of the tree.

Step three creates the build directory and runs cmake into it:

```
$ mkdir build && cd build && cmake ../ && cd ..
```

Step four goes back into the build directory, makes, and copies the Data directory across:

```
$ cd build && make && cp -a ../Data .
```

That last copy is the step people miss. The engine loads its assets from a Data directory at runtime, and the map you are about to open lives there, so a build without the copy produces an engine that starts and then cannot find the world.

The Windows build uses MSYS2. After installing MSYS2 as a normal Windows application, you open the msys2 terminal and install a long pacman list of the mingw-w64 toolchain plus the same libraries the Linux build needs, and then you use steps two to four of the Ubuntu instructions on the same terminal.

There is also a Docker route, and the Dockerfile in the repository shows a two-image design. The base image holds the system packages, and the comment at the top of the build file is emphatic that system packages live in the base file and apt-get calls should not be added to the build image. The build image then clones the repository with the submodules, runs cmake and make for the LimonEngine target, and tars and gzips the build directory.

## Running the engine and the editor built into it

The engine takes a parameter which is the path of the world to load, and if no parameter is passed it falls back to the world file in the Data directory:

```
$ ./LimonEngine ./Data/Maps/World001.xml
```

The fact that the world is an XML file is a small architectural tell, and it is consistent with the rest of the design, since the engine leans on tinyxml2 and on a data directory of plain files.

There is no separate editor binary. Pressing F2 switches to editor mode, which allows creating maps, and pressing 0 switches to debug mode, which renders the physics collision meshes and disconnects the player from physics so you can fly and pass through objects. The plus and minus keys change mouse sensitivity, and movement is wasd with the mouse for looking around.

Inside the editor, assets are automatically scanned and listed, with a filters widget to narrow them. 3D object assets get previews using the world lighting information, and textures get previews too.

The features that stand out in the editor are the ones that make it a game engine rather than a level editor. Mass can be changed after object creation, both in the editor and at runtime through the API, and the engine swaps the collision shape, between the full mesh or baked shape and a convex hull, and re-registers with physics automatically. The catch is that this has no effect on animated objects, which are always kinematic. Inanimate objects are not allowed to have AI.

You can create animations for doors and similar in the editor, and for animation creation the time step is 60 for each second. When a new animation is created by the animation editor, the object used to create it is assumed to have that animation, and you can undo that assumption with a remove animation button.

Cameras can be created and attached to an object animated with the sequencer, and activating that gives cut-scene style camera effects.

## Five extension types, one parameter contract, two languages

The extension model is the most interesting part of the design, and it is the clearest statement of what the engine wants to be.

There are five types of extension. Actions cover triggers and buttons. AI covers actors. Player covers input handling. Camera Attachment covers custom camera behaviour, perspective and orthographic. And RenderMethod covers custom GPU rendering primitives, which are wired into the render pipeline editor.

All of them are configured through the same unified parameter contract, and are usable from either C++ or Python. The unified parameter automatically provides serialization and an editor interface, on top of communication with the engine and with other extensions. That is a well-thought-out piece of design, because the thing that usually makes engine extension systems painful is that each extension type invents its own configuration mechanism.

The loading story is worth knowing precisely. The engine tries to load custom C++ extensions from a shared library with a platform-specific name, libcustomTriggers.dll on Windows, libcustomTriggers.so on GNU/Linux and libcustomTriggers.dylib on macOS. If a map uses a customisation and the library is missing, that customisation does not work, but the rest of the map does. Python extensions, by contrast, are discovered from script files and require no separate library at all.

So the failure mode is graceful rather than fatal, which is the right choice for a map format that may reference custom behaviour the reader does not have.

The samples directory shows the five types in use, with files like CoinPickUpOnTrigger, CowboyEnemyAI, DoorAnimationAction, ObjectAttachedCameraRig, OrthographicCameraRig, SSAOKernelRenderMethod and ShooterPlayerExtension, and a KillCowboyPlayer example that shows the player extension type doing the obvious thing. The documentation is served on readthedocs, and there is a Discord channel for chat.

## Profiling, and the parts you cannot see from the README

Two entries in the feature list deserve their own reading because they are about working on the engine rather than making a game with it.

The first is Tracy profiler integration, including GPU stages, extensions, and an API for users, plus a Tracy profiler server within the Editor for a quick glance. Having the server embedded in the editor means you can watch a frame's timings without leaving the tool, which is how you find out that your shadow map cascade count is the problem.

The second is the C++ and Python API for extensibility and dynamic loading of extensions, which is the mechanism behind the five extension types.

What the README does not give you is the usual engine documentation: no list of supported platforms in detail, no renderer feature matrix, no asset format list, no performance figures, and no compatibility statement for the OpenGL or Vulkan version in use, even though the topics list includes cross-platform and the graphics backends live in a GraphicBackends/ directory in the tree.

The repository layout does show the shape of the code. There is an Engine/ directory, a src/ directory, a GraphicBackends/ directory, libs/ for the third party code, cmake/ for the build scripts, resources/, samples/, docs/, a Data/ directory with the assets, a CMakeLists.txt at the top, and two Dockerfiles, one for the base image and one for the build. There is also a.travis.yml from the era when that was the CI, alongside the.github/ directory, and an INSTALLATION file alongside a Dockerfile.

The project page is limonengine.com, the documentation is at limonengine.readthedocs.io, and the status page linked from the README is where a current feature picture would live. Prebuilt binaries for Windows, Linux and macOS are published on the releases page, and there is a 0.6 tech demo video and a featurette for the same version.

## Where LimonEngine is the wrong choice

The first wrong case is a production game with a release deadline. The tagged versions stop at 0.6 from 2019, and while the master branch is still being pushed to, a project with no release cadence for seven years is one where you are tracking a moving target, and the branch is where a hobbyist puts work rather than where a maintainer curates a version.

The second is a project that needs a modern renderer. The feature list is built around cascaded shadow maps, point shadow mapping and SSAO, and the graphics backends sit in their own directory without a detailed feature matrix in the README. If you need modern techniques such as ray traced reflections, virtual shadow maps or a compute based renderer, there is nothing in the documentation that suggests them, and reading the source is the only way to find out.

The third is a team that wants an engine with a large third party ecosystem. Extensions here are a unified parameter contract with a shared library load, which is a clean design, but the ecosystem around it is the samples directory and whatever the Discord produces. There is no plugin marketplace and no maintained list of third party extensions.

The fourth is a project that needs scripting in a mainstream language for gameplay. Python is available for extensions, which covers a lot, and the engine itself is C++.

The alternative worth weighing is a mature open source engine, which gives you a community, documentation and a release process, at the cost of a much larger codebase to learn and a heavier build. LimonEngine's value is precisely that it is small enough to hold in your head, which is an unusual and useful property for a student or for someone who wants to understand how a renderer, a physics step and an editor fit together in one tree.

## Conclusion

Adopt LimonEngine if you want to read a complete 3D engine you can build and step through, since the source is one small C++ tree with a documented extension model. Keep away for a production title, because the last tagged release is 0.6 from 2019 and the project is explicitly organised around ease of study rather than around a supported release cadence. Before you build it, expect a real dependency chain, since the Ubuntu instructions pull in cmake, assimp, bullet, SDL3, freetype, tinyxml2, glew and glm, and note the last push was on 2026-10-20 with prebuilt binaries for Windows, Linux and macOS published on the releases page.

## FAQ

### What is LimonEngine and what is it built for?

It is a multi-platform 3D game engine in C++ that mainly focuses on first person games, with the focus of its development stated as ease of use and ease of study. It includes a node-based render pipeline editor, a built-in editor with an animation sequencer, rigid body physics, 3D spatial sound, dynamic lighting with cascaded shadow maps and SSAO, and a material editor.

### How do I build LimonEngine on Ubuntu?

Install the dependencies with apt, covering cmake, git, assimp, bullet, SDL3, freetype, tinyxml2, glew and glm, then clone the repository and run git submodule update --init, create a build directory and run cmake into it, and finally run make and copy the Data directory into the build directory. That last copy is what makes the assets available at runtime.

### What kinds of extensions can I write for LimonEngine?

There are five types: Actions for triggers and buttons, AI for actors, Player for input handling, Camera Attachment for custom camera behaviour, and RenderMethod for custom GPU rendering primitives. All five use the same unified parameter contract and are usable from either C++ or Python, with C++ extensions loaded from a platform-specific shared library and Python extensions discovered from script files.

### How do I open the editor in LimonEngine?

The editor is part of the engine binary rather than a separate tool. Pressing F2 switches to editor mode, which allows creating maps, and pressing 0 switches to debug mode, which renders the physics collision meshes and disconnects the player from physics so you can fly and pass through objects. The engine takes the world path as a parameter, falling back to a default map in the Data directory.

## Sources

- [enginmanap/limonEngine on GitHub](https://github.com/enginmanap/limonEngine)
- [License: LGPL-3.0](https://github.com/enginmanap/limonEngine/blob/master/LICENSE)
- [Project website](http://www.limonengine.com)
- [README](https://github.com/enginmanap/limonEngine/blob/master/README.md)
- [Releases](https://github.com/enginmanap/limonEngine/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/enginmanap-limonengine
