Creating a Godot Engine-based simulator
In this tutorial, we’ll use the Godot game engine to create a simple, not-so-fancy simulator that serves as a barebones boilerplate for Godot-based simulators prepared for distributed simulation using the Inhumate RTI.
You’ll create a simple “walking simulator” where the player can move around using W, A, S, and D, drop boxes, and interact with the physics engine. Not exactly an exciting player experience, but it is a straightforward way to structure the project to take advantage of Inhumate Suite features. The simulator will support recording, playback, co-simulation (multiplayer), and much more.
Setup the project
Create a new Godot project and prepare it with the Inhumate Godot integration package.
Note: This tutorial requires .NET SDK and the Godot Engine - .NET with C# support.
-
Download the integration package from the Inhumate website
-
Create and start a new project.
-
Create a new folder in your
res://inFileSystem. Name itaddons. -
Go to the
AssetLibtab, clickImport..., select the package zip file, change install folder to the addons folder, checkIgnore asset root, and finally clickInstall. -
Verify that the package has been added in your filesystem.
-
Project > Tools > C# > Create C# solution.
- Add required NuGet Package by doing one of the two:
- Run this command in your project folder:
dotnet add package Inhumate.RTI- Add this to your project’s
.csprojfile:
<ItemGroup><PackageReference Include="Inhumate.RTI" Version="1.5.1" /><ItemGroup> -
Build project by pressing the hammer icon.
-
Project Settings > Plugins tab > check
Enabled - Finally, reload the project and you’re ready to use the Inhumate integration package!
Create the environment
In this section, we’ll create a simple enclosed arena to serve as the playing field and an interactive box scene.
- Add a
Node3Das the root, save the scene, and name it (optional)demo. - Make a square “arena” by using either
StaticBody3Dcombined withCollisionShape3DandMeshInstance3D, or multipleCSGBox3Dwith aCSGCombiner3D. Enable collision. See image below for reference. - Add
DirectionalLight3D. -
Create a Rigidbody cube scene with required nodes. Name it
box. This scene will be used later.
You should now have a playable level scene.
Create the player
Next, we’ll set up the player and enable basic movement and spawning of boxes.
- Create a Rigidbody capsule scene and name it
player. Add required nodes. - In the Rigidbody node, set
Massand linear, angularDampall to 10. EnableAngular XandAngular ZinPhysicsBody3Daxis lock. This will make movement implementation easier. - Add
Camera3Das a child. This will be your point of view when playing. Adjust it to your liking. -
Make a simple player controller script that moves the player with
W,A,S, andDand instantiate the cube scene by pressingB.Start by adding your members, and switch camera if you have multiple:
@onready var camera = $Camera3D @export var box_scene: PackedScene @export var move_force: float = 1000.0 @export var turn_torque: float = 50.0 @export var spawn_distance: float = 3.0 # Called when the node enters the scene tree for the first time. func _ready() -> void: camera.make_current()Add the
_physics_process()function and add your code for the player movement:func _physics_process(delta: float) -> void: var forward_input := 0.0 var turn_input := 0.0 # W / S movement if Input.is_key_pressed(KEY_W): forward_input += 1.0 if Input.is_key_pressed(KEY_S): forward_input -= 1.0 # A / D turning if Input.is_key_pressed(KEY_A): turn_input += 1.0 if Input.is_key_pressed(KEY_D): turn_input -= 1.0 # Forward/back force if forward_input != 0.0: var forward_dir = -transform.basis.z apply_central_force(forward_dir * forward_input * move_force) # Rotation torque if turn_input != 0.0: apply_torque(Vector3.UP * turn_input * turn_torque)And instantiate your box scene with
_input():func _input(event: InputEvent) -> void: if event is InputEventKey and event.pressed and not event.echo: if event.keycode == KEY_B: _spawn_box() func _spawn_box() -> void: if not box_scene: return var instance: Node3D = box_scene.instantiate() var forward = -global_transform.basis.z var spawn_pos = global_transform.origin + forward * spawn_distance get_tree().current_scene.add_child(instance) instance.set_deferred("global_position", spawn_pos) - Attach the script and add your box scene in the inspector. Place the player and try playing the scene. Move around, drop boxes, and interact with them while being constrained by the arena.
At this point, the player, boxes, and arena are set up. You can now explore the basic features of the Inhumate Suite in this environment.
Add RTI nodes
Let’s add some nodes from our RTI Godot integration package and then look at the results in Inhumate Viewer.
Note: These nodes determine how scenes are represented in the Viewer and handled in the RTI. Feel free to change the values to suit your needs.
-
Add
RTI Static Geometrynode to the arena walls and floor. -
Add
RTI EntityandRTI Positionnodes to the player scene. Set theTypeandSizeproperties.

-
Add
RTI EntityandRTI Positionnodes to the box scene. Set theTypeandSizeproperties.

Start Inhumate Viewer. When you run the project, you should see the player and the arena in the 3D tab in the viewer.

Support runtime control and scenario loading
Now we’ll prepare the project for runtime control and scenario loading using the RTI by creating a new scene and some configuration.
- Create a scenario by right-clicking in your filesystem and creating a new resource. Search
RTIScenarioand click create. -
Open the scenario, name it, add your demo scene, and optionally add a description.

- In your
res://folder, find and openrtisettings.tres. -
By default,
Home Sceneshould be filled. If not, add thedefaulthome.tscnscene from the package. Add your scene in theScenariosproperty.
- Change your Main Scene in project settings to
defaulthome.tscnfrom the package.
Now, if you run the project, you should be able to select your scenario and press Load from the runtime control in Inhumate Viewer. Your demo scene has now loaded. Press Start and run around, spawn and interact with boxes and see the viewer mirror your actions. Try the other controls: Pause, Stop, and Reset.
Support playback and co-simulation
To support playback and co-simulation, the scene needs an RTI spawner that dynamically adds entities (the player and spawned boxes).
- Remove the player from your demo scene. Spawning will be handled by the RTI spawner.
- Create a copy of the player with the controller script excluded. Name it
PlayerPlayback. This object will act as a “remote representation” during playback, ignoring any inputs. - Create multiple empty
Node3D(three is fine) and place them around the arena. These will act as spawn points. - Add the
RTISpawnernode to your demo scene. - In the spawner node, add the box and player playback scenes in
Spawnable Entitieswith their respective types. -
Specify the player scene and add the player spawn points.

With this setup, you are ready to test playback and co-simulation using Inhumate Recorder.
- Load a scenario, press
Start, play for a bit, then pressStopfollowed byPlay. - Replay earlier recordings using the three dots menu and selecting
Play. - Run another instance of the project to test co-simulation and verify you can see the other player.
Conclusion
You have now completed the basic setup for integrating the Inhumate Suite with a Godot project. Playback and co-simulation should be working, and you are ready to continue experimenting with additional features and configurations.