rive-app / rive-flutter

Flutter runtime for Rive

Home Page:https://rive.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Rive StateMatchine with multiple layers does not work properly

Sh1d0w opened this issue · comments

commented

Description

I have a Rive StateMachine with 3 layers in it. When an input is fired I have different conditions that trigger animations on all 3 of the layers.

It works perfectly with Rive for React, but when I import and use the Rive animation in flutter it only triggers the animation from the last layer and then exits, without animating the rest at the same time. Subsequent triggers also does not seem to trigger any animations.

Steps To Reproduce

Use the animation from the attached archive.

var ctrl = StateMachineController.fromArtboard(art, 'DivisionMachine',
        onStateChange: (
      String stateMachineName,
      String stateName,
    ) {
      print(stateMachineName);
      print(stateName);
    }) as StateMachineController;
    art.addController(ctrl);

    final divisionInput = ctrl.findInput<double>('division');

    if (divisionInput != null) {
      divisionInput.value = 7;
    }

    final suitInput = ctrl.findInput<double>('rank');
    if (suitInput != null) {
      suitInput.value = 3;
    }

    SMITrigger promote = ctrl.findSMI('promote');
    SMITrigger demote = ctrl.findSMI('demote');
    SMITrigger toClub = ctrl.findSMI('toClub');
    SMITrigger toDiamond = ctrl.findSMI('toDiamond');
    SMITrigger toHeart = ctrl.findSMI('toHeart');
    SMITrigger toSpade = ctrl.findSMI('toSpade');

     promote.fire();
     toHeart.fire();
 

Source .riv/.rev file

poc.zip

Expected behavior

When I hit the trigger all layers of animations are executed simultaneously.

Device & Versions (please complete the following information)

  • Device: iOS simulator
  • Flutter Version: Channel stable, 3.13.0
commented

@luigi-rosso any chance you can look into this, please? Thanks 🙏

Hi @Sh1d0w, I don't think I'm reproducing the problem correctly. This seems to behave properly for how the layers are setup:

Screen.Recording.2023-08-31.at.8.46.42.PM.mov

Does that look as expected or is something missing that I'm not catching?

Code I used:

import 'package:flutter/material.dart';
import 'package:rive/rive.dart';

class SimpleStateMachine extends StatefulWidget {
  const SimpleStateMachine({Key? key}) : super(key: key);

  @override
  State<SimpleStateMachine> createState() => _SimpleStateMachineState();
}

class _SimpleStateMachineState extends State<SimpleStateMachine> {
  SMITrigger? _promote;
  SMITrigger? _heart;

  void _onRiveInit(Artboard artboard) {
    final controller =
        StateMachineController.fromArtboard(artboard, 'DivisionMachine');
    artboard.addController(controller!);
    _promote = controller.findInput<bool>('promote') as SMITrigger;
    _heart = controller.findInput<bool>('toHeart') as SMITrigger;
    final divisionInput = controller.findInput<double>('division');

    if (divisionInput != null) {
      divisionInput.value = 7;
    }

    final suitInput = controller.findInput<double>('rank');
    if (suitInput != null) {
      suitInput.value = 3;
    }
  }

  void _onTap() {
    _promote?.fire();
    _heart?.fire();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Simple State Machine'),
      ),
      body: Stack(
        children: [
          Center(
            child: GestureDetector(
              onTap: _onTap,
              child: RiveAnimation.asset(
                'assets/rank_change.riv',
                fit: BoxFit.cover,
                onInit: _onRiveInit,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

commented

@luigi-rosso Thanks for looking into this. Yes that's the correct behaviour. But in my app it does not do this with the latest version of the plugin. It skips the whole layer of background change, and only triggers the stars animation.

Screen.Recording.2023-09-01.at.8.26.15.mov

Weird. Let me setup a bare flutter repo and I will try to reproduce it there, as our app is closed source.

Thanks again for your time, will get back to you. 🙏

commented

@luigi-rosso OK I've found out what the issue is. From the difference in your code and mine it seems that it works when it is triggered from onTap event, all good.

But if I do it like my original post, e.g. in the rive's onInit callback, it does not work.

Is that expected, a limitation, or a bug? As I would expect to setup and trigger the animation right inside the init, not via gesture? What would be the correct way to do that in such case?

The use case is as you can see I have a very complex animation, so I have some Flutter logic which trigger should be fired, so auto play does not suit my need. I need to setup the input first and then based on some conditions to trigger the correct animation right after the initialisation without user interference.

commented

I've workaround it by creating an async function _animate that I call from onInit and before the triggers I put this

await Future.delayed(Duration(milliseconds: 100));

It works, but not sure if this is intended or not. Feel free to close if you don't think this is bug. Thanks for your help mate!