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

玩家近战部队脚本失效求助:逻辑与敌方一致却无法移动

问题

开发策略防御游戏时,玩家近战部队在前方友军被摧毁后仍无法移动,但敌方近战部队逻辑正常。两款脚本框架一致,以下是脚本代码:

玩家近战逻辑脚本

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);
        }
    }
}
问题分析与修复方案

核心问题

  1. 玩家脚本额外锁定了移动速度:玩家近战脚本中,检测到敌人时会执行Move.MovementSpeed = 0,但后续即使Move.enabled重新开启,MovementSpeed并未恢复初始值,导致部队无法移动。敌方脚本无此操作,仅通过Move.enabled控制移动状态。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:37:03