玩家近战部队脚本失效求助:逻辑与敌方一致却无法移动
问题
开发策略防御游戏时,玩家近战部队在前方友军被摧毁后仍无法移动,但敌方近战部队逻辑正常。两款脚本框架一致,以下是脚本代码:
玩家近战逻辑脚本
public class MeleeTroopLogic : MonoBehaviour { [SerializeField] private float AttackSpeed; [SerializeField] public float Damage; [SerializeField] private float ViewRange; [SerializeField] private float BoundaryRange; [SerializeField] private LayerMask EnemyLayer; [SerializeField] private LayerMask FriendlyLayer; [SerializeField] private float ColliderDistance; [SerializeField] private float FriendlyColliderDistance; [SerializeField] private BoxCollider2D AttackRange; [SerializeField] private BoxCollider2D SpaceDistance; private float AttackCooldown = Mathf.Infinity; Health TroopHealth; PlayerTroopsMovement Move; private Animator anim; private void Awake() { Move = GetComponentInParent<PlayerTroopsMovement>(); } void Update() { AttackCooldown += Time.deltaTime; if(Enemydetected()) { Move.MovementSpeed = 0; if(AttackCooldown >= AttackSpeed) { AttackCooldown = 0; Attack(); } } if(Move != null) { Move.enabled = !(Enemydetected() || AllyDetected()); } } private bool Enemydetected() { RaycastHit2D hit = Physics2D.BoxCast(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z),0,Vector2.right, 0, EnemyLayer); if(hit.collider != null) { TroopHealth = hit.transform.GetComponentInChildren<Health>(); } return hit.collider != null; } private bool AllyDetected() { RaycastHit2D hit = Physics2D.BoxCast(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * BoundaryRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z), 0, Vector2.right, 0, FriendlyLayer); return hit.collider != null; } private void OnDrawGizmos() { EnemyGizmo(); AllyGizmo(); } private void EnemyGizmo() { Gizmos.color = Color.red; Gizmos.DrawWireCube(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z)); } private void AllyGizmo() { Gizmos.color = Color.blue; Gizmos.DrawWireCube(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * ViewRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z)); } private void Attack() { if(TroopHealth != null) { TroopHealth.TakeDamage(Damage); } } }
敌方近战逻辑脚本
public class EnemyMeleeTroopLogic : MonoBehaviour { [SerializeField] private float AttackSpeed; [SerializeField] private float Damage; [SerializeField] private float ViewRange; [SerializeField] private float BoundaryRange; [SerializeField] private float ColliderDistance; [SerializeField] private float FriendlyColliderDistance; [SerializeField] private LayerMask FriendlyLayer; [SerializeField] private LayerMask EnemyLayer; [SerializeField] private BoxCollider2D AttackRange; [SerializeField] private BoxCollider2D SpaceDistance; private float AttackCooldown = Mathf.Infinity; Health TroopHealth; EnemyTroopsMovement Move; private Animator anim; private void Awake() { Move = GetComponentInParent<EnemyTroopsMovement>(); } void Update() { AttackCooldown += Time.deltaTime; if (Enemydetected()) { if (AttackCooldown >= AttackSpeed) { AttackCooldown = 0; Attack(); } } if (Move != null) { Move.enabled = !(Enemydetected() || AllyDetected()); } } private bool Enemydetected() { RaycastHit2D hit = Physics2D.BoxCast(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z), 0, Vector2.left, 0, FriendlyLayer); if (hit.collider != null) { TroopHealth = hit.transform.GetComponentInChildren<Health>(); } return hit.collider != null; } private bool AllyDetected() { RaycastHit2D hit = Physics2D.BoxCast(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * BoundaryRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z), 0, Vector2.right, 0, EnemyLayer); return hit.collider != null; } private void OnDrawGizmos() { EnemyGizmo(); AllyGizmo(); } private void EnemyGizmo() { Gizmos.color = Color.red; Gizmos.DrawWireCube(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z)); } private void AllyGizmo() { Gizmos.color = Color.blue; Gizmos.DrawWireCube(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * BoundaryRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z)); } private void Attack() { if (TroopHealth != null) { TroopHealth.TakeDamage(Damage); } } }
问题分析与修复方案
核心问题
- 玩家脚本额外锁定了移动速度:玩家近战脚本中,检测到敌人时会执行
Move.MovementSpeed = 0,但后续即使Move.enabled重新开启,MovementSpeed并未恢复初始值,导致部队无法移动。敌方脚本无此操作,仅通过Move.enabled控制移动状态。 - Gizmo显示错误:玩家脚本的
AllyGizmo方法中,绘制立方体的X轴尺寸错误使用了ViewRange,而非对应的BoundaryRange,导致友军检测范围的可视化显示不准确,干扰问题排查。
修改后的玩家近战逻辑脚本
public class MeleeTroopLogic : MonoBehaviour { [SerializeField] private float AttackSpeed; [SerializeField] public float Damage; [SerializeField] private float ViewRange; [SerializeField] private float BoundaryRange; [SerializeField] private LayerMask EnemyLayer; [SerializeField] private LayerMask FriendlyLayer; [SerializeField] private float ColliderDistance; [SerializeField] private float FriendlyColliderDistance; [SerializeField] private BoxCollider2D AttackRange; [SerializeField] private BoxCollider2D SpaceDistance; private float AttackCooldown = Mathf.Infinity; Health TroopHealth; PlayerTroopsMovement Move; private Animator anim; private void Awake() { Move = GetComponentInParent<PlayerTroopsMovement>(); } void Update() { AttackCooldown += Time.deltaTime; if(Enemydetected()) { // 移除MovementSpeed = 0的设置,统一用Move.enabled控制移动 if(AttackCooldown >= AttackSpeed) { AttackCooldown = 0; Attack(); } } if(Move != null) { Move.enabled = !(Enemydetected() || AllyDetected()); } } private bool Enemydetected() { RaycastHit2D hit = Physics2D.BoxCast(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z),0,Vector2.right, 0, EnemyLayer); if(hit.collider != null) { TroopHealth = hit.transform.GetComponentInChildren<Health>(); } return hit.collider != null; } private bool AllyDetected() { RaycastHit2D hit = Physics2D.BoxCast(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * BoundaryRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z), 0, Vector2.right, 0, FriendlyLayer); return hit.collider != null; } private void OnDrawGizmos() { EnemyGizmo(); AllyGizmo(); } private void EnemyGizmo() { Gizmos.color = Color.red; Gizmos.DrawWireCube(AttackRange.bounds.center + transform.right * ViewRange * ColliderDistance, new Vector3(AttackRange.bounds.size.x * ViewRange, AttackRange.bounds.size.y, AttackRange.bounds.size.z)); } private void AllyGizmo() { Gizmos.color = Color.blue; // 修复尺寸参数,用BoundaryRange替代ViewRange Gizmos.DrawWireCube(SpaceDistance.bounds.center + transform.right * BoundaryRange * FriendlyColliderDistance, new Vector3(SpaceDistance.bounds.size.x * BoundaryRange, SpaceDistance.bounds.size.y, SpaceDistance.bounds.size.z)); } private void Attack() { if(TroopHealth != null) { TroopHealth.TakeDamage(Damage); } } }
额外建议
在PlayerTroopsMovement脚本的OnEnable方法中添加初始速度重置逻辑,确保组件重新启用时移动速度恢复正常:
private void OnEnable() { MovementSpeed = initialMovementSpeed; // 假设initialMovementSpeed是你定义的初始速度变量 }
内容的提问来源于stack exchange,提问作者RGVC
相关产品推荐
相关产品推荐

