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

Unity弹药碰撞脚本弹药耗尽仍可摧毁小行星问题

问题现象

Unity开发弹药系统时出现逻辑异常:初始弹药值设为10,弹药耗尽后本应跳转死亡界面,实际仍可触发碰撞逻辑持续摧毁小行星,原始实现代码如下:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ExplosionOnTouch : MonoBehaviour
{
    // Start is called before the first frame update
    public int Ammo = 10;
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (Ammo > 0)
        {
            Ammo = Ammo - 1;
            Destroy(gameObject);
        }
        else
        {
        SceneManager.LoadScene("DeathScreen", LoadSceneMode.Single);
        }
    }
}
问题原因
  • 核心问题是Ammo是实例字段:如果这个脚本挂在子弹预制体上,每生成一颗新子弹,该子弹实例的Ammo都会重置为Inspector里配置的初始值10,碰撞时仅扣减当前子弹自己的弹药计数,扣完1就销毁自身,永远不会触发弹药归零的分支,全局总弹药数根本没有被累计扣减。
  • 没有做碰撞对象校验:只要碰到任何带碰撞体的物体都会触发弹药扣减/场景跳转逻辑,容易误触发。
  • 销毁目标错误:代码里Destroy(gameObject)销毁的是挂载脚本的当前物体,没有显式销毁碰撞到的小行星,逻辑和预期不符。
修复方案
  1. 优先把弹药计数逻辑从子弹实例剥离,单独做全局/玩家维度的弹药管理;如果暂时不想拆分脚本,可把Ammo设为静态字段,让所有实例共享同一个总弹药计数。
  2. 增加碰撞层判断,仅当碰撞对象是小行星时才触发弹药逻辑。
  3. 修正销毁目标,碰撞后同时销毁小行星和子弹(如果脚本挂在子弹上),弹药归零时正常跳转死亡场景。
  4. 增加弹药重置方法,避免静态值跨局残留。

修复后的参考代码:

using UnityEngine;
using UnityEngine.SceneManagement;
public class ExplosionOnTouch : MonoBehaviour
{
    // 静态字段所有实例共享,全局统一扣减总弹药
    public static int Ammo = 10;
    // 配置小行星所在层,在Inspector面板选择对应层即可
    public LayerMask asteroidLayer;

    private void OnCollisionEnter2D(Collision2D collision)
    {
        // 非小行星碰撞直接忽略,不触发逻辑
        if (((1 << collision.gameObject.layer) & asteroidLayer) == 0)
        {
            return;
        }

        if (Ammo > 0)
        {
            Ammo--;
            // 销毁碰撞到的小行星
            Destroy(collision.gameObject);
            // 销毁当前子弹(脚本挂在子弹上时保留这行,挂在其他物体上可删除)
            Destroy(gameObject);
        }
        else
        {
            SceneManager.LoadScene("DeathScreen", LoadSceneMode.Single);
        }
    }

    // 重开游戏时调用该方法重置弹药,避免静态值跨局残留
    public static void ResetAmmo()
    {
        Ammo = 10;
    }
}

额外优化建议

  • 长期维护建议单独实现单例模式的弹药管理器,把弹药扣减、数值校验、事件触发逻辑统一收口,不要把全局状态存在子弹这类临时生成的物体上。
  • 可以给弹药数增加UI更新事件,每次弹药变化时主动刷新UI显示,避免UI和实际数值不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:39:12