Unity PVZ类游戏塔台攻击逻辑Bug求助:多敌人场景异常
PVZ类游戏塔台射击逻辑问题修复方案
我正在开发一款PVZ类游戏,原本期望实现:敌人进入塔台攻击范围时塔台射击,离开时停止射击。但当前塔台持续射击,于是基于碰撞检测实现了相关逻辑,代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class attackRange : MonoBehaviour { public towerAttacker towerAttacker; void OnTriggerEnter2D(Collider2D collision) { if (collision.tag == "enemyCollider") { towerAttacker.shootStart(); // It will detect once but once too many enemies are present it only counts as 1 } } void OnTriggerStay2D(Collider2D collision) { if (collision.tag == "enemyCollider") { towerAttacker.shootStart(); // It detects constantly but makes the object go into rapid fire mode } } void OnTriggerExit2D(Collider2D collision) { if (collision.tag == "enemyCollider") { towerAttacker.StopAllCoroutines(); // Stop when there is no collision detected } } }
该逻辑在单敌人场景下正常,但多敌人场景异常:
- OnTriggerEnter2D仅检测一次,多敌人时仅触发一次射击逻辑
- OnTriggerStay2D会导致塔台进入快速射击模式
- OnTriggerExit2D会误停所有协程(只要有一个敌人离开就停止射击,哪怕还有其他敌人在范围内)
修复思路
核心是跟踪范围内的敌人数量,只有当敌人数量从0变1时启动射击,从1变0时停止射击,避免重复触发或误停止。
修复后的AttackRange代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AttackRange : MonoBehaviour { public TowerAttacker towerAttacker; private int enemyCount = 0; void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("enemyCollider")) { enemyCount++; // 仅第一个敌人进入时启动射击 if (enemyCount == 1) { towerAttacker.StartShooting(); } } } void OnTriggerExit2D(Collider2D collision) { if (collision.CompareTag("enemyCollider")) { enemyCount--; // 防止数量出现负数(应对碰撞检测异常) enemyCount = Mathf.Max(enemyCount, 0); // 最后一个敌人离开时才停止射击 if (enemyCount == 0) { towerAttacker.StopShooting(); } } } }
配套TowerAttacker类调整
不要直接用StopAllCoroutines(),给射击协程单独引用,避免误停其他协程:
using System.Collections; using UnityEngine; public class TowerAttacker : MonoBehaviour { private Coroutine shootingCoroutine; public float shootInterval = 1f; // 可在Inspector调整射击间隔 public void StartShooting() { // 避免重复启动协程 if (shootingCoroutine == null) { shootingCoroutine = StartCoroutine(ShootLoop()); } } public void StopShooting() { if (shootingCoroutine != null) { StopCoroutine(shootingCoroutine); shootingCoroutine = null; } } private IEnumerator ShootLoop() { while (true) { // 这里替换成你的实际射击逻辑(比如实例化子弹、锁定敌人等) Debug.Log("塔台发射子弹"); yield return new WaitForSeconds(shootInterval); } } }
关键说明
- 用
enemyCount精准控制射击启停时机,彻底解决多敌人场景的异常 - 替换
collision.tag ==为CompareTag(),性能更优且避免空引用风险 - 移除
OnTriggerStay2D,无需持续触发启动逻辑 - 单独管理射击协程,避免
StopAllCoroutines()误停其他协程
内容的提问来源于stack exchange,提问作者Nicole Erasga
相关产品推荐
相关产品推荐

