Unity敌人受玩家撞击滑动过远,寻求调整解决方案
解决敌人被击中后滑动过度的问题
你遇到的敌人被击中后持续滑动至地图边缘的问题,核心原因是物理系统的阻力/摩擦力不足,或是NavMeshAgent与物理运动的冲突,不需要调整LayerMask(除非碰撞检测层设置错误),主要通过以下方式解决:
1. 调整刚体与物理材质参数
- Rigidbody设置:确保敌人挂载
Rigidbody组件,勾选Use Gravity,提高Drag(空气阻力,建议0.5-2)和Angular Drag(旋转阻力,建议1-3),让滑动时的速度快速衰减。 - 物理材质优化:给Terrain和敌人的Collider添加物理材质,提升
Dynamic Friction(动态摩擦力,建议0.6-0.8)和Static Friction(静摩擦力),增加地面对敌人的阻力,缩短滑动距离。
2. 协调NavMeshAgent与物理运动
当前代码未处理受击逻辑,敌人被击中时NavMeshAgent仍在尝试导航,会和物理力冲突导致滑动不止,需添加受击时的Agent暂停逻辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class EnemyController : MonoBehaviour { public float lookRadius = 10f; public float maxSlideDistance = 5f; // 最大滑动距离 Transform target; NavMeshAgent agent; CharacterCombat combat; Rigidbody rb; void Start() { target = PlayerManager.instance.player.transform; agent = GetComponent<NavMeshAgent>(); combat = GetComponent<CharacterCombat>(); rb = GetComponent<Rigidbody>(); } void Update() { // 仅在Agent启用时执行导航逻辑 if (!agent.enabled) return; float distance = Vector3.Distance(target.position, transform.position); if (distance <= lookRadius) { agent.SetDestination(target.position); if (distance <= agent.stoppingDistance) { CharacterStats targetStats = target.GetComponent<CharacterStats>(); if (targetStats != null) { combat.Attack(targetStats); } FaceTarget(); } } } void FaceTarget () { Vector3 direction = (target.position - transform.position).normalized; Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z)); transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f); } // 受击时调用此方法(需在玩家攻击逻辑中触发) public void TakeHit(Vector3 hitDirection, float hitForce) { agent.enabled = false; // 施加受击力 rb.AddForce(hitDirection.normalized * hitForce, ForceMode.Impulse); StartCoroutine(ControlSlide()); } IEnumerator ControlSlide() { Vector3 startPos = transform.position; // 等待滑动停止或达到最大距离 while (Vector3.Distance(transform.position, startPos) < maxSlideDistance && rb.velocity.magnitude > 0.1f) { yield return null; } // 停止滑动 rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; // 恢复AI导航 agent.enabled = true; agent.SetDestination(target.position); } void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawSphere(transform.position, lookRadius); } }
3. 额外验证点
- 确保Terrain的Layer设置为
Ground,敌人的Collider与Terrain的Layer能正常触发物理碰撞(在Physics Settings中检查碰撞矩阵)。 - 若使用NavMesh,确认Terrain已被烘焙进NavMesh,避免敌人滑动后无法重新导航。
状态示意图



内容的提问来源于stack exchange,提问作者Muhammad Fattan
相关产品推荐
相关产品推荐

