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
相关产品推荐
相关产品推荐

