ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Unity 使用物理射线(Physics.Raycast),实现扇形区域碰撞检测三种方法(借鉴大神,仅作为笔记用)

2019-11-01 19:50:33  阅读:453  来源: 互联网

标签:return 射线 检测 controller Raycast 碰撞检测 Unity 角度 精度


Unity 使用物理射线(Physics.Raycast),实现扇形(Fan-Shaped)区域碰撞检测。
参考之前的制作简单AI: Unity 有限状态机(Finite State Machine)的理解 与 实现简单的可插拔(Pluggable)AI脚本对象。
源码:GentleTank/PluggableAI/Scripts/Decision/LookDecision.cs

方法一:

实现原理:(lookAngle / 2) / lookAccurte

  很简单,就是射多几条角度平均的射线。可以设置角度,精度(射线数量),来调节扇形区域的检测。每条射线夹角是总夹角处于2,再除于精度。
  

1. 默认是射出一条向前的射线,精度为0。

 

 

2. 设置角度为90,精度为1,就会多出两条相对正前方45度的射线。

 

 

3.设置精度为2。

 

 

实现代码

//
// LookDecision
//


//放射线检测
private bool Look(StateController controller)
{
var defaultStats = controller.defaultStats;

//一条向前的射线
if (LookAround(controller, Quaternion.identity, Color.green))
return true;

//多一个精确度就多两条对称的射线,每条射线夹角是总角度除与精度
float subAngle = (defaultStats.lookAngle / 2) / defaultStats.lookAccurate;
for (int i = 0; i < defaultStats.lookAccurate; i++)
{
if (LookAround(controller, Quaternion.Euler(0, -1 * subAngle * (i + 1), 0), Color.green)
|| LookAround(controller, Quaternion.Euler(0, subAngle * (i + 1), 0), Color.green))
return true;
}

return false;
}

//射出射线检测是否有Player
static public bool LookAround(StateController controller, Quaternion eulerAnger,Color DebugColor)
{
Debug.DrawRay(controller.eyes.position, eulerAnger * controller.eyes.forward.normalized * controller.defaultStats.lookRange, DebugColor);

RaycastHit hit;
if (Physics.Raycast(controller.eyes.position, eulerAnger * controller.eyes.forward, out hit, controller.defaultStats.lookRange) && hit.collider.CompareTag("Player"))
{
controller.chaseTarget = hit.transform;
return true;
}
return false;
}

最终效果

查找角度:90、精度:6,追杀角度15、精度2。

 

 

  • 红坦克是查找时敌人发出的绿色射线;
  • 绿坦克是追杀时发出红色射线;
  • 蓝坦克在第一条默认射线就检测到敌人,所以就不需要在添加额外角度射线。

     

     

    查找精度:50、追杀精度:10。

  •  

     基本像个扇形了,而且性能没有太大变化。

  • 方法2:
      相对方法一,可以说又省代码,又省内存。缺点就是检测扇形区域每一帧只有一个方向。
      原理:只用一条射线,每次调用的时候旋转一定角度。如果一秒走30帧,那就是一秒可以变化30次角度。一般来说也够了。实现起来就相当简单了。使用Mathf.Repeat来获取角度就好了。

    //
    // LookDecision
    //

    [Range(0, 360)]
    public float angle = 90f; //检测前方角度范围
    [Range(0, 100)]
    public float distance = 25f; //检测距离
    public float rotatePerSecond = 90f; //每秒旋转角度

    //放射线检测
    private bool Look(StateController controller)
    {
    if (LookAround(controller, Quaternion.Euler(0, -angle / 2 + Mathf.Repeat(rotatePerSecond * Time.time, angle), 0), distance, debugColor))
    return true;
    return false;
    }

  •  

     上图中射线其实是一直在摆动的。

  • 方法3:

      就是结合方法1和方法2了,多条线同时旋转检测,算是结合前两者的优点了。

      原理就是在方法2基础上,多加一层循环,即同一帧有多条线检测,如下修改代码。

  • [Range(1, 50)]
    public float accuracy = 1f; //检测精度

    private bool Look(StateController controller)
    {
    float subAngle = angle / accuracy; //每条射线需要检测的角度范围
    for (int i = 0; i < accuracy; i++)
    if (LookAround(controller, Quaternion.Euler(0, -angle / 2 + i * subAngle + Mathf.Repeat(rotatePerSecond * Time.time, subAngle), 0), distance, debugColor))
    return true;
    return false;
    }

  •  

     

    说明:
    蓝色坦克:攻击了红坦克。红坦克就同时放出
    红色坦克:巡逻时不知道被谁打了,同时放出四条黄色射线旋转检测,每条射线只要旋转90°就可以检测完周围360°。
    绿色坦克:发现了敌人,每次先直接射出一条正前方的红线(因为攻击时经常只需要这一条第一帧就抓到敌人),另外一条就是旋转的检测射线。
    黄色坦克:正在巡逻。三条绿色同时旋转,检测角度为90°,所以每条射线只要旋转30°。

标签:return,射线,检测,controller,Raycast,碰撞检测,Unity,角度,精度
来源: https://www.cnblogs.com/Damon-3707/p/11779192.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有