Skip to content

Instantly share code, notes, and snippets.

@willnationsdev
Last active February 27, 2024 20:03
Show Gist options
  • Save willnationsdev/45c80df273cc3241be750aecbef6cfae to your computer and use it in GitHub Desktop.
Save willnationsdev/45c80df273cc3241be750aecbef6cfae to your computer and use it in GitHub Desktop.
A Basic Controller for a 3D Rigidbody in Godot 3.0
# ---
# Note: I honestly can't remember where this gist came from.
# This sounds like something I would've uploaded from sample code people shared on Reddit while asking questions.
# So, as far as my part in sharing this code, I would consider it to be MIT licensed.
# If someone on Reddit suddenly pops up saying I'm not crediting them, then I'll gladly add the credit.
# ---
# A Rigidbody Controller for basic 3D movement
extends RigidBody
# not sure what to put here to get proper turning
var turn_speed = Vector3(1,0,0)
# not sure what to put here to get proper movement
var movement_speed = Vector3(1,0,0)
# The direction in which to conduct a raycast to check for jumping
var floor_jump_dir = Vector3(0,1,0)
# jump_flag
var jump_enabled = true
const JUMP_RAYCAST_CHECK_RANGE = 10.0
# Add input action dependencies if not present
func _ready():
if not InputMap.has_action("turn_left"):
# add associated turn_left event
InputMap.add_action("turn_left")
var left_key = InputEventKey.new()
left_key.set_scancode(KEY_LEFT)
InputMap.action_add_event("turn_left",left_key)
# do the same for all of the other actions mentioned in the
# _integrate_forces method
# this will ensure that all necessary actions and associated events EXIST
# so long as at least one of these RigidbodyController3D scripts is used
# The documentation of Rigidbody advises against adding
# physics forces during _input, suggesting to use
# _integrate_forces instead.
# http://docs.godotengine.org/en/latest/classes/class_rigidbody.html#class-rigidbody-set-angular-velocity
func _integrate_forces(state):
# Detect input and alter the state accordingly
if Input.is_action_pressed("turn_left"):
state.set_angular_velocity(-turn_speed)
if Input.is_action_pressed("turn_right"):
state.set_angular_velocity(turn_speed)
if Input.is_action_pressed("move_forward"):
state.set_linear_velocity(movement_speed)
if Input.is_action_pressed("move_backward"):
state.set_linear_velocity(-movement_speed)
if Input.is_action_pressed("jump") and can_jump(state):
state.set_linear_velocity(jump_speed)
func can_jump(state):
# Use raycasting start at points surrounding the model,
# pointed downwards to determine if ground is below.
# Measure how far the rays go before they collide with anything.
# Should be pretty short.
# Can use enable_jump as a toggle
# [self] is to preclude the raycast from hitting yourself
var hit = state.get_space_state().intersect_ray(Vector3(),JUMP_RAYCAST_CHECK_RANGE * -floor_jump_dir, [self])
if hit.size() == 0:
return false
if hit.collider.is_in_group("floor"):
return true
# if one wanted to do wall jumping, then they would need to raycast
# in a different direction and check for a wall tag probably
# Might even be more efficient to have a member variable on the collider
# itself to check against. Especially if you have a lot of floors/walls
# in a single level. Something like...
# if hit.collider.can_jump_off_from():
# return true
return false
@Monnorthegodlydev
Copy link

my i please use parts of this code for my open source godot 4 project
thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment