Is there a way to know if an animation is in play status?

I’m creating a first-person 3D action adventure. My character has a sword. I created 2 animations for the sword, one for idle (state 0) and one for attack (state 1).

I have a method that changes the state on mouse click.
everything works, except that every time I press the mouse the animation resets immediately.

I need to know if there is a Scene.AnimationIsPlay or something like that to create a condition that waits for the animation to finish before allowing the state change.

I don’t think that there is a ready state machine solution available for Castle Game Engine.

However in my personal experience, while great for prototyping especially a complex state system, it may not be the best solution for a simple usecase or game mechanics that require precision control of what happens in-game. In other words, I propose to try a simpler solution:

Castle Game Engine: CastleSceneCore: Class TCastleSceneCore PlayAnimation accepts TPlayAnimationParameters which in turn has Transition field, see Castle Game Engine: CastleSceneCore: Class TPlayAnimationParameters

Setting transition duration to something meaningful (like 0.2-0.5 seconds) will make sure the animations will “blend” properly between each other.

The interval between the sword swings this way will be controlled fully from the code (by setting a timeout during which the next attack command will be ignored) and therefore game logic will dictate how animations perform, not the other way around.

Of course I understand this may not be the solution you are looking for. Then you may try to mimic State Machine behavior, which would be relatively trivial for such a simple case. Just get the animation duration by Castle Game Engine: CastleSceneCore: Class TCastleSceneCore and after attack action started set a timeout for which the next attack action will be ignored, just like in previous case but this time you are using animation duration as timeout value, making sure the animation is finished before the next attack can be started.

OK thank you.
I had thought about using a timing system to do this, but I wanted to make sure there were no alternative methods.
However, it might be an idea to add a simple Boolean property to the TCastleScene class that indicates whether there is an animation in Play at that moment.

Hi!

We had a similar needs in some of our projects, including “The Unholy Society” – https://www.unholy-society.com/ . There’s a great and reliable solution:

Observe when your animation ends using TPlayAnimationParameters.StopNotification . See API docs on Castle Game Engine: CastleSceneCore: Class TPlayAnimationParameters , there’s a ready example code there.

The important snippet is to play your animation like this:

      PlayAnimationParams := TPlayAnimationParameters.Create;
      try
        PlayAnimationParams.Name := 'sword_attack';
        PlayAnimationParams.StopNotification := {$ifdef FPC}@{$endif} MyAnimationStop;
        PlayAnimationParams.Loop := false;
        SceneGun.PlayAnimation(PlayAnimationParams);
      finally FreeAndNil(PlayAnimationParams) end;

and then you can define MyAnimationStop to do something, e.g. maybe switch to idle:

procedure TViewXxx.MyAnimationStop(const Scene: TCastleSceneCore;
  const Animation: TTimeSensorNode);
begin
  SceneGun.PlayAnimation('idle', true);
end;

It has been tested using scenarios very similar to your needs – see examples

  • examples/fps_game/ , in file examples/fps_game/code/gameviewplay.pas – we use for a very similar situation, to switch weapon animation to “idle” after shoot

  • examples/platformer/code/gameviewplay.pas

  • examples/short_api_samples/animation_stop_notification/animation_stop_notification.dpr (this is the sample example code as on API docs, Castle Game Engine: CastleSceneCore: Class TPlayAnimationParameters )

( All the above are paths within the Castle Game Engine examples subdirectory, which you have installed along with CGE :slight_smile: )