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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:57:23