Current Task: Engine::AssetSystem correlation with Editor::DomainSystem.

What is Horizon Engine?

Horizon is a modular game engine I’m writing in C++23. Even though it’s not finished yet, I believe I can explain the purpose and the future plans.

The one thing I truly care about is that you can replace any feature or any part of it if necessary. Not extend it at the spots I picked for you — simply replace it. The renderer, asset loading strategies, mesh format, whatever a material means in your game. Of course Horizon ships defaults for all the things I mentioned, but they’re not something you can’t replace. If you don’t want them, just write your own and the default ones will be crushed by Horizon for you.

Note: Please be aware that the console implementations are not included in the repository due to confidentiality agreements with Sony and Microsoft.

Can this approach cause lots of performance issues?

I’m still considering this. That’s why I’m trying to handle most things at compile-time. Of course, some decisions happen at runtime while you’re developing the game. Whenever you build the released version, I will make sure that your game runs at its best performance. Or if you don’t like my build system, just replace it with yours.

Why does Horizon Engine exist?

Every engine has a ground reason. You don’t find out where it is until you need to go below it, which is always late.

Unity will let you write a render pipeline. It won’t let you change what a Mesh is, or how it reaches the GPU, or how assets load at runtime — that’s in the C++ core and you don’t touch it. You can write an importer, you can plug a provider into Addressables, but you’re building on top of a loading mechanism you can’t remove. So when your game needs something that mechanism doesn’t do, you end up running your system next to Unity’s and paying for both.

Unreal hands you the source, which is more than most engines do, and I don’t want to be unfair about that. But reading the source isn’t owning it. There’s an EULA, there’s a royalty past a threshold, you can’t publish your fork, and the terms are Epic’s to change. And with all five million lines in front of you, you still can’t get out of UObject. The reflection system is way too heavy, the OOP-based scene system is way too slow. Don’t get me wrong, they have pretty amazing features that I love a lot. But the engine is way too heavy. And it makes the games heavy as well.

I can list a lot more things that I don’t like in those engines. But it’s not important. So that’s why I created Horizon. If you think you need to change something under the hood, be my guest.

  • Run the editor as light as possible.
  • If you think my features are unoptimized, feel free to replace them.
  • If you don’t like my scripting language integration, just replace it with your own scripting language, or add Lua or C#, or continue with C++ entirely without a scripting language.

What’s the catch?

I mean, there is no license catch. You just need a crew if you want to modify it. Otherwise one person can do everything, in a very long time.

  • No license fee.
  • No royalty, at any revenue. I’m not going to come asking for a cut.
  • Fork it, rewrite it, ship your own Horizon.
  • All I ask for is a mention. Just put Horizon in your splash screen and thank me for the engine in your credits.

The real catch is: I’m just one guy who puts all his soul and effort into this engine. Some of my friends sometimes give feedback, but still, I’m the only engineer here. The docs will be behind the code, and you’ll need to understand the engine by yourself most of the time.

The engine also won’t cover for you. Register two load strategies for one asset type and it doesn’t quietly pick one — it stops and tells you. I did that on purpose. It also means Horizon gets in your way more than a mature engine would, and some days that reads as annoying rather than principled.

If you need something to ship right now, don’t use it. I still need about a year to make Horizon as mature as possible.

How do users add their own feature?

Horizon has runtime reflection, so you're still bound to runtime reflection in some cases. All you have to do is create your own object like below.

using namespace Horizon;

HCLASS(AssetLoadStrategyAttribute["MeshAsset"])
class CustomMeshStreaming : public IAssetLoadStrategy
{
public:
    IAsset* Load(const AssetEntry& entry) final;
    b8 Unload(const Guid& id) final;
};

After the reflection addition, Horizon will manifest the class for you automatically in a file called TypeManifestation.h, like below.

builder.For<CustomMeshStreaming>("CustomMeshStreaming")
    .WithBase(TypeIdOf<IAssetLoadStrategy>())
    .WithAttribute<AssetLoadStrategyAttribute>("MeshAsset", false)
    .Build();

All the interfaces will give you just what the engine needs. The rest is your responsibility. For example, Horizon needs the MeshAsset class to resolve meshes, or the WorldAsset class to resolve the ECS. So all you have to be careful about is your naming for some specific parts.

Like every other engine, changing something drastically can cause you to change other parts. For example, if you change how WorldAsset defines itself, check whether you need to add an EntityComponentRunStrategy for your WorldAsset.

To-do List

I planned these tasks to define the future of Horizon. If you think I'm missing a very crucial core part, you can contact me on LinkedIn.

One shot tasks

  • Resolve the correlation between Engine::AssetSystem & Editor::DomainSystem
  • Improve Importer and Loader usage for AssetSystem and DomainSystem.
  • WorldAsset, StaticMeshAsset, SkeletalMeshAsset, AudioAsset, AnimationAsset, TextureAsset, MaterialAsset, ScriptAsset etc.
  • Add Default Load Strategy for each asset.
  • Migrate main/FrameGraph to pure-game-engine with multi-thread features. (First run will be embedded)
  • Integrate Lua for scripting system (Counts as R&D)
  • Write lexer and parser for Auto Reflection Manifest Tool (ARMT) (This task can be prioritized)
  • Resolve GameProject dll injection.
  • Integrate GameInput SDK for Windows and GDK.
  • Integrate FMOD as a base then remove FMOD + write your own audio system.
  • Integrate Jolt as a base then create interface like AssetSystem for users' custom implementations.

Continuous Improvement tasks

  • Asset Browser, Scene Hierarchy, Inspector, Scene Visualizer, Game Visualizer
  • Material Node Graph, FrameGraph's Node Graph, Audio Graph, Animation Blend Graph
  • Particle Graph
  • Components for ECS

Check out the progress