Godot Version
Godot 4.5.1 Stable
Question
I’ve run into a snag in attempting to create a state machine for use in my practice Dungeon Crawler. It appears to be a conflict between the requirements of the movement code I’m using and the State Machine itself.
First, the State Machine I’m working with is derived from this video: https://www.youtube.com/watch?v=VtJXqRsFezY. It is a node-based system that uses a basic Node as the PlayerStateMachine and several child nodes that correspond to movement. In my case, the states I want are for movement, rotation and idle.
The movement code I’m using uses tweening, and uses the transform method that requires a CharacterBody3D/Node3D.
Movement Code
func _physics_process(_delta: float) → void:
if tween is Tween:
if tween.is_running():
return
if Input.is_action_pressed("Forward") and !forward.is_colliding():
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "transform", transform.translated_local(Vector3.FORWARD * 2), SPEED)
if Input.is_action_pressed("Backwards"):
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "rotation:y", rotation.y + deg_to_rad (int(180)), 0.7)
if Input.is_action_pressed("Left"):
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "transform:basis", transform.basis.rotated(Vector3.UP, PI / 2), SPEED)
if Input.is_action_pressed("Right"):
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "transform:basis", transform.basis.rotated(Vector3.UP, -PI / 2), SPEED)
if Input.is_action_pressed("Strafe L") and not left.is_colliding():
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "transform", transform.translated_local(Vector3.LEFT * 2), SPEED)
if Input.is_action_pressed("Strafe R") and not right.is_colliding():
tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "transform", transform.translated_local(Vector3.RIGHT * 2), SPEED)
So the problem I’m facing is that transform is not compatible with the Node that the state machine scripts are attaching to, and changing these nodes to a Node3D or CharacterBody3D breaks it entirely (I receive ‘null instance’ errors). I’m attempting to troubleshoot that part on my own, but my question is really regarding my current movement code and if this is the right approach I should be taking.
The current state.gd looks like this, for reference
State.gd
```
class_name State
extends Node3D
signal transitioned(new_state_name: StringName)
#Enter a state
func enter() → void:
pass
#Exit a state
func exit() → void:
pass
#update process
func update(_delta: float) → void:
pass
#update physics process
func physics_update(_delta: float) → void:
pass
And here is IdleState.GD
```
class_name IdleState
extends State
func update(_delta: float) → void:
if Input.is_action_pressed(“Forward”):
transitioned.emit(“MoveState”)
elif Input.is_action_pressed("Left") or Input.is_action_pressed("Right"):
transitioned.emit("RotateState")
```