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

Unity中如何在触发区域内通过InvokeRepeating实现定时发射炮弹?

解决Unity触发区域内才重复发射炮弹的问题

你的代码核心问题是:InvokeRepeating在Start()中直接启动,导致不管玩家是否处于触发区内,炮弹都会每3秒发射一次,isFiring变量完全没参与发射逻辑的判断,所以无法实现需求。

下面提供两种简洁的修复方案:

方案一:在发射方法中判断触发状态

改动最小的方式,直接在发射方法里加isFiring的判断,只有满足条件才执行发射:

public class FireProjectile : MonoBehaviour
{
    public GameObject Player;
    public Transform launchPoint;
    public GameObject projectile;
    public float launchVelocity = 10f;
    public bool isFiring;

    void Start()
    {
        InvokeRepeating("fireProjectile", 0f, 3f);
    }

    void fireProjectile()
    {
        // 玩家不在触发区时直接返回,不发射
        if (!isFiring) return;
        
        var _projectile = Instantiate(projectile, launchPoint.position, launchPoint.rotation);
        _projectile.GetComponent<Rigidbody>().velocity = launchPoint.forward * launchVelocity;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject == Player)
        {
            isFiring = true;
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject == Player)
        {
            isFiring = false;
        }
    }
}

这种方式的优点是改动极小,缺点是InvokeRepeating会一直后台运行,但每3秒一次的空判断几乎没有性能开销,适合简单场景。

方案二:触发时启动/停止重复调用

更高效的方式,仅在玩家进入触发区时启动发射,离开时立即停止,避免无用的重复执行:

public class FireProjectile : MonoBehaviour
{
    public GameObject Player;
    public Transform launchPoint;
    public GameObject projectile;
    public float launchVelocity = 10f;

    void Start()
    {
        // 初始不启动发射逻辑
    }

    void fireProjectile()
    {
        var _projectile = Instantiate(projectile, launchPoint.position, launchPoint.rotation);
        _projectile.GetComponent<Rigidbody>().velocity = launchPoint.forward * launchVelocity;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject == Player)
        {
            // 防止重复触发导致发射频率异常,先判断是否已在运行
            if (!IsInvoking("fireProjectile"))
            {
                InvokeRepeating("fireProjectile", 0f, 3f);
            }
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject == Player)
        {
            CancelInvoke("fireProjectile");
        }
    }
}

这种方式更符合逻辑设计,只有在需要的时候才运行发射逻辑,性能更优。

注意事项

  • 确保触发区域的Collider组件勾选了Is Trigger,且玩家对象同时拥有Collider(非触发)和Rigidbody组件,否则OnTriggerEnter/OnTriggerExit不会触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:25:17