美文网首页
Rigibody 2D

Rigibody 2D

作者: JJJJJJJJJJC | 来源:发表于2019-07-18 19:49 被阅读0次

    Rigibody 2D:

    所有被附加在同一个具有Rigidbody2D组件的GameObject、以及其子GameObject上的Collider2D,都会被隐式地附加到该Rigidbody2D上。当Collider2D被附加到Rigidbody2D上后,它将随着Rigidbody2D移动。一个Collider2D不应该直接使用Transform或者其offset属性来移动它,而是应该使用Rigidbody2D的移动代替之。这样会得到最好的表现和正确的碰撞检测。被附加在同一个Rigidbody2D的Collider2D之间不会发生碰撞。所以我们可以创建一个包含多个Collider2D的复合Collider2D,这样所有的Collider2D的移动、旋转都将与Rigidbody2D的运动同步。

    那么针对之前使用Transform移动的方式,我们应该改为如下方式:
    void FixedUpdate()
        {
            rigidbody2D.MovePosition (rigidbody2D.position + Vector2.left * speed * Time.fixedDeltaTime);
        }
    

    似乎没有规定要在Fixed里移动.
    或者如下方式:

    void Start () {
            rigidbody2D.velocity = Vector2.left * speed;
        }
    

    注意前一种方式每一物理帧设置一次Rigidbody2D的位置,看起来Rigidbody2D在以一定速度移动,但实际上它的velocity依旧是零。

    后一种方式则不存在上面的问题,设置好velocity后,物理系统会自动对它进行模拟,代码看起来也更简洁。

    再看看Rigidbody2D的Body Type属性:


    它有三个可选项:Dynamic(动态,默认)、Kinematic(运动学)、Static(静态)。
    这三种类型确定了不同的运动行为(移动和旋转)和碰撞方式。
    注意虽然Rigidbody2D描述了与其他物体碰撞,但是如果没有附加Collider2D组件,它仍然是不能检测到碰撞的。
    • Constraints 冻结位置 这个选项的当冻结时,那么这些数值就不会受力的影响,想要改变只能通过代码进行修改。

    • Mass 质量

    • Linear Drag(线性阻力)为0,但是这个物体跑着跑着还是会停止是因为它与别的碰撞体有摩擦力。

    • Collision Detection:碰撞体之间的碰撞检测方式:

      • Discrete(离散):在一个 物理更新期间,物理可以相互重叠、穿越。当速度太快时,碰撞只会在最新的位置检测,这就意味着,如果速度太快,使用这个选项会有问题。
      • Continuous(连续):这个就不会存在Discete的问题,但是CPU消耗高。
    • Sleeping Model:睡眠模式.在什么情况下,会休眠以节省性能。

      • Never Sleep:从不休眠
      • Start Awake:物体最初是醒着的
      • Start Asleep:物体最初是休眠的,但是遇到碰撞就会苏醒。
    • Interpolate:在物理更新中,物体移动的插值算法

      • None
      • Interpolate:基于上一帧物体位置来插值模拟
      • Extrapolate:基于预测下一帧物体位置来插值模拟

    关于Body Type,这个属性不要在运行时去修改它。原因还是引用官方文档的说明:

    意思就是运行时去改变此属性会引起不同的表现。具体什么表现,就是前面说的会立即引发一系列的重计算,这会是性能的额外开销。

    再看看三种不同的Body Type究竟确定了哪些不同的运动行为和碰撞方式。

    Body Type —— Dynamic

    Dynamic Rigidbody2D被设计用来制作在物理模拟下会移动的物体。它会与所有类型的Rigidbody2D进行碰撞,是最常用的Rigidbody2D类型、默认的类型,同时也是最耗费性能的类型。
    文档中粗体部分的意思就是千万不要使用Transform组件来设置Dynamic Rigidbody2D的position和rotation。
    如果想要移动或旋转它,可以使用上面提到的方式,通过Rigidbody2D的接口来完成。

    Body Type —— Kinematic

    Kinematic所谓的碰撞仅限于脚本.物理上是不会产生任何物理效果的.

    Kinematic Rigidbody2D被设计用来制作在物理模拟下会移动、但是仅仅在明确的用户控制下运动的物体,它不会受到重力和AddForce、AddTorque等力相关的函数的影响。

    文档中粗体部分的意思是Kinematic Rigidbody2D对系统资源的要求比Dynamic Rigidbody2D更低(所以更有效率)。Kinematic Rigidbody2D被设计用来通过Rigidbody2D.MovePosition或Rigidbody2D.MoveRotation来进行重定位。

    对于Kinematic Rigidbody2D,velocity属性对它依旧有效,只不过施加力和重力都不会对velocity造成影响。

    Kinematic Rigidbody2D仅仅只会与Dynamic的Rigidbody2D发生碰撞(在不勾选Use Full Kinematic Contacts的情况下),它在碰撞行为上类似于Static Rigidbody2D,可以理解为具有无限质量、无法被撼动(不能通过力或碰撞改变速度,但是可以设置其速度和位置、旋转)的刚体。

    Body Type —— Static

    Static Rigidbody2D被设计用来制作在物理模拟下不会移动的物体。它在表现上可以理解为一个具有无限质量、不可移动的物体。此时velocity、AddForce、gravity、MovePosition、MoveRotation都是不可用的。

    文档中粗体部分意思是Static Rigidbody2D对资源最不敏感(对性能要求低),Static Rigidbody2D仅仅会与Dynamic Rigidbody2D发生碰撞。两个Static Rigidbody2D之间也不会发生碰撞,因为他们本来就被设计成不可移动的。

    Simulated(模拟)

    该属性就是字面意思,设置为true(勾选)时开启模拟;设置为false(不勾选)时关闭模拟。
    关闭时不与Static碰撞.

    模拟包括:

    • 运动
    • Collider2D的碰撞
    • Joint2D的约束效果
    • 是否驻留在内存
    • 如果为false.以上效果都消失.也就是说设为false可以用于代替取消激活Collider2d.

    更改此属性在内存和处理上,都比直接启用/禁用Collider2D组件和Joint2D组件更有效率。要知道原理的话,可以查看官方文档,这里就不再作详细解释了。

    Use Full Kinematic Contacts(使用全运动触点)

    如果想要Kinematic Rigidbody2D与所有类型的Rigidbody2D发生碰撞,可以勾选此选项。勾选上后,它在碰撞上类似于Dynamic Rigidbody2D,但是不会受到力的影响。
    只能在脚本触发ColliderEnter等事件函数.其他物理效果并不会生效.

    当此属性被设置为false(不勾选)时,该Kinematic Rigidbody2D只会与Dynamic Rigidbody2D发生碰撞;它不会与其他的Kinematic Rigidbody2D或Static Rigidbody2D(设置为trigger时除外)发生碰撞。所以此时脚本上的碰撞检测函数(OnCollisionEnter2D,OnCollisionStay2D,OnCollisionExit2D)不会被触发。

    总结:

    1、在操作附加了Rigidbody2D的物体时,不要直接通过操作Transform来移动、旋转它。

    2、要接受碰撞的Rigidbody2D必须添加Collider2D组件。

    3、如果一个Rigidbody2D需要移动,但不接受力的作用,那么需要将它设置成Kinematic;如果它附加了Collider2D组件,在Rigidbody的Use Full Kinematic Contacts属性为false(不勾选)时,它只会与Dynamic的Rigidbody2D碰撞,而不会与Kinematic的或者Static的Rigidbody2D发生碰撞;如果需要它能与受所有类型的Rigidbody2D碰撞,那就设置Use Full Kinematic Contacts为true(勾选)。

    4、如果一个Rigidbody2D需要移动,并且接受完全的物理模拟,包括重力、碰撞、施加力等,那么需要将Rigidbody2D设置成Dynamic,并附加Collider2D组件。

    5、如果一个Rigidbody2D不需要移动,也不需要接收力的作用,但是需要接受碰撞,那么需要将Rigidbody2D设置为Static,并附加Collider2D组件。

    6、在运行中不要修改Rigidbody2D的Body Type属性。

    7、在运行中,如果想要停止/启用对一个Rigidbody2D进行物理模拟,那么将这个Rigidbody2D的Simulate属性设置为false/true会比关闭/打开它的Collider2D、Joint2D组件效率高。

    Dynamic:

    • 物理 通吃
    • 脚本碰撞 通吃.
    • 脚本触发 通吃.

    Kinematic:

    • 物理 Dynamic.其余全失效.
    • 脚本碰撞 Dynamic/Use
    • 脚本触发 通吃

    Static:

    • 物理 Dynamic
    • 脚本碰撞 Dynamic/Use
    • 脚本触发 除了Static都行.

    常用API

    AddForce:这个方法是真实地给物体施加力。等同于动能方程。我的按键必须持续的按下,它才能持续的给物体施加力,增加物体的速度。如果是kinematic的刚体类型,则这个施加力是无效的。

    Velocity:这个就是刚体的速度属性,当刚体加力或者被撞飞的时候,就会有速度。当然我们也可以直接赋值是刚体具有速度来移动。

    MovePosition:这个就是直接改变刚体的位置。同等position=vecto2。通常在Kinematic类型使用。
    MoveRotation:同上

    除此之外,刚体组件还有一些方法很常用。

    • AddForceAtPosition: 从某位置施加力.

    • Cast:指定方向,指定距离进行射线检测,然后将射线的信息获取.

    • IsTouchingCollider() :传入一个碰撞体的引用,判断该碰撞提与我的刚体是否接触。

    • OverlapPoint:输入一个position,看刚体是否与这个点重叠。

    • OverlapCollider(过滤器,接受数据数组):输入一个过滤器数据结构,检测刚体重叠的碰撞器。

    • GetContacts(接受碰撞的数组) : 接受能与刚体发生碰撞(脚本,非物理.碰撞规则参考上面的总结)的碰撞器数组.

    相关文章

      网友评论

          本文标题:Rigibody 2D

          本文链接:https://www.haomeiwen.com/subject/sqyrlctx.html