The Ultimate Asset Pipeline for Godot Engine

Check out the most exciting untextured "Unreal" chair of the year, and what it means for the Godot Community!

Migeran

11 min read

Our new website is a work in progress, please let us know what more you would like to see.

Introduction

Do you want to reuse assets created for Unreal and Unity in Godot?

Want to create native graphics assets in Blender without exporting?

Do you want Live, Interactive Previews inside Blender?

Do you want to embed Godot into other Applications?

Bonus: Do you want to use the Godot Editor on an iPad?

With our Godot Integration Architecture, all this and more is going to be possible. Read on to learn more about our design, the current status and our plans for the future.

After you read our post, we also have a big ask from you: Please fill out this form , and tell us your thoughts, which features you need most, what you liked and most importantly what is missing. We are looking forward to hearing from you!

The Power of Asset Pipelines

One of the most critical points of game development (including any other 3D, graphics-intensive application development) is the Asset Pipeline: in essence the process of getting graphics assets (models, textures, animations ... etc.) from the mind of the graphics artists into the game engine.

And we need it in a form that allows high performance, real-time rendering with as good quality as allowed by the target hardware and the engine.

The standard method is to use an elaborate Export / Import process from the graphics designers' tools into the Game Engine. During the design process, the artists have to follow specific rules to make sure that the exported assets can be imported into the Game Engine without any hiccups.

This Export / Import procedure is a destructive operation: the industry standard transfer formats like FBX and the open standard GLTF are not native formats of any engine. This means that they cannot represent every feature of the game engine thus providing a suboptimal workflow. For example, transparent, glass-like surfaces were not supported by GLTF, even though it is possible to represent them in Godot.

There was a great presentation at this year's Blender Conference by Miro Horváth exactly about this topic: Game Asset Production Pipeline for ARMA Reforger .

Reuse what is already available

One of the key advantages of starting a project with Unity and Unreal Engine is the untold number of assets designed for those engines. Despite the great efforts of the Godot Community, this is a hard-to-fix problem.

At Migeran, we wanted to build a vehicle simulator with high-quality assets (maps, vehicles, pedestrians, and other props) based on Godot 4. We already had expertise in developing and customizing the Carla Simulator , so we knew that it has everything we need, but all the assets were made in Unreal Engine's native format. Check it out from the Carla 0.9.13 announcement post :

What if we could reuse, what is already available without losing a lot of information during the export process?

Lossless export functions are (understandably) not very high on the priority list for any commercial game engine.

Godot Integration Architecture Overview

The Architecture, as implemented today has 4 important elements:

  • An embeddable Godot Engine with a Runtime C API
  • An extended GDExtension API that can be used by the Host Process
  • New Python bindings designed for this use case
  • Tool-specific integration/extensions scripts are written in Python - Currently implemented for Unreal Engine.

I will elaborate on each component below.

Embeddable Godot Engine with Runtime C API

To embed Godot into another process, we not only have to build it as a shared library (which is already done for Example for Android), but also to define a simple, easy-to-use C API, that can be used by the host process to initialize the engine, and later control its main loop.

The extended GDExtension API: Shared Libraries no longer required

In its original design, Godot looks for plugins that use the GDExtension API in dynamically loaded shared libraries, that are loaded and managed by Godot itself.

For our use case, we had to extend this design, so the host process can also register new GDExtensions with the embedded engine directly. This way the host process can interact with any core or extension class using the GDExtension API to access the full capabilities of the engine.

We also extended the GDExtension API with more introspection capabilities: it is now possible to query all exported types (core and extension) and to register for notification if an extension type is added or removed.

The New Migeran PyGodot Bindings

If there is an Elephant in the Room, introduce him!

We are well aware of TouilleMan's great Godot Python Extension , and usually, we are a big fan of Not reinventing the wheel.

Why did we decide to create our own version in this case? In some cases very similar software problems - in our case using Python to access the Godot APIs - can be solved in completely different ways, with different design goals.

Our goals were:

  • No external dependencies (e.g. no Cython or Godot-CPP dependency)
  • Completely dynamic: our bindings use the new introspection capabilities of the GDExtension API to discover Godot types, no need to generate code/release new bindings whenever there is a new version of the Godot Engine.
  • Use an existing Python VM, don't start a new one.
  • Provide bindings for the Godot Runtime API, so a new engine instance can be started from an existing Python VM like this:
import godot
print("Godot module imported successfully!")
array_mesh = godot.ArrayMesh()
vertex_array = []
normal_array = []
uv_array = []
# Filling of arrays omitted for brevity.
index_array = [0, 1, 2, 0, 2, 3] # NOTE: Godot engine uses clockwise indexing.
surface_array = [None] * 13
surface_array[0] = vertex_array # Mesh.ARRAY_VERTEX
surface_array[1] = normal_array # Mesh.ARRAY_NORMAL
surface_array[2] = [] # Mesh.ARRAY_TANGENT
surface_array[3] = [] # Mesh.ARRAY_COLOR
surface_array[4] = uv_array # Mesh.ARRAY_TEX_UV
surface_array[5] = [] # Mesh.ARRAY_TEX_UV_2
surface_array[6] = [] # Mesh.ARRAY_CUSTOM0
surface_array[7] = [] # Mesh.ARRAY_CUSTOM1
surface_array[8] = [] # Mesh.ARRAY_CUSTOM2
surface_array[9] = [] # Mesh.ARRAY_CUSTOM3
surface_array[10] = [] # Mesh.ARRAY_BONES
surface_array[11] = [] # Mesh.ARRAY_WEIGHTS
surface_array[12] = index_array # Mesh.ARRAY_INDEX
Mesh_PRIMITIVE_TRIANGLES = 3
array_mesh.add_surface_from_arrays(Mesh_PRIMITIVE_TRIANGLES, surface_array)

Of course we can also save our newly created Mesh into a resource file:

resource_saver = godot.ResourceSaver()
error_code = resource_saver.save(array_mesh, "/path/to/test_plane.tres")

Host Process Integration

We are currently working on Unreal Engine integration, and as you can see from the first image, we can already convert simple static meshes without materials. The next step is adding PBR material support, and then observing all the basic sample meshes provided with Unreal inside Godot.

We chose to use Python because it is the most common integration language in the industry, it is Blender's main extension API, and both Unreal Engine and Unity support it.

What about using C# with Unity? With the latest GDExtension support in Godot's C# bindings, it should be pretty straightforward to add support for using C#, if there is interest in it from the community.

Where do we go from here?

As you can see we have already laid the foundations and have shown the Proof of Concept. But there is much work ahead.

Unreal Engine and Unity Integration

We intend to develop tools for both Unreal and Unity, which make the migration of assets, but also scripts (e.g. Unreal Blueprints) a straightforward experience.

The goal is not to provide a 100% automated solution, but to provide tools that can already do 80% of the work, and enable developers who are working on the specific migration projects, to quickly develop their custom scripts to handle the project-specific tasks.

Blender Integration

With the above pieces of technology in place, it will be possible to create the Ultimate Blender Integration of Godot into Blender. This includes:

  • Accessing the full capabilities of the Engine from the Blender Python API
  • A new viewport with Godot doing the Rendering
  • Integrating Godot with the Blender Nodes system, so Blender Artists can add the necessary conversion/augmentation steps into their Blender Node Systems, and thus update the resulting Godot assets automatically with every change in the Blender model.

Embedded Godot with Graphics

Currently, we embed Godot in Headless mode, so no graphics output can be shown inside the Host Application. While this is already good enough for doing automated pipeline integrations, like converting foreign assets to native Godot formats, we want to go further.

We want to be able to embed the Godot Engine output into the host application. This will allow features like Live Interactive Previews inside Blender: the artist could see the assets she is working on without any delays or additional steps. This will provide a huge productivity boost for the graphics asset design, especially for Indie Games with very tight budgets.

Multiple Godot Instances in a Single Process

Currently, only a single instance of Godot may be initialized in one process. However, there are many use cases, where hosting multiple instances in one process would have huge benefits:

  • Run the Godot Editor and the developed game/application in the same process. This might not be as important on desktop platforms, but on mobile, especially on iPadOS, it is a crucial requirement to enable Godot Editor usage.
  • Create a network server, where multiple instances of a game may be served by a single process. This would come in handy in cases, where each instance of the game only requires very low resources (e.g. a networked card game with 2-4 players). It is possible to run each instance of the game in a separate process, but it requires additional system resources, which increases the operating costs of such a game substantially. With this feature, even multiple different games could run isolated in a single process. A similar solution is used by CloudFlare  in their V8 Isolates based Engine  that powers CloudFlare Workers.

At the moment the PyGodot bindings are still a bit limited, some features, like enums, are not included yet. It is also not possible to implement new extension classes in Python. We intend to add these missing features, to have a complete solution.

Tell us what you think!

We hope that our vision of the Ultimate Asset Pipeline and all the related technologies make you as excited as we are.

We have a big ask from you: Please fill out this form , and tell us your thoughts, which features you need most, what you liked and most importantly what is missing. We are looking forward to hearing from you!

Sign up for our newsletter  to be the first to know about updates on this topic or any other insights that we share.

If you are interested in starting an outsourced software development project, contact us, we would love to work with you.

About Migeran

Migeran is a full-service software engineering company. In the past 15 years, we have been delivering software projects for our clients in a large variety of markets using a broad set of technologies, including:

  • AR / VR solutions based on Godot Engine and Unreal Engine
  • Native and cross-platform mobile apps built in Java / Kotlin, Swift / Objective-C and JavaScript / TypeScript with React Native.
  • Business applications based on Web and Mobile frontends and Java, Python, Ruby and PHP backend

Our first own product, Migeran for iOS was acquired by Intel in 2015 and released as the Multi-OS Engine.

We are available for new projects, you may contact us if you would like to learn more or have a project that you would like to discuss with us.

Share this post on Twitter.