GodotФорумВопросы

Проблема с animationPlayer

Страницы: 1 2 Следующая »
#0
18:19, 1 апр 2025

Добрый день, наткнулся на проблему, пока не понимаю где искать решение.
Игрок при получении урона должен проигрывать анимацию и отскакивать от врага.
Почему-то отскок срабатывает только после завершения анимации (на какой бы строке кода она не находилась). Нужно сделать так, чтобы игрок отскакивал и проигрывал анимацию одновременно.

Функция на получение урона у игрока:

func take_damage(damage_amount : int, damage_vector : Vector2):
  if can_take_damage:
    enemy_position = damage_vector
    health -= damage_amount
    if health > 0:
      fsm.change_state("take_damage")
      iframes()
    else:
      can_take_damage = false
      fsm.change_state("die")
  pass

Функция на нанесение урона у противника:

func _on_spike_entered(area: Area2D) -> void:
  if area.get_parent() is Player:
    player_body = area.get_parent()
    area.get_parent().take_damage(1, self.position)
    GL.change_hp(-1)
    $Timer.start()
  pass

Функция в FSM "take_damage":

func enter():
  
  var impulse_direction = entity.position.x - entity.enemy_position.x
  if impulse_direction < 0:
    entity.velocity = Vector2(-200,-200)
  else:
    entity.velocity = Vector2(200,-200)
    
  entity.animPlayer.play("Anim_Take_Damage")
#1
19:44, 1 апр 2025

MalkHadiel
У тебя в  func take_damage() нет никаких анимаций, а есть какая-то (предположительно) стейт машина и какие то iframes().
Что это, я понятия не имею.

Не мог бы ты конкретизировать вопрос, чтобы он был по Годо, а не по твоей логике?

#2
19:59, 1 апр 2025

Попробую.
Есть player к которому привязан fsm, та самая стейт машина.
Если враг попадает по игроку, то у него вызывается функция "take_damage", которая в качестве аргументов принимает величину урона "damage_amount" и направление урона "damage_vector".
Если после получения урона здоровье больше нуля - игрок переходит в состояние "take_damage" (В самом низу которая).
В нем игроку придаётся импульс entity.velocity с направлением в зависимости от "enemy_position = damage_vector". И потом в этом же состоянии проигрывается анимация.
Непонятно почему сначала играет анимация, и только потом срабатывает импульс.

#3
20:01, 1 апр 2025

По сути плеер анимации прерывает выполнение физики игрока.

#4
(Правка: 20:41) 20:28, 1 апр 2025

> > чтобы он был по Годо, а не по твоей логике?
MalkHadiel
> Попробую.
... рассказывает про логику )))

MalkHadiel
> fsm, та самая стейт машина.
Я же сказал, я не знаю, что это, как ты её писал. Нет такого класса в комплекте.

MalkHadiel
> Непонятно почему сначала играет анимация, и только потом срабатывает импульс.
Ты отладчиком запускал?
Или хотя бы print-ов понавставляй, чтобы понимать, чего творится.

Я ведь не могу за тебя это всё делать.

MalkHadiel
> По сути плеер анимации прерывает выполнение физики игрока.
Это невозможно в принципе *

  • p.s. Если конечно не предположить дикого, что у тебя в анимациях трансформы тела модифицируются. Ведь нет?
  • ** Сразу вспомнился мемо-шаблон "Anakin and Padme" ))))

    #5
    20:55, 1 апр 2025

    Не понимаю тогда как в логике годо это описать)

    Я же сказал, я не знаю, что это, как ты её писал. Нет такого класса в комплекте.

    В комплекте нету, по сути штука нужна чтобы не писать спагетти код, но она выполнению физики никак не мешает.

    Это невозможно в принципе *

    Да я знаю, потому и удивлён)))
    В анимации только выбирается сама анимация от animSprite и её кадр.
    Но если время анимации выставить секунды на 3, то прыжок только после её завершения случится.

    Принты уже вешал, по ним импульс срабатывает раньше анимации.

    #6
    20:59, 1 апр 2025

    Видео не могу скинуть сейчас(
    После обновления движка почему-то запись экрана не работает. Показывает просто серый фон.

    #7
    21:32, 1 апр 2025

    MalkHadiel
    > Но если время анимации выставить секунды на 3, то прыжок только после её завершения случится.
    Значит у тебя что то завязано на типа animation_finished.

    #8
    1:10, 4 апр 2025

    MalkHadiel
    > Добрый день, наткнулся на проблему, пока не понимаю где искать решение.
    > Игрок при получении урона должен проигрывать анимацию и отскакивать от врага.
    > Почему-то отскок срабатывает только после завершения анимации (на какой бы строке кода она не находилась). Нужно сделать так, чтобы игрок отскакивал и проигрывал анимацию одновременно.
    >
    > Функция на получение урона у игрока:
    >
    > func take_damage(damage_amount : int, damage_vector : Vector2):
    > if can_take_damage:
    > enemy_position = damage_vector
    > health -= damage_amount
    > if health > 0:
    > fsm.change_state("take_damage")
    > iframes()
    > else:
    > can_take_damage = false
    > fsm.change_state("die")
    > pass
    > Функция на нанесение урона у противника:
    >
    > func _on_spike_entered(area: Area2D) -> void:
    > if area.get_parent() is Player:
    > player_body = area.get_parent()
    > area.get_parent().take_damage(1, self.position)
    > GL.change_hp(-1)
    > $Timer.start()
    > pass
    > Функция в FSM "take_damage":
    >
    > func enter():
    >
    > var impulse_direction = entity.position.x - entity.enemy_position.x
    > if impulse_direction < 0:
    > entity.velocity = Vector2(-200,-200)
    > else:
    > entity.velocity = Vector2(200,-200)
    >
    > entity.animPlayer.play("Anim_Take_Damage")


    Учись пользоваться AI.

    Проблема в том, что в enter() состояния "take_damage" вы устанавливаете velocity, но в движке Godot переменные не применяются мгновенно — движение происходит только в следующем _physics_process(), а анимация начинает проигрываться сразу.

    Решение:
    Чтобы игрок одновременно отскакивал и проигрывал анимацию, вам нужно добавить move_and_slide() (или move_and_collide(), если используете KinematicBody2D/CharacterBody2D) в момент установки velocity, а не ждать следующего кадра физики.

    func enter():
      var impulse_direction = entity.position.x - entity.enemy_position.x
      if impulse_direction < 0:
        entity.velocity = Vector2(-200,-200)
      else:
        entity.velocity = Vector2(200,-200)
      
      entity.move_and_slide()  # <-- добавляем движение сразу
      
      entity.animPlayer.play("Anim_Take_Damage")

    Альтернативный вариант (если velocity обрабатывается в _physics_process()):
    Если у вас уже есть логика движения в _physics_process(), то вместо мгновенного вызова move_and_slide() можно временно изменить velocity, а код движения сам все обработает.

    Пример:

    # FSM: take_damage
    func enter():
      var impulse_direction = entity.position.x - entity.enemy_position.x
      entity.velocity = Vector2(200 * sign(impulse_direction), -200)
      entity.animPlayer.play("Anim_Take_Damage")
    
    # Player.gd (пример кода в _physics_process)
    func _physics_process(delta):
      velocity.y += gravity * delta
      velocity = move_and_slide(velocity, Vector2.UP)

    Итог:

    Теперь игрок сразу будет отскакивать и одновременно проигрывать анимацию!

    #9
    (Правка: 10:26) 9:30, 4 апр 2025

    Tiranas
    > в движке Godot переменные не применяются мгновенно
    Эта фраза - бред. Остальное и не читал.

    > Учись пользоваться AI.

    Изображение


    Программировать надо учиться.

    #10
    10:31, 4 апр 2025

    Der FlugSimulator
    > Эта фраза - бред. Остальное и не читал.
    Читать надо, а то всё будет потоком бреда

    вот ещё ответ от другой нейронки

    Для решения проблемы нужно изменить последовательность действий таким образом, чтобы игрок начинал отскакивать сразу же после получения урона, а не дожидался окончания анимации. Это можно сделать следующим образом:

    Сразу применяем импульс: В функции take_damage передаем направление удара в состояние FSM и добавляем импульс до начала анимации.
    Параллельное выполнение анимации и движения: В FSM используем функцию enter, чтобы запустить анимацию и добавить начальное движение одновременно.
    Вот пример изменений в коде:

    Функция take_damage
    Добавляем передачу направления удара в FSM:

    func take_damage(damage_amount : int, damage_vector : Vector2):
      if can_take_damage:
        enemy_position = damage_vector
        health -= damage_amount
        if health > 0:
          # Передаем направление удара в FSM
          fsm.set_data("impulse_direction", damage_vector)
          fsm.change_state("take_damage")
          iframes()
        else:
          can_take_damage = false
          fsm.change_state("die")

    Функция take_damage в FSM
    Здесь применим начальный импульс и запустим анимацию одновременно:

    func enter():
      # Получаем направление удара из данных FSM
      var impulse_direction = fsm.get_data("impulse_direction")
      var x_dir = sign(impulse_direction.x - entity.position.x)
      
      # Добавляем начальный импульс
      entity.velocity = Vector2(x_dir * 200, -200)
      
      # Запускаем анимацию
      entity.animPlayer.play("Anim_Take_Damage")

    Таким образом, игрок будет получать начальный импульс сразу после получения урона, а анимация начнет воспроизводиться параллельно движению.

    Der FlugSimulator
    > Лучше учиться программировать.
    Сейчас ситуация изменилась: знания уже не в приоритете, а важнее стало умение использовать инструменты.

    #11
    10:36, 4 апр 2025

    Der FlugSimulator
    А тебе идёт бубен, и в программировании поможет.

    #12
    10:53, 4 апр 2025

    Tiranas
    > в движке Godot переменные не применяются мгновенно
    > Читать надо, а то всё будет потоком бреда

    Зачем мне читать остальное, если переменные применяются именно в момент присваивания.
    Хоть в Godot, хоть где ещё.

    Tiranas
    > Сейчас ситуация изменилась: знания уже не в приоритете,
    Это бы в перлы.

    #13
    10:56, 4 апр 2025

    Der FlugSimulator
    > Это бы в перлы.
    Через тройку лет и это устареет.

    #14
    16:14, 4 апр 2025

    Поразительно конечно.
    Один не может толком сформулировать вопрос, логи приложить и полный код.
    Второй, нисколько этим не смущаясь, копипастит сюда какие то буквы из интернет бредогенератора, будучи уверен, что они имеют какое то отношение к проблеме.
    Тут охотно веришь, что "знания уже не в приоритете".

    Страницы: 1 2 Следующая »
    GodotФорумВопросы