zoukankan      html  css  js  c++  java
  • unity学习(四)——物理系统

    Rigidbody

    Rigidbody 是 GameObject进行物理行为的主要部件。一旦与 Rigidbody关联,物体将会立刻受到重力的影响。如果再添加一个或多个 Collider不见,GameObject会因碰撞而移动。
    因为 Rigidbody组件接管了与它相关联的 GameObject的移动,你就不应该再通过由脚本来改变 Transform属性来移动此物体。因此,你应该用力学来推动 GameObject且让物理引擎来计算结果。(要好好学物理了。。)
    以下还有一些情况你也可能会需要含有 不会被物理引擎控制的 Rigidbody的 GameObject。例如,你可能会需要直接从脚本控制你的角色但仍它仍可以被 triggers(后面会介绍)探测到,这种由脚本产生的非物理移动被称为 kinematic运动。Rigidbody组件有一个 kinematic属性,这个属性把它从物理引擎的控制中移除并通过脚本移动。从脚本改变 Is Kinematic以允许打开/关闭物体的物理是可行的,但是会有一些运行上的开销(尽量少用)。

    睡眠模式

    当 Rigidbody移动的比预定义的最小线/旋转速度慢时,物理引擎会假定它已经停止。这样做后 GameObject将不会再移动了,直到它受到碰撞或力,并进入“睡眠”模式。这种优化意味着 Rigidbody不再占用处理器的时间来更新,直到他再次被“唤醒”(即再次处于运动状态)。
    在大多数情况下,Rigidbody组件进入睡眠或唤醒是很明显地。然而,如果 Static Collider(没有 Rigidbody的 GameObject)通过修改 Transform位置来靠近或原理某个 GameObject,这个GameObject可能唤醒失败。这可能会导致,当地板从它下方移走后, Rigidbody GameObject悬在空中。对于这种情况, GameObject使用 WakeUp函数显式地唤醒 GameObject。

    Colliders

    Collider组件定义了 GameObject的形状,以供物理碰撞用。Collider是不可见的,不需要与 GameObject网格形状相同。在 gameplay中,大概的网格形状就够用了。
    最简单的 colliders是初始 collider种类。在 3D中,这些种类有 Box(盒) Collider,Sphere(球) Collider和 Capsule(胶囊) Collider。在 2D,你可以用 Box Collider 2D和 Circle Collider 2D。

    Compound(复合) Colliders

    复合 colliders估计 GameObject的形状,且只花费少量处理器开销。你也可以为 child GameObjects灵活地添加额外的 colliders。例如,你可以相对于 parent GameObject的坐标轴转动盒子。当你构建了这样的复合 collider,你就应该只使用一个 Rigidbody组件,放置在层级系统中的源 GameObject上。
    初始 colliders在不能用于剪切变换。

    Mesh(网格) Colliders

    对于某些情况,偶数个复合 colliders不够精确。在 3D中,你可以使用网格 Colliders来精确地匹配 GameObject的网格形状。
    这类 colliders比起初始种类来说,会消耗更多处理器资源,尽可能少用。当然,网格 collider不会与另一个网格 collider碰撞(也就是说,在他们接触时,什么都不会发生)。在一些情况中,你可以在 Inspector中将网格 collider标记为 Convex来绕过这条特性。这会产生一种“convex hull” collider形状。(这种形状跟起始网格很像,但不会有任何 undercut)(?)这样做的好处是,一个 convex mesh collider可以与其他 mesh collider碰撞,所以当你有一个移动中的角色时,你可以使用这条特性。

    Static(静态) Colliders

    你为没有 Rigidbody组件的 GameObject添加 colliders来构造地板、墙和在场景中不需要移动的元素。这些元素被称为静态碰撞物。你不能通过改变 Transform位置来重定位静态碰撞物,因为这将严重影响物理引擎的性能。在有 Rigidbody的 GameObject上的 Colliders被称为动态碰撞物。静态碰撞物能与动态碰撞物交互,但是由于它们没有 Rigidbody,它们不能因碰撞而移动。

    物理材料(Physics materials)

    当 colliders交互时,它们的表面需要对它们所表示的材料的属性进行仿真。例如,一层冰很滑,一个橡胶球会摩擦且具有弹性。虽然 colliders的形状在碰撞期间不会形变,但是它们的摩擦和弹力能由物理材料来配置。

    Triggers

    在碰撞发生时,脚本系统能检测到,且使用 OnCollisionEnter函数初始化动作。然而,你也可以使用物理引擎来简单地检测到一个 collider在没有产生碰撞时进入其他区域。一个配置为 Trigger的 collider(使用 Is Trigger属性)与固态物体不同,且能简单地允许其他 collider穿过。在一个 collider进入它的区域后,trigger会在 此物体的脚本中调用 OnTriggerEnter函数。

    Collision callbacks for scripts(脚本的碰撞回调)

    当碰撞发生时,物理引擎会调用与物体相关联的脚本的特定函数。你可以在这些函数里添加自己的代码来处理碰撞时间。比如说,当汽车撞到障碍物后,你可能需要播放事故音效。
    在检测到碰撞时,会调用 OnCollisionEnter函数进行第一次物理更新。在物体碰撞接触期间,OnCollisionStay会被调用,OnCollisionExit指示接触结束。Trigger colliders调用与之类似的 OnTriggerEnter, OnTriggerStay, OnTriggerExit函数。
    正常来说,对于非 trigger碰撞,与之涉及的至少其中的一个物体必须有 non-kinematic Rigidbody(也就是 Is Kinematic关闭)。如果物体都是 kinematic Rigidbodies,那么 OnCollisionEnter将不会被调用。对于 trigger碰撞,则没有这些限制。

    Collider interactions

    Collider之间的交互取决于它们的 Rigidbody组件是如何配置的。下面介绍三个重要的配置:静态 Collider,Rigidbody Collider和 Kinematic Rigidbody Collider。

    Static Collider

    这是一个无 Rigidbody有 Collider的 GameObject。Static colliders被用于水平几何(level geometry),水平几何指的是总是呆在同一个地方且从不移动。有 rigidbody的物体可以与静态 collder碰撞,但静态 collider不会移动。
    物理引擎假设静态碰撞物从不移动和改变且可以基于此做出许多优化。如果你打算改变静态碰撞物,那么这将会导致物理引擎将进行额外的重计算,从而损失性能。更坏地,这些改变有时会将这个碰撞物置于未定义状态,从而产生错误的物理计算。比如说,依靠被修改的静态 Collider的光线投射(raycast)将不再能检测到它,或在一个随即位置检测到它。不仅如此,被一个移动的静态 collider撞到的 Rigidbodies将不会被唤醒且静态碰撞物没有产生任何摩擦。基于以上原因,只有有 Rigidbodies的碰撞物才能被修改。

    Rigidbody Collider

    这是一个有 Collider和 non-kinematic Rigidbody关联的 GameObject。Rigidbody碰撞物完全由物理引擎来进行仿真且能被碰撞和力影响到。它们可以与其他物体(除静态碰撞物)进行碰撞。

    Kinematic Rigidbody Collider

    这是一个有 Collider和 kinematic Rigidbody(即 Is Kinematic打开)关联的 GameObject。你可以通过在脚本中修改 kinematic rigidbody物体的 Transform组件来移动它。但它却不会受到碰撞和力的影响。Kinematic rigidbodies应该被用于能被移动或偶尔可被 disabled/abled但行为与静态碰撞物不一致的碰撞物。比如说滑动门应该当作一个可移动的物理障碍且在需要时可以被打开。不像静态碰撞物,一个移动的 kinematic rigidbody将会受到其他物体的摩擦且能唤醒其他 rigidbodies。
    即使是在不可移动期间,kinematic rigidbody碰撞物的行为也与静态碰撞物不同。比如说,如果碰撞物被设置为 trigger,你也需要给它添加一个 rigidbody来接收你脚本中的 trigger事件。如果你不想让这个 trigger因重力下落或被其他物理因素影响,你可以在它的 rigidbody中设置 Is Kinematic。
    Rigidbody组件可以在任何时候都可使用 Is Kinematic属性在 normal和 kinematic行为中切换。
    一个常见的例子,即“ragdoll”影响:一个角色在动画里正常移动但因爆炸或剧烈碰撞而被弹飞。这个角色的肢体可由它们自己的允许 IsKinematic的 Rigidbody组件给定。这些肢体将会正常地移动直到 IsKinematic被关闭,之后,它们会立刻像物理物体行动。此时,一个碰撞或爆炸的力会传到角色身上,并炸飞它们的肢体。(我的理解:角色是拼凑的,在IsKinematic打开时,角色肢体不会因为力而自由运动,但在 IsKinematic关闭后,就可以由受到的力做自由运动。)

    Joints(关节)

    Joint组件连接 一个Rigidbody和其他 Rigidbody或空间中一个固定的点。Joints作用于移动 rigidbodies的力,且限制了它们的移动。Joints给予 Rigidbodies以下程度的自由:

    unity提供了作用于不同种类力和限制 Rigidbody组件的 Joints,并给予这些 bodies不同的运动:

    属性 功能
    Character(角色) Joint 模拟球和插座关节,就像臀部和肩膀。约束 rigidbody线性运动的自由度,对角自由度没有限制。
    Configurable Joint 模拟骨骼关节,就像布娃娃一样。你可以为这个关节配置力并在任何程度的自由度上约束 Rigidbody的移动。
    Fixed Joint 限制 rigidbody的移动,使之跟随其关联的物体一起移动。当你需要 rigidbodies能简单的彼此分开或你想连接两个 rigidbodies的移动,这是很有用的。
    Hinge(枢纽) Joint 关联一个 rigidbody到另一个 rigidbody或空间中一个共同起源的点且允许 rigidbodies从那个源点绕着某个特定的轴旋转。用于模拟门或手指关节
    Spring(弹簧) Joint 保持 rigidbodies的距离,但它们之间的距离稍微拉伸。弹簧的作用就像一块橡皮筋,试图将两个锚点拉到完全相同的位置。

    终于写完论文了,继续看文档...

    持续碰撞检测(Continuous collision detection, CCD)

    unity提供了以下两种CCD方法:

    • 基于扫描的CCD(Sweep-bases CCD)
    • 预测型CCD(Speculative CCD)
      在Inspector窗口选择一个rigidbody并设置Collision Detection为Continuous 或 Continuous Dynamic,即可使用基于扫描的CCD,设置Collision Detection为 Continuous Speculative则为预测型CCD模式。

    基于扫描的CCD

    基于扫描的CCD使用 Time Of Impact(TOI)算法来为物体计算潜在的碰撞,通过使用它当前的速度来扫描它前面的轨迹。如果物体的移动方向上有任何接触,那么算法会计算撞击的时间以及继续移动物体直到那个时间点。从那时起,此算法会执行子步骤,计算TOI之后的速度,然后重新扫描。
    因为这种方法依赖的是线性扫描,它会忽略躯干的角运动,这就导致当物体在以一定速度旋转时,会引起隧道效应。比如说,弹球机的弹片被固定在一段,且绕着一个固定点旋转。这个弹片只有角运动。因此,它会很轻易地错失与弹球的碰撞。

    另一个问题就是这种方法的性能。如果你有很多高速的近距离的CCD物体,会因为额外的扫描、物理引擎执行更多的CCD子步骤而造成 开销迅速增多。

    预测型CCD(Speculative CCD)

    预测型CCD通过增加物体的 broad-phase axis-aligned minimum bounding box(AABB)来工作的,基于物体的线/角速度。
    (这篇博客介绍AABB是什么:AABB, 也就是说用一个立方体来包围物体)
    此算法选择所有在下一个物理步骤中潜在的接触点。所有接触点都会被注入到solver中,以确保所有的接触约束都能得到满足,这样物体就不会在碰撞期间引起隧道效应了。
    下图显示了一个从t0移动的球,如果它运动路线上没有墙的话,会移动到 t1。通过将它当前位置扩展为AABB,预测算法获得n1和n2两条法线。算法告诉solver预测这些接触点,以使球不会穿过墙面。

    因为接触只在碰撞检测阶段被计算,而解决和整合阶段没有,故预测型CCD普遍比基于扫描的方法开销要小些。不仅如此,因为预测型CCD基于物体的线/角运动扩展了 broad-phase AABB,它能找到基于扫描CCD遗失的接触点。

    然而预测型CCD会产生幽灵碰撞,即物体运动被一个不该产生的预测接触所影响。这是因为预测型CCD收集基于最近点算法收集所有潜在的接触点,所以接触法线并不是很精确。这通常会使高速物体沿着嵌合的碰撞特征滑动并跳起来,尽管它们不应该这样做。比如说,在下图中,一个球在起点t0水平向右移动,且在整合后有一个预测位置t1。扩展AABB与盒子b0和b1重叠,且CCD在c0和c1有两个预测触点。因为预测型CCD使用最近点算法产生接触点,c0有一个倾斜法线,这会让solver误以为是一个斜坡。

  • 相关阅读:
    linux下好用的软件
    linux下常见目录的介绍
    slam相关链接
    GPS 使用的三种坐标系 ECEF、ENU、LLA坐标系
    平面度计算 C++实现
    QT Cmake添加srv和msg
    pcl点云与ros之间的数据类型转换
    ROS分布式设置
    qt中播放视频和音频
    linux tips
  • 原文地址:https://www.cnblogs.com/qing2019/p/12729518.html
Copyright © 2011-2022 走看看