Flutter setState() is not updating a Flame SpriteAnimationWidget

132

This was actually a bug, we are fixing it here.

Meanwhile, as a workaround, you can change the key of the widget every time that you change the animation and it should update the widget.

Share:
132
Andy K
Author by

Andy K

Updated on January 02, 2023

Comments

  • Andy K
    Andy K over 1 year

    I am currently using a SpriteAnimationWidget from Flame, and I want to have different animations by clicking buttons.

    To test out if this works, I am changing the animation parameter of the SpriteAnimationWidget with a button click. After 1 second, the widget has to return to its original animation.

    Here is my code:

    Future<void> playReaction() async {
      setState(() {
        isPlaying = true;
        state = 'reaction';
      });
    
      await Future.delayed(Duration(milliseconds: 1000));
    
      setState(() {
        isPlaying = false;
        state = 'idle';
      });
    }
    

    And inside the build, I am returning:

    if(state == 'reaction') {
      spriteAnimation = reactionSprite!.createAnimation(row: 0, stepTime: 0.1, from: 0,  to: 10);
      print('reaction');
    }
    else if(state == 'idle'){
      spriteAnimation = sprite!.createAnimation(row: 1, stepTime: 0.2, from: 0,  to: 4);
      print('idle');
    }
    
    return Container(
      height: widget.size,
      child: Stack(
          fit: StackFit.expand,
          children: [
            Positioned.fill(
              child: SpriteAnimationWidget(
                animation: spriteAnimation!,
                anchor: Anchor.center,
              )
            ),
          ]
      ),
    );
    

    The variables sprite and reactionSprite are sprite sheets that I preload using SpriteSheet.fromColumnsAndRows().

    The problem is that, although my app successfully runs playReaction() and reaches print('reaction'), the SpriteAnimationWidget is still playing the idle animation instead of the reaction animation. I know that it's being rebuilt somehow because I can see that there is a slight unnatural discontinuity in the animation when I hit the button (plus the print messages).

    Why is setState() not updating the SpriteAnimationWidget with a new animation parameter?

    I am relatively new to Flutter and Flame, so I would love some help or advice.

    ps. I tried using the same sprite sheet for the change with a different row (instead of using a completely different sprite sheet as in the code above), but the result was the same.

    • spydon
      spydon over 2 years
      I wonder if this is related to the playReaction being async, can you try to make it not async, just removing the delayed part and see if it works?
    • Andy K
      Andy K over 2 years
      @spydon Thank you for the comment, but I don't think that's the case. I tried the same code with a SpriteWidget, and it worked. To be exact, when I pressed the button, the app successfully returned a SpriteWidget (which only shows one still frame), waited for one second, then returned the SpriteAnimationWidget it used to show before pressing the button. I don't understand why it won't work when I'm doing the same thing for only SpriteAnimationWidgets with different animations.
    • spydon
      spydon over 2 years
      That is very strange! My best suggestion is to join the Flame discord and see if anyone else have experienced this issue. discord.com/invite/pxrBmy4