---
title: "Multiplayer in Godot 4.0: RPC syntax, channels, ordering"
excerpt: "New RPC syntax and features in Godot 4.0. Introducing channels and ordered transfer mode."
categories: ["progress-report"]
author: Fabio Alessandrelli
image: /storage/app/uploads/public/615/766/117/6157661176579529840022.png
date: 2021-09-25 14:00:00
---

Howdy Godotters! Time for [another update](https://godotengine.org/article/multiplayer-changes-godot-4-0-report-1) on Godot 4.0's multiplayer networking.

We have been really busy working on the foundation of the networking and multiplayer classes lately, and there are quite a few new features to talk about. In this post, we'll start by showing some of the new RPC syntax and features.

*See other articles in this Godot 4.0 networking series:*

1. [Multiplayer in Godot 4.0: On servers, RSETs and state updates](https://godotengine.org/article/multiplayer-changes-godot-4-0-report-1)
2. (you are here) [Multiplayer in Godot 4.0: RPC syntax, channels, ordering](https://godotengine.org/article/multiplayer-changes-godot-4-0-report-2)
3. [Multiplayer in Godot 4.0: ENet wrappers, WebRTC](https://godotengine.org/article/multiplayer-changes-godot-4-0-report-3)
4. [Multiplayer in Godot 4.0: Scene Replication (part 1)](https://godotengine.org/article/multiplayer-changes-godot-4-0-report-4)

### Simplified RPC configuration

First of all, many users found the old `master` and `puppet` keywords in `3.x` were confusing.

The `master` keyword would mean that a function could be called on the "network master", while `puppet` that a function could be called only on the "non-master" peers. Additionally, the old `master` keyword had very little usage, since `remote` could be used in its place with little to no effort.

Learning from this, we decided to have a unified `@rpc` annotation with a few optional parameters.

#### Authority

```
@rpc
func my_rpc():
	print("RPC called.")
```

By default, `@rpc` only allows calls from the **multiplayer authority**, which is the server by default. You can optionally set the multiplayer authority on a per-node basis via the `Node.set_multiplayer_authority()` method.

In this sense, the `@rpc` annotation alone behaves like the old `puppet` keyword.

```
@rpc(any_peer)
func my_rpc():
	print("RPC called by: ", multiplayer.get_remote_sender_id())
```

As mentioned above, the `@rpc` annotation can also take optional parameters. If one of those parameters is `any_peer`, the RPC will be callable by any connected peer, behaving like the old `remote` keyword. You can get the ID of the peer that is making the call via the `MultiplayerAPI.get_remote_sender_id()` method.

```
@rpc(any_peer)
func my_rpc():
	var peer_id = multiplayer.get_remote_sender_id()
	if peer_id == get_multiplayer_authority():
		# The authority is not allowed to call this function.
		return
	print("RPC called by: ", peer_id)
```

There is no direct replacement for the rarely used `master` keyword. In those cases, `@rpc(any_peer)` can be used by adding an extra check against the called ID as is done above.

#### Calling functions locally

```
@rpc(call_local)
func my_sync_rpc():
	print("RPC called")
```

In Godot, it's possible to instruct the engine that a specific function has to also be called locally when sending RPCs.

In Godot `3.x`, this was done using even more dedicated keywords (e.g. `puppetsync`, `remotesync`, etc). In Godot 4.0, `sync` is now an optional parameter of the `@rpc` annotations.

Parameters do not need to be in a particular order, so `@rpc(call_local, any_peer)` and `@rpc(any_peer, call_local)` have the equivalent meaning of defining an RPC that any peer can call. Thanks to the `sync` parameter, the RPCs will also be executed locally on the sending peer.

### Simplified RPC calls

In Godot `3.x`, we used to have 2 different transfer modes for RPCs: reliable and unreliable.

Calling `rpc("my_func")` would transfer it reliably, while calling `rpc_unreliable("my_func")` would transfer it unreliably.

In most cases though, you would always want the same transfer mode to be used (with few exceptions).

```
@rpc(unreliable)
func my_unreliable_rpc():
	print("RPC called.")
```

In Godot `4.0` we decided to also make the transfer mode a parameter of the `@rpc` annotation.

You will still be able to to override the configuration for a specific RPC using a dedicated `rpc_raw` function (not implemented yet).

### Channels and ordering

Two new features of the multiplayer API in Godot `4.0` are the introduction of channels, and the ordered transfer mode.

#### Channels

Most realtime network protocols, including ENet and WebRTC, support the concept of *channels*.

You can think of channels like separate streams inside the same connection, or even separate connections to the same remote peer if you wish. Each channel acts independently from each other, and like rivers flowing at different speeds reliable messages sent on different channels, might arrive in a different order.

This might at first seem like a limitation, but it is actually their true power.

Every time you send a message (RPC) in a reliable way, the protocol needs to keep track of it and wait until the client acknowledge its receival before sending more messages. While there are many techniques protocols use to optimize this process (e.g. buffering multiple messages), this inevitably introduces latency.

In your game, you will likely have some RPCs that are quite unrelated from the others (e.g. the player chat). These RPCs don't have to be perfectly in sync with the rest of the game (while retaining internal order). In those cases, especially when transfering larger amount of data, using a separate channel is an efficient way to reduce latency and lower the risk of disconnections.

```
@rpc(any_peer, 1)
func my_chat_func():
	print("RPC received on channel 1.")
```

Godot 4.0 will make these optimizations easier, allowing you to specify a different channel to use other than the default by passing an integer as the last parameter of the `@rpc` annotation.

This also comes handy with the other new feature, the "ordered" transfer mode.

#### Ordering

```
@rpc(unreliable_ordered)
func my_ordered_rpc():
	print("Ordered RPC received")
```

In general, unreliable RPCs are not guaranteed to arrive in order. If the server sends first the message `A` and then the message `B`, a client *could* receive `B` first, and then `A`.

An "ordered" RPC is an unreliable RPC that still guarantees the received messages to be in the right order. That is, if the clients receive `B`, it will automatically discard any message that the server sent before that (including `A` if received at a later time).

**A note of caution:** Ordered transfer mode is a powerful tool to further squeeze performances out the network connections, but it has the downside of potentially increasing packet loss if not used properly.

```
@rpc(unreliable_ordered, 1)
func _update_players_state(state):
	# Code to update the state of the players
	pass

@rpc(unreliable_ordered, 2)
func _update_enemies_state(state):
	# Code to update the state of the enemies.
	pass
```

When using the ordered transfer mode, be advised **you should not send heterogeneous messages** over the same channel.

In the code snippet above, we are are designing a game where we don't mind if the player and enemy states are a bit offsetted in the client. However, we do want each state to only be updated if the received one is newer (hence the "ordered" mode).

In this case, we must use different channels for the 2 RPCs because we want 2 separate orderings. Otherwise, a "players" update could be dropped because a newer "enemies" state has already been received, which is not what we want.

### Future work

There are a lot of exciting new things to talk about, from heavy refactoring of the networking classes and exposing most low-level ENet functions, to the high level work done on the new scene replicator. Stay tuned for more :)

### Reference work

- [RPC refactor](https://github.com/godotengine/godot/pull/49221)
- [`@rpc` annotation PR](https://github.com/godotengine/godot/pull/49882)
- [Master/puppet removal, authority](https://github.com/godotengine/godot/pull/51481) (only recently merged as it required some consensus on the new namings).


cs and navigation {#physics}

Godot 4 marks a big return of Godot's in-house 3D physics engine, **Godot Physics**. For years, Godot has relied on the **Bullet** engine to provide a solid foundation for your 3D projects. We felt, however, that a bespoke solution would give us more flexibility when implementing new features and fixing issues.

But first, we needed to bring Godot Physics on-par with Bullet feature-wise, and improve performance and precision of these features along the way. This included adding new collision shapes, [cylinder](https://github.com/godotengine/godot/pull/45854) and [heightmap](https://github.com/godotengine/godot/pull/47347), as well as re-implementing [SoftBody nodes](https://github.com/godotengine/godot/pull/46937). In addition to feature-specific improvements, general optimization techniques, such as broadphase optimization and multithreading support, were implemented for both 2D and 3D environments. Some of these improvements can also be found in recent Godot 3 releases.

![SoftBody implementation in Godot Physics](/storage/app/media/godot-soft-bodies-small.gif)

With that done, it was time to improve the the user side of things. In Godot 4 setting up scenes is a breeze after a [major reorganization of physics nodes](https://github.com/godotengine/godot/pull/48908). A lot of properties previously unique to specific body types are now available to all **PhysicsBody** nodes. This allows us to introduce the new **CharacterBody** node to replace old kinematic bodies and make the configuration of characters much simpler. Scripting them is simpler now as well. In previous versions of the engine properties related to moving, sliding, and colliding had to be passed to each corresponding method manually. They can now be set up using scenes, on the nodes themselves reducing code needed to have desired physical interactions.

But a new release is not just new big features. A significant effort was put to fix various issues causing jitters and imprecise computations. You can read more about all this work by contributors Camille Mohr-Daurat ([pouleyKetchoupp](https://github.com/pouleyKetchoupp)), [lawnjelly](https://github.com/lawnjelly), and Fabrice Cipolla ([fabriceci](https://github.com/fabriceci)) in [this blog post](https://godotengine.org/article/physics-progress-report-1) by Camille, who helms the physics development in Godot.

To breathe more life into physical bodies, the next major version of Godot also introduces a new navigation system. Previous versions of the navigation were entirely node-based, which limited their usability and performance. Thanks to work done by [Andrea Catania](https://github.com/AndreaCatania), Godot 4 features a server-based approach to navigation.

The new **NavigationServer** supports fully dynamic environments and on-the-fly navigation mesh baking. You can stream regions, which makes the system applicable to large open spaces. Physics bodies can be marked as obstacles for automatic collision avoidance, and it all works much faster than before thanks to multithreading support.

Andrea described the new system with a great practical example in a [dedicated article](https://godotengine.org/article/navigation-server-godot-4-0), and we recommend you give it a read.

### Scripting {#scripting}

[A recent study shows](https://godotengine.org/article/godot-community-poll-2021) that 100% of Godot users love to write a lot of code for their projects! With **GDScript** being the most used language, we wanted to really improve the coding experience in Godot 4 with some of the most requested and long-awaited language features. You can now reap the benefits of first-class functions and lambdas, new property syntax, the `await` and `super` keywords, and typed arrays. New built-in annotations make the language clearer and improve syntax for exported properties. And to top it off, your scripts can now automatically generate documentation that can be studied with the built-in help and the Inspector dock tooltips.

![Lambdas and typed arrays in GDScript](/storage/app/uploads/public/60b/4f2/b0a/60b4f2b0a8130694314324.png)

Despite growing in features, the GDScript runtime is only faster and more stable in Godot 4. This was achieved by a complete rewrite of the language backend by our main scripting maintainer George Marques ([vnen](https://github.com/vnen)). If you are interested in further reading George has provided several detailed reports on the new language features ([1](https://godotengine.org/article/gdscript-progress-report-new-gdscript-now-merged), [2](https://godotengine.org/article/gdscript-progress-report-feature-complete-40)), as well as on the decision-making process for the new language parser and runtime ([1](https://godotengine.org/article/gdscript-progress-report-writing-tokenizer), [2](https://godotengine.org/article/gdscript-progress-report-writing-new-parser), [3](https://godotengine.org/article/gdscript-progress-report-type-checking-back), [4](https://godotengine.org/article/gdscript-progress-report-typed-instructions)). The documentation feature was implemented by a student, Thakee Nathees ([ThakeeNathees](https://github.com/ThakeeNathees)), during the last year's Google Summer of Code. You can read their report [here](https://godotengine.org/article/gsoc-2020-progress-report-1#gdscript-doc).

Sometimes user-level scripting is not enough, though. Being an open source project, Godot has always valued extensibility. With the existing *GDNative* API layer, you don't even have to fork the engine to extend it. But it was our first attempt at making a nice abstraction layer for engine internals that you could plug-and-play into. And so for all its benefits, GDNative didn't feel quite there yet.

This is why with Godot 4, we introduce a new system called **GDExtension**. By design, it takes the best parts of creating GDNative extensions and writing custom engine modules. The code that you make can be ported into the engine if needs be, and, vice versa, some engine parts can be made into a GDExtension library, reducing engine bloat. All this still without having to recompile the engine.

The new GDExtension system was implemented by Juan and George, and further improved by many contributors, especially while porting the [official godot-cpp C++ bindings](https://github.com/godotengine/godot-cpp). Resident XR enthusiast and Godot contributor Bastiaan Olij ([BastiaanOlij](https://github.com/BastiaanOlij)) took time to make a blog post to [introduce GDExtensions](https://godotengine.org/article/introducing-gd-extensions).

### GUI a


ing}

### GDScript {#gdscript}

With **GDScript** being the most used language among current Godot users, we wanted to really improve the coding experience in Godot 4 with some of the most requested and long-awaited language features. You can now reap the benefits of first-class functions and lambdas, new property syntax, the `await` and `super` keywords, and typed arrays. New built-in annotations make the language clearer and improve syntax for exported properties. And to top it off, your scripts can now automatically generate documentation that can be studied with the built-in help and the Inspector dock tooltips.

<video autoplay loop muted>
  <source src="/storage/app/media/4.0/beta1/scripting-gdscript.mp4?1" type="video/mp4">
</video>

Despite growing in features, the GDScript runtime is only faster and more stable in Godot 4. This was achieved by a complete rewrite of the language backend by our main scripting maintainer George Marques ([vnen](https://github.com/vnen)). If you are interested in further reading George has provided several detailed reports on the new language features ([1](https://godotengine.org/article/gdscript-progress-report-new-gdscript-now-merged), [2](https://godotengine.org/article/gdscript-progress-report-feature-complete-40)), as well as on the decision-making process for the new language parser and runtime ([1](https://godotengine.org/article/gdscript-progress-report-writing-tokenizer), [2](https://godotengine.org/article/gdscript-progress-report-writing-new-parser), [3](https://godotengine.org/article/gdscript-progress-report-type-checking-back), [4](https://godotengine.org/article/gdscript-progress-report-typed-instructions)). The documentation feature was implemented by a student, Thakee Nathees ([ThakeeNathees](https://github.com/ThakeeNathees)), during the last year's Google Summer of Code. You can read their report [here](https://godotengine.org/article/gsoc-2020-progress-report-1#gdscript-doc).

C#

There is, of course, great news for those waiting on C# support to return to the engine, as it was noticeably missing from alpha builds throughout 2022. The much anticipated port to .NET 6 has been mostly [completed](https://github.com/godotengine/godot/pull/64089)! It was added relatively recently and so has not been tested in the alphas as much as other features. Please be cautious in your testing and report any issues that you face.

With the move to **.NET 6**, users can now target a newer framework that brings optimizations and new APIs. With .NET 6, projects use C# 10 by default and all features are available.

Godot 4 moves away from reflection, instead relying on source generators to improve performance, moving a lot of the work that we used to do at runtime to compile time. This also allows us to find and report errors when building the project instead of failing when running the game, such as using unsupported types in exported properties. We hope the new analyzers will help users avoid common pitfalls and write better code.

Of course, the 4.0 release is also a great opportunity to break compatibility to try and make the API better. Anything that changed in core APIs is also reflected in the .NET APIs and one of the most notable changes is the use of 64-bit types as scalar values, this means many APIs that used `int` or `float` now use `long` and `double` with the most noticeable being the `_Process` method. A `Variant` type is also now implemented that is used in every API that takes variants where we were using `System.Object` in the past. This brings some improvements such as avoiding boxing the values and you can read more about it in [this proposal](https://github.com/godotengine/godot-proposals/issues/3837).

Another change worth mentioning is the ability to declare signals as C# events. Declaring signals is done by writing a delegate with the `[Signal]` attribute like in the past, but now the delegate name must end with the `EventHandler` suffix and an event will be generated, which can be used to connect to and disconnect from the signal. Emitting a signal is currently done with the `EmitSignal` method but that may change in the future:

```cs
[Signal]
delegate void ValueChangedEventHandler(string newValue);

// The compiler generates the following event
public event ValueChangedEventHandler ValueChanged;

// Connect
ValueChanged += Foo;

// Disconnect
ValueChanged -= Foo;

// Emit
EmitSignal(SignalName.ValueChanged);
```

There's still more work to be done in the .NET module, some of which will likely still break compatibility even during the beta so make sure to keep backups and clear the `.godot` directory on updates to ensure a clean build.

One of the big changes that we are still working on is support for writing GDExtensions in C#. With GDExtension, C# classes will be registered in the engine and work as the built-in classes do, which should improve the support of C# nodes and resources throughout the engine.

Currently, the .NET version of Godot still requires a separate build of Godot, just as in Godot 3. However, we are planning on unifying the editor so there won't be a standard and a .NET build anymore but a single editor that will download the necessary additional components when .NET is used.

Stay tuned for a deeper dive in the new features and upcoming changes in future progress reports!

**Important remarks:**

- The Godot editor requires the .NET 6.0 SDK to be installed in order to use C#.
- Godot 4 doesn't support C# projects imported from Godot 3. It may be possible to edit your project file manually, but otherwise it's recommended to let Godot generate a new one.
- Currently, mobile and web platforms are not available, with support likely coming in Godot 4.1.

### GDExtension {#gdextension}

Sometimes user-level scripting is not enough, though. Being an open source project, Godot has always valued extensibility. With the existing *GDNative* API layer, you don't even have to fork the engine to extend it. But it was our first attempt at making a nice abstraction layer for engine internals that you could plug-and-play into. And so for all its benefits, GDNative didn't feel quite there yet.

This is why with Godot 4, we introduce a new system called **GDExtension**. By design, it takes the best parts of creating GDNative extensions and writing custom engine modules. The code that you make can be ported into the engine if need be, and, vice versa, some engine parts can be made into a GDExtension library, reducing engine bloat. All this still without having to recompile the engine.

The new GDExtension system was implemented by Juan and George, and further improved by many contributors, especially while porting the [official godot-cpp C++ bindings](https://github.com/godotengine/godot-cpp). Resident XR enthusiast and Godot contributor Bastiaan Olij ([BastiaanOlij](https://github.com/BastiaanOlij)) took time to make a blog post to [introduce GDExtensions](https://godotengine.org/article/introducing-gd-extensions).

## Gui and Text {#gui


---
title: "Agile input processing is here for smoother, more responsive gameplay"
excerpt: ""
categories: ["progress-report"]
author: Pedro J. Estébanez
image: /storage/app/uploads/public/612/136/3cc/6121363ccb95e735957693.png
date: 2021-08-21 17:00:00
---

Since it's not very usual I post here, let me remind you who I am. I'm Pedro, a.k.a. [RandomShaper](https://twitter.com/RandomPedroJ) in the Godot community. I've been contributing to the engine since 2016, when I discovered it –version 2.1 was the newest– and decided to use it to create my game [Hellrule](http://pedrocorp.net/#hellrule). Precisely while testing this project on different models of Android phones, I found the need to make the improvements I'm explaining in this post.

### Old behavior in Godot 3.3.x and before

In a game engine, the *engine loop* is the sequence of steps that is happening again and again to let the game run. This includes rendering, physics, input processing, and more. Optimizing this loop to run with as little CPU time as possible is important to have smooth gameplay on high-end and low-end hardware alike.

Godot's engine loop used to look like this (this is heavily simplified to just show what we are talking about here):

![loop_before.png](/storage/app/uploads/public/611/d83/0a3/611d830a38eb5069138855.png)

The key element of this is the possibility of multiple physics steps being processed per cycle of the engine loop. Consider a game that wants its gameplay logic and physics to run at 60 FPS. To achieve this, the engine needs to poll for the player's inputs from various sources, such as a mouse, keyboard, gamepad or touchscreen. Ideally, the engine would read the player's inputs once per each of those gameplay-physics steps so it reacts as quickly as possible to player actions. Also, rendering would happen at that very same pace, so everything stays in sync.

However, depending on the demands of the game and the hardware it's running on at a given time, that may not be possible. If the device running the game is not powerful enough to keep everything at 60 FPS, the engine will run at a lower effective FPS rate. Rendering and idle processing will then occur less than 60 times per second, but the engine will do its best to have the gameplay-physics running at the target rate, by executing more than one of those physics steps per visible frame.

If you look again at the game loop above, you'll understand that a consequence of the engine looping at a lower frequency is that, user input is also pumped and handled less frequently, which leads to having a **lower responsiveness** in addition to a less smooth update of the display.

#### New behavior in Godot 3.4 beta and later

In order to avoid that, Godot needed to somehow **uncouple input from render** so the engine main loop looked more like this:

![loop_after.png](/storage/app/uploads/public/611/d83/0c8/611d830c8ef48415300361.png)

To make that happen, I've added the concept of **input buffering**, which allows that one thread –usually the one consuming events from the OS– stores the input events from the player in a buffer as they are received while the main thread of the engine **flushes them at key points of the cycle**. This new approach improves the responsiveness of the game in situations of lower-than-ideal FPS.

### Remarks

- This enhancement is implemented in two pieces. One belongs to the core of the engine, whereas the other must be implemented on each platform. At this point, only Android has the platform-specific part implemented. (To be honest, that's most likely the platform where agile input flushing is needed the most, due to the huge range of hardware capabilities found across devices.)
- However, the doors are open wide for it to be implemented for other platform given the base is already done.
- **Both Godot 3.4 and 4.0** will enjoy agile input, exposed as the `input_devices/buffering/agile_event_flushing` project setting.
- The project setting mentioned above is **disabled by default**. The rationale is that not every project may want to have batches of input events coming multiple times per frame. Also, until this feature is implemented universally, enabling it causes differences of behavior across platforms. Nonetheless, elaborating on the latter, my game has been in the wild for months with agile input flushing on Android and without it on iOS with no issues. As long as you make your game physics-centric, whether agile input is enabled or not won't have any side effects. The game will just be more responsive when it's enabled and available, but it will keep working without agile input.


---
title: "Godot gets CSG support"
excerpt: "After years of discussion on how to implement CSG, Godot finally gets suport for it. This implementation is simple, but makes use of Godot's amazing architecture to shine."
categories: ["progress-report"]
author: Juan Linietsky
image: /storage/app/uploads/public/5ae/4d0/8c6/5ae4d08c674b5082905650.png
date: 2018-04-28 00:00:00
---

After years of discussion on how to implement CSG, Godot finally gets suport for it. This implementation is simple, but makes use of Godot's advanced architecture to shine.

### Wait, what is CSG?

CSG stands for "Construtive Solid Geometry", and is a tool to combine basic (and not so basic) shapes to create more complex shapes. In the 3D modelling software, CSG is mostly known as "Boolean Operators".

![](/storage/app/media/csg/csg7.gif)

### Why is CSG relevant?

The aim of CSG in Godot is for it to be used in level prototyping. This technique allows to create simple versions of most common shapes by combining primitives. Interior environments can be created by using inverted primitives instead.

CSG is a vital tool for level design (and level designers in companies) as it allows to test gameplay environments without modelling a single triangle. Unreal has always offered similar boolean CSG, while Unity has recently acquired ProBuilder (which is a different type of tool, but still aimed at prototyping level geometry).

For developers, creating 3D art is a time consuming process. For indies or small companies, it may even involve outsourcing to third party artists. With CSG, a game can be developed almost entirely without relying on 3D environment artists, only for that content to be filled in the end when gameplay is already working.

![](/storage/app/media/csg/csg5.png)

### How does it work?

Godot provides a bunch of Primitive nodes:

* **Sphere**
* **Box**
* **Cylinder** (can be used as Cone)
* **Torus** (donut shape)
* **Polygon** (can be drawn in 2D and then extruded)
* **Mesh** (can use any custom geometry)

![](/storage/app/media/csg/csg1.png)

Each of these operates on the parent CSG node, in order. Supported operations are:

* **Union**: Geometry of both primitives is merged, intersecting geometry is removed
* **Intersection**: Only intersecting geometry remains, the rest is removed
* **Subtraction**: The second shape is susbtracted from the first, leaving a dent with it's shape.

![](/storage/app/media/csg/csg2.png)

##### Process order

Every CSG node will first process it's children nodes (an their operation: union, intersection substraction), in tree order and apply them to itself one after the other.

There is a special CSGCombiner node that is pretty much an empty shape. It will only combine children nodes. It's used for organization mostly.

##### Polygon and lofting

The CSGPolygon node is very convenient, a Polygon is drawn in 2D (in X,Y coordinates), and it can be extruded in the following ways:

* **Depth**: Extruded back a given amount
* **Spin**: Extruded while spinning aroud it's origin.
* **Path**: Extruded along a Path node. This operation is commonly called *lofting*.

![](/storage/app/media/csg/csg3.png)

##### Custom meshes

Any mesh can be used for CSG, this makes it easier to implement some types of custom shapes. Even multiple materials will be properly supported. There are some restrictions for geometry, though:

* It must be closed
* It must not self-intersect
* Is must not contain internal faces
* Every edge must connect to only two other faces

![](/storage/app/media/csg/csg4.png)

Make sure CSG geometry remains relatively simple, as complex meshes can take a while to process.

##### A note on performance

If adding objects together (such as table and room objects). It's better if this is done as separate CSG trees. Forcing too many objects in a single tree will eventually start affecting performance. Only use binary operations where you actually need them.

### Godot CSG Implementation

As many libraries seemed to exist for this, I decided to pick one and put it in Godot and implement it over a weekend. Of course, this unfortunately did not work well. A few things stopped me. Pretty much every library I found was:

* Under GNU GPL or GPL, making it incompatible with Godot
* Using really crappy algorithms such as voxel or BSP, making them inefficient.
* Designed for 3D modelling or mathematics, so they used very tuned algorithms dealing with avoiding precision errors.

Nothing was really meant for games. This led me to write a custom one for Godot, with focus exclusively on performance.

The current implementation is really simple. It does brute force clipping of triangles without relying on vertex IDs, or isolating edges to detect interior faces. Instead the implementation in Godot does triangle-triangle raytracing to detect which halves ended up inside the intersection.

This is expensive per se, but it's optimized by doing a pre-aabb intersection and balanced binary trees to minimize the amount of ray tests. As a result, the performance is really good.

As the implementation is pure brute force, some visual artifacts may rarely appear in some cases if you look well, but truth is that they don't have any practical impact as CSG in Godot is mostly meant for level prototyping. In fact I'm sure for some types of game CSG could easily be usable in production.

### Future

The main missing feature now is the ability to export the scene to a 3D modelling software (likely via GLTF2), so the process of replacing CSG art by final art can be done by a professional artist. This will be added soon.

Please test well! And remember that we make Godot with love for everyone. If you are not already, please consider [becoming our patron](https://www.patreon.com/godotengine), so we can continue doing this for you!


---
title: "GDScript progress report: Writing a new parser"
excerpt: "Showing the work for the new GDScript parser, why it is done and how it improves over the old one. Also show a bit of new features."
categories: ["progress-report"]
author: George Marques
image: /storage/app/uploads/public/5ed/43c/e24/5ed43ce245f10218039510.png
date: 2020-06-01 11:37:58
---

As you might be aware right now I'm currently working on revamping the GDScript compiler. After finishing the tokenizer in the last report, I've been working on the new parser.

The main point to bring in this rewrite is to make a bit more "textbook-like" as mentioned in the previous article, so I split grammar production in different functions. Before we had big `switch` statements with many cases to parse the code, now we delegate the work to specific functions. This makes it easier to find where a particular piece of code is.

*See other articles in this Godot 4.0 GDScript series:*

1. [GDScript progress report: Writing a tokenizer](https://godotengine.org/article/gdscript-progress-report-writing-tokenizer)
2. (you are here) [GDScript progress report: Writing a new parser](https://godotengine.org/article/gdscript-progress-report-writing-new-parser)
3. [GDScript progress report: Type checking is back](https://godotengine.org/article/gdscript-progress-report-type-checking-back)
4. [GDScript progress report: New GDScript is now merged](https://godotengine.org/article/gdscript-progress-report-new-gdscript-now-merged)
5. [GDScript progress report: Typed instructions](https://godotengine.org/article/gdscript-progress-report-typed-instructions)
6. [GDScript progress report: Feature-complete for 4.0](https://godotengine.org/article/gdscript-progress-report-feature-complete-40)

## Less lookahead

The previous parser relied on the tokenizer ability to buffer tokens to ask for a few the next (and sometimes the previous) tokens in order to decide what the code means. The new tokenizer lacks this ability on purpose to make sure we can use the bare minimum of a lookahead to parse the code.

Minimizing lookahead means the code is easier to parse. If we were to introduce a new syntax for a feature, now we have to make sure it does not increase the complexity of the parser by demanding too much tokens at once.

The new parser only stores the current and previous token (or the current and the next if you look it in another way). It means that GDScript only needs one token of lookahead to be fully parsed. This takes us to a simpler language design and implementation.

## A Pratt parser for expressions

Those who are familiar with programming language implementation will know that parsing expressions is always tricky. When you consider precedence of operators, and that an arbitrary expression can be left operand of a, say, `+` operator, it can get very tricky to decide how to build the parse tree.

There are different solutions to this but I like the [Pratt parsing](https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/) for its simplicity. It consists in a function table in which the index is the token type. This means that deciding which parser function to call is just a lookup based on the current token.

![](/storage/app/media/gdscript-pratt-table.png)

This makes it very easy to see—and change—the precedence of every operators. The functions do have to share the signature, but it's usually not a big deal since most of them aren't called outside the expression parser.

## Multiple error detection

Also mentioned in the previous article, the idea is to show multiple errors at once so you don't need to fix one to discover the next. The new parser has support to store an arbitrary number of errors.

When it finds something unexpected, the parser enters *"panic mode"*. While in this mode, it will ignore every token until it finds one that can only be the beginning of a statement. At this point, it can leave the panic mode and go back to regular parsing. While this can cause cascading errors due to missing or extra token, it can show errors in different parts of the file at once.

This will also help completion since the parser won't need to stop on the first error and can check what's next in the file to also suggest.

## Pretty tree printer

As I did with the tokenizer, I added a print mode to replace the old `gd_parser` test. It prints the tree in an unambiguous readable way so problems with parsing can be detected.

So a script like this:

```gdscript
class_name MyClass extends Node2D

const SPEED = 200
@export var player_name = "Vladimir"

func _ready():
    $Button.button_up.connect(_on_button_pressed)
    print("Ready!")

func _on_button_pressed():
    print("Player is \"%s\"" % player_name)

func _process(delta):
    $Body.move(delta * SPEED)
```

Will be printed like this:

```
Class MyClass Extends Node2D :
|   Constant SPEED
|   |   = 200
|   @export ()
|   Variable player_name
|   |   = "Vladimir"
|   Function _ready(  ) :
|   |   $Button.button_up.connect( _on_button_pressed )
|   |   print( "Ready!" )
|   Function _on_button_pressed(  ) :
|   |   print( ("Player is "%s"" % player_name) )
|   Function _process( delta ) :
|   |   $Body.move( (delta * SPEED) )
```

## Annotations

Shown briefly in the previous example, I implemented annotations as outlined in [GIP #828](https://github.com/godotengine/godot-proposals/issues/828). Those are meant to replace a few keywords and improve the ability to add new integrations without having to create new keywords and big changes in the parser.

This also means that the old `export` syntax is now extinct in favor of specific annotations. This makes it in general easy to remember and understand and don't require much effort in the GDScript implementation, since their arguments are the same as expected in the internal hint strings.

There will be an [update to the documentation](https://github.com/godotengine/godot-docs/pull/3623) to explain the new way.

## `await` replaces `yield`

The old `yield` syntax was a bit convoluted complicated to understand, forcing you to deal with function states. It was especially harder to understand given it did the opposite of other languages do with the same keyword.

The `await` syntax can be used to wait for signals or coroutines alike:

```gdscript
func coroutine():
    await $Button.button_up # Will suspend the function and resume when the button is pressed.
    return true

func _ready():
    var result = await coroutine() # Will suspend the function and wait for the coroutine result.
    print(result) # true
```

## Breaking things to make them anew

I wanted to make this new parser working with the current system sooner rather than later. So I amended the dependencies on the old parser and tokenizer to use the new one. Since this is rather time consuming, a lot of things were disabled in the meantime.

I do mention what's missing in my [initial Pull Request](https://github.com/godotengine/godot/pull/39093) but here is a shortlist:

* Type checking.
* Code completion.
* Warnings.
* Language server.
* `setget` (will be replaced by [properties](https://github.com/godotengine/godot-proposals/issues/844)).
* Some optimizations.

This will be fixed in the next steps

## Future

There's still a long road ahead to make GDScript a better language in general. The next step is to read the type checks so the systems that depend on it can also be reactivated. Hopefully the new type checker will be more precise than the previous one (I learned a lot since then). And it will allow use of some new features like typed arrays.


2D: Fix UV editor not using texture transform ([GH-84076](https://github.com/godotengine/godot/pull/84076)).
- 2D: Fix generating terrain icon with certain image formats ([GH-84507](https://github.com/godotengine/godot/pull/84507)).
- 2D: Keep scene tiles even if the TileMap is invisible ([GH-85753](https://github.com/godotengine/godot/pull/85753)).
- 3D: Only allow MeshInstance3D-inherited nodes in MultiMesh Populate Surface dialog ([GH-84933](https://github.com/godotengine/godot/pull/84933)).
- Animation: Fix imported track flag on sliced animations ([GH-85061](https://github.com/godotengine/godot/pull/85061)).
- Animation: Prevent a crash when calling `AnimationMixer::restore` with an invalid resource ([GH-85428](https://github.com/godotengine/godot/pull/85428)).
- Animation: Fix AnimationPlayer seeking for Discrete keys ([GH-85569](https://github.com/godotengine/godot/pull/85569)).
- Animation: Fix Tween loop initial value ([GH-85681](https://github.com/godotengine/godot/pull/85681)).
- Audio: Fix importing WAV files with odd chunk sizes ([GH-85556](https://github.com/godotengine/godot/pull/85556)).
- Buildsystem: Use Python venv if detected when building VS project ([GH-84593](https://github.com/godotengine/godot/pull/84593)).
- Buildsystem: Fix invalid Python escape sequences ([GH-85818](https://github.com/godotengine/godot/pull/85818)).
- Core: Set language encoding flag when using `ZIPPacker` ([GH-78732](https://github.com/godotengine/godot/pull/78732)).
- Core: Fix crash when hashing empty `CharString` ([GH-85389](https://github.com/godotengine/godot/pull/85389)).
- Core: Prevent infinite recursion when printing errors ([GH-85397](https://github.com/godotengine/godot/pull/85397)).
- Core: Fix property groups overriding real properties ([GH-85486](https://github.com/godotengine/godot/pull/85486)).
- Core: Do not reload resources and send notification if locale is not changed ([GH-85787](https://github.com/godotengine/godot/pull/85787)).
- Editor: Remove exp hint of a few properties ([GH-80326](https://github.com/godotengine/godot/pull/80326)).
- Editor: Fix UV editor not showing polygon correctly ([GH-84116](https://github.com/godotengine/godot/pull/84116)).
- Editor: Inspector: Fix clearing array/dictionary element with `<Object#null>` ([GH-84237](https://github.com/godotengine/godot/pull/84237)).
- Editor: Allow dragging editable children ([GH-84310](https://github.com/godotengine/godot/pull/84310)).
- Editor: Fix errors on file rename or move in the Filesystem Dock ([GH-84520](https://github.com/godotengine/godot/pull/84520)).
- Editor: Fix issue with 3D scene drag and drop preview node ([GH-85087](https://github.com/godotengine/godot/pull/85087)).
- Editor: Fix SnapGrid is almost invisble in light theme ([GH-85585](https://github.com/godotengine/godot/pull/85585)).
- Editor: Fix theme application in various editor dialogs ([GH-85745](https://github.com/godotengine/godot/pull/85745)).
- Export: Fix order of operations for macOS template check ([GH-84990](https://github.com/godotengine/godot/pull/84990)).
- **Export: iOS: Use `mdfind` to check if Xcode is installed in one-click deploy code ([GH-85774](https://github.com/godotengine/godot/pull/85774)).**
  * It's not obvious from the commit, but this should fix freezes that some macOS users have been experiencing when opening Godot if they don't have Xcode installed.
- GDExtension: Fix updating cached singletons when reloading GDScripts ([GH-85373](https://github.com/godotengine/godot/pull/85373)).
- **GDExtension: Fix crash when using incompatible versions of Godot Jolt ([GH-85779](https://github.com/godotengine/godot/pull/85779)).**
  * We knew that old versions of Jolt were crashing in Godot 4.2, but we underestimated how widely used Jolt is, and the fact that it's difficult for users to keep their addons up-to-date with the current Asset Library. So we added a small hack to prevent loading older Jolt versions to avoid that crash. To use Jolt in Godot 4.2, be sure to update it to [0.11.0-stable](https://github.com/godot-jolt/godot-jolt/releases/tag/v0.11.0-stable).
- GDScript: Improve autocompletion with `get_node` ([GH-79386](https://github.com/godotengine/godot/pull/79386)).
- GDScript: Filter groups and categories from autocompletion ([GH-85196](https://github.com/godotengine/godot/pull/85196)).
- GUI: Enable scrolling of output with UI scale changes ([GH-82079](https://github.com/godotengine/godot/pull/82079)).
- GUI: VideoPlayer: Fix reloading translation remapped stream ([GH-84794](https://github.com/godotengine/godot/pull/84794)).
- GUI: Restored Control properties when you undo a parenting of a Control to a Container ([GH-85181](https://github.com/godotengine/godot/pull/85181)).
- GUI: Make sure `Window`'s title is respected before we compute the size ([GH-85312](https://github.com/godotengine/godot/pull/85312)).
- GUI: RTL: Fix CharFX character offset calculation ([GH-85363](https://github.com/godotengine/godot/pull/85363)).
- GUI: Limit window size updates on title change ([GH-85542](https://github.com/godotengine/godot/pull/85542)).
- GUI: Fix size and visuals of the `InputEventConfigurationDialog` ([GH-85790](https://github.com/godotengine/godot/pull/85790)).
- GUI: Limit window size updates on title translation change ([GH-85828](https://github.com/godotengine/godot/pull/85828)).
- Import: Fix memory leak on error paths in tinyexr loader ([GH-85002](https://github.com/godotengine/godot/pull/85002)).
- Import: Fix memory corruption and assert failures in convex decomposition ([GH-85631](https://github.com/godotengine/godot/pull/85631)).
- Input: Fix SubViewport physics picking ([GH-85665](https://github.com/godotengine/godot/pull/85665)).
- Navigation: Fix missing NavigationLink property updates in constructor ([GH-83802](https://github.com/godotengine/godot/pull/83802)).
- Navigation: Fix missing NavigationRegion property updates in constructor ([GH-83812](https://github.com/godotengine/godot/pull/83812)).
- Navigation: Fix missing NavigationAgent property updates in constructor ([GH-83814](https://github.com/godotengine/godot/pull/83814)).
- Navigation: Fix missing NavigationObstacle property updates in constructor ([GH-83816](https://github.com/godotengine/godot/pull/83816)).
- Navigation: Fix memory leak in 'NavigationServer3D' involving static obstacles ([GH-84816](https://github.com/godotengine/godot/pull/84816)).
- Navigation: Fix NavigationRegion2D transform update ([GH-85258](https://github.com/godotengine/godot/pull/85258)).
- Particles: Only allow MeshInstance3D-based nodes in particles emission shape node selector ([GH-84891](https://github.com/godotengine/godot/pull/84891)).
- Plugin: Correctly check scripts that must inherit `EditorPlugin` ([GH-85271](https://github.com/godotengine/godot/pull/85271)).
-


---
title: "Multiplayer in Godot 4.0: Scene Replication"
excerpt: "Create multiplayer games in an instance (pun intended) with the new MultiplayerSpawner and MultiplayerSynchronizer nodes.
Check out the key concepts, and get started with a quick tutorial on how to make a simple game using Godot multiplayer features!"
categories: ["progress-report"]
author: Fabio Alessandrelli
image: /storage/blog/covers/multiplayer-in-godot-4-0-scene-replication.jpg
date: 2023-02-23 11:30:00
---

Howdy Godotters! It's been more than a year since I last wrote on this blog, "... blah blah, blah blah, blah" (cf. [C. L. C. Chuckie](https://en.wikipedia.org/wiki/LeChuck)), and with Godot 4.0 nearing release, it's time to write something to jumpstart you into creating your own multiplayer experience with Godot.

Since the [last blog post](/article/multiplayer-changes-godot-4-0-report-4), we rewrote the scene replication API to be more user-friendly, adding two "configuration" nodes:

- The [`MultiplayerSpawner`](https://docs.godotengine.org/en/latest/classes/class_multiplayerspawner.html) node to configure where nodes can be remotely instantiated by which peer.
- The [`MultiplayerSynchronizer`](https://docs.godotengine.org/en/latest/classes/class_multiplayersynchronizer.html) node to configure which node properties can be synchronized by which peer.

So, without further ado let's see how to create a simple multiplayer game using these new features (jump to the bottom for the full project).

## Scene setup

First of all, let's setup our multiplayer scene:

![Scene Tree of UI nodes for starting client or server](/storage/blog/multiplayer-in-godot-4-0-scene-replication/multiplayer-ui.png)

And wire up the signals to start a server or client:

```
# multiplayer.gd
extends Node

const PORT = 4433

func _ready():
	# Start paused.
	get_tree().paused = true
	# You can save bandwidth by disabling server relay and peer notifications.
	multiplayer.server_relay = false

	# Automatically start the server in headless mode.
	if DisplayServer.get_name() == "headless":
		print("Automatically starting dedicated server.")
		_on_host_pressed.call_deferred()

func _on_host_pressed():
	# Start as server.
	var peer = ENetMultiplayerPeer.new()
	peer.create_server(PORT)
	if peer.get_connection_status() == MultiplayerPeer.CONNECTION_DISCONNECTED:
		OS.alert("Failed to start multiplayer server.")
		return
	multiplayer.multiplayer_peer = peer
	start_game()

func _on_connect_pressed():
	# Start as client.
	var txt : String = $UI/Net/Options/Remote.text
	if txt == "":
		OS.alert("Need a remote to connect to.")
		return
	var peer = ENetMultiplayerPeer.new()
	peer.create_client(txt, PORT)
	if peer.get_connection_status() == MultiplayerPeer.CONNECTION_DISCONNECTED:
		OS.alert("Failed to start multiplayer client.")
		return
	multiplayer.multiplayer_peer = peer
	start_game()

func start_game():
	# Hide the UI and unpause to start the game.
	$UI.hide()
	get_tree().paused = false
```

Then setup our world scene with some physics objects, and add it to the multiplayer scene:

![Scene Tree and 3D view of the multiplayer scene](/storage/blog/multiplayer-in-godot-4-0-scene-replication/multiplayer-level.png)

## Synchronizing properties

So, now that we have our scene set up and peers can connect, let's add a [MultiplayerSynchronizer](https://docs.godotengine.org/en/latest/classes/class_multiplayersynchronizer.html) to our object scene and configure it to sync some of its properties.

Synchronized properties can be configured by selecting them from a list or entering their path.

![Editor view of a scene with a MultiplayerSynchronizer](/storage/blog/multiplayer-in-godot-4-0-scene-replication/multiplayer-synchronizer.png)

Running the game now you will notice that the objects start synchronizing as soon as the client connects.

*Tip:* You can run and debug multiple instances simultaneously from the editor by changing the value in `Debug -> Run Multiple Instances`.

![Editor debug menu](/storage/blog/multiplayer-in-godot-4-0-scene-replication/debug-multiple-instances.png)

## Spawning and despawning scenes

The [MultiplayerSpawner](https://docs.godotengine.org/en/latest/classes/class_multiplayerspawner.html) node automates the process of replicating dynamically instantiated nodes across peers, including when joining mid-game or reconnecting.

This mostly boils down to the following MultiplayerSpawner properties:

- `spawn_path`: Defines the path where the spawner will add the nodes it instantiates.
- `Auto Spawn List`: Defines the scenes to be automatically replicated when added as a child of `spawn_path` by the authority (server by default).
- `spawn_function`: (Optional) Defines a function to be called on all peers when using the `spawn` custom instantiation method.

You can use the [`set_multiplayer_authority()`](https://docs.godotengine.org/en/latest/classes/class_node.html#class-node-method-set-multiplayer-authority) method to control which peer is allowed to instantiate scenes via the spawner (the server by default).

## Selecting levels

Currently, using `get_tree().change_scene_to_packed()` (or `change_scene_to_file()`) during a multiplayer session can be problematic when players join mid-game or re-join a match. While we are working on supporting the `change_scene*` methods out of the box in future Godot releases, it is currently possible to simulate the behavior using a MultiplayerSpawner to spawn the level scene.

This ensures that if our game needs to change the active level, the appropriate one will also be instantiated on connected clients as well as on newly connected ones.

To do that, let's remove our static world from the multiplayer scene, add a MultiplayerSpawner node, and configure it with our level(s) in the "Auto Spawn List".

![Level spawner](/storage/blog/multiplayer-in-godot-4-0-scene-replication/level_spawner.png)

Now let's add a `change_level()` function which instantiates the (selected) level and call it from the `start_game()` function.

```
func start_game():
	# Hide the UI and unpause to start the game.
	$UI.hide()
	get_tree().paused = false
	# Only change level on the server.
	# Clients will instantiate the level via the spawner.
	if multiplayer.is_server():
		change_level.call_deferred(load("res://level.tscn"))

# Call this function deferred and only on the main authority (server).
func change_level(scene: PackedScene):
	# Remove old level if any.
	var level = $Level
	for c in level.get_children():
		level.remove_child(c)
		c.queue_free()
	# Add new level.
	level.add_child(scene.instantiate())

# The server can restart the level by pressing Home.
func _input(event):
	if not multiplayer.is_server():
		return
	if event.is_action("ui_home") and Input.is_action_just_pressed("ui_home"):
		change_level.call_deferred(load("res://level.tscn"))
```

Now the level will be instantiated by the server as soon as it starts, and clients will instantiate it as soon as they connect.

The server can also call `change_level()` at any moment to restart the current level, or to select a different one (as long as the selected level is in the "Auto Spawn List" of all peers).

Additionally, when scenes controlled by a multiplayer spawner contain a multiplayer synchronizer referencing the root node of the scene, the configured "Spawn" properties will be automatically set on remote peers during the spawning process.

Similarly to what we did in the multiplayer scene, we could add one or more MultiplayerSpawner to the level scene to replicate nodes that have a dynamic lifecycle like bullets, powerups, etc.

*Tip:* You can further customize the number of nodes that can be spawned remotely at any given time via the `spawn_limit` property. In this case we can set `spawn_limit = 1` since only one level is allowed to be active at any given time.


## Spawning players

For the player characters we usually need to transfer part of the authority over to the peer which each character represents.

In this scenario it is good practice to use a child node dedicated to the player inputs, and leave the multiplayer authority of the character nodes to the server. This helps maintaining proper isolation between controls and game logic, making the setup less error-prone.

Keeping that in mind, let's create the player scene with a synchronizer for the character itself, and a synchronizer for the player input.

![Player synchronizer](/storage/blog/multiplayer-in-godot-4-0-scene-replication/player_input_sync.png)

We then attach a script to the player input synchronizer and configure it to gather the local input based on the configured authority.

```
# player_input.gd
extends MultiplayerSynchronizer

# Set via RPC to simulate is_action_just_pressed.
@export var jumping := false

# Synchronized property.
@export var direction := Vector2()

func _ready():
	# Only process for the local player.
	set_process(get_multiplayer_authority() == multiplayer.get_unique_id())

@rpc("call_local")
func jump():
	jumping = true

func _process(delta):
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	if Input.is_action_just_pressed("ui_accept"):
		jump.rpc()
```

We handle jumping with a reliable RPC (we don't want to miss the player jumping action!), while we use the synchronizer itself to constantly sync the direction the user wants to go.

We can then move the player character on the main authority by reading the synchronized input state:

```
# player.gd
extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

# Set by the authority, synchronized on spawn.
@export var player := 1 :
	set(id):
		player = id
		# Give authority over the player input to the appropriate peer.
		$PlayerInput.set_multiplayer_authority(id)

# Player synchronized input.
@onready var input = $PlayerInput

func _ready():
	# Set the camera as current if we are this player.
	if player == multiplayer.get_unique_id():
		$Camera3D.current = true
	# Only process on server.
	# EDIT: Let the client simulate player movement too to compesate network input latency.
	# set_physics_process(multiplayer.is_server())

func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# Handle jump.
	if input.jumping and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Reset jump state.
	input.jumping = false

	# Handle movement.
	var direction = (transform.basis * Vector3(input.direction.x, 0, input.direction.y)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()
```

We will then use the server synchronizer to keep the position and velocity in sync and to set the player id on spawn (which will in turn configure the appropriate input authority).

![Server synchronizer](/storage/blog/multiplayer-in-godot-4-0-scene-replication/player_server_sync.png)

Finally, we can add a multiplayer spawner to our level, and use it to spawn players as they connect.

![Player spawner](/storage/blog/multiplayer-in-godot-4-0-scene-replication/player_spawner.png)

```
# level.gd
extends Node3D

const SPAWN_RANDOM := 5.0

func _ready():
	# We only need to spawn players on the server.
	if not multiplayer.is_server():
		return

	multiplayer.peer_connected.connect(add_player)
	multiplayer.peer_disconnected.connect(del_player)

	# Spawn already connected players.
	for id in multiplayer.get_peers():
		add_player(id)

	# Spawn the local player unless this is a dedicated server export.
	if not OS.has_feature("dedicated_server"):
		add_player(1)

func _exit_tree():
	if not multiplayer.is_server():
		return
	multiplayer.peer_connected.disconnect(add_player)
	multiplayer.peer_disconnected.disconnect(del_player)

func add_player(id: int):
	var character = preload("res://player.tscn").instantiate()
	# Set player id.
	character.player = id
	# Randomize character position.
	var pos := Vector2.from_angle(randf() * 2 * PI)
	character.position = Vector3(pos.x * SPAWN_RANDOM * randf(), 0, pos.y * SPAWN_RANDOM * randf())
	character.name = str(id)
	$Players.add_child(character, true)

func del_player(id: int):
	if not $Players.has_node(str(id)):
		return
	$Players.get_node(str(id)).queue_free()
```

We can now run the game and test that connecting to a host will correctly spawn the appropriate level and players, give us control of our character, and properly synchronize the object positions.

![Client and server](/storage/blog/multiplayer-in-godot-4-0-scene-replication/client_server_side_by_side.png)

Here is the [full project source](/storage/blog/multiplayer-in-godot-4-0-scene-replication/project.zip), compatible with current 4.0 RC releases.

And that's it for this long awaited introductory post to the new replication system. More advanced topics like bandwidth optimizations, spawning customized scenes and the visibility system will be discussed in a separate tutorial.

## Reference work

Design proposals: [#3359](https://github.com/godotengine/godot-proposals/issues/3359) and [#3459](https://github.com/godotengine/godot-proposals/issues/3459).

Initial implementation: [#55950](https://github.com/godotengine/godot/pull/55950).

And yes, as the top image hints we are adding multiplayer features to the TPS demo, so as always stay tuned for more ;).


---
title: "Godot 3.2 will get pseudo 3D support in 2D engine"
excerpt: "Godot support for 2D is already mature and most of our users enjoy working with it. There is, however a growing trend of adding 3D layers to 2D games, which can be seen in successful titles such as Hollow Knight or Rayman Origins."
categories: ["progress-report"]
author: Juan Linietsky
image: /storage/app/uploads/public/5ca/776/3d9/5ca7763d99acc514180027.png
date: 2019-04-05 00:00:00
---

# Pseudo 3D support

Godot support for 2D is already mature and most of our users enjoy working with it. There is, however a growing trend of adding 3D layers to 2D games, which can be seen in successful titles such as [Hollow Knight](https://www.youtube.com/watch?v=nvzUzQbkikY) or [Rayman Origins](https://www.youtube.com/watch?v=_umLnGZZBrg).

This is possible because the engines in which such games are made are actual 3D engines using 2D planes. In the end, doing this is possible but it requires understanding and being familiar with how 3D engines work.

#### Same technique in Godot

This is also possible in Godot using the 3D engine, via nodes such as [Sprite3D](https://docs.godotengine.org/en/3.1/classes/class_sprite3d.html), but truth is that this technique requires user to do more work and understand more about how 3D space functions.

Parallax (via [ParralaxBackground](https://docs.godotengine.org/en/3.0/classes/class_parallaxbackground.html)) works to some extent, but it's more aimed to be used as a far away background rather than adding depth to the game play area.

Because of this, a new way to implement pseudo 3D was added to the 2D engine, so the same results can be obtained with pure 2D programming, making it much easier to develop this type of games while using all the existing 2D tools (and assets) Godot provides.

### Canvas layers

Godot 2D engine already has a node named [CanvasLayer](https://docs.godotengine.org/en/3.0/tutorials/2d/canvas_layers.html). Everything that is a child or grandchild of it will render on this layer. The layer index can be specified as a number (and it´s also tree-ordered) to control depth placement, so no real Z positioning is required.

Using this node is a common practice to make user interfaces, because they won´t scroll together with the rest of the Viewport, as layers can move independently.

Yet, moving together with the viewport may actually be desired, so a new option was added: "Follow Viewport". Toggling it on will ensure that this layer will move together with the actual viewport when using a [Camera2D](https://docs.godotengine.org/en/3.1/classes/class_camera2d.html).

### Adding depth

Together with *Follow Viewport*, there is a new "Scale" property. This value allows scaling the canvas while following the viewport. It's a simple setting but it can be used to do "Pseudo 3D" with ease:

In practice, just create your level using several CanvasLayer nodes. Edit them together as if you were using an *Orthogonal* view in 3D:

![cledit.png](/storage/app/uploads/public/5ca/774/33b/5ca77433b020d570359819.png)

In the above screenshots, a few CanvasLayer nodes were created. Aftwerwards, the TileMap from the 2D Platformer demo was brute-duplicated and put in every single of them.

Finally, the "Follow Viewport" option was enabled together with a a scale value. This enables the pseudo 3D effect in each layer.

### Previewing without running the game

Previewing the effect in the editor is very easy, just use the new "Preview Canvas Scale" option in the 2D view menu:

### Limitations

The main limitation of this technique is that it's not possible to move a single object in multiple layers, as they will definitely need to be separate ones (none of the games mentioned above use this, though). This can still be worked around with a [RemoteTransform2D](https://docs.godotengine.org/en/3.1/classes/class_remotetransform2d.html) node, though requires a bit more work.

### Future

This is an experimental feature, so don't forget to give feedback! Also, if you are not one, please consider [becoming our patron](https://www.patreon.com/godotengine), to help accelerate Godot development.


---
title: "Introducing C# in Godot"
excerpt: "The next alpha release of Godot 3.0 is about to be published and it will be the first version that ships with C# support. This post gives an introduction to C# scripting in Godot and how to use it in your project."
categories: ["progress-report"]
author: Ignacio Roldán Etcheverry
image: /storage/app/uploads/public/59e/b96/e71/59eb96e712765766078430.png
date: 2017-10-21 19:19:02
---

Alpha2 is around the corner and I'm glad to announce that it will come with the first usable version of C# as a Godot scripting language.

It's still at an early stage and there is a lot of work ahead, but it's a good opportunity for users to have a first look at it and return feedback.

## Acknowledgements

We did not communicate much about it until the C# support was ready for broader testing in the master branch, but Juan and I have been working on this feature as contractors for the Godot project (I as an intern and Juan as mentor/advisor).

Indeed, when we decided to implement Mono/C# as a scripting language in Godot over a year ago, we reached out to Microsoft with Miguel de Icaza's support to see if they would consider funding this work with a donation. They did, and I'm glad to announce that we received a $24,000 donation from Microsoft, which we used to fund my and Juan's work via our non-profit charity Software Freedom Conservancy.

On behalf of the Godot team, I would like to take this opportunity to thank again Microsoft and Miguel de Icaza for their huge generosity in funding our work on this project.

## Introduction

In order to bring C# programming to Godot, we are [embedding](http://www.mono-project.com/docs/advanced/embedding/) the Mono runtime into the engine. As of alpha2, Godot is using Mono 5.2 and [C# 7.0](https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/) is supported.

I will write more posts about the internals and how things work in the future but, for this one, I would like to focus on introducing the language and how to write Godot scripts with it.

## From GDScript to C#* *

The following will be a short tutorial explaining the basics of C# programming in Godot and some of the differences you can expect when coming from a language like GDScript.

### Scripts and classes

The first thing you must know is how to declare the script class. Unlike GDScript, in C# you must declare your script class explicitly. A file can have many classes; a class must have the same name as its file (case sensitive) in order for Godot to know that it's the script class:

```cs
// Coin.cs
using Godot; // Namespace that contains all Godot types

// Class Coin has same name as its file. Godot will detect it
public class Coin : Node
{
    public override void _Ready()
    {
        GD.print("Hello, Godot!");
    }
}
```

The above example would be the equivalent to GDScript's:

```gdscript
extends Node

func _ready():
    print("Hello, Godot!")
```

As you can see, the C# API's naming convention uses PascalCase _(Note: As of alpha2, there are still a few names in snake\_case. Renaming will be finished for the next alpha or beta release)_. Global scope methods and constants are available in the `GD` class, except those that are math related are located in the `Mathf` class.

### Static typing

Let's check the following code in GDScript:

```gdscript
var player = get_node("player")
# player is an instance of type KinematicBody2D
var on_floor = player.is_on_floor()
```

If you try the following in C#, it will fail to compile:

```cs
Node player = GetNode("player");
// Error: 'Node' does not contain a definition for 'IsOnFloor'
bool onFloor = player.IsOnFloor();
```

This happens because C# is statically typed. `GetNode` can return an instance of any type that derives from `Node`, but `Node` itself does not declare the method `IsOnFloor`. You must cast the instance to `KinematicBody2D` in order to use that method:

```cs
KinematicBody2D player = (KinematicBody2D)GetNode("player");
// or a shorter way, thanks to type inference
var player = (KinematicBody2D)GetNode("player");

bool onFloor = player.IsOnFloor(); // Compiles
```

Note that the previous cast will throw an exception if the returned instance is not of type `KinematicBody2D`. If you prefer it, you can use the `as` keyword, which will return `null` instead:

```cs
var scene = ResourceLoader.Load("res://player.tscn") as PackedScene;
if (scene != null)
    AddChild(scene.Instance());
else
    GD.print("Not of type PackedScene");
```

Another way to check if an instance is of a type in specific, is by using the `is` keyword:

```cs
public override void _Input(InputEvent ev)
{
    if (ev is InputEventMouse)
    {
        var mouseEvent = (InputEventMouse)ev;
        Vector2 mousePos = mouseEvent.Position;
    }
    else if (ev is InputEventKey)
    {
        var keyEvent = (InputEventKey)ev;
        bool aPressed = keyEvent.Pressed && keyEvent.Scancode == GD.KEY_A;
    }
}
```

### Other differences

There are many more examples to mention; for the beta release, we will have a page in the documentation with a list. Here are a few more that I deem important:

- The default constructor for `Basis`, `Transform2D` and `Quat` initializes all fields to the default value. If you want the same initial value as in GDScript, you can use `Basis.Identity`, `Transform2D.Identity` and `Quat.Identity`.
- A few methods of the API return `Variant`. This means they can return anything. In C# those methods return `object` (`System.Object`).

#


# Downloads

{% include articles/download_card.html version="4.3" release="rc1" article=page %}

**Standard build** includes support for GDScript and GDExtension.

**.NET build** (marked as `mono`) includes support for C#, as well as GDScript and GDExtension.
- See also [C# platform support](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/index.html#c-platform-support).

If you want to test the new Windows ARM64 builds, they're not integrated in our download page yet, so here are direct links:
- [Editor for Windows ARM64 (Standard)](https://github.com/godotengine/godot-builds/releases/download/4.3-rc1/Godot_v4.3-rc1_windows_arm64.exe.zip)
- [Editor for Windows ARM64 (.NET)](https://github.com/godotengine/godot-builds/releases/download/4.3-rc1/Godot_v4.3-rc1_mono_windows_arm64.zip)

{% include articles/prerelease_notice.html %}

## Known issues

During the Release Candidate stage, we focus exclusively on solving showstopping regressions (i.e. something that worked in a previous release is now broken, without workaround). You can have a look at our current [list of regressions and significant issues](https://github.com/orgs/godotengine/projects/61) which we aim to address before releasing 4.3. This list is dynamic and will be updated if we discover new blocking issues after more users start testing the RC snapshots.

With every release, we are aware that there are going to be various issues which have already been reported but haven't been fixed yet, due to limited resources. See the GitHub issue tracker for a complete list of [known bugs](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Abug+).

## Bug reports

As a tester, we encourage you to [open bug reports](https://github.com/godotengine/godot/issues) if you experience issues with this release. Please check the [existing issues on GitHub](https://github.com/godotengine/godot/issues) first, using the search function with relevant keywords, to ensure that the bug you experience is not already known.

In particular, any change that would cause a regression in your projects is very important to report (e.g. if something that worked fine in previous 4.x releases, but no longer works in this snapshot).

## Support

Godot is a non-profit, open source game engine developed by hundreds of contributors on their free time, as well as a handful of part or full-time developers hired thanks to [generous donations from the Godot community](https://fund.godotengine.org/). A big thank you to everyone who has contributed [their time](https://github.com/godotengine/godot/blob/master/AUTHORS.md) or [their financial support](https://github.com/godotengine/godot/blob/master/DONORS.md) to the project!

If you'd like to support the project financially and help us secure our future hires, you can do so using the [Godot Development Fund](https://fund.godotengine.org/) platform managed by [Godot Foundation](https://godot.foundation/). There are also several [alternative ways to donate](/donate) which you may find more suitable.


---
title: "Optional typing in GDScript"
excerpt: "Exposing the new addition to GDScript: optional type hints and all the perks it brings."
categories: ["progress-report"]
author: George Marques
image: /storage/app/uploads/public/5b1/f4f/b2f/5b1f4fb2f023a968578982.png
date: 2018-07-22 17:11:27
---

While GDScript is made with the ease-of-use in mind, many people wanted to add type information into their scripts. This helps avoiding potential bugs and also allows a better code completion. We're now introducing an additional syntax to add type hints to your GDScript code. It is completely optional and old scripts will work as they always did.

**Note:** This is a new feature in the *master* branch, and will be available in Godot 3.1.

## How the type hints can help?

It is quite common to use a variable only with values of the same type. With the dynamic nature of GDScript, you can inadvertently overwrite a variable with a different type and break your code logic in a way that might be hard to realize.

For instance, if your function expects a number, but you missed an input validation somewhere and is passing a string to it instead, you only will see an error at runtime (and only if you reach that point). In a larger code base, it's quite easy to miss things like that.

With type hints, Godot can know beforehand that you are passing the wrong type and show an error while you are editing the related code, even if you never run it.

## Syntax

This is quite a controversial topic (like tabs vs. spaces) and everyone has their own preference that's based on their background in other languages. We adopted a post-fixed type syntax that is very similar to Python (yes, Python has type hints too). This was chosen because GDScript is already similar to Python and this style is easy to integrate in the language parser, also considering that it is still optional.

For variables and constants, you can add a type hint with a colon (`:`) after the name when declaring it. Constants don't need type hints, since their type is inferred from the assignment, but you can add one as well:

```
const GRAVITY : Vector2 = Vector2(0, 9.8)
var power : float = 150.0
```

Type can be inferred from the assigned value if you add the colon (`:`) but omit the type. This can make the code more concise:

```
var direction_vector : = Vector2(1, 0)
# direction_vector is of type Vector2 because of the assigned constant
var my_sprite := $MySprite as Sprite
# my_sprite is of type Sprite because of casting
```

Functions follow the same syntax for the arguments. For the return type, you use a forward arrow (`->`) along with type before the colon to start the function body:

```
func my_func(arg1 : int, arg2 : String = "") -> void:
    return
```

Casting types is accomplished by using the `as` keyword. For built-in types, it errors out if it's not possible to convert. For objects it simply returns `null`:

```
var number_input : int = $LineEdit.text as int
var my_sprite : Sprite = $Sprite as Sprite
```

The type can be: a built-in Variant type (`int`, `Vector3`, `Color`, `Basis`, etc.); a core class (`Node`, `Resource`, `File`, etc.); a named constant that contains a Script resource (`const MyClass = preload("res://my_class.gd"`); a named script class (one made with the `class_name` syntax).

## Introducing the concept of "safe lines"

As suggested by our dear core developer reduz (Juan Linietsky), GDScript now has "safe lines" marked in the editor. The reasoning behind this is that the duck-typing should still work as it always did, so it's not possible to error if some variable or function is not defined on the accessed class.

Something very common is to tell an animation player to start like this:

```
$AnimationPlayer.play("walk")
```

With the type inference, Godot knows that `$AnimationPlayer` is a `Node` but can't tell which subtype it really is (in this case an `AnimationPlayer`). Since the `play()` function is not defined on the inferred type (Node), the engine don't know at this point if it really exists, nor the types for arguments and returns.

A statically typed language, such as C++ and C#, would force you to explicitly cast to the specific subtype, otherwise it would throw an error. So you'd need to do this:

```
($AnimationPlayer as AnimationPlayer).play("walk")
```

This is inconvenient most of the time for GDScript. Many times it's not even really needed. Instead of erroring out, the editor now shows a subtle greenish highlight in the lines that are safe according to type hints:

![Safe line highlight](/storage/app/media/safe-line.png)

Some users might find this *too* subtle. This is actually the idea: it should not stand out for people who aren't really interested in it. In any case, you can change the color in the editor settings and also disable the highlight if you prefer the old full-dynamic style.

## Code completion

The type inference code to provide completion candidates and function hints was rewritten. It fixed some long-standing annoying bugs. The experience is much improved, even if you are not using the type hints.

If your code has type hints, it provides a proper completion even across scripts. This includes singletons and scripts attached to other nodes in the tree.


## How it was implemented

Since many people seem to be interested in the devblogs, I'll add a section here explaining how I did the changes to enable the optional typing in GDScript.

### Tokenizer

The first part of parsing a language is to split the code in recognizable *tokens*. The symbols (`+`, `>=`, `|`), keywords (`if`, `func`, `class`), literal values (`2`, `"string"`), and identifiers ( `Vector2`, `Node`, `my_var`) are all changed to an abstraction This helps the next phase, since it won't need to deal with text anymore, but just a series of tokens. Then all whitespace and comments will simply be ignored and don't have to be taken into consideration.

The changes in the tokenizer are minimal, only to introduce the forward arrow symbol (`->`) and the casting keyword (`as`).

A peculiarity in the compiled scripts on export is that they are stored as a sequence of tokens. Using this new tokens in an old Godot version will cause a big problem. This is avoided by having a version number that was incremented with this change. So compiled scripts in this version won't run with older export templates (that's one reason why it's important to match editor and template version).

### Parser

The next step is make the new syntax be recognized by the parser. A parser takes the sequence of tokens and from them develop a tree structure. This tree resolves what each line is doing and also sorts out the order of operations based on their precedence.

The GDScript parser is relatively simple, so it's just a matter of understanding the small decisions it make to know what's a function declaration, what's a function call, what's an assignment, etc. I looked into the declarations of variables, constants, and functions to enable the parser to recognize the type hints (though it would simply discard them for now). The expression-parsing routine was also change to detect the casting operation.

Casting is a new type of node in the tree, since it'll be handled by the compiler in a particular way.

### Moving inheritance resolution

The old GDScript only resolved the inheritance when compiling the script, which only happens if you save the script and show errors only when you try to load it (i.e. not when you edit it). However, the parser needs this information to know the types of members declared in the parent.

I moved this code from the compiler to the parser (with all the needed adjustments). The compiler simply uses the information from the parser to avoid looking it again. There was also another change in the compiler to fix the order if you are using inner classes, allowing you to reference classes later in the file without problems.

### Static type checks

Now the parser makes the tree and determine the inheritance. Then a pass on the built tree is needed to check if the types used in the code are compatible or not. It is by far the biggest change in the code.

![Static type check](/storage/app/media/type-error.png)

This is done by looking into each statement and applying type-resolution and type-checks depending of the kind of statement. E.g. if it's an assignment, check if the expression type matches the variable being assigned. This also requires knowing what are the base types of the objects, which can be solved now that the inheritance is resolved in the parser itself.

Another required change is having autoload singletons loaded in the editor. This way the parser can look at them as well when trying to figure out the types. That change was added earlier with another pull request.

### New typed instructions

After the parser is done, changes are need in the compiler and the GDScript bytecode to support the type information. GDScript bytecode can be seen as kind of "machine language" that runs on top of the engine core. The compiler is responsible to take the parse tree and create this lower level code.

The new instructions allow a runtime-check in the types that could not be determined in the parser. Albeit this might make things *slower*, it guarantees that the variables will always have the proper type. Since it's different dealing with built-in types, core classes, and scripts, three new assignment instructions were created to deal with each of them. The same applies to the casting operation.

The compiler changes are required to make use of those new instructions, and also to handle the new type of parser node (for casting).

### Editor niceties

With the backend done, it was time to move into the editor. First and somewhat simpler, I added a colored highlight to the type hints, to help visualizing then in the code. Thanks to the work of Paul Batty ([Paulb23](https://github.com/Paulb23)) who isolated the syntax highlighter to the GDScript module, it was simpler to add this small change that didn't need to affect the core.

For the safe lines, however, it required a change in TextEdit and in the script editor to support it.

The completion code was rewritten. It was quite hacked since it grew organically over time, so it was hard to add new features to it. With the new code it can better make use of the type hints, and also fix some long-standing bugs that made the completion not so pleasant to use.

The new code use the old only as reference. The type inference was improved to consider some other cases (like the returned value from a function) and also to heavily rely on recursive structures, making it simpler to supported indexed variables and methods.

## Future

With optional typing, it's possible to improve GDScript further in other directions. Some of the benefits may also apply to people who are not using the type hints. The ideas for the futures are:
co
- Enable type hints for signals.
- Add a system to show warnings in the editor. This allows the game developers to catch things that are not invalid but may cause issues.
- New instructions for typed code to allow faster execution. This includes avoiding the Variant evaluator and using typed arrays as well.
- Further optimizations in the compiling stage to remove redundant instructions, reduce constant expressions to final constant, among other things.


---
title: "Editor improvements for Godot 4.0"
excerpt: "If you are following my progress, you might have noticed that I took a two month break from rendering to work on many long standing editor improvements and features."
categories: ["progress-report"]
author: Juan Linietsky
image: /storage/app/uploads/public/606/23c/e43/60623ce430cfe148969930.jpeg
date: 2021-03-29 00:00:00
---

If you are following me on [Twitter](https://twitter.com/reduzio) (where I post my progress on different Godot features I work on), you might have noticed that I took a two month break from rendering to work on many long standing editor improvements and features.

While I am far from being the only contributor working on editor-related tasks, I put together a list of everything I have been working for the past two months!

### Improved Subresource Editing

With the new inspector in Godot 3.1, a lot of new possibilities opened, including the ability to open sub-resources in the same inspector tab. Before this, users had to go back and forth in the list of properties of each sub-resource, which was very confusing.

The new inspector worked well, but on the visual side we never really managed to nail how to deal with sub-resources. After asking the community for help and ideas, some work as put into it which hugely improved usability.

![inspector_subresources.png](/storage/app/uploads/public/606/234/b98/606234b9803d7721021210.png)

The final version does a bit less color shifting by default so it's a bit more homogeneous. Also, the new layout makes it much clearer where each subresource begins and ends.

### Improved and reorganized Project Settings

The Project Settings dialog has seen a makeover. The categories have been reorganized to make more sense and reduce bloat and a new "advanced" mode has been introduced.

This new mode removes most project settings other than the basic ones to ensure that new users don't feel overwhelmed by the huge amount of options and flexibility and can learn their way through the most important customization options available.

Once confident enough, the "advanced" tab is set, which allows for editing of the rest of the settings as well as the extra customization options.

![fsvideo.gif](/storage/app/uploads/public/606/236/cd3/606236cd3aaaa846188732.gif)

Once enabled, the "advanced" setting is remembered for the current project.

### Improved Process/Pause mode

While not entirely an editor feature, Godot 4.0 unifies the process and pause settings into a single menu. This allows for disabling of nodes in a tree fashion. This was one of the most user-requested features, as Godot allows for easily hiding nodes but not disabling them.

![processmode.png](/storage/app/uploads/public/606/237/5a7/6062375a7b56e842890373.png)

Additionally, as can be seen above the scene tree editor will show the disabled nodes in a more grayed out fashion.

### Preview Sun and Sky

Another very requested feature was also implemented, which is the ability to have a preview light and preview sun in the 3D editor. The new dialog was created mainly with two goals:

* Allow to have a quick frame of reference regarding to lighting when importing or editing 3D scenes stand-alone.
* Give new Godot users the ability to visualize their assets with a default set of high quality settings, as it is always a common source of confusion that, when just imported, assets look too plain in Godot.

![preview_sun_sky.jpeg](/storage/app/uploads/public/606/238/ab8/606238ab83faa358200840.jpeg)

As these settings are only meant for preview, they won't be visible when running the game but both have a quick way to create the _actual_ nodes based on these settings with just a button press at the bottom.

When either nodes (DirectionalLight3D or WorldEnvironment) exist in a scene, the preview setting also disables automatically, ensuring consistency and ease of use.

### Default Importer Settings

Another common problem Godot users run into is that setting default values for certain types of imported assets was confusing. This is resolved by the new "Default Importer Settings" tab in the Project Settings dialog.

![default_importer_settings.jpeg](/storage/app/uploads/public/606/239/8ce/6062398ce1d11236821896.jpeg)

Thew new tab allows to precisely customize importer options for each type of resource. This feature was also back-ported to Godot 3 and will be available on the upcoming Godot 3.3 release.

### New 3D asset import workflow

Importing 3D assets was a hit or miss experience in Godot. Import options were limited to a tiny "Import" menu that attempted to do too much and fell short.

The new importer has an "Advanced" mode, which allows to precisely customize every individual node, mesh, material and animation.

![new_3d_importer.jpeg](/storage/app/uploads/public/606/23a/63b/60623a63b1f01150089329.jpeg)

Additionally, handling of external assets was re-thought. In Godot 3.x, assets are simply saved to file by name, which can be very confusing or create chaotic situations when overwriting files.

In the new importer, this process is done via manual steps, so the user has more control on which assets are moved to external files, which paths are used, etc.

![importer_assets.jpeg](/storage/app/uploads/public/606/23a/e6d/60623ae6de535875757353.jpeg)

As a result, it's more obvious where everything goes and what's happening during the import process.

The new system also solves the problem of assigning external materials to replace the ones in the imported file in a very elegant way, allowing to either make the materials that come with the asset external, or just replace them by existing external ones.

### Ability to "keep" files

Often, users would prefer that Godot does not import some files (like PNG, CSV, etc) and deal with them manually during the game run-time.

This is now possible with the "keep" option. When selected, the assets will be kept and put in the game export "as-is".

![keepfiles.png](/storage/app/uploads/public/606/23b/cc0/60623bcc0ddb6675929183.png)

### Threaded importing

Another very common problem users face in Godot is the long time it takes to import large amounts of images. To aid this, the new importer has been reworked to operate using multiple threads.

This results in a performance improvement of over ten times (if you have a modern computer with multiple cores).

### Future

With the editor work done, I will now go back to working on rendering for the next month to finalize the missing bits and pieces pending in my TODO list. Afterwards, it will be time to start working towards our first Godot 4.0 alpha! And again, remember we do this out of love for you and the game development community so you can have the best possible engine we can make with the same freedom as if you made it yourself.

If you are not, please consider [becoming our patron](https://www.patreon.com/godotengine)!