kidscancode / godot_recipes

Lessons, tutorials, and guides for game development using the Godot game engine.
MIT License
240 stars 37 forks source link

[Discussion] Controlling animation states #54

Open cbscribe opened 3 years ago

cbscribe commented 3 years ago

Discussion for http://godotrecipes.com/animation/animation_state_machine/

2blackbar commented 3 years ago

Despite copying everything exactly like in tutorial, somehow im getting " Can't travel to 'idle' if state machine is not playing. Maybe you need to enable Autoplay on Load for one of the nodes in your state machine or call .start() first?"

How is that possible that we get such different results with identical code ? Why i have to battle with this now for 2 hours and still theres no info anywhere about this error. Id prefere to just copy the code and study it, i have no clue why i have this error, heres my script :

`extends KinematicBody2D var SPEED = 240 # maksymalna predkosc var ACCELERATION = 2000 # przyspieszenie var velocity = Vector2.ZERO # ruch var state_machine

-------------FUNC NA STARCIE

func _ready(): state_machine = $AnimationTree.get("parameters/playback")

func get_input(): var current = state_machine.get_current_node() velocity = Vector2.ZERO if Input.is_action_just_pressed("AT1"): if state_machine.is_playing(): state_machine.travel("attack") return if Input.is_action_pressed("RIGHT1"): velocity.x += 1 $Sprite.scale.x = 1 if Input.is_action_pressed("LEFT1"): velocity.x -= 1 $Sprite.scale.x = -1 if Input.is_action_pressed("UP1"): velocity.y -= 1 if Input.is_action_pressed("DOWN1"): velocity.y += 1

if velocity.length() > 0:
    state_machine.travel("walk")
if velocity.length() == 0:
    state_machine.travel("idle")
velocity = velocity.normalized() * SPEED

velocity = move_and_slide(velocity)

------------------------------AUTOUPDATE CALY CZAS---------------------------------------

func _physics_process(delta): get_input() velocity= move_and_slide(velocity)

`

WolfgangSenff commented 3 years ago

This is because the code is not the problem. The problem is that in the Godot UI, you need to go to your AnimationTree and set it to active. Ignore the red boxes here, not on my home computer so not easy to take screenshots (not allowed to have it on my work machine), but see the Active checkbox here? Make sure that's on for your AnimationTree. Screen Shot 2021-07-12 at 7 19 09 PM

2blackbar commented 3 years ago

Thank You, I solved it, i just did not set start animation, that icon next to trashcan.... well, someone has to be the stupid one sometimes. Im trying to do x y z axis in 2d mode, do you know where i can look for some help ?

maxnim1986 commented 3 years ago

The travel function works even without transitions between the nodes. I wonder how a bug of such magnitude remained unnoticed. This renders using the state machine impossible at the moment. I have tested versions 3.2.2, 3.4,3.1 all stable official versions.

0Pixelated0 commented 2 years ago

it says " _travel: Condition "!p_state_machine->states.has(p_travel)" is true. Returned: false <C++ Source> scene/animation/animation_node_state_machine.cpp:177 @ _travel() " instead of running an animation

whenever an animation should be running

i need help

extends KinematicBody2D

export (int) var GRAVITY = 1 # in pixels export (int) var JUMP = 55 # start speed px/s export (int) var SPEED = 50 # px/s export var destination = Vector2(72,392)

export (PackedScene) var Bullet var state_machine var sprite_node var velocity = Vector2.ZERO #(0, 0)

func _ready(): sprite_node = get_node("Sprite") state_machine = $AnimationTree.get("parameters/playback")

func shoot(): var b = Bullet.instance() owner.add_child(b) b.transform = $Muzzle.global_transform

func _physics_process(delta):

if (Input.is_action_just_pressed("reset")):
    position = destination

# if no keyboard input for left/right then x speed is 0
velocity.x = 0
if (Input.is_action_pressed("right")):
    velocity.x = SPEED
    sprite_node.set_flip_h(false)
elif (Input.is_action_pressed("left")):
    velocity.x = -SPEED
    sprite_node.set_flip_h(true)
if velocity.length() == 0:
    state_machine.travel("idle")
if velocity.length() > 0:
    state_machine.travel("run")

velocity.y += GRAVITY

if is_on_floor() and (Input.is_action_just_pressed("up")) or is_on_floor() and (Input.is_action_just_pressed("jump")):
    velocity.y -= JUMP
    state_machine.travel("jump")

velocity = move_and_slide(velocity)

velocity.y += GRAVITY * delta
velocity = move_and_slide(velocity, Vector2.UP)
if Input.is_action_just_pressed("jump"):
    if is_on_floor():
        velocity.y = JUMP

func _on_Area2D_body_entered(body): body.position = destination

WolfgangSenff commented 2 years ago

@0Pixelated0 - can you post a pic of your state machine as well? It looks like probably there's either a typo in your state name, or maybe the state is missing altogether from your state machine. But it's hard to know without seeing the state machine itself.

nbourre commented 2 years ago

When trying to use the same method for an enemy, the Walk and Idle states seems to fight each one other.

Godot_v3 4 2-stable_mono_win64_mjvZBolugL

Here's my current AnimationTree Godot_v3 4 2-stable_mono_win64_CftzLgxkyK

Here's the code :

extends KinematicBody2D

enum {WALKING, IDLE}

const MAX_VELOCITY = 50
const MAX_FALL_VELOCITY = 500
const GRAVITY = 100

var current_state = WALKING

var acceleration = .5

var velocity = Vector2(0, 0)
var direction = 1
var direction_flip = false

var state_machine

var msg_acc = 0
var msg_rate = .50

func _ready():
    state_machine = $AnimationTree.get("parameters/playback")
    state_machine.travel("Walk")

func _physics_process(delta):
    msg_acc += delta
    move_character(delta)
    detect_direction_change()

func move_character(delta): 

    if direction_flip:
        direction_flip = false
        scale.x *= -1
        debug("velocity: " + str(velocity))

    if (not is_on_floor()):
        velocity.y += GRAVITY
        if velocity.y > MAX_FALL_VELOCITY:
            velocity.y = MAX_FALL_VELOCITY

    velocity.x = MAX_VELOCITY * direction
    if velocity.x > MAX_VELOCITY:
        velocity.x = MAX_VELOCITY
    elif velocity.x < -MAX_VELOCITY:
        velocity.x = -MAX_VELOCITY

    velocity = move_and_slide(velocity, Vector2.UP)

func detect_direction_change():
    if is_on_floor():
        if $WallDetector.is_colliding() or not $FloorDetector.is_colliding():
            direction *= -1
            direction_flip = true
            debug("direction: " + str(direction))

func debug(msg):
    print("[" + str(OS.get_ticks_msec()) + "] : " + msg)