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

Unity C#:为敌人添加位置移动功能的技术求助

敌人移动功能实现方案

下面提供两种常见的敌人移动实现方式,你可以根据需求选择或结合使用:

一、固定路径巡逻移动(左右/上下来回)

适合不需要追踪玩家的静态敌人,比如在平台间来回巡逻、上下浮动的敌人。

修改后的脚本(添加巡逻逻辑)

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

public class Enemy : MonoBehaviour
{
    public float damageRadius = 0.5f;
    public int meleeDamage = 200;
    // 巡逻移动参数
    public float moveSpeed = 2f;
    public float moveRange = 3f; // 相对于初始位置的移动距离
    public bool moveHorizontal = true; // true=左右移动,false=上下移动

    [HideInInspector]
    Entity entityScript;
    private Vector3 startPosition;
    private int moveDirection = 1; // 1=正方向,-1=反方向

    void Start()
    {
        entityScript = GetComponent<Entity>();
        startPosition = transform.position; // 记录初始位置作为巡逻起点
    }

    void Update()
    {
        PatrolMove();
        CheckForPlayerAndDamage();
        CheckForHealthAndDie();
    }

    // 巡逻移动逻辑
    void PatrolMove()
    {
        if (entityScript.isDead) return; // 死亡后停止移动

        if (moveHorizontal)
        {
            // 左右移动:按方向平移
            transform.Translate(Vector2.right * moveSpeed * moveDirection * Time.deltaTime);
            
            // 到达边界后反转方向
            if (Mathf.Abs(transform.position.x - startPosition.x) >= moveRange)
            {
                moveDirection *= -1;
                // 可选:翻转敌人Sprite朝向
                transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
            }
        }
        else
        {
            // 上下移动:按方向平移
            transform.Translate(Vector2.up * moveSpeed * moveDirection * Time.deltaTime);
            
            // 到达边界后反转方向
            if (Mathf.Abs(transform.position.y - startPosition.y) >= moveRange)
            {
                moveDirection *= -1;
            }
        }
    }

    void CheckForPlayerAndDamage()
    {
        var colliders = Physics2D.OverlapCircleAll(transform.position, damageRadius);
        foreach (var collider in colliders)
        {
            if (collider.gameObject.tag == "Player")
            {
                collider.gameObject.GetComponent<Entity>().ApplyDamage(meleeDamage);
            }
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, damageRadius);
        
        // 绘制巡逻范围Gizmo,方便调试
        if (moveHorizontal)
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawLine(new Vector3(startPosition.x - moveRange, startPosition.y), 
                           new Vector3(startPosition.x + moveRange, startPosition.y));
        }
        else
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawLine(new Vector3(startPosition.x, startPosition.y - moveRange), 
                           new Vector3(startPosition.x, startPosition.y + moveRange));
        }
    }

    public void CheckForHealthAndDie()
    {
        if(entityScript.isDead)
        {
            Destroy(gameObject);
        }
    }
}

关键注意点

  • 确保敌人对象带有Rigidbody2D组件,建议将Body Type设置为Dynamic,不需要物理碰撞也可以用Kinematic
  • 在Inspector面板中可调整moveSpeed(移动速度)、moveRange(巡逻范围),通过moveHorizontal切换左右/上下移动
  • 代码加入死亡判断,敌人死亡后自动停止移动

二、追踪玩家的移动

适合需要主动追击玩家的敌人,会朝着玩家位置移动。

修改后的脚本(添加追踪逻辑)

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

public class Enemy : MonoBehaviour
{
    public float damageRadius = 0.5f;
    public int meleeDamage = 200;
    // 追踪移动参数
    public float chaseSpeed = 3f;
    public float chaseRange = 8f; // 敌人开始追踪的触发范围

    [HideInInspector]
    Entity entityScript;
    private Transform playerTransform;

    void Start()
    {
        entityScript = GetComponent<Entity>();
        // 通过标签找到玩家对象
        playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform;
    }

    void Update()
    {
        if (playerTransform != null)
        {
            ChasePlayer();
        }
        CheckForPlayerAndDamage();
        CheckForHealthAndDie();
    }

    // 追踪玩家逻辑
    void ChasePlayer()
    {
        if (entityScript.isDead) return;

        // 计算敌人与玩家的距离
        float distanceToPlayer = Vector2.Distance(transform.position, playerTransform.position);
        
        // 玩家在追踪范围内时,开始移动
        if (distanceToPlayer <= chaseRange)
        {
            // 计算朝向玩家的单位方向向量
            Vector2 moveDirection = (playerTransform.position - transform.position).normalized;
            
            // 移动敌人
            transform.Translate(moveDirection * chaseSpeed * Time.deltaTime);
            
            // 翻转Sprite朝向玩家
            if (moveDirection.x > 0 && transform.localScale.x < 0)
            {
                transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
            }
            else if (moveDirection.x < 0 && transform.localScale.x > 0)
            {
                transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
            }
        }
    }

    void CheckForPlayerAndDamage()
    {
        var colliders = Physics2D.OverlapCircleAll(transform.position, damageRadius);
        foreach (var collider in colliders)
        {
            if (collider.gameObject.tag == "Player")
            {
                collider.gameObject.GetComponent<Entity>().ApplyDamage(meleeDamage);
            }
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, damageRadius);
        
        // 绘制追踪范围Gizmo
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, chaseRange);
    }

    public void CheckForHealthAndDie()
    {
        if(entityScript.isDead)
        {
            Destroy(gameObject);
        }
    }
}

关键注意点

  • 确保玩家对象的标签设置为Player,否则无法找到玩家目标
  • chaseRange控制敌人开始追踪的触发距离,超出范围时敌人会停止移动
  • 用normalized处理方向向量,避免敌人与玩家的距离影响移动速度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:28:10