Hi! I've recently switched from visual scripting in Unreal Engine to Godot, so I'm very much getting to grips with GDScript. I'm making a sidescrolling platformer and I'm having trouble switching my character animation back to running, after the jump animation is triggered.

I'm using Dialogue Manager, and had a lot of trouble disabling player movement. This mostly seems to work, but when the player character lands after jumping, the fall animation does not switch back to the running animation, unless another input is pressed.

I'm sure there's a more sensible way to organise all this, but like I said, still getting to grips with it.
Can anyone help me with this?

`extends CharacterBody2D

var health = 10
var SPEED = 190.0
const JUMP_VELOCITY = -260.0

Get the gravity from the project settings to be synced with RigidBody nodes.

var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

@onready var anim = $AnimatedSprite2D
@onready var all_interactions = []
@onready var interactlabel = $"Interaction Components/InteractLabel"
@onready var actionable_finder: Area2D = $"Interaction Components/ActionableFinder"

func _physics_process(delta):

Add the gravity.

if not is_on_floor():
velocity.y += gravity * delta
if velocity.y > 0:
anim.play("Fall")

move_and_slide()

if health <= 0:
	queue_free()
	get_tree().change_scene_to_file("res://main.tscn")

Initiate conversation with actionables

func unhandled_input(event: InputEvent) -> void:
if Input.is_action_just_pressed("ui_accept"):
var actionables = actionable_finder.get_overlapping_areas()
if actionables.size() > 0:
actionables[0].action()
velocity.y = 0
velocity.x = 0
anim.play("Idle")
return

Get the input direction and handle the movement/deceleration.

var direction = Input.get_axis("ui_left", "ui_right")
if direction == -1:
get_node("AnimatedSprite2D").flip_h = true
elif direction == 1:
get_node("AnimatedSprite2D").flip_h = false

if direction:
	velocity.x = direction * SPEED 
	if velocity.y == 0:
		anim.play("Run")
else:
	velocity.x = move_toward(velocity.x, 0, SPEED) 
	if velocity.y == 0:
		anim.play("Idle")
	
	
# Handle Jump.
if Input.is_action_just_pressed("ui_up") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	anim.play("Jump")
else: 
	if velocity.y > 0:
		anim.play("Fall")`
  • SnapCracklins replied to this.
  • Donalf you may want to do a state machine so you have states that the game can read to determine whether the player is idle, running, jumping, falling or dead. (A "dead" state is a good idea so you can disable player input when you die.) Then just tell your program what state goes where and when.

    Can you show your physics process as well? You usually want to code your collisions or put those functions there. Make sure you have _velocity = move_and_slide(_velocity,Vector2.UP) as this tells the editor what the floor is. (You probably have done this, but new stuff is easy to miss).

    SIMPLE STATE MACHINE:

    var _characterState : int = 0
    enum _CHARACTER_STATES {IDLE, RUN, JUMP, FALL, DEAD}
    
    
    func _statesMachine():
        match _characterState:
            _CHARACTER_STATES.IDLE:
                ## idle function
            _CHARACTER_STATES.RUN:
                ## run function
            _CHARACTER_STATES.JUMP:
                ## basically put each frame-by-frame movement function here
            _CHARACTER_STATES.FALL:
                ## etc
            _CHARACTER_STATES.DEAD:
                ## disable input

    And then place the logic accordingly:

    if is_on_floor() and _velocity.x > 0:
        _characterState = 0

    You need to tune it but that should work.

    Donalf you may want to do a state machine so you have states that the game can read to determine whether the player is idle, running, jumping, falling or dead. (A "dead" state is a good idea so you can disable player input when you die.) Then just tell your program what state goes where and when.

    Can you show your physics process as well? You usually want to code your collisions or put those functions there. Make sure you have _velocity = move_and_slide(_velocity,Vector2.UP) as this tells the editor what the floor is. (You probably have done this, but new stuff is easy to miss).

    SIMPLE STATE MACHINE:

    var _characterState : int = 0
    enum _CHARACTER_STATES {IDLE, RUN, JUMP, FALL, DEAD}
    
    
    func _statesMachine():
        match _characterState:
            _CHARACTER_STATES.IDLE:
                ## idle function
            _CHARACTER_STATES.RUN:
                ## run function
            _CHARACTER_STATES.JUMP:
                ## basically put each frame-by-frame movement function here
            _CHARACTER_STATES.FALL:
                ## etc
            _CHARACTER_STATES.DEAD:
                ## disable input

    And then place the logic accordingly:

    if is_on_floor() and _velocity.x > 0:
        _characterState = 0

    You need to tune it but that should work.

      SnapCracklins

      Thank you!
      I think a state machine is a little bit beyond me at this point, but I'll look into it.
      I have move_and_slide, but without _velocity and Vector2.UP -
      Physics and movement is from the Godot template CharacterBody2D: Basic Movement - so starting from this:

      Edit: It works the way I want it to now, but there are a number of checks in multiple places, that I can see could cause problems.
      I'll put some effort into figuring out a state machine - thanks so much for you advice!

      Ok, for some reason this works, but only when moving right, the same problem happens when moving left: animation gets stuck in jump.
      I can see why a state machine for something like this is important, but that will take me a while.
      If I can just hack this together for now, it'll be ok!

        Donalf for the record, implementation isn't terribly difficult. You just throw that state machine in your physics process just like you would an input, then put whatever you movement logic is into the match sequence. But if you're still learning, do what works.

        I do see another problem. You are using "get_axis" which is essentially get_action_strength(input1) - get_action_strength(input2) ... are you using a game controller for input or a keyboard? Because get_action_strength returns a float.... what may be happening is you're adding floats together that aren't adding up to 1 or -1. You may want to either normalize those inputs to 1 or use is_action_pressed(input) instead.

        Normalization is easy, it's just a bit more code:

        if direction > 0:
            direction = 1
        if direction < 0:
            direction = -1