You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flame引擎组件添加至World/Game的判定准则与最佳实践

关于Flame中组件添加至World还是Game的选择准则

我发现要让组件跟随Camera,似乎需要将其添加至World。官方文档有提及但解释模糊。按我之前的理解,未添加至World的组件无法渲染,但实际测试中直接调用add()(添加至Game)也能正常显示组件——只是不会跟随Camera;添加至World时则能跟随。

想知道最佳实践是什么:是否应始终将组件添加至World以保证一致性与安全性?还是存在可直接使用add()的场景?核心问题就是:在Flame中添加对象时,依据什么准则决定将其添加至World还是Game?


Camera可跟随对象的代码示例

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';


void main() {
  runApp(const FooApp());
}

class FooApp extends StatelessWidget {
  const FooApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GameWidget.controlled(gameFactory: CameraTrackingExample.new),
    );
  }
}

class CameraTrackingExample extends FlameGame {
  late final MyMap map;
  late final SpriteComponent _appleSpriteComponent;

  final _speed = 200.0;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    map = MyMap();
    world.add(map);

    final appleSprite = await Sprite.load('apple.png');
    _appleSpriteComponent = SpriteComponent(
      position: Vector2(400, 100),
      size: Vector2(100, 100),
      sprite: appleSprite,
      anchor: Anchor.center,
    );
    world.add(_appleSpriteComponent);

    camera.follow(_appleSpriteComponent);
  }

  @override
  void update(double dt) {
    super.update(dt);

    _appleSpriteComponent.position.y += _speed * dt;
  }
}

class MyMap extends PositionComponent {
  MyMap()
      : super(
          size: Vector2.all(length),
        );

  static const double length = 1500;

  @override
  void render(Canvas canvas) {
    super.render(canvas);

    const steps = 10;
    for (var i = steps; i >= 0; i -= 1) {
      canvas.drawRect(
        Rect.fromCenter(
          center: Offset(width * 0.5, height * 0.5),
          width: width / steps * i.toDouble(),
          height: height / steps * i.toDouble(),
        ),
        Paint()..color = Color.fromARGB(255, 0, ((200 / steps) * i).toInt(), 0),
      );
    }
  }
}

Camera无法跟随对象的代码示例

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';


void main() {
  runApp(const FooApp());
}

class FooApp extends StatelessWidget {
  const FooApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GameWidget.controlled(gameFactory: CameraTrackingExample.new),
    );
  }
}

class CameraTrackingExample extends FlameGame {
  late final MyMap map;
  late final SpriteComponent _appleSpriteComponent;

  final _speed = 200.0;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    map = MyMap();
    add(map); // 👈 移除了world调用

    final appleSprite = await Sprite.load('apple.png');
    _appleSpriteComponent = SpriteComponent(
      position: Vector2(400, 100),
      size: Vector2(100, 100),
      sprite: appleSprite,
      anchor: Anchor.center,
    );
    add(_appleSpriteComponent); // 👈 移除了world调用

    camera.follow(_appleSpriteComponent);
  }

  @override
  void update(double dt) {
    super.update(dt);

    _appleSpriteComponent.position.y += _speed * dt;
  }
}

class MyMap extends PositionComponent {
  MyMap()
      : super(
          size: Vector2.all(length),
        );

  static const double length = 1500;

  @override
  void render(Canvas canvas) {
    super.render(canvas);

    const steps = 10;
    for (var i = steps; i >= 0; i -= 1) {
      canvas.drawRect(
        Rect.fromCenter(
          center: Offset(width * 0.5, height * 0.5),
          width: width / steps * i.toDouble(),
          height: height / steps * i.toDouble(),
        ),
        Paint()..color = Color.fromARGB(255, 0, ((200 / steps) * i).toInt(), 0),
      );
    }
  }
}

解答:组件添加至World或Game的选择准则

Flame中FlameGame默认包含两个核心层级,作用完全不同:

  1. World层级:属于游戏的「世界空间」,Camera的平移、缩放、旋转等所有变换操作只会作用于这个层级内的组件。如果你的组件需要跟随Camera移动(比如游戏角色、地图、场景道具),必须通过world.add()添加。
  2. Game根层级:属于「屏幕空间」,直接通过add()添加的组件不受Camera变换影响,始终以固定位置渲染在屏幕上。这类组件适合做UI元素,比如生命值条、得分面板、菜单按钮等,它们不需要随场景移动,保持在屏幕固定位置显示。

最佳实践

  • 所有游戏场景内的实体(角色、敌人、地图、道具等)都添加至World,确保它们能正确响应Camera的各种操作,保持场景逻辑的一致性。
  • 所有UI元素(HUD、菜单、提示框等)直接添加至Game根层级,避免被Camera变换干扰,始终稳定显示在屏幕上。

你之前的误解是混淆了「Camera可见」和「受Camera变换影响」:未添加到World的组件依然会被渲染,但它们处于独立的屏幕空间,Camera的跟随操作不会改变它们的渲染位置,所以看起来没有跟随Camera移动。


内容的提问来源于stack exchange,提问作者shingo.nakanishi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:48:09