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

Unity中使用IEnumerator实现FireGun函数延迟失效,需求为每秒生成一颗子弹的问题咨询

Unity中使用IEnumerator实现FireGun函数延迟失效,需求为每秒生成一颗子弹的问题咨询

嘿,我明白你的困扰了——你想实现按住鼠标时每秒发射一颗子弹,但现在代码不仅没实现延迟,反而疯狂生成子弹根本停不下来,对吧?咱们来一步步拆解问题出在哪,然后给你解决办法。

问题根源分析

你的代码现在有两个核心问题:

  1. 输入检测逻辑错误:在PlayerController2的Update里,你用了Input.GetButton("Fire1")——这个函数会每帧返回true,只要玩家按住鼠标左键。这就导致每帧都会调用weaponscript.fireGun(),同时启动一堆WaitASecond协程,等于每帧都在预约1秒后生成子弹,最后会有几十上百颗子弹同时爆发,完全失控。
  2. 协程的使用方式不对:你在WeaponScript里的fireGun只是启动一个延迟生成单颗子弹的协程,但没有做“同一时间只能有一个发射协程运行”的限制,也没控制发射间隔的逻辑,本质上只是给单颗子弹加了延迟,而不是实现“每秒一颗”的发射节奏。

解决方案(两种可选,按需选择)

方案1:用冷却时间变量控制发射间隔(简单直接)

这种方式适合“点击一次发射一颗,必须等1秒才能再次发射”,或者“按住时持续每秒发射”的需求。

第一步,修改PlayerController2,添加冷却时间控制:

// 在PlayerController2的私有变量里加一行
private float fireCooldown = 0f;

void Update()
{
    // 保留你原来的其他逻辑(经验升级、生命值判断等)...

    if (Input.GetButton("Fire1") && gamepause == false)
    {
        // 检查冷却是否结束
        if (fireCooldown <= 0f)
        {
            // 根据状态调用对应发射函数
            if (doubleshot)
            {
                weaponscript.fireDoubleGun();
            }
            else
            {
                weaponscript.fireGun();
            }
            // 重置冷却时间为1秒
            fireCooldown = 1f;
        }
        // 每帧减少冷却时间
        fireCooldown -= Time.deltaTime;
    }

    // 其他原有代码...
}

第二步,简化WeaponScript的fireGun,去掉多余的协程(因为冷却已经在Player端控制了):

public void fireGun()
{
    // 直接生成子弹,不用延迟
    GameObject projectile = Instantiate(bullet, firepoint.position, firepoint.rotation);
    projectile.GetComponent<Rigidbody2D>().AddForce(firepoint.up * fireForce, ForceMode2D.Impulse);
}

方案2:用协程持续控制发射节奏(适合按住持续发射)

如果你的需求是“按住鼠标就持续每秒发射一颗,松开就停止”,可以用这种方式,让Weapon自己管理发射循环:

第一步,修改WeaponScript:

// 在WeaponScript里加一个标记,防止重复启动协程
private bool isFiring = false;

// 改成循环发射的协程
private IEnumerator ContinuousFireRoutine()
{
    isFiring = true;
    // 循环发射直到停止
    while (true)
    {
        GameObject projectile = Instantiate(bullet, firepoint.position, firepoint.rotation);
        projectile.GetComponent<Rigidbody2D>().AddForce(firepoint.up * fireForce, ForceMode2D.Impulse);
        // 等待1秒再发射下一颗
        yield return new WaitForSeconds(1f);
    }
}

// 新增启动发射的方法
public void StartContinuousFire()
{
    if (!isFiring)
    {
        StartCoroutine(ContinuousFireRoutine());
    }
}

// 新增停止发射的方法
public void StopContinuousFire()
{
    if (isFiring)
    {
        StopCoroutine(ContinuousFireRoutine());
        isFiring = false;
    }
}

// 保留原来的fireDoubleGun不变
public void fireDoubleGun()
{
    GameObject projectile = Instantiate(bullet, firepoint.position, firepoint.rotation);
    projectile.GetComponent<Rigidbody2D>().AddForce(firepoint.up * fireForce, ForceMode2D.Impulse);
    GameObject projectile2 = Instantiate(bullet, firepoint.position, firepoint.rotation);
    projectile2.GetComponent<Rigidbody2D>().AddForce(firepoint.up * fireForce, ForceMode2D.Impulse);
}

第二步,修改PlayerController2的输入逻辑,用GetButtonDown和GetButtonUp来控制启动/停止:

void Update()
{
    // 保留原有其他逻辑...

    // 按下鼠标时启动发射
    if (Input.GetButtonDown("Fire1") && gamepause == false)
    {
        if (doubleshot)
        {
            weaponscript.fireDoubleGun();
        }
        else
        {
            weaponscript.StartContinuousFire();
        }
    }

    // 松开鼠标时停止发射
    if (Input.GetButtonUp("Fire1"))
    {
        weaponscript.StopContinuousFire();
    }

    // 其他原有代码...
}

为什么原来的代码不行?

再帮你理一遍:

  • Input.GetButton("Fire1")每帧触发,等于每帧都在预约新的延迟生成任务,1秒后这些任务会同时执行,导致子弹爆炸式生成;
  • 你原来的协程只是给单颗子弹加了延迟,但没有控制“同一时间只能有一个发射流程”,完全没实现“每秒一颗”的节奏限制。

备注:内容来源于stack exchange,提问作者GeniusCoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 10:54:11