How to Make a Walking Simulator in Godot 4

You can access the full course here: BUILD A WALKING SIMULATOR WITH GODOT 4

Embark on an exciting journey to create your very own immersive walking simulator in Godot – where stunning landscapes and captivating storytelling await your first steps!

Walking simulators are a great genre that incorporate environment and story-telling – but they would be nothing without a robust interaction system. Interactions bring any game to life by providing depth and promoting player engagement. From simple actions like picking up items to complex puzzles or dialogues with NPCs, an effective interaction system is a vital part of game development.

In this tutorial, we will be focusing on creating an interaction system using the Godot Engine with a specific focus on applications for walking simulators. Through this, we will explore object creation, how to display prompts, and interaction execution using scripts. While you are expected to know some Godot and GDScript, you can also explore our full course, Build a Walking Simulator with Godot 4 for more guided assistance on building your walking simulator.

Without further delay, let’s dive into this core system for walking simulators.

Project Files

To help you follow this walking simulator tutorial smoothly, we have compiled the necessary assets seen in this course. You can download the project files from the link below and reference them alongside the tutorial.

Download Project Files Here
CTA Small Image

Interaction Controller – Part 1

Let’s start with implementing our walking simulator interaction system in Godot. This system will allow us to look at an object, display a prompt on the screen, and interact with it. We’ll start by creating nodes for our player using a Raycast 3D.

Setting up the Player Controller

First, we need to set up our player controller. Go to the player controller and add a new child node to the Camera 3D, named Raycast 3D.

Godot Camera3D with RayCast3D node being added as a child node

You can think of Raycast 3D as a laser that can point in a direction and fire off. We can choose how far we want to fire it and it can return information about whatever it is hitting.

By default, the raycast is pointing down. However, we want it to point forward. So, in the inspector, set the target position to be zero on the x, zero on the y, and negative two on the z.

Inspector for Raycast3D object in Godot with Target Position properties edited

Now, you can see that the blue line is pointing forwards.

Godot with Raycast line now pointing in the player's forward direction

Rename this raycast to “interaction controller”.

InteractionController as now seen in Godot's Scene Hierarchy

Adding the Interaction Prompt

Next, we need to add the interaction prompt. This is the text that will appear on the screen when we are hovering over an interactable object in our walking simulator. It will give us a prompt so we can see what the interaction is going to do.

Add a child node to the interaction controller and create a label.

Creating a child node of type Label in Godot

This label will switch us into 2D mode because we are now working with UI. Increase the size of the box that appears.

Godot UI label with increased box size

At the top of the viewport, there’s a small circular green button. This is where we can choose our anchor presets. Since our text box will be in the middle of our screen, select the center preset. This will move the anchor points down to the center, ensuring that the text box maintains its central position no matter how we resize our screen.

Setting the Godot label to be center anchored

Next, add some example text to the label. For instance, you might have a square bracket, the key to interact (which could be “E”), and a description such as “Pickup item”.

Example text for Godot label

Rename this label to “interaction prompt”.

InteractionPrompt label as seen now in Godot's Scene hierarchy

Finally, adjust the alignment and font size of the text. Set the horizontal alignment to be center, vertical to be center…

Horizontal and vertical alignment properties for Godot label set to Center

… and increase the font size to around 24.

Godot Label settings with font size set to 24

This should give us some large, centered font.

Godot label with newly adjusted settings from previous steps

By default, we want the text to be empty because we don’t want it to appear on the screen when we’re not interacting with something. So delete the text after you finish adjusting the text how you want for your walking simulator

Creating the Interaction Scripts

Now, it’s time to create two scripts. The first script will be called “interactable object”, and the second will be “interaction controller”. These will form the core of our interaction system for our walking simulator.

Creating a new GDScript script in Godot for interaction controller

Let’s start with the “interactable object” script. This script will be attached to all the objects we want to interact with.

class_name InteractableObject
extends Node3D
@export var interact_prompt : String
@export var can_interact : bool = true
func _interact():
  print("Override this function.")

We’re giving it a class name of “InteractableObject” because we want to access this node of a specific type in our other script. The variables in this script include an “interact prompt” of type string, which will show to the player when they hover over the object, and a boolean “can interact”, which determines if the player can interact with the object at a certain time.

The “_interact()” function is a placeholder that will be overridden with specific interaction logic in derived classes. This script will act as the parent class, and any children (doors, objects, lights, etc.) will be inheriting this script and having access to its variables and functions.

Next, let’s move to the “interaction controller” script.

extends RayCast3D
@onready var interact_prompt_label : Label = get_node("InteractionPrompt")
func _process(delta):
  var object = get_collider()
  interact_prompt_label.text = ""
  if object and object is InteractableObject:

This script extends a RayCast3D node to detect interactive objects in a 3D environment. It gets the collider of whatever object it is currently hitting in the walking simulator. If the object exists and is of type InteractableObject, then it can continue on with the if statement.

Interaction Controller – Part 2

In this next section, we will continue building our interaction system in the Godot engine by creating an interactable object for our walking simulator. This object will have a function that will be called when the player interacts with it. We will also set up an interaction prompt that will appear on the screen when the player is looking at an interactable object. Let’s get started.

Building the Interaction Controller

The first thing we need to do is to modify our interaction controller script. The interaction controller is responsible for checking if the walking simulator player is looking at an interactable object and calling the interact function on that object when the player presses the interact key.

Here’s the code for our interaction controller:

extends RayCast3D
@onready var interact_prompt_label : Label = get_node("InteractionPrompt")
func _process(delta):
  var object = get_collider()
  interact_prompt_label.text = ""
  if object and object is InteractableObject:
    if object.can_interact == false:
    interact_prompt_label.text = "[E] " + object.interact_prompt
    if Input.is_action_just_pressed("interact"):

In this script, we first get a reference to the object that the player is currently looking at using the get_collider() function. We then check if this object is an instance of the InteractableObject class and if it can be interacted with. If it can, we update the interaction prompt label with the object’s interaction prompt and check if the player has pressed the interact key. If the player has pressed the interact key, we call the object’s _interact() function.

Creating an Interactable Object

Now that we have our interaction controller set up, let’s create an interactable object in an actual walking simulator. For this example, we will create a pedestal that turns on a light when interacted with.

Pedestal scene added to demonstrate interaction controller in Godot

Here’s the code for our interactable object:

extends InteractableObject
@onready var light_bulb = get_node("LightBulb")
func _interact ():
  light_bulb.visible = true
  can_interact = false

In this script, we first get a reference to the light bulb node. We then override the _interact() function. When this function is called, we make the light bulb visible and set can_interact to false to prevent further interactions.

Testing the Interaction System

With everything set up, we can now test our interaction system. If everything is working correctly, you should be able to walk up to the pedestal, see the interaction prompt, and turn on the light by pressing the interact key.

Demonstration of the pedestal interaction in Godot

This is just a simple example of what you can do with this interaction system – whether for a walking simulator or something else. You can easily extend this system to create more complex interactions, such as collecting items, solving puzzles, or interacting with NPCs. The possibilities are endless!

Walking Simulator Wrap-Up

In this tutorial, you’ve learned how to develop an effective interaction system in the Godot Engine. This interaction controller that can effectively detect and respond to interactable objects within a game’s 3D environment. A basic interacting object with a functioning interaction trigger was also created.

You can now use this knowledge as a foundation to design more complex interactions for your walking simulator game, be it complex puzzles, object collections, or character dialogues. Continue practicing and experimenting to master these skills for a more immersive game experience.

Of course, this is just one component of walking simulators. If you’d like to learn more, Zenva’s Build a Walking Simulator with Godot 4 course expands on these topics – with techniques that can easily be applied to other Godot games as well.

Good luck with your future endeavors in game development!

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.

Transcript – Interaction Controller – Part 1

Welcome back everyone. In this lesson, we are going to begin looking at implementing our interaction system. This is going to basically allow us to look at an object, have a prompt appear on screen, and then basically interact with it to do whatever we want. Okay, so how do we do this? Well, pretty much what we’re going to do is we’re going to start by creating our nodes for our player. This will be possible by using an array cast. I’m going to go to my player controller here.

I’ll right-click on the camera 3D and add a new child node called a Raycast 3D. Raycast 3D, the best way of thinking about this is it is basically like a laser. We can point this laser in a direction and fire it off, but we can also choose how far we want to fire it and it can then return to us information about whatever it is hitting. By default, this raycast is pointing down, so in the inspector, we’re going to set the target position to be zero on the x, zero on the Y, and negative two on the Z.

Thus, the blue line is pointing forwards. I’m actually going to go ahead and rename this recast to be our interaction controller. We can also add in our text. The text is going to appear on screen when we are hovering over an interactive object, giving us a prompt so we can see what that interaction is going to do. We can then interact.

I’m going to right-click on our interaction controller, add a child node, and create a label. This label switches us over into 2D mode because we are now working with UI. I’ll increase this box and then at the top of our viewport, I’ll click on this little circle green button for our anchor presets. Since this is going to be something in the middle of our screen, I’ll click on the center preset right here, which moves the anchor points down to the center. So no matter how large or small we resize our screen, this text box is always going to maintain its central position.

We can now give it some example text. For instance, we might have a square bracket, our key to interact, which is going to be E, and then we might have something such as a pickup item. This is what the text would look like. Let’s rename this to be our interaction prompt.

Our text looks a bit weird at the moment. It’s sort of at the top left corner. So I’ll adjust the horizontal alignment to center, vertical to center and go to label settings to increase the font size. We can then press play and see what it looks like. So, when we’re hovering over an item, you could imagine that prompt appearing.

By default, we’re going to set the text to be nothing because we don’t want that appearing on screen when we’re not interacting with something. We will then go ahead and create two scripts. The first script in our file system is called interactable object.

Our next script will be the interact controller. I’m actually going to select our interaction controller node here because when we create a script it’s going to automatically inherit from recast 3D, which is what we want. So we have two scripts. We have the interaction controller, which is attached to our recast node, and we have an Interactable controller, which is just existing in our file system.

We will start with the interactable object script because it is what we are going to attach to everything we want to interact with. This will be a pretty small script. We’re going to give it a class name of Interactable object, and we are also going to extend from node 3D. We are giving it the name of Interactable Object because we want to access this node of a specific type in our other script. Giving it a class name is just going to make it easy in the script to access and modify the variables and functions we have here.

In terms of variables, we’re going to have two; interact prompt type sting and Can Interact type Boolean which will be true by default. We will also have one function, and this is going to be called underscore interact. This script is not what we are going to be attaching to our objects we want to interact with. Rather this script will be a script we are going to inherit from. Each inherited class doors, objects, lights will have access to the variables and functions from the parent class and we can override the functions.

Now, let’s move to the interaction controller. Here we can delete the ready function since we will not be needing that, but we are going to keep the process because we will be using it. We’re going to create an onready variable called interact prompt label. Every single frame we need to get whatever object we are looking at. So if the object exists and if it is of type interactable object, then we can continue on with the statement.

So, in the next lesson, we are going to continue on with this function and actually create ourselves an interactable object to see it in action. Thanks for watching and I’ll see you all in the next lesson.

Transcript – Interaction Controller – Part 2

Welcome back, everyone. Let’s continue on with our script. So what we need to do now is we have, well first of all, we have already in the process function gone access to whatever collider we are currently looking at. We are setting our prompt label to be empty and then down here we are checking to see if the object we are hitting exists. And if that object is of type interactable object, then we are going to run the code down here.

Now if the object that we are looking at it cannot be interacted, okay, in our interact object we have that can interact balling. If that is false, then we want to return. So if object can interact equals, equals false, then return because we don’t want to do anything if we are unable to interact with it.

Now, otherwise, if we can interact with it, we are going to set our prompt label. So interact, prompt label text equals and we’re going to have the little E here so that we know what button to press and then go plus object dot. And then we can access the interact prompt variable here. So dot interact, prompt, there we go.

And then finally we need a way of actually detecting when we have pressed the interact key to then call the attract function. So here we’re going to go, if input is action just pressed interact, then we are going to go object interact, okay? And we are calling that interact function right here. So there we go. That is pretty much it for our interaction controller.

Now let’s look at actually setting up an interaction inside of our project. Okay, I’ve got a little scene here set up with some trees and some rocks. And what I’m going to do is I am going to make it so that we are going to have these little pedestals placed around and whenever we walk up to one of these pedestals and interact with it, it is going to turn on a light.

So if we go to the modus folder, this is all included in the course files tab. You should see there is a pedestal ts cn. I’m just going to drag that in here and it is going to create us this object right here. And on this object we are going to create a new script. So we can just go ahead and yeah, we can just create a new script on it right here. And I’m just going to call this one pedestal interaction. Okay?

Now we can delete all of the code we have here and we want to extend it from interactable object. Extending it from interactable object means that we have access to the interact function as well as these two variables here. So if we save this and we select the pedestal here in our scene view, you’ll see in the inspector we have the interact prompt that we can assign. So maybe we can say a turn on and we can also enable if we can or cannot interact with it.

So what we now need to do is we need to first of all set up a function that is going to override the interact function on interactable object. Because remember whenever we interact with this, it is calling this function here and we have this print line of code. But what if we want to add our own logic? Well, to do that we can override the function and this is done by just creating the exact same function name. So we’ll go funk, interact, and in here we will just print out, turn on light for now just to see if it works.

So what we’re doing here is since we are extending from the interactable object script, whenever we create a function with the exact same name as exists in this script, we are overriding it, meaning that when the interact function is called, it is called here instead of in the base interactable object script. So let’s save this, let’s press play and see if it works. So we can walk up to the pedestal here and if I look over it, it says turn on. If I press E, you can see down in the output it is printing out that message, which is great.

Now let’s make it so this light here is first of all going to start off in the off state. So let’s open up that pedestal scene by just clicking on the open in editor button here we’ll select the light bulb object and this light bulb object. We want to go to visibility and disable that. Okay, so inside of our script, what we then want to do is create a variable for the light bulb. So on ready var light bulb. And this is going to equal get node. And this node here is going to just be light bulb.

And then down here, when we interact with it, we are going to go light Bulb visible equals true. And we then also want to set, can interact to be false. We only want to interact with this object once. So back in our scene here, back in our main scene, I mean we can press play and if we walk over to the pedestal here, turn it on, there we go.

So now what we can do is we can make a little game out of this. We can actually move these around here. We can maybe make a couple duplicates and place them around the level. And now you have a little game where you have a walking simulator, you can walk up to these different pedestals, turn them on.

So now of course you can see how you can expand this into really whatever sort of game you wish. You can have a game where you might need to collect a number of things. You can have a game where you might need to complete a puzzle and maybe when you interact with something, it moves one of the puzzle pieces. It might open you up a secret door that you can enter in. There are a lot of different things you can do with this interaction system in combination with the player controller. So yeah, thank you for watching.

Ready to elevate your learning journey? Explore our all-access plan with 300+ courses, guided learning pathways, monthly new courses, and so much more today!