栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 游戏开发 > 其他

Unity3D物体自动躲避障碍物

其他 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Unity3D物体自动躲避障碍物

 Unity版本

        2017.4.4f1

基本思路

        物体向前发射一个射线,检测到碰撞后,根据碰撞信息选择新的方向。最终结果如下。

 具体实现步骤代码 1.物体添加胶囊体碰撞组件CapsuleCollider

通过发射虚拟胶囊体来检测碰撞api

bool Physics.CapsuleCast (Vector3 point1, Vector3 point2, float radius, Vector3 direction, out RaycastHit hit, float maxDistance)

 points参数如图所示,radius是Capsule的radius,direction为当前面向,hit为碰撞信息,maxDistance为检测距离:

根据参数申请一下变量并初始化:

    //检测距离
    float distance = 1;
    //物体速度
    public float speed = 1;
    //物体下一帧面向
    Vector3 nexForward;
    //capsule端点
    Vector3 point1, point2;
    //capsule组件
    public CapsuleCollider capsule;

    // Use this for initialization
    void Start()
    {
        capsule = GetComponent();
        nexForward = transform.forward;
        point1 = capsule.center - new Vector3(0, 0.5f * capsule.height, 0);
        point2 = capsule.center + new Vector3(0, 0.5f * capsule.height, 0);
    }
2.申请CheckCollision函数来检测碰撞并计算下一帧的面向。

检测到碰撞点后,由碰撞点的Normal方向和物体当前面向来计算新面向。主要方法为

nexForward = Vector3.Cross(hit.normal, Vector3.Cross(transform.forward, hit.normal));

这个公式的大概意思为,计算出当前面向向量transform.forward在碰撞面上的投影向量。可以理解为:hit.normal是阳光方向,transform.forward是一个带方向的射线,得到的是射线在面上的投影射线。投影向量作为碰撞后的新方向。

(1)需要排除掉transform.forward//hit.normal的特殊情况;

(2)检测到碰撞点后,需要从碰撞点出发,用新的面向进行二次检测,防止物体卡入角落。

具体代码如下

void CheckCollision()
    {
        //动态检测距离,速度越大越需要提前检测
        distance = speed * Time.deltaTime;
        RaycastHit hit;
        //用于二次检测
        Vector3 hitPoint;
        //capsulecast
        if (Physics.CapsuleCast(transform.position + point1, transform.position + point2, capsule.radius, transform.forward, out hit, distance))
        {
            hitPoint = hit.point + capsule.radius * hit.normal;
            //如果朝向垂直于碰撞平面
            if (Vector3.Cross(transform.forward, hit.normal) == Vector3.zero)
            {
                nexForward = Vector3.Cross(hit.normal, Vector3.up);
            }
            else
            {
                nexForward = Vector3.Cross(hit.normal, Vector3.Cross(transform.forward, hit.normal));
            }
            bool left = false;
            bool right = false;
            //从碰撞点起,向两边检测两边碰撞
            if (Physics.CapsuleCast(hitPoint + capsule.center - new Vector3(0, 0.5f * capsule.height, 0), hitPoint + capsule.center + new Vector3(0, 0.5f * capsule.height, 0), capsule.radius, nexForward, out hit, distance))
            {
                left = true;
            }
            if (Physics.CapsuleCast(hitPoint + capsule.center - new Vector3(0, 0.5f * capsule.height, 0), hitPoint + capsule.center + new Vector3(0, 0.5f * capsule.height, 0), capsule.radius, -nexForward, out hit, distance))
            {
                right = true;
            }
            if (left)
            {
                if (!right)
                {
                    nexForward = -nexForward;
                }
            }
            //归一化
            nexForward.Normalize();
        }
    }
3.在update函数中更新物体面向,并向前移动
     // Update is called once per frame
    void Update()
    {
        CheckCollision();
        if (nexForward != Vector3.zero)
            transform.forward = nexForward;
        transform.Translate(new Vector3(0, 0, speed * Time.deltaTime));
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/901356.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号