zoukankan      html  css  js  c++  java
  • 碰撞检测问题及解决

    在Unity3D中,碰撞可以形象理解为现实世界中的碰撞,并且由于物理引擎的模拟,使碰撞物体也会如现实世界一样产生相同的碰撞结果,如运动轨迹的改变、反弹等,总之碰撞的结果为产生我们不期望的物体运动行为。为了避免产生这种碰撞,就需要进行碰撞检测。

    碰撞检测实现一

    碰撞检测的原理是在物体移动的前方放置一个虚拟物体,它与物体进行同步运动。如果有障碍,则要先与虚拟物体碰撞。一旦检测到虚拟物体的碰撞,则运动物体停止移动。

    • 实现时则是使用虚拟射线来进行检测,检测时使用到的api分别如下截图:

    clip_image002

    图 - 1 Physic.Raycast射线扫描API

    • 碰撞检测的具体实现如下截图:

    clip_image004

    图 - 2 碰撞检测

    • 碰撞检测的调用实现如下截图:

    clip_image005

    图 - 3 调用碰撞的实现

    实现一的问题及分析

    以上实现经过分析,原理想法上没问题,就是每隔一个固定频率后进行射线碰撞检测。但是效果上却总是会在一些偶然的情况下发生碰撞,具体情形如下截图:

    clip_image006

    图 - 4 碰撞导致不期望的运动

    •  Update受制于FPS问题

    经过分析,发现update虽然是每帧执行的,但是Unity3D的FPS——每秒的帧数,是变化的,它的值取决于渲染场景的面数;渲染速度又受机器的性能特别是CPU、内存、显卡不同而表现很大的差异。如果场景中渲染的面数太多,并且机器配置不够好,可能导致FPS很低,从而使渲染的两帧之间时间间隔很大,而在这个间隔内,碰撞已经发生,从而出现了上面的碰撞现象。

    对于物理运动中需要进行固定频率的动作,Unity3D提供了FixedUpdate方法,这个频率是系统参数,可以更改。因此,我们使用FixedUpdate来替换Update可解决此问题。

    •  射线检测问题

    如图 - 2 碰撞检测实现中,虽然多加了几条射线,但毕竟只是物体中的个别点。在我们的场景中,物体都是规则的且正常运动规律显著,所以只需要把几个特征点找到然后分别进行射线检测即可。但是这个毕竟是存在缺陷的,如果能够对物体整个面进行检测,那就完美了。

    幸运的是,自Unity3D 版本3以来,针对刚体的碰撞检测问题,专门提供了Rigidbody.SweepTest方法。需要注意的是Physics.Raycast里面有一个层的概念,而且不是必须刚体才会被检测到;而Rigidbody.SweepTest则只检测刚体碰撞,与层无关。

    碰撞检测的改善性实现

    经过以上分析,可以知道碰撞检测会用到关键性方法Rigidbody.SweepTest,它的API如下截图:

    clip_image008

    图 - 5 刚体碰撞检测的API

    改善后的实现如下截图:

    clip_image009

    图 - 6 改善性实现代码

    经过试验,改善后的实现可以很好解决碰撞问题

  • 相关阅读:
    转换方法
    数组去重
    js常见兼容
    封装cookie
    常用函数封装
    手绘 代码
    Python变量和数据类型,类型转换
    语句块的概念及注释符的使用
    ipython和pip,模块安装方法
    第一个python程序
  • 原文地址:https://www.cnblogs.com/huntdream/p/2978111.html
Copyright © 2011-2022 走看看