Okay, so im new to this so will try my best on being as clear as possible because i know its hard to understand people like me who have no clue haha.
I appreciate the reply and will try to answer your questions as best i can 
I think also you have answered one important gap in my knowledge that to make the state machine only run one script at a time it needs to be implemented in the state manager… i thought i had done this but maybe i am wrong
so this is the layout of my enemy scene
this is my state machine manager or CharacterStateMAchine code
extends Node
class_name CharacterStateMachine
@export var character : CharacterBody2D
@export var animation_tree : AnimationTree
@export var current_state : State
var states : Array[State]
func _ready() -> void:
#creating array of states
for child : State in get_children():
if (child is State):
states.append(child)
#telling the states what they need to function
child.character = character
child.playback = animation_tree["parameters/playback"]
#connect to interrupt signal
child.connect("interrupt_state", on_state_interrupt_state)
else:#warning if a child is not a state
push_warning("Child " + child.name + " is not a State for CharacterStateMachine")
func _physics_process(delta : float) -> void:
if (current_state.next_state != null): #if current state holds something switch
switch_states(current_state.next_state)
current_state.state_process(delta)
func check_if_can_move() -> bool: #checking if the state allows the character to move
return current_state.can_move
func switch_states(new_state : State) -> void: #creating new_state argument to pass into function
if (current_state != null):
current_state.on_exit()#if i need to do anything else when state exits
current_state.next_state = null #resets state to null for next change
current_state = new_state #change of state
current_state.on_enter() #any code i want to execute upon entering a new state
func _input(event :InputEvent) -> void:
current_state.state_input(event)
func on_state_interrupt_state(new_state : State):
switch_states(new_state)
All the State scripts are extensions of this script State.gd
which is below
extends Node
class_name State
@export var can_move : bool = true
#@export var cancel_velocity : bool = false
var character : CharacterBody2D
var playback : AnimationNodeStateMachinePlayback
var next_state : State
signal interrupt_state(new_state : State)
func state_process(delta : float) -> void:
pass
func state_input(event : InputEvent) -> void:
pass
func on_enter() -> void:
pass
func on_exit() -> void:
pass
so the problem being either the two states that seem to be running at the same time or maybe the velocity is just overwriting somehow. My lack of understanding of either state machines or of how to move a CharacterBody2D using velocityis the issue.
here is the chase state
extends State
class_name ChaseState
@export var movement_speed : float = 1200.0
@export var chase_state : String = "chase"
@export var idle_state : State
@export var attack_state : State
@onready var hit_state : State = $"../Hit"
@onready var state_machine : CharacterStateMachine = $".."
@onready var enemy : CharacterBody2D = $"../.."
@onready var distance_to_player : Vector2
@onready var direction : Vector2 = Vector2.ZERO
@onready var player : CharacterBody2D
func on_enter():
playback.travel(chase_state)
func _process(delta):
player = get_tree().get_nodes_in_group("player")[0]
distance_to_player = player.position - enemy.position
direction = player.position - enemy.position
direction = direction.normalized()
if direction && state_machine.check_if_can_move():
enemy.velocity.x = direction.x * movement_speed * delta
elif state_machine.current_state != hit_state:
enemy.velocity.x = move_toward(enemy.velocity.x, 0, movement_speed)
func _on_player_detection_body_exited(body):
next_state = idle_state
func _on_attack_range_body_entered(body):
next_state = attack_state
and here is the attack state
extends State
@onready var state_machine : CharacterStateMachine = $".."
@onready var enemy : CharacterBody2D = $"../.."
@export var return_state : State
func on_enter():
playback.travel("attack")
enemy.velocity.y = -200 # this works
# enemy.velocity.x = 200 # <-have also tried this but doesnt work
enemy.velocity.x = move_toward(100,500, 500) #doesnt work
func _on_animation_tree_animation_finished(anim_name):
next_state = return_state
By putting a bool on i mean i am declaring a bool that is supposed to check if in the attack state.
Then the chase state script checks if this is true so that if false it stops applying its change in velocity.
But i know now what im saying in this sentance above is completely dumb because i shouldnt have any code in the chase state running whilst it is in a different state.
The code i think is being overwritten is below which is (inside the AttackState) because the Y velocity change works but the X velocity change doesnt and when commented out the attack state velocity chage works.
func on_enter():
playback.travel("attack")
enemy.velocity.y = -200 # this works
# enemy.velocity.x = 200 # tried this but commented out to try code below
enemy.velocity.x = move_toward(100,500, 500) #doesnt work
I think i may have a poor understanding of using velocity to change the players position.
As i never know when to multiply by delta or if i need to at all.
Even after reading the documentaion i feel like im still a bit confused between changing the velocity and using move_toward.
In honesty thats the first time ive heard the term execution loop i will look that up tonight and try to get an understanding.
I dont really get the difference between _process and _physics_process but i know that they execute every frame.
i think i know _ready executes the code when you start the game up for the first time.
_input i think i know thar it only is triggered when you press a key that you have assigned to something.
Sorry about such an essay just trying to be as thorough as possible to make it easier but i may have made it confusing bringing up so much haha i really appreciate you taking the time to reply 