I been trying for months to solve issues with my code (specifically with animations and audio playing correctly), and I finally realized how to do it. However, the problem is, it involves state machines -- a thing I have not a single iota of understanding. I mean, I been coding for months now, I can do raycasting and stuff (not Wolfenstein raycasting, but, like, press E to interact type stuff). But, what I wonder, is how do I set up even a simple one? I prefer code based, but node-based works, too. If the docs has a guide on state machines, please let me know lol. Even a partial demonstration would help. I'm not very good at math (or even anything slightly mindbending). So, if you have to explain it, explain it to me like I'm from the medieval era or smthn.
#How can one master the ways of the State Machine?
1 messages · Page 1 of 1 (latest)
The docs don't have an updated tutorial for state machines, just one for Godot 3 : https://docs.godotengine.org/en/3.2/tutorials/misc/state_design_pattern.html
It's usable, but you have to update the code to match Godot 4
Introduction: Scripting a game can be difficult when there are many states that need to handled, but only one script can be attached to a node at a time. Instead of creating a state machine within ...
But there's a few videos and tutorials around, so you can take a look and see if they help:
https://www.youtube.com/watch?v=ow_Lum-Agbs https://shaggydev.com/2023/10/08/godot-4-state-machines/
I have gone through every tutorial, still no working result.
Am I cooked, chat?
Unless, I switch to Godot 3 -_-
The concept of a state machine is the same, regardless of Godot version. It is a well known thing in programming
That said, it is probably better if you explain or show what you tried, and what is not working as you expected
I tried doing a node-based state machine. But, I kept running into issues with nonexistent functions and such. But, then I found an enum-based one. But, problem with that one is, is that it's kinda janky, as i copy and pasted the states all over the place to get it to work. (And, I doubt making it at 4 AM helped, either.)
I can send pictures of code Inna bit, I need to go to my PC.
Sorry if I come off as rude, I just am a bit frustrated with this coding issue.
idk how to copy and paste code into the code format thing so it doesn't surpass discord's word limit thing mb
Making code that late (or early) surely does not help. I can barely be awake that early, let alone code properly 😅
I'm not sure about the Discord limits, but you can always put the code on a external place and link here (like using GitHub or pastebin, etc)
That said, I think you should look into the tutorials and try recreating then, instead of trying to adapt into your already existing code. There's more than one way to do state machines, using nodes or classes or enums are all valid. It seems your struggle is more with how to organize the code, than to just understand state machines
See also https://www.gdquest.com/tutorial/godot/design-patterns/finite-state-machine/, which is more textual and makes easier to follow and copy code if needed .
I also made a very simple example, using only code for states (no enums or nodes). Consider this structure, where the player only have one main script:
You can have a base script which all states derive from:
extends Node
class_name BaseState
var player
func _set_player(_player):
player = _player
func _on_enter():
pass
func _on_physics_process(_delta : float):
pass
func _on_exit():
pass
Then, each state (another gd script) overrides the functions it needs. This is the Iddle State (iddle_state.gd):
extends BaseState
class_name IddleState
func _on_enter():
print("Now on IDDLE STATE")
# here, for example, you can change the animation
# for example, if the player has a AnimationPlayer that holds the animations
# and the walk animation
player.animation_player.play("IDDLE")
pass
func _on_physics_process(_delta : float):
pass
func _on_exit():
print("Exiting the IDDLE STATE")
pass
And this is the walk state (walk_state.gd):
extends BaseState
class_name WalkState
func _on_enter():
print("Now on WALK STATE")
# here, for example, you can change the animation
player.animation_player.play("WALK")
pass
func _on_physics_process(_delta : float):
# do whatever
pass
func _on_exit():
print("Exiting the WALK STATE")
pass
And the player, where it has a Dictionary with all states already created at the start, then setting a current state when ready, with a function to change states when needed. The state change is triggered by the velocity being zero or not (so, when the player tries to move), but it could be done by any other thing, and some parts of the code can even be put inside the states themselves:
extends CharacterBody2D
class_name Player
const SPEED : float = 2000
@onready var animation_player: AnimationPlayer = $AnimationPlayer
var current_state_name := ""
var current_state : BaseState
var available_states := {
"IDDLE" = IddleState.new(),
"WALK" = WalkState.new()
}
func _ready() -> void:
for state_name in available_states: # loops all states in the available_states dictionary
# note that state_name is the string name of the state
available_states[state_name]._set_player(self) # tells each state what it will be controlling: the player
change_state("IDDLE")
func _physics_process(_delta: float) -> void:
var dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if (dir.is_zero_approx()): # no input, so no movement
change_state("IDDLE")
else:
change_state("WALK")
current_state._on_physics_process(_delta)
velocity = dir * _delta * SPEED
move_and_slide()
func change_state(_next_state_name : String):
if (current_state_name == _next_state_name):
return # does not change to state if it is already the current
if (current_state): # if the current_state is not null
current_state._on_exit() # calls exit on the current
current_state = available_states[_next_state_name] # changes to another state
current_state._on_enter() # calls on_enter on the new state
You can also paste code into discord and format it using backticks` see
When you surround some words with single backticks like `this`, it will be formatted as code.
You can also include code blocks by surrounding the code with three backticks. If you add "swift" then you will also get basic syntax highlighting:
```swift
print("hello world")
```
Discord will then show it as a code block like this:
print("hello world")
If your code snippet is rather long, you can upload it to a text paste site. One option that supports syntax highlighting for GDScript is https://bpa.st/