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

Unity 2D俯视角敌人追踪玩家并避障脚本问题求助

Unity 2D俯视角敌人追踪玩家并避障脚本问题求助

嘿,别慌!新手刚接触Unity脚本遇到问题太正常啦,我来帮你把这个脚本补全优化,让敌人既能稳稳追踪玩家,又能聪明躲开障碍物。

先看看你的需求和未完成的代码:

I'm having a problem using this script. Could you help a newbie?
I need the enemy to chase the player and avoid obstacles. Game from above

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

public class enemy : MonoBehaviour
{
    public float speed = 5f; 
    public float maxSpeed = 10f; 
    public float avoidanceForceMultiplier = 5f; 
    public float raySpacing = 0.5f; 
    public LayerMask obstacleLayerMask;

    private Rigidbody2D rb;
    private Transform Player;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        Player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
    }

    private void Update()
    {
        // Determine direction of movement
        Vector2 playerDirection = (Player.position - transform.position).normalized;

        // Cast rays to detect obstacles
        RaycastHit2D[] hits = new RaycastHit2D[3];
        Vector2 rayStart = transform.position * pla...

你的代码在Update方法里截断了,而且还有几个可以调整的细节,比如物理逻辑的时机、空值判断这些。下面是补全并优化后的完整脚本,我会逐段给你解释:

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

public class Enemy : MonoBehaviour // 类名首字母大写是C#规范,方便后续维护
{
    public float speed = 5f; 
    public float maxSpeed = 10f; 
    public float avoidanceForceMultiplier = 5f; 
    public float raySpacing = 0.5f; 
    public float rayLength = 1.5f; // 新增射线长度,控制障碍物检测的距离
    public LayerMask obstacleLayerMask;

    private Rigidbody2D rb;
    private Transform player; // 变量名首字母小写更符合编码习惯

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // 增加空值判断,避免找不到Player时直接报错崩溃
        GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
        if (playerObj != null)
        {
            player = playerObj.GetComponent<Transform>();
        }
        else
        {
            Debug.LogError("场景里找不到标签为Player的物体哦!");
        }
    }

    // 物理相关逻辑用FixedUpdate更合适,和Unity的物理更新帧同步,移动会更平滑
    private void FixedUpdate()
    {
        if (player == null) return; // 找不到玩家就不执行后续逻辑

        // 1. 计算朝向玩家的基础方向
        Vector2 playerDirection = (player.position - transform.position).normalized;

        // 2. 计算避障需要修正的方向
        Vector2 avoidanceDirection = CalculateAvoidanceDirection();

        // 3. 合并追踪方向和避障方向,得到最终移动方向
        Vector2 finalDirection = (playerDirection + avoidanceDirection).normalized;

        // 4. 给刚体施加力控制移动,同时限制最大速度
        rb.AddForce(finalDirection * speed);
        rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
    }

    private Vector2 CalculateAvoidanceDirection()
    {
        Vector2 avoidanceDir = Vector2.zero;
        int hitObstacleCount = 0;

        // 发射三条射线:正前方、左前方、右前方(适配俯视角的检测范围)
        Vector2[] rayDirections = new Vector2[]
        {
            transform.right, // 敌人自身正前方(如果你的游戏用Y轴当前方,改成transform.up即可)
            transform.right + transform.up * raySpacing, // 右前方偏移
            transform.right - transform.up * raySpacing  // 左前方偏移
        };

        foreach (Vector2 dir in rayDirections)
        {
            RaycastHit2D hit = Physics2D.Raycast(transform.position, dir, rayLength, obstacleLayerMask);
            if (hit)
            {
                // 编辑器里绘制红色射线,方便调试时看到检测到障碍物的区域
                Debug.DrawRay(transform.position, dir * rayLength, Color.red);
                // 计算远离障碍物的方向
                avoidanceDir += (Vector2)transform.position - hit.point;
                hitObstacleCount++;
            }
            else
            {
                // 没检测到障碍物时绘制绿色射线
                Debug.DrawRay(transform.position, dir * rayLength, Color.green);
            }
        }

        if (hitObstacleCount > 0)
        {
            // 归一化方向后乘以力度系数,控制避障的强度
            return avoidanceDir.normalized * avoidanceForceMultiplier;
        }

        return Vector2.zero; // 没有障碍物时返回零向量,不影响追踪
    }
}

最后给你几个使用时的小提醒:

  • 确保你的障碍物所在的图层,和脚本里obstacleLayerMask选择的图层完全一致,不然射线检测不到障碍物。
  • 可以在Unity编辑器里调整rayLength、avoidanceForceMultiplier这些参数,找到最适合你游戏的手感。
  • 如果你的游戏里敌人的前方是transform.up(比如2D游戏常用Y轴朝上),记得把rayDirections里的transform.right改成transform.up。

备注:内容来源于stack exchange,提问作者Kokotrek Youtube

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 12:58:11