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

玩家死亡后启动EndingScreen Activity导致应用崩溃的问题排查求助

玩家死亡后启动EndingScreen Activity导致应用崩溃的问题排查求助

嘿,刚入门就敢做游戏项目,给你点个赞!不过遇到这个跳转崩溃的问题确实闹心,我先从你给的LogCat和代码里找找问题根源,再给你具体的解决步骤~

先看崩溃的核心原因

从你贴的LogCat里能看到关键错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference

而且崩溃发生在Thread-2,也就是你的游戏循环子线程里。这说明两个问题:

  1. 你在**非UI线程(游戏子线程)**里尝试启动Activity,这违反了Android的规则——所有UI相关操作(包括启动Activity)必须在主线程执行。
  2. 你用的getContext()在子线程里返回了null,导致创建Intent时找不到有效的上下文。

再看你代码里的问题点

你在draw方法里处理玩家死亡跳转的逻辑,而draw是被游戏循环的子线程调用的,这本身就不符合Android的UI操作规范。另外getContext()在子线程环境下可能因为线程绑定问题取不到有效的上下文,直接导致NullPointerException。

具体解决办法

我给你一步步改代码:

1. 给Game类保留有效的Activity引用

在Game类里添加一个Activity成员变量,构造的时候传入MainActivity的实例,避免依赖可能为空的getContext():

private Activity mGameActivity;

// 修改你的Game类构造方法,传入Activity实例
public Game(Activity activity, ...) {
    mGameActivity = activity;
    // 其他初始化代码...
}

注意:在MainActivity里创建Game实例的时候,要传this进去,比如new Game(this, ...)。

2. 把跳转逻辑移到Update方法,并且切换到主线程执行

玩家死亡的判断逻辑应该放在update方法里(负责逻辑更新),而不是draw方法(只负责绘制),然后用runOnUiThread把跳转操作切到主线程:

public void update() {
    // 先判断玩家是否死亡
    if (player.getHealthPoints() <= 0) {
        // 加个playerDead判断,避免重复触发跳转
        if (!playerDead) {
            playerDead = true;
            // 切换到主线程执行跳转操作
            mGameActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // 创建Intent,用有效的Activity上下文
                    Intent intent = new Intent(mGameActivity, EndScreen.class);
                    intent.putExtra("score", gameLoop.getCurrentKillCount());
                    mGameActivity.startActivity(intent);
                    // 停止游戏循环,避免后续还在更新逻辑
                    gameLoop.stopLoop();
                }
            });
        }
        return;
    }

    // 下面是原来的更新逻辑...
    joystick.update();
    player.update();
    // ...其余代码保持不变
}

3. 清理Draw方法里的跳转逻辑

把draw方法里的跳转相关代码删掉,让它只负责绘制:

@Override
public void draw(Canvas canvas) {
    super.draw(canvas);

    // 绘制所有游戏元素的代码...
    tilemap.draw(canvas, gameDisplay);
    player.draw(canvas, gameDisplay);
    // ...其余绘制代码保持不变

    // 只保留绘制游戏结束相关的UI(如果有的话)
    if (playerDead) {
        // 比如绘制游戏结束的文字或图片,不要在这里处理跳转
        // gameOver.draw(canvas);
    }
}

4. 最后检查AndroidManifest.xml

确保EndScreen已经在Manifest里注册了,这是很容易忘的点:

<application ...>
    <!-- 你的其他Activity -->
    <activity android:name=".EndScreen"/>
</application>

为什么这样改能解决问题?

  • 用Activity实例作为上下文,避免了getContext()返回null的情况
  • 用runOnUiThread把启动Activity的操作放到主线程,符合Android的UI操作规则
  • 把逻辑判断和绘制职责分开,代码结构更清晰,也避免了子线程操作UI的问题

按照这个步骤改完,应该就能正常跳转到结束界面啦,祝你项目顺利完成!

备注:内容来源于stack exchange,提问作者Benny Stein - Scinto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 15:49:34