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

Unity2D敌人翻转与攻击功能异常问题求助

Unity敌人翻转(Flip)失效问题求助

我在学习Unity敌人制作教程时,发现教程未讲解玩家走到敌人对立面时如何实现敌人flip(翻转)功能。我尝试扩大raycast(射线检测)区域,期望玩家从后方进入检测范围时敌人能自动翻转,但敌人朝左时运行正常,一旦翻转后就完全失效,无法排查出原因,求解决办法。

敌人射线检测示意图

我的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Skeleton : MonoBehaviour
{
    #region Public Variables
    public Transform rayCast;
    public LayerMask raycastMask;
    public GameObject target;
    public float rayCastLength;
    public float attackDistance; //最小攻击距离
    public float moveSpeed;
    public float timer; //攻击冷却时间
    public bool inRange; //检测玩家是否在范围内
    #endregion

    #region Private Variables
    private RaycastHit2D hit;
    private Animator anim;
    private float distance; //敌人与玩家的距离
    public bool attackMode;
    private float intTimer;
    #endregion

    void Awake() {
        intTimer = timer;
        anim = GetComponent<Animator>();
    }
    
    void Update() {
        if (inRange)
        {
            hit = Physics2D.Raycast(rayCast.position, Vector2.left, rayCastLength, raycastMask);
        }

        //检测到玩家时
        if(hit.collider != null)
        {
            EnemyLogic();
        }
        //未检测到玩家时
        else if(hit.collider == null)
        {
            inRange = false;
        }

        //玩家离开范围时
        if (inRange == false)
        {
            anim.SetBool("canWalk", false);
            StopAttack();
            anim.SetInteger("Idle", 0);
        }
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        if(col.gameObject.tag == "Player")
        {
            target = col.gameObject;
            inRange = true;
            Flip();
        }
    }

    void EnemyLogic()
    {
        distance = Vector2.Distance(transform.position, target.transform.position);

        if(distance > attackDistance)
        {
            Move();
            StopAttack();   
        }
        else if(attackDistance >= distance)
        {
            Attack();
        }
    }

    void Move()
    {
        anim.SetInteger("Idle", 1);
        anim.SetBool("canWalk", true);
        if (!anim.GetCurrentAnimatorStateInfo(0).IsName("attack"))
        {
            Vector2 targetPosition = new Vector2(target.transform.position.x, transform.position.y);
            transform.position = Vector2.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
        }
    }

    void Attack()
    {
        timer = intTimer; //重置冷却时间
        attackMode = true;

        anim.SetInteger("Idle", 1);
        anim.SetBool("canWalk", false);
        anim.SetBool("Attack", true);
    }

    void StopAttack()
    {
        attackMode = false;
        anim.SetBool("Attack", false);
    }

    //检测玩家是否在对立面
    void Flip()
    {
        Vector3 rotation = transform.eulerAngles;
        if(target.transform.position.x < transform.position.x)
        {
            rotation.y = 180f;
        }
        else
        {
            rotation.y = 0f;
        }

        transform.eulerAngles = rotation;
    }
}

问题分析

  1. 射线方向固定错误:当前射线始终朝Vector2.left发射,当敌人Y轴旋转180度朝右后,射线方向与敌人朝向相反,导致无法检测到右侧的玩家,这是翻转后失效的核心原因。
  2. 翻转逻辑触发不及时:仅在玩家首次进入Trigger区域时调用Flip(),玩家在范围内移动到敌人另一侧时,不会触发重新翻转。

修复方案

1. 修正射线检测方向

让射线方向跟随敌人当前朝向,使用transform.right获取敌人朝向的向量(Y轴旋转180度后,transform.right会自动变为向左,匹配敌人朝向):

// 替换Update方法中的射线检测代码
if (inRange && target != null)
{
    Vector2 rayDirection = transform.right;
    hit = Physics2D.Raycast(rayCast.position, rayDirection, rayCastLength, raycastMask);
}

2. 增加实时翻转检测

在EnemyLogic()中加入实时翻转判断,确保玩家移动到敌人另一侧时,敌人能及时翻转:

void EnemyLogic()
{
    distance = Vector2.Distance(transform.position, target.transform.position);
    // 实时判断是否需要翻转
    Flip();

    if(distance > attackDistance)
    {
        Move();
        StopAttack();   
    }
    else if(attackDistance >= distance)
    {
        Attack();
    }
}

3. 优化Flip方法(可选)

可以通过修改localScale实现翻转,避免旋转可能带来的组件冲突问题:

void Flip()
{
    if(target == null) return;
    bool isPlayerOnLeft = target.transform.position.x < transform.position.x;
    // 通过缩放X轴实现翻转,1为朝右,-1为朝左
    transform.localScale = new Vector3(isPlayerOnLeft ? -1 : 1, 1, 1);
}

4. 完善空值判断

在Update中增加target为空的判断,避免空引用错误:

void Update() {
    if (inRange && target != null)
    {
        Vector2 rayDirection = transform.right;
        hit = Physics2D.Raycast(rayCast.position, rayDirection, rayCastLength, raycastMask);
    }
    else if(inRange && target == null)
    {
        inRange = false;
    }

    // 后续逻辑保持不变...
}

内容的提问来源于stack exchange,提问作者mumber162

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:15:19