Unity 2D敌人AI无法跳上上方平台追击玩家问题求助
Unity 2D敌人AI追击问题:无法跳上玩家所在的前方上方平台
项目设置细节
场景
- 使用Tilemap
- 挂载Tilemap Collider 2D
- 挂载Static Rigidbody 2D
- 挂载Composite Collider 2D
- 挂载Platform Effector 2D
- LayerMask设置为
Ground
敌人
- 标签为
Trap - 挂载Box Collider 2D
- 挂载冻结Z轴旋转的Rigidbody 2D
敌人控制脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyController : MonoBehaviour { public float walkSpeed = 4f; public float chaseSpeed = 6f; public float detectionDistance = 10f; public float maxWalkDistance = 10f; public float jumpForce = 10f; public LayerMask groundLayer; private Rigidbody2D rb; private SpriteRenderer spriteRenderer; [SerializeField] private Transform player; private bool isFacingRight = true; private Vector2 initialPosition; private bool shouldFlip = false; private void Start() { rb = GetComponent<Rigidbody2D>(); spriteRenderer = GetComponent<SpriteRenderer>(); initialPosition = transform.position; } private void Update() { float distanceToPlayer = Vector2.Distance(transform.position, player.position); if (distanceToPlayer <= detectionDistance) { // Chase the player ChasePlayer(); } else { // Walk left and right within a set distance WalkLeftAndRight(); } } private void WalkLeftAndRight() { // Calculate the movement direction Vector2 movement = isFacingRight ? Vector2.right : Vector2.left; // Check if the enemy has reached the maximum walking distance float currentDistance = Mathf.Abs(transform.position.x - initialPosition.x); if (currentDistance >= maxWalkDistance) { shouldFlip = !shouldFlip; // Toggle the flip flag initialPosition = transform.position; // Reset initial position } // Check for ground detection in front of the enemy Vector2 groundCheckPosition = transform.position + (isFacingRight ? Vector3.right : Vector3.left) * 0.2f; bool isGroundAhead = Physics2D.Raycast(groundCheckPosition, Vector2.down, 0.2f, groundLayer); // Move the enemy if (isGroundAhead) { rb.velocity = new Vector2(movement.x * walkSpeed, rb.velocity.y); } else { shouldFlip = !shouldFlip; // Reverse direction if no ground ahead } // Flip the sprite if needed if (shouldFlip) { FlipSprite(); } // Check for obstacles above the enemy Vector2 obstacleCheckPosition = transform.position + Vector3.up * 0.5f; // Adjust the height as needed bool hasObstacleAbove = Physics2D.Raycast(obstacleCheckPosition, Vector2.up, 1f, groundLayer); // Check for obstacles and jump if necessary Vector2 obstacleAheadCheckPosition = transform.position + (isFacingRight ? Vector3.right : Vector3.left) * 0.2f; bool hasObstacle = Physics2D.Raycast(obstacleAheadCheckPosition, movement, 0.2f, groundLayer); if (hasObstacle && IsGrounded() && !hasObstacleAbove) { // Jump to overcome the obstacle rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); } } private void ChasePlayer() { // Calculate the direction to the player Vector2 directionToPlayer = (player.position - transform.position).normalized; // Move the enemy towards the player rb.velocity = new Vector2(directionToPlayer.x * chaseSpeed, rb.velocity.y); // Flip the sprite if needed if ((directionToPlayer.x > 0 && !isFacingRight) || (directionToPlayer.x < 0 && isFacingRight)) { FlipSprite(); } // Jump if the player is on a higher platform if (IsPlayerAbove() && IsGrounded()) { rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); } } private void FlipSprite() { isFacingRight = !isFacingRight; spriteRenderer.flipX = !isFacingRight; } private bool IsPlayerAbove() { // Check if the player is directly above the enemy float xOffset = 0.2f; RaycastHit2D hit = Physics2D.Raycast(transform.position + Vector3.up * xOffset, Vector2.up, 1f, groundLayer); return hit.collider != null; } private bool IsGrounded() { // Check if the enemy is grounded float yOffset = 0.1f; RaycastHit2D hit = Physics2D.Raycast(transform.position - Vector3.up * yOffset, Vector2.down, 1f, groundLayer); return hit.collider != null; } }
当前问题
当玩家跳至敌人前方的上方平台时,敌人无法跳跃上去追击玩家。
问题分析与解决方案
核心问题
IsPlayerAbove()逻辑偏差:当前方法仅检测敌人正上方的地面,无法识别玩家在前方平台的情况。- 追击阶段缺少针对性检测:ChasePlayer方法未判断前方是否存在可跳跃的平台,仅依赖错误的触发条件。
修改方案
1. 新增前方平台检测方法
替换原IsPlayerAbove(),改为检测玩家是否在敌人前方的上方区域:
private bool IsPlayerOnFrontPlatform() { // 判断玩家是否在敌人朝向的前方 bool playerIsInFront = (player.position.x > transform.position.x && isFacingRight) || (player.position.x < transform.position.x && !isFacingRight); if (!playerIsInFront) return false; // 检测前方是否有向上的平台,覆盖玩家所在高度范围 float horizontalOffset = 0.5f; float verticalRange = 2f; Vector2 checkStart = transform.position + (isFacingRight ? Vector3.right : Vector3.left) * horizontalOffset; RaycastHit2D hit = Physics2D.Raycast(checkStart, Vector2.up, verticalRange, groundLayer); // 确认玩家处于该平台的高度区间内 bool playerInVerticalRange = player.position.y > transform.position.y && player.position.y <= transform.position.y + verticalRange; return hit.collider != null && playerInVerticalRange; }
2. 更新追击阶段的跳跃逻辑
修改ChasePlayer方法,添加两种触发跳跃的场景:
private void ChasePlayer() { Vector2 directionToPlayer = (player.position - transform.position).normalized; // 保留原有移动逻辑 rb.velocity = new Vector2(directionToPlayer.x * chaseSpeed, rb.velocity.y); if ((directionToPlayer.x > 0 && !isFacingRight) || (directionToPlayer.x < 0 && isFacingRight)) { FlipSprite(); } bool shouldJump = false; // 场景1:玩家在前方的平台上 if (IsPlayerOnFrontPlatform() && IsGrounded()) { shouldJump = true; } // 场景2:前方无地面,但玩家在更高处,需要跳跃到平台 Vector2 frontGroundCheck = transform.position + (isFacingRight ? Vector3.right : Vector3.left) * 0.3f; bool hasGroundInFront = Physics2D.Raycast(frontGroundCheck, Vector2.down, 0.3f, groundLayer); if (!hasGroundInFront && player.position.y > transform.position.y && IsGrounded()) { shouldJump = true; } if (shouldJump) { rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); } }
3. 优化地面检测(可选)
使用多点检测提升地面判断的可靠性:
private bool IsGrounded() { float checkRadius = 0.1f; // 敌人底部左右两个检测点 Vector2 leftCheck = new Vector2(transform.position.x - 0.2f, transform.position.y - 0.3f); Vector2 rightCheck = new Vector2(transform.position.x + 0.2f, transform.position.y - 0.3f); return Physics2D.OverlapCircle(leftCheck, checkRadius, groundLayer) != null || Physics2D.OverlapCircle(rightCheck, checkRadius, groundLayer) != null; }
额外注意事项
- 调整
jumpForce数值:若跳跃高度不足,可适当增大至12f左右。 - 验证LayerMask:确保
groundLayer包含所有平台图层,无遗漏。 - 检查Platform Effector 2D:确认平台的单向通行属性正确,允许敌人从下方跳跃通过。
内容的提问来源于stack exchange,提问作者Symbiote Scorns
相关产品推荐
相关产品推荐

