Creating physics-based games in Godot 4 opens up exciting new possibilities โ and I’ve taken full advantage of them in my latest YouTube video: “Godot 4 Marble Game“.
This project started as an experiment to explore the upgraded physics engine in Godot 4.4.1. I wanted to build something simple, visually appealing, and mechanically satisfying โ a marble game was the perfect fit. Rolling physics, precise control, camera smoothing, and interactive level elements all come together to create a polished, responsive experience.
๐ฎ Whatโs in the Game?
The marble is controlled using input-driven forces applied to a RigidBody3D
, allowing realistic rolling movement and interactions with obstacles. The camera dynamically follows the marble, with rotation and zoom controls for better visibility and player feedback.
The level design takes inspiration from classic marble games, with ramps, platforms, and triggers that demonstrate what Godot 4โs physics system can handle out of the box. No third-party plugins were used โ just native Godot tools and a lot of testing.
๐ง Why Godot?
Godot 4 is more than just a game engine โ itโs a free, open-source, and lightweight tool that gives developers full control without the overhead. This game was built to showcase how powerful and accessible Godot 4 really is.
- ๐ธ Free & Open-Source: No licenses, no royalties โ ever.
- ๐ชถ Lightweight & Efficient: Fast to load, easy on system resources, and works great even on modest hardware.
- ๐ GDExtension System: Extend engine functionality with C++ without touching the core engine code.
- ๐ฎ Improved Input Handling: Responsive and consistent controls across mouse, keyboard, gamepad, and touch.
- โ๏ธ Smoother Physics & Interpolation: Realistic motion, better feel, and a more polished game experience.
- ๐ ๏ธ Enhanced 3D Editor Tools: Powerful scene tools, gizmos, and debugging make 3D development intuitive.
- ๐ Cross-Platform Export: Build once, deploy to PC, mobile, web, and consoles.
These made the development process smoother and more enjoyable than ever.
๐น Watch the Video
I break down the key gameplay mechanics and show the game in action in our latest YouTube video. Whether you’re here for inspiration, education, or just love marble games โ you’ll want to check it out.
๐งฐ Want the Project Files?
Here’s the full project code and a breakdown of the code on the channel. Subscribe and stay tuned for more in-depth tutorials, devlogs, and tips for building your own Godot 4 games.
ball.gd
extends RigidBody3D
@export var camera_3d : Camera3D
@export var movement_speed : float = 385.0
@export var max_velocity : float = 7.5
@export var jump_power : float = 6.0
var grounded = false
func _physics_process(delta):
movement(delta)
if linear_velocity.x > max_velocity:
linear_velocity.x = max_velocity
if linear_velocity.x < -max_velocity:
linear_velocity.x = -max_velocity
if linear_velocity.z > max_velocity:
linear_velocity.z = max_velocity
if linear_velocity.z < -max_velocity:
linear_velocity.z = -max_velocity
if Input.is_action_just_pressed("jump") and grounded:
jump()
func movement(delta):
var f_input = Input.get_action_raw_strength("backward") - Input.get_action_raw_strength("forward")
var h_input = Input.get_action_raw_strength("right") - Input.get_action_raw_strength("left")
var camera_tranform = camera_3d.get_camera_transform()
var relative_camera_direction_z = camera_tranform.basis.z.normalized()
var relative_camera_direction_x = camera_tranform.basis.x.normalized()
var direction_f = f_input * relative_camera_direction_z
var direction_h = h_input * relative_camera_direction_x
apply_central_force(direction_f * movement_speed * delta)
apply_central_force(direction_h * movement_speed * delta)
func jump():
apply_central_impulse(Vector3.UP * jump_power)
camera.gd
extends Node3D
@export_category("Configurables")
@export var cam_v_max : float = 110.0
@export var cam_v_min : float = -75.0
@export var h_sensitivity : float = 0.1
@export var v_sensitivity : float = 0.1
@export var h_acceleration : float = 15.0
@export var v_acceleration : float = 15.0
@export var smooth_camera_tolerance : float = .3
var camrot_h : float = 0.0
var camrot_v : float = 0.0
@onready var bano = $"../Bano"
@onready var h_rotation = $HRotation
@onready var v_rotation = $HRotation/VRotation
# Called when the node enters the scene tree for the first time.
func _ready():
#hide mouse at start
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta):
global_position = lerp(global_position, bano.get_node("MeshInstance3D").global_position,smooth_camera_tolerance)
camrot_v = clamp(camrot_v, cam_v_min, cam_v_max)
h_rotation.rotation_degrees.y = lerp(h_rotation.rotation_degrees.y, camrot_h, delta * h_acceleration)
v_rotation.rotation_degrees.x = lerp(v_rotation.rotation_degrees.x, camrot_v, delta * v_acceleration)
rotation_degrees.z = 0
func _input(event):
if event is InputEventMouseMotion:
camrot_h += -event.relative.x * h_sensitivity
camrot_v += -event.relative.y * v_sensitivity
elif event is InputEventJoypadMotion:
if event.axis == 2:
camrot_h += -event.axis_value * h_sensitivity * 100
elif event.axis == 3:
camrot_v += -event.axis_value * v_sensitivity * 100
ground_ray.gd
extends RayCast3D
@export var ball : RigidBody3D
@export var ball_mesh : MeshInstance3D
func _physics_process(_delta):
global_position = ball_mesh.global_position
if is_colliding():
ball.grounded = true
else:
ball.grounded = false
Follow along, learn with us, and letโs build amazing games in Godot 4.
Leave a Reply