Godot Version
I’m currently trying to make really rough prototype for a game in Godot 4.5.
Question
I’m currently trying to make a missile(rigidbody2d) that has different stages during it’s launch. For these different stages I’m using a finite state machine that uses child nodes for states(that I took from a YouTube video I can’t remember the link to). I only have two stages right now, a boost stage where the rocket is supposed to move slowly and follow the cursor and a cruising state where the missile zips off on it’s own. My issue is, anything impulses that I’m applying to the missile in the boost state doesn’t affect it, until the state switches to cruising where it seems all the impulses are applied at once.
The missile still follows the mouse in the boost state so I’m pretty sure it’s all running as intended. And even if there’s no impulses applied in the cruising state, the missile still zips off really quick once it switches states, leading me to assume that it’s the impulses I tried applying in the boost state hitting it all at once. Removing any impulses from the boost state also make the missile move as intended once the cruising state is activated.
State Machine code:
extends Node
class_name StateMachine
@export var inital_state : State
var current_state: State
var states := {}
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
# Look through all the states attatched to this state machine, checking if they're states
for child in get_children():
if child is State:
# Recall: making the index to the state the name of the state
states[child.name.to_lower()] = child
child.Transitioned.connect(on_child_transmition)
if inital_state:
inital_state.Enter()
current_state = inital_state
print("states: ", states)
print("initial state: ", inital_state)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
# Check if there's a current state and run it's version of _process
if current_state:
current_state.Update(delta)
func _physics_process(delta: float) -> void:
# Same as _process
if current_state:
current_state.Physics_Update(delta)
func on_child_transmition(state, new_state_name):
# Checks if the state is correct
if state != current_state:
print("Error: given state isn't current state")
return
# Searches for and checks if the new state even exists
var new_state = states.get(new_state_name.to_lower())
if !new_state:
print("Error: new state doesn't exist")
return
if current_state:
#print("Leaving: ", current_state) # Debug line
current_state.Exit()
print("Entering: ", new_state) # Debug Line
new_state.Enter()
current_state = new_state
Boost state code:
extends State
class_name BoostState
@export var boost_force := 100
@export var move_speed := 10
@export var launch_delay := 1.0
@export var rotation_speed := 1.0
@onready var rocket: RigidBody2D = $"../.."
func Enter():
var launch_vector = Vector2(cos(rocket.global_rotation), sin(rocket.global_rotation))
rocket.apply_central_impulse(launch_vector*boost_force)
func Exit():
pass
# Stand in for _process
func Update(delta: float):
if(launch_delay <= 0):
Transitioned.emit(self, "Cruising")
launch_delay -= delta
#follow/move towards mouse
var mouse_pos := rocket.get_global_mouse_position()
var rocket_pos := rocket.global_position
var dx := mouse_pos.x - rocket_pos.x
var dy := mouse_pos.y - rocket_pos.y
var target_angle := atan2(dy,dx)
rocket.global_rotation = lerp_angle(rocket.global_rotation, target_angle, rotation_speed)
# Stand in for _physics_process
func Physics_Update(_delta: float):
var move_vector = Vector2(cos(rocket.global_rotation), sin(rocket.global_rotation))
rocket.apply_central_impulse(move_vector*move_speed)
Cruising state code:
extends State
class_name CruisingState
@export var cruise_speed := 100.0
@export var detection_range := 500.0
@export var detection_angle := 30.0
@onready var rocket: RigidBody2D = $"../.."
func Enter():
pass
func Exit():
pass
# Stand in for _process
func Update(_delta: float):
pass
# Stand in for _physics_process
func Physics_Update(_delta: float):
var thrust_vector := Vector2(cos(rocket.global_rotation), sin(rocket.global_rotation))
rocket.apply_central_impulse(thrust_vector*cruise_speed)
I feel a state machine like this is a bit much and if I can’t find a solution I may just scrap it for something a lot simpler. But I am very curious what’s going on here and any help would be very much appreciated.