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

Flutter敌人周期性左右移动动画延迟问题求助

无间隙实现敌人周期性左右移动动画解决方案

问题根源分析

你当前实现出现停顿的核心原因有两点:

  1. 每次移动都重新创建AnimationController,初始化、重置控制器的额外开销会导致动画衔接出现间隙。
  2. 使用Timer.periodic固定间隔触发动画,无法精准匹配动画实际完成时间,累积偏差后出现停顿。

解决方案:复用控制器+状态监听链式触发新动画

遵循你要求的「添加新动画机制而非无限循环」的思路,我们可以复用同一个AnimationController,在每次动画完成时立即创建新的反向移动动画并启动,确保无间隙衔接。

修正后的完整代码

import 'package:flutter/material.dart';

class EnemyMovementWidget extends StatefulWidget {
  const EnemyMovementWidget({super.key});

  @override
  State<EnemyMovementWidget> createState() => _EnemyMovementWidgetState();
}

class _EnemyMovementWidgetState extends State<EnemyMovementWidget> with TickerProviderStateMixin {
  AnimationController? _enemyController;
  Animation<double>? _enemyAnimation;
  double _currentFrom = 0.0;
  double _currentTo = 800.0;
  final Duration _moveDuration = const Duration(milliseconds: 1000);

  @override
  void initState() {
    super.initState();
    // 仅初始化一次控制器,避免重复创建开销
    _enemyController = AnimationController(vsync: this, duration: _moveDuration);
    _startMoveAnimation();
    runAi();
  }

  void _startMoveAnimation() {
    // 创建新的移动动画(符合添加新动画的机制)
    _enemyAnimation = Tween<double>(begin: _currentFrom, end: _currentTo)
        .animate(CurvedAnimation(parent: _enemyController!, curve: Curves.linear))
      ..addListener(() {
        _changeMove(_enemyAnimation!.value);
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          // 动画完成后立即切换方向,启动下一段新动画
          _swapMoveDirection();
          _enemyController!.reset();
          _startMoveAnimation();
          _enemyController!.forward();
        }
      });
  }

  void _swapMoveDirection() {
    final temp = _currentFrom;
    _currentFrom = _currentTo;
    _currentTo = temp;
  }

  void _changeMove(double position) {
    // 此处更新敌人位置逻辑
    debugPrint("Enemy position: $position");
  }

  void runAi() async {
    await Future.delayed(const Duration(milliseconds: 8200));
    // 启动第一段动画
    _enemyController!.forward();
  }

  @override
  void dispose() {
    _enemyController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

关键优化点

  • 复用控制器:仅在initState中初始化一次AnimationController,避免重复创建带来的性能开销和延迟。
  • 精准衔接:通过AnimationStatus.completed监听动画完成事件,在回调中立即切换方向并启动新动画,确保两段动画无间隙衔接。
  • 符合需求的新动画机制:每次移动都创建新的Tween动画实例,而非使用无限循环动画,满足你的设计要求。

内容的提问来源于stack exchange,提问作者sonic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:15:33