Unity 2D:如何让追踪目标的敌人通过射线检测避开障碍物
敌人绕开障碍物的实现方案
针对你遇到的敌人被方形障碍物卡住的问题,这里提供几种基于现有射线检测的实现思路:
方法一:偏移目标方向(简单快速)
当射线检测到障碍物时,利用障碍物表面的法向量调整目标方向,让敌人向远离障碍物的偏移方向移动:
// 假设已通过射线得到hit对象(RaycastHit2D hit) if (hit.collider != null) { // 获取障碍物表面的法向量(垂直于障碍物的方向) Vector2 obstacleNormal = hit.normal; // 计算偏移量,系数可根据障碍物大小调整 Vector2 avoidOffset = obstacleNormal * 1.5f; // 调整目标方向向量,加入偏移量后归一化 toVec = (targetPos - rb.position + avoidOffset).normalized; } // 应用最终移动速度 rb.velocity = toVec * moveSpeed;
核心逻辑:通过法向量让敌人避开障碍物表面,避免直接碰撞,适配大多数简单场景。
方法二:添加侧向躲避力(物理驱动更自然)
不直接修改目标方向,而是给敌人施加侧向力,让它在保持追踪趋势的同时绕开障碍物:
if (hit.collider != null) { // 计算敌人指向障碍物的向量 Vector2 toObstacle = hit.point - rb.position; // 生成两个垂直于障碍物的候选躲避方向 Vector2 avoidDirLeft = new Vector2(-toObstacle.y, toObstacle.x).normalized; Vector2 avoidDirRight = new Vector2(toObstacle.y, -toObstacle.x).normalized; // 选择更靠近原目标方向的躲避方向 Vector2 finalAvoidDir = Vector2.Dot(avoidDirLeft, toVec) > Vector2.Dot(avoidDirRight, toVec) ? avoidDirLeft : avoidDirRight; // 添加躲避力并归一化速度,保证总移动速度不变 rb.velocity += finalAvoidDir * moveSpeed * 0.5f; rb.velocity = rb.velocity.normalized * moveSpeed; } else { // 无障碍物时正常追踪目标 rb.velocity = toVec.normalized * moveSpeed; }
核心逻辑:利用物理力实现自然躲避,敌人会根据目标位置自动选择更优的绕路方向。
方法三:临时目标点绕路(适配固定方形障碍物)
针对固定的方形障碍物,预先计算其四个角落坐标,选择最优角落作为临时目标,绕过后再恢复追踪:
// 假设障碍物的Transform为obstacleTransform,获取四个角落的世界坐标 Vector2[] obstacleCorners = new Vector2[4]; obstacleCorners[0] = obstacleTransform.TransformPoint(new Vector2(-0.5f, -0.5f)); // 左下 obstacleCorners[1] = obstacleTransform.TransformPoint(new Vector2(0.5f, -0.5f)); // 右下 obstacleCorners[2] = obstacleTransform.TransformPoint(new Vector2(0.5f, 0.5f)); // 右上 obstacleCorners[3] = obstacleTransform.TransformPoint(new Vector2(-0.5f, 0.5f)); // 左上 // 筛选出"敌人到角落+角落到目标"总距离最短的角落 Vector2 bestCorner = obstacleCorners[0]; float minTotalDist = float.MaxValue; foreach (var corner in obstacleCorners) { float totalDist = Vector2.Distance(rb.position, corner) + Vector2.Distance(corner, targetPos); if (totalDist < minTotalDist) { minTotalDist = totalDist; bestCorner = corner; } } // 先向临时角落移动 toVec = (bestCorner - rb.position).normalized; // 到达角落附近后,恢复追踪原目标 if (Vector2.Distance(rb.position, bestCorner) < 0.3f) { toVec = (targetPos - rb.position).normalized; } // 应用移动速度 rb.velocity = toVec * moveSpeed;
核心逻辑:通过固定绕路点实现精准绕开,适合场景中位置固定的障碍物。
内容的提问来源于stack exchange,提问作者pizzarob
相关产品推荐
相关产品推荐

