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

Unity移动端触摸控制时协程发射子弹过快的修复求助

解决Unity触摸移动时子弹发射过快的问题

问题根源

  1. 重复启动协程:TouchMove.Update()每帧都会执行,只要检测到触摸存在就调用weapon.StartFiring(),每次调用都会启动一个新的TryAttack协程。多个协程同时运行,各自按0.5f间隔生成子弹,最终发射速度远超设定值。
  2. 代码块逻辑错误:原代码中if (touch.phase == TouchPhase.Ended)未加花括号,导致weapon.StopFiring()每帧都会执行,协程刚启动就被停止,同时下一帧又重新启动,逻辑彻底混乱。

修复后的代码

Weapon脚本(优化协程管理)

using System.Collections;
using UnityEngine;

public class Weapon : MonoBehaviour
{
    [SerializeField]
    private GameObject projectilePrefab;
    [SerializeField]
    private float attackRate = 0.5f;

    private Coroutine firingCoroutine; // 保存协程引用,避免重复启动

    public void StartFiring()
    {
        // 仅当协程未运行时才启动
        if (firingCoroutine == null)
        {
            firingCoroutine = StartCoroutine(TryAttack());
        }
    }

    public void StopFiring()
    {
        // 停止协程并清空引用
        if (firingCoroutine != null)
        {
            StopCoroutine(firingCoroutine);
            firingCoroutine = null;
        }
    }

    private IEnumerator TryAttack()
    {
        while (true)
        {
            Instantiate(projectilePrefab, transform.position, Quaternion.identity);
            yield return new WaitForSeconds(attackRate);
        }
    }
}

TouchMove脚本(修复触摸逻辑)

using UnityEngine;

public class TouchMove : MonoBehaviour
{
    private Vector3 touchPosition;
    private Rigidbody2D rb;
    private Vector3 direction;
    private float moveSpeed = 10f;
    private Weapon weapon;

    private void Awake() 
    {
       weapon = GetComponent<Weapon>();    
    }

    private void Start() 
    {
        rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        if(Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);
            touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
            touchPosition.z = 0;
            direction = (touchPosition - transform.position);

            switch(touch.phase)
            {
                case TouchPhase.Began:
                case TouchPhase.Moved:
                case TouchPhase.Stationary:
                    // 触摸开始、移动或静止时,移动角色并启动射击
                    rb.velocity = new Vector2(direction.x, direction.y) * moveSpeed;
                    weapon.StartFiring();
                    break;
                case TouchPhase.Ended:
                case TouchPhase.Canceled:
                    // 触摸结束或取消时,停止移动和射击
                    rb.velocity = Vector2.zero;
                    weapon.StopFiring();
                    break;
            }
        }
        else
        {
            // 无触摸时,确保停止所有动作
            rb.velocity = Vector2.zero;
            weapon.StopFiring();
        }
    }
}

修复说明

  1. Weapon脚本:
    • 新增firingCoroutine变量跟踪协程状态,避免重复启动多个协程实例。
    • 使用直接引用协程方法的方式启动协程,比字符串形式更可靠且性能更优。
  2. TouchMove脚本:
    • 用switch语句清晰处理不同触摸阶段,逻辑更直观。
    • 确保只有在有效触摸阶段才启动射击,触摸结束或无触摸时停止所有动作。
    • 修复了原代码中缺少花括号导致的逻辑错误,保证代码块执行的正确性。

内容的提问来源于stack exchange,提问作者프로필

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:05:20