Search code examples
android-studioflutterflame

Flutter: update was called on null


I am trying to make a game with flutter's library Flame. But I am getting this error every time. It is saying that the update is called on null. But I have initialized in the initialize function. I have tried several ways but nothing seems to work. Please help me fix the bug.

    import 'dart:math';
    import 'dart:ui';

    import 'package:flame/flame.dart';
    import 'package:flame/game.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:small_game/components/Enemy.dart';
    import 'package:small_game/components/enemy_spawner.dart';
    import 'package:small_game/components/heath_bar.dart';
    import 'package:small_game/components/highscoreText.dart';
    import 'package:small_game/components/player.dart';
    import 'package:small_game/components/score_text.dart';
    import 'package:small_game/components/startText.dart';
    import 'package:small_game/states.dart' as gameState;

    class GameController extends Game{
      Random rand;
      Size screenSize;
      double tileSize;
      Player player;
      EnemySpawner enemySpawner;
      List<Enemy> enemies;
      HealthBar healthBar;
      int score;
      ScoreText scoreText;
      SharedPreferences storage;
      gameState.State state;
      HighScoreText highScoreText;
      StartText startText;

      GameController(this.storage){
        initialize();
      }

      void initialize() async{
        rand = Random();
        resize(await Flame.util.initialDimensions());
        player = Player(this);
        state = gameState.State.menu;
        enemies = List<Enemy>();
        enemySpawner = EnemySpawner(this);
        healthBar = HealthBar(this);
        score = 0;
        highScoreText = HighScoreText(this);
        startText = StartText(this);
      }

      @override
      void render(Canvas canvas) {
        Rect background = Rect.fromLTWH(0, 0, screenSize.width, screenSize.height);
        Paint backgroundPaint = Paint()..color = Color(0xffFCFCFA);
        canvas.drawRect(background, backgroundPaint);
        player.render(canvas);
        if(state == gameState.State.menu){
           startText.render(canvas);
           highScoreText.render(canvas);
        } else if(state == gameState.State.playing) {
          enemies.forEach((Enemy enemy) => enemy.render(canvas));
          scoreText.render(canvas);
          healthBar.render(canvas);
        }
      }

      @override
      void update(double t) {
        if(state == gameState.State.menu){
          highScoreText.update(t);
          startText.update(t);
        } else if(state == gameState.State.playing) {
          enemies.forEach((Enemy enemy) => enemy.update(t));
          enemies.removeWhere((Enemy enemy) => enemy.isDead);
          player.update(t);
          scoreText.update(t);
          healthBar.update(t);
          enemySpawner.update(t);
        }
      }

      void resize(Size size){
        screenSize = size;
        tileSize = screenSize.width / 10;
      }

      void onTapDown(TapDownDetails d){
        enemies.forEach((Enemy enemy) {
          if(state == gameState.State.menu){
            state = gameState.State.playing;
          }
          if(enemy.enemyRect.contains(d.globalPosition)){
            enemy.onTapDown();
          }
        });
      }

      void spawnEnemies(){
        double x,y;
        switch(rand.nextInt(4)){
          case 0:
            //TOP
            x = rand.nextDouble() * screenSize.width;
            y = -tileSize * 2.5;
            break;
          case 1:
            //RIGHT
            x = (tileSize * 2.5) + screenSize.width;
            y = rand.nextDouble() * screenSize.height;
            break;

          case 2:
            //BOTTOM
            x = rand.nextDouble() * screenSize.width;
            y = (tileSize * 2.5) + screenSize.height;
            break;
          case 3:
            //LEFT
            x = -(tileSize * 2.5);
            y = rand.nextDouble() * screenSize.height;
        }
        enemies.add(Enemy(this, x, y));
      }

    }

My error:

I/flutter (20131): ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (20131): The following NoSuchMethodError was thrown during a scheduler callback: I/flutter (20131): The method 'update' was called on null. I/flutter (20131): Receiver: null I/flutter (20131): Tried calling: update(0.0) I/flutter (20131): I/flutter (20131): When the exception was thrown, this was the stack: I/flutter (20131): #0
Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5) I/flutter (20131): #1 GameController.update (package:small_game/gameController.dart:69:17) I/flutter (20131): #2 GameRenderBox._update (package:flame/game.dart:360:10) I/flutter (20131): #3 GameRenderBox._tick (package:flame/game.dart:353:5) I/flutter (20131): #4 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1033:15) I/flutter (20131): #5 SchedulerBinding.handleBeginFrame. (package:flutter/src/scheduler/binding.dart:951:11) I/flutter (20131): #6 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8) I/flutter (20131): #7 SchedulerBinding.handleBeginFrame (package:flutter/src/scheduler/binding.dart:949:17) I/flutter (20131): #8 SchedulerBinding.scheduleWarmUpFrame. (package:flutter/src/scheduler/binding.dart:780:7) I/flutter (20131): #17 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19) I/flutter (20131): #18 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5) I/flutter (20131): #19 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12) I/flutter (20131): (elided 8 frames from package dart:async and package dart:async-patch) I/flutter (20131): I/flutter (20131): I/flutter (20131): This exception was thrown in the context of a scheduler callback. When the scheduler callback was registered (as opposed to when the exception was thrown), this was the stack: I/flutter (20131): #0 new _FrameCallbackEntry. (package:flutter/src/scheduler/binding.dart:112:33) I/flutter (20131): #1 new _FrameCallbackEntry (package:flutter/src/scheduler/binding.dart:115:6) I/flutter (20131): #2 SchedulerBinding.scheduleFrameCallback (package:flutter/src/scheduler/binding.dart:459:49) I/flutter (20131): #3 GameRenderBox._scheduleTick (package:flame/game.dart:341:50) I/flutter (20131): #4 GameRenderBox.attach (package:flame/game.dart:328:5) I/flutter (20131): #5 RenderObjectWithChildMixin.attach (package:flutter/src/rendering/object.dart:2886:14) I/flutter (20131): #6 AbstractNode.adoptChild (package:flutter/src/foundation/node.dart:132:13) I/flutter (20131): #7 RenderObject.adoptChild (package:flutter/src/rendering/object.dart:1232:11) I/flutter (20131): #8 RenderObjectWithChildMixin.child= (package:flutter/src/rendering/object.dart:2879:7) I/flutter (20131): #9 RenderObjectToWidgetElement.insertChildRenderObject (package:flutter/src/widgets/binding.dart:1020:18) I/flutter (20131): #10 RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:4986:35) I/flutter (20131): #11 RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4752:5) I/flutter (20131): #12 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3101:14) I/flutter (20131): #13 Element.updateChild (package:flutter/src/widgets/framework.dart:2904:12) I/flutter (20131): #14 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16) I/flutter (20131): #15 Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5) I/flutter (20131): #16 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3924:5) I/flutter (20131): #17 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3919:5) I/flutter (20131): #18 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3101:14) I/flutter (20131): #19 Element.updateChild (package:flutter/src/widgets/framework.dart:2904:12) I/flutter (20131): #20 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:998:16) I/flutter (20131): #21 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:969:5) I/flutter (20131): #22 RenderObjectToWidgetAdapter.attachToRenderTree. (package:flutter/src/widgets/binding.dart:915:17) I/flutter (20131): #23 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2328:19) I/flutter (20131): #24 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:914:13) I/flutter (20131): #25 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:795:7) I/flutter (20131): #26 runApp (package:flutter/src/widgets/binding.dart:845:7) I/flutter (20131): #27 main (package:small_game/main.dart:17:3) I/flutter (20131): (elided 14 frames from package dart:async and package dart:async-patch)


Solution

  • Your initialize function is async, meaning it will run in the background. Therefore when update is first called, startText is null and gives you the NPE. You probably want to add some check on update to make sure it's initialized before moving forward with update code, or make initialize sync and then do whatever async stuff you need later (since initializing startText is certainly not one of them).