Unity 2D塔防游戏中塔楼近距离Y轴相邻时无法正常锁定敌人问题
问题分析与解决方案
核心问题
- 2D旋转逻辑错误:使用3D的
Quaternion.LookRotation处理2D场景旋转,导致方向计算混乱,多塔同时触发检测时旋转状态被错误覆盖。 - 碰撞检测逻辑不可靠:
OnCollisionStay2D依赖碰撞体持续接触,多塔靠近时易出现检测冲突,且无法精准控制目标选择优先级。 - 旋转代码冗余冲突:连续两次赋值
transform.rotation,逻辑重复且破坏正确的旋转计算。
分步解决方案
1. 替换为2D专属旋转逻辑
在2D游戏中,物体仅需绕Z轴旋转,直接通过方向向量计算角度即可,替代3D旋转方法:
// 计算指向敌人的2D方向向量(忽略Z轴) Vector3 direction = target.transform.position - transform.position; direction.z = 0; // 计算Z轴旋转角度,减90度适配Sprite默认向上方向 float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg - 90f; transform.rotation = Quaternion.Euler(0, 0, angle);
2. 改用触发器+范围目标列表(替代OnCollisionStay2D)
OnCollisionStay2D触发逻辑不可控,改用触发器维护范围内敌人列表,在Update中主动选择目标,避免多塔冲突:
修改后的完整代码:
using UnityEngine; using System.Collections.Generic; public class BaseTowerScript : MonoBehaviour { public float FireCooldown; private float FireTimer; public GameObject TowerBullet; private List<GameObject> enemiesInRange = new List<GameObject>(); private GameObject currentTarget; private void Update() { // 帧率适配的冷却更新 if (FireTimer < FireCooldown) { FireTimer += Time.deltaTime; } // 筛选有效目标(优先列表中第一个存活敌人) currentTarget = null; foreach (var enemy in enemiesInRange) { if (enemy != null) { currentTarget = enemy; break; } } // 有目标则执行锁定与射击 if (currentTarget != null) { RotateToTarget(currentTarget); TryShoot(); } } private void RotateToTarget(GameObject target) { Vector3 direction = target.transform.position - transform.position; direction.z = 0; float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg - 90f; transform.rotation = Quaternion.Euler(0, 0, angle); } private void TryShoot() { if (FireTimer >= FireCooldown) { GameObject nBullet = Instantiate(TowerBullet, transform.position, transform.rotation); // 给子弹添加足够的向前推力 nBullet.GetComponent<Rigidbody2D>().AddForce(transform.up * 15f, ForceMode2D.Impulse); FireTimer = 0; } } // 敌人进入范围时加入列表 private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Enemy")) { enemiesInRange.Add(other.gameObject); } } // 敌人离开范围时移除列表 private void OnTriggerExit2D(Collider2D other) { if (other.CompareTag("Enemy")) { enemiesInRange.Remove(other.gameObject); } } }
3. 正确配置图层碰撞忽略
确保塔楼之间不会互相触发检测:
- 创建
Tower专属图层,将所有塔楼设置为该图层 - 打开
Edit > Project Settings > Physics 2D - 在
Layer Collision Matrix中,取消Tower图层与自身的碰撞勾选
4. 额外优化建议
- 用
Time.deltaTime更新冷却,保证不同帧率下冷却速度一致 - 可扩展目标选择逻辑(如选择最近敌人、血量最低敌人)
- 给子弹预设添加
Rigidbody2D并设置合适的质量,避免飞行异常
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

