Candy for You: Design of A Flutter Interaction Engine

Best practice of Flutter from Alibaba’s Xianyu tech team

What Is Candy?

  • It is an app-embedded, lightweight, easy-to-develop, and stable interaction engine.
  • The game series complies with industry standards.
  • The rendering system is highly integrated with the Flutter system. Game scenes can be seamlessly mixed with the Flutter UI.
  • The animation system provides strong support for mainstream formats and features easy extensibility.

This article mainly explains why and how we developed this engine.


Apps generally use embedded HTML5 mini-games, but these present some hidden dangers and are not recommended by many app stores. Therefore, we needed to find a new and safe method to develop app-based embedded mini-games. We wanted this method will feature easy development, stable performance, and complete functionality. These three desires informed our search for a new method.


  • Using the native game capabilities

Currently, the ecosystem for native game development is not very mature. Moreover, using Native development requires two sets of code on both sides, incurring relatively high development costs and subsequent maintenance costs.

  • Using game engines, such as Cocos2d-x and Unity

Currently, game engines are very mature. However, they are generally used to develop intensive games. The engine size is relatively large, and therefore introducing a game engine will significantly increase the package size. In addition, due to complexity, it takes a lot of time to start the engines, difficult to achieve opening game pages in seconds. After a game engine is loaded, the memory consumption is very large. Communication and interaction between the game engine and app are relatively complicated. Currently, there is no proper hybrid stack to support it. Game engines have weak UI capabilities and cannot be used for complex app UI logic. If a game engine is used to develop embedded mini-games, it cannot integrate UIs on mini-game pages, such as game scenes and feeds.

  • Using the Flutter lightweight interaction engine

Flutter itself is a cross-terminal app solution based on Skia, a 2D rendering engine. It has intrinsic 2D rendering capabilities. Therefore, Flutter offers a promising method for the development of app-based embedded mini-games. Currently, Flutter has some lightweight game engines, such as Flame. Flame supports simple game logic and animation capabilities. At the same time, the entire game is ultimately inserted into an app as a widget. This allows seamless integration of the game part and the UI part on mini-game pages.

Based on the above considerations, we decide to use a Flutter lightweight interaction engine.

Flame or Independent Design

  1. Incomplete game system: The engine provides only Game and Component. Scene and GameObject concepts do not exist. As a result, the nesting of game objects is complex and not well-suited to multiple scenes.
  2. The engine is entirely implemented using Canvas. Partial refresh is not supported in game scenes, posing performance risks.
  3. Lack of a GUI system: It is difficult to nest UIs in a scene.
  4. The engine lacks a gesture event system.
  5. Support for non-mainstream animation formats: Skeletal animation is supported through Flare. DragonBones is not supported. Particle animation was only implemented recently, and it does support mainstream formats well.
  6. Memory problems exist in resource management. Resources are not released after they are loaded.
  7. The engine lacks device model adaptability.

Based on these concerns, we decide to design a new Flutter interaction engine.

  1. We improved the game system based on the EVA engine of the Alibaba Group and the Unity engine in the industry.
  2. We reused Flutter’s partial refresh.
  3. We reused the Flutter UI as the GUI.
  4. We reused Flutter gesture management.
  5. We implemented skeletal animation and particle animation that support mainstream formats.
  6. We reused the app resource library (image library).
  7. We implemented global 750 adaptation.

Among the preceding points, 2 to 4 essentially integrate the rendering system of the interaction engine into the Flutter rendering system. The following introduces our engine design in order based on how it solves the preceding problems.

Candy Engine Design

Framework Design

After decomposition, the interaction engine needs to have a game system, rendering system, lifecycle system, GUI system, physical system, animation system, resource system, and event system (gesture management).

According to our previous idea, interactive game rendering needs to be integrated into the Flutter rendering system. Based on this idea, we can reuse the Flutter UI system and also need to integrate the gesture management of the game and Flutter. Finally, we obtain a framework as shown in Figure 4–2.

The interaction engine architecture consists of four parts.

  • Interface layer

This provides externally exposed game interfaces, including interfaces for creating games, creating game objects, and adding game components. It also encapsulates factory interfaces for some commonly used game objects and game components.

  • Game system

The game world management system manages organizational relationships among Games, Scenes, GameObjects, and Components and controls the startup and shutdown of the game subsystems and rendering system.

  • Game subsystem

This supplements gamification capabilities with a lifecycle system, physical system, animation system, and resource system, which are called by the game system.

  • Rendering system

This is responsible for game rendering. The rendering system of the engine is highly integrated with the Flutter rendering logic. Therefore, it is compatible with the GUI system and event system (gesture management).

Game System

  1. Game: game class. It is responsible for overall game management, Scene loading management, and subsystem management and scheduling.
  2. Scene: game scene class. It is responsible for the management of each game object in game scenes.
  3. GameObject: game object class. It is the smallest unit of game objects in the game world. Any object in the game world is a GameObject.
  4. Component: game component class. These indicate the capability attributes of a game object. For example, SpriteComponent, the sprite component, indicates the sprite rendering capability.

A GameObject possesses different capabilities by combining various Components. Different combinations make GameObjects distinctive. Figure 4–3 shows the organizational relationships of the entire game system.


Rendering System

First, the number of game objects must be effectively integrated with the three trees of Flutter. Therefore, each GameObject must correspond to a Widget, Element, and RenderObject.

The integration process helps solve the following problems:

  1. Conversion and integration between the coordinate system of the Flutter layout
  2. Processing for dynamically adding and deleting game objects
  3. Processing for dynamically modifying the game rendering depth
  4. Support for game objects by Flutter Inspector

The overall rendering integration is relatively complex and many BadCases need to be eliminated. Subsequent articles will describe the process of integrating the interaction engine rendering with the Flutter rendering system in detail. Therefore, we will not give a detailed description here.

GUI System

The following provides a segment of GUI sample code. The development process is relatively simple.

final GUIObject gui = IdleFishGame.createGUI(
child: GestureDetector(
child: Container(
width: 100.0,
height: 60.0,
decoration: BoxDecoration(
color: const Color(0xFFA9CCE3),
borderRadius: const BorderRadius.all(
child: const Center(
child: Text(
'Flutter UI example',
style: TextStyle(
fontSize: 14.0,
behavior: HitTestBehavior.opaque,
onTap: () {
print('UI is clicked');
position: Position(100, 100),

Event System

The integration process is as follows:

  1. GestureBoxComponent registers gesture callback methods registered by the developers with the gesture detector.
  2. The RenderObject corresponding to the GameObject duplicates the hitTest logic and processes the click hitTest according to Flutter specifications. The GestureBoxComponent determines whether a click can be consumed.
  3. The GameObject duplicates handEvent to send a click event to the GestureBoxComponent for consumption.
  4. After receiving the click event, GestureBoxComponent sends it to the gesture detector.
  5. The gesture detector transmits the click to the gesture arena for gesture competition. The winning gesture is returned to the gesture detector and finally is returned for the gesture event response. Naturally, this step belongs to the Flutter logic.

Other Subsystems

Currently, we support skeletal animation and particle animation. The supported resources are DragonBones for skeletal animation and EgretFeather for particle animation. Due to space constraints, the specific animation implementation will be discussed in detail in subsequent articles.

Resource System

Currently, the resource system of the interaction engine is relatively simple. This article gives a brief introduction. The resource system was designed by reusing the app resource system. This ensures that the app has only one resource library, reducing memory overhead and increasing the resource reuse rate. Figure 4–6 shows the resource system architecture. A proxy layer compatible with the app resource system and backup resource system is added between the game system and resource system. The backup resource system is automatically called if the app resource system is not registered.

The backup resource system is currently divided into two parts:

Backup image library: reuses Flutter ImageCache. This part reuses Flutter capabilities for memory management.

Animation JSON resource management: Currently, only the JSON read logic is implemented. Cache management is not implemented due to low JSON reusability.

The resource system does not have remote loading and preloading capabilities, which we plan to implement in the future. Later articles will share the specific design implementation.


We have encountered many problems during the design and implementation process of the Candy engine. For example, Flutter experiences some memory leakage during the rendering process and memory collection is not prompt. Later articles will detail the troubleshooting and solutions to these problems and the testing and analysis of the Candy engine’s performance and stability, so stay tuned.

(Original article by Chen Xuwei陈绪伟)

Alibaba Tech

First-hand & in-depth information about Alibaba's tech innovation in Artificial Intelligence, Big Data & Computer Engineering. Follow us on Facebook!