Cocos 3.0 3D物理系统

时间:2021-6-6 作者:qvyue

参考
Cocos Creator 3D 物理模块介绍
Cocos Creator 3.0 3D 物理讲解
选择适合你项目的物理系统

一、3D 物理简介

Cocos Creator 3.0 目前支持轻量的碰撞检测系统 builtin 和具有物理模拟的物理引擎 cannon.js ,以及功能完善强大的 bullet 的 asm.js/wasm 版本(ammo.js),并为开发者提供了高效统一的组件化工作流程和便捷的使用方法。

Cocos 3.0 3D物理系统
image.png
1.碰撞检测: builtin

builtin 仅有碰撞检测的功能,相对于其它的物理引擎,它没有复杂的物理模拟计算。如果您的项目不需要这一部分的物理模拟,那么可以考虑使用 builtin,这将使得游戏的包体更小。

若使用 builtin 进行开发,请注意以下几点:

  • builtin 只有 trigger 类型的事件。
  • Collider 中的 isTrigger 无论值真假,都为运动学类型的触发器。
2.物理引擎: cannon.js

cannon.js 是一个开源的物理引擎,它使用 js 语言开发并实现了比较全面的物理功能,如果您的项目需要更多复杂的物理功能,那么您可以考虑使用它。 cannon.js 模块大小约为 141KB

3.物理引擎: ammo.js

ammo.js 是 bullet 物理引擎的 asm.js/wasm 版本,由 emscripten 工具编译而来。 Bullet 具有完善的物理功能,以及更佳的性能,未来我们也将在此投入更多工作。

需要注意的是,目前 ammo.js 模块具有 1.5MB 左右的大小。

4. 不使用物理

若不需要用到任何物理相关的组件和接口,可以取消黄色框的勾选,这样在发布时将有更小的包体。

:若处于取消勾选的状态,项目将不可以使用物理相关的组件和接口,否则运行时将会报错。

5.对比
  • builtin 极其轻量的碰撞检测系统,仅支持盒、球、胶囊体形状和触发事件
  • cannon.js 纯 js 开发的物理引擎,支持大部分特性,易于扩展,但性能不够好,包体约为 141 KB
  • ammo.js 由 bullet 物理引擎编译而来,支持所有特性,性能最优,但包体较大且不易扩展,其中 js 版本的包体约为 1.32 MB,wasm 版本的包体约为 690 KB
Cocos 3.0 3D物理系统
image.png
二、2D 物理简介

Cocos Creator 3.0 支持内置的轻量 Builtin 物理系统和强大的 Box2D 物理系统。Builtin 物理系统只提供了碰撞检测的功能,对于物理计算较为简单的情况,我们推荐使用 Builtin 物理模块,这样可以避免加载庞大的 Box2D 物理模块并构建物理世界的运行时开销。而 Box2D 物理模块提供了更完善的交互接口和刚体、关节等已经预设好的组件。

你可以根据需要来选择适合自己的物理模块,通过编辑器主菜单中的 项目 -> 项目设置 -> 功能裁剪 切换物理模块的使用。

Cocos 3.0 3D物理系统
image.png
三、物理组件

刚体rigidbody :刚体是指在运动中和受力作用后,形状和大小不变,而且内部各点的相对位置不变的物体。
碰撞体collider:碰撞体是给物体加一个判定框,当碰撞框重叠的时候,两物体发生碰撞。碰撞体是检测物理碰撞的框架,他永远跟随物体的刚体移动,不会产生偏差。

Cocos 3.0 3D物理系统
image.png

Cocos 3.0 3D物理系统
盒碰撞器组件 BoxCollider
  • 刚体组件(RigidBody) 它负责操控物理对象与运动相关的属性,以及配置分组,一个节点最多一个
  • 碰撞器组件(Collider) 它负责操控物理对象上形状相关的属性,一个节点可以有多个
  • 触发器(Trigger) 它是勾选上了IsTrigger的碰撞器组件,它会像幽灵一样穿透其它物体,并提供穿透开始、保持,以及结束的事件

是否一定要加刚体组件是提问最多的,这里介绍一个小技巧:

  • 需要配置分组,加
  • 需要设置为运动学或者动力学类型(不加意味着是静态类型),加
1.刚体

刚体是组成物理世界的基本对象,可以让一个节点受到物理影响并产生反应。刚体组件用于控制模拟相关的部分属性:

Cocos 3.0 3D物理系统
image.png
// TypeScript
const rigidBody = this.getComponent(RigidBody);

目前刚体类型包括 STATIC、DYNAMIC 和 KINEMATIC 三种。

  • STATIC,表示静态刚体,可用于描述静止的建筑物,若物体需要持续运动,应设置为 KINEMATIC 类型;
  • DYNAMIC,表示动力学刚体,能够受到力的作用,请通过物理规律来运动物体,并且请保证质量大于 0;
  • KINEMATIC,表示运动学刚体,通常用于表达电梯这类平台运动的物体,请通过 Transfrom 控制物体运动;

Static 静态刚体,可用于描述静止的建筑物,只与 Dynamic 和 Kinematic 类型的物体产生事件
Dynamic 动力学刚体,能够受到力的作用,物理引擎会接管该物体的运动,通过物理层的数值来操控
Kinematic 运动学刚体,通常用于表达电梯这类平台运动的物体,通过修改变换信息来操控

Cocos 3.0 3D物理系统
76bde0722ff65cd0d42c92835c29e874.gif

图中白色为静态,蓝色为运动学,黄色为动力学。其中白色和蓝色都是操控的变换信息,很明显的看出几个表现

  • 白色和蓝色之间会出现穿透现象
  • 白色的静态物体也可以运动
  • 两个黄色方块表现不同,白色上方的静止不动,蓝色上方的会跟随着运动

以上现象的原因是:

  • 静态和运动学都不会受到力的作用,所以产生了穿透,这是正常现象
  • 静态物体的确是可以运动的,静态是指在时空中,每一个时刻都是静态,不会考虑其它时刻的状态
  • 与静态物体不同,运动学物体会根据附近时刻估算出运动状态(比如速度),又由于摩擦力的作用,因此带动了黄色方块
2.刚体质心

目前质心固定在刚体组件绑定的节点上,质心和碰撞体是相对关系。通过调整形状的偏移 center,可以使质心在形状上进行偏移。

Cocos 3.0 3D物理系统
image.png
3.休眠

休眠刚体时,会将刚体所有的力和速度清空,使刚体停下来。
处于休眠状态中的物体,不会再对其进行碰撞检测和模拟。这会节约大量的CPU开销。

Cocos 3.0 3D物理系统
image.png
// 休眠
if (rigidBody.isAwake) {
    rigidBody.sleep();
}
// 唤醒
if (rigidBody.isSleeping) {
    rigidBody.wakeUp();
}
4.让刚体动起来

针对不同的类型,让刚体运动的方式不同:

  • 对于静态刚体,应当尽可能保持物体静止,但仍然可以通过 Transform 来改变物体的位置。
  • 对于运动学刚体,应当通过改变 Transform 使其运动。
  • 对于动力学刚体,需要改变其速度,有以下几种方式:
(1)通过重力

刚体组件提供了 useGravity 属性,将 useGravity 属性设置为 true。

(2)通过施加力

刚体组件提供了 applyForce 接口,签名为:

applyForce (force: Vec3, relativePoint?: Vec3)

根据牛顿第二定律,可对刚体某点上施加力来改变物体的原有状态。

rigidBody.applyForce(new Vec3(200, 0, 0));
(3)通过扭矩

力与冲量也可以只对旋转轴产生影响,使刚体发生转动,这样的力叫做扭矩。

刚体组件提供了 applyTorque 接口,签名为:

applyTorque (torque: Vec3)

通过此接口可以施加扭矩到刚体上,因为只影响旋转轴,所以不需要指定作用点。

(4)通过施加冲量

刚体组件提供了 applyImpulse 接口,签名为:

applyImpulse (impulse: Vec3, relativePoint?: Vec3)

根据动量守恒,对刚体某点施加冲量,由于物体质量恒定,从而使刚体改变原有状态。

rigidBody.applyImpulse(new Vec3(5, 0, 0));
(5)通过改变速度

刚体组件提供了 setLinearVelocity 接口,可用于改变线性速度,签名为:

setLinearVelocity (value: Vec3)

示例:

rigidBody.setLinearVelocity(new Vec3(5, 0, 0));

刚体组件提供了 setAngularVelocity 接口,可用于改变旋转速度,签名为:

setAngularVelocity (value: Vec3)

示例:

rigidBody.setAngularVelocity(new Vec3(5, 0, 0));

参考拉小登博客 让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity

1.力,循序渐进——ApplyForce
顾名思义,ApplyForce方法会在刚体上施加一个力。学过物理力学的同学都知道,F=ma,有了力F就有了加速度a,有了加速度,物体就会有速度,就会慢慢动起来。(但是不会立马动起来,因为力不会直接影响速度)。
举个简单的例子,小明推一个静止的箱子,箱子不会立马飞出去,而是慢慢的、越来越快的动起来(减速也一样)。
2.速度,叠加——ApplyImpulse
与ApplyForce不同,ApplyImpulse不会产生力,而是直接影响刚体的速度。通过ApplyImpulse方法添加的速度会与刚体原有的速度叠加,产生新的速度。
3.一触即发——SetLinearVelocity
setLinearVelocity与ApplyImpulse一样,直接影响刚体的速度。不一样的是,setLinearVelocity添加的速度会覆盖刚体原有的速度。不过,在SetLinearVelocity方法不会自动唤醒sleeping的刚体,所以在调用该方法之前,记得将刚体body.wakeUp()一下。

5.限制刚体的运动
(1)通过休眠

休眠刚体时,会将刚体所有的力和速度清空,使刚体停下来。

(2)通过阻尼

刚体组件提供了 linearDamping 和 angularDamping 属性:

  • linearDamping 属性用于设置线性阻尼。
  • angularDamping 属性用于设置旋转阻尼。

阻尼参数的范围建议在 0 到 1 之间,0 意味着没有阻尼,1 意味着满阻尼。

注:执行部分接口,例如施加力或冲量、改变速度、分组和掩码会尝试唤醒刚体。

(3)通过因子

刚体组件提供了 linearFactor 和 angularFactor 属性:

  • linearFactor 属性用于设置线性因子。
  • angularFactor 属性用于设置旋转因子。

因子是 Vec3 的类型,相应分量的数值用于缩放相应轴向的速度变化,默认值都为 1,表示缩放为 1 倍,即无缩放。

注意:

  • 将因子某分量值设置为0,可以固定某个轴向的移动或旋转。
  • 在 cannon 和 ammo 后端中,因子作用的物理量不同,cannon 中作用于速度,ammo 中作用于力。

使用矩形碰撞盒,碰撞后发现模型的移动轨迹从直线变歪。将angularFactor 的三个轴属性全部改为0即可解决。

6.地面判断
Cocos 3.0 3D物理系统
image.png

角色是否在地面上,可以通过法线的指向来得知,对应的条件为normal.y > 0。有时候还需要知道地面的倾斜情况,这里通过normal.y的大小就能知道,越接近于1,哪么地面就越平(法线垂直向上);越接近于0,哪么地面就越陡峭。

7.跳跃

一旦能够确定是否在地面后,就可以加上跳跃行为了。首先需要明确的一点是,这里使用的是动力学类型的刚体(原因是我希望通过物理引擎接管刚体后得到更加真实的物理反馈),所以需要通过改变物理数值来达到目的,例如直接将角色线性速度的y分量设置为5,如下图(图中碰撞体用的是胶囊体,这与实际场景相关,可自行更改)。

Cocos 3.0 3D物理系统
asr43-w6gh9.gif

直接改y轴速度,可以良好的工作在完全水平的地面上。但有时候跳跃还需要根据地面斜度来做出不同的行为,这里提供一个思路:提供一个配置因子,范围为0到1,根据因子将当前法线和垂直法线插值,得出目标法线,再乘以跳跃的速率,进而得出期望的跳跃速度,将其加入到角色的线性速度之中。

8.行走和站立

站立行为,如果希望角色不会摔倒,哪么直接将AngularFactor全设置为0即可。行走行为,可根据角色的运动状态来实现,假设需要将角色往x轴运动,哪么就修改角色x轴的线性速度。因此控制行走,只需要两个量,一个是运动方向,另一个是运动速率。

做出好的运动控制的唯一窍门就是控制好速度,但这也是最容易错误使用的点:

  • 随意设置速度,这是运动不真实最根本的原因
  • 设置过大的速度,这将很容易出现穿透现象,可以尝试上文介绍的多步模拟技术
  • 没有掌握控制速度的方式,有些开发者直接修改为某个固定值大小,这当然不是错误的做法,但修改速度之前应当考虑清楚这是不是想要的结果。
  • 有个小技巧是,如果是跳跃行为,可以考虑直接设置为固定值;
  • 如果是行走行为,更好的方式是根据上个时刻的状态进行修改
  • 使用了Kinematic类型的刚体,期望物理引擎会帮助你处理好碰撞行为,通过上文可以知道这是不可能的。
  • 但实际上有很多好的角色控制都基于Kinematic进行实现,这里面的技术细节远比本文介绍的复杂。
四、分组 掩码
1.碰撞矩阵
Cocos 3.0 3D物理系统
image.png

默认情况下只有一个 DEFAULT 分组,新建分组默认不与其它组碰撞。点击 + 按钮可以新增分组。

注:新增分组的 index 和 name 均不能为空,且不能与现有项重复。
注:分组不可以删除,但可以修改分组的名称。

这张表列出了所有的分组,你可以通过勾选来决定哪两组会进行碰撞检测。如上图所示,DEFAULT和water是否会进行碰撞检测将取决于是否选中了对应的复选框。

根据上面的规则,在这张表里产生的碰撞对有:

  • DEFAULT – water
  • DEFAULT – DEFAULT

而不进行碰撞检测的分组对有:

  • water – water

通过刚体组件上的 Group 属性来配置对应的物理元素的分组:

Cocos 3.0 3D物理系统
image.png

在Cocos Creator 3.0 正式版震撼来袭!中,有提到碰撞矩阵相关变化:

[IMPROVE] 重构 3d 物理碰撞矩阵,碰撞矩阵仅用于初始化刚体的分组和掩码,不再维护更新,废除 Use Collision Matrix 配置项

2.设置掩码

参考Cocos Creator 3D 物理碰撞group和mask设置方法

a.假设场景中有:场景障碍物,玩家A,玩家B,穿墙的导弹

  • 障碍物阻挡玩家A和玩家B
  • 玩家A和玩家B不碰撞,但会被导弹击中
  • 导弹可以穿越障碍物,但会击中玩家A和玩家B

b.设置分组group

  • 设置障碍物的collider的group为0,(注意!!!代码中实际设置为1
  • 设置玩家A的collider的group为1,(注意!!!代码中实际设置为1
  • 设置玩家B的collider的group为2,(注意!!!代码中实际设置为1
  • 设置导弹的collider的group为3,(注意!!!代码中实际设置为1

c.以障碍物为例,分析过程如下:

只要以下条件为真就会进行检测:(GroupA & MaskB) && (GroupB & MaskA)

障碍物和A会阻挡

  • A的分组是0010,所以障碍物的mask为1
  • 障碍物的分组是0001,所以A的mask为1

同理,障碍物和B会阻挡

  • B的分组是0100,所以障碍物的mask为1
  • 障碍物的分组是0001,所以B的mask为1

障碍物和导弹不碰撞,即导弹能穿墙,此时把上面两部分合并,得到:
障碍物的collider的mask为(1

如果障碍物和导弹碰撞,和上面一样:

  • 导弹的分组是1000,所以障碍物的mask为1
  • 障碍物的分组是0001,所以导弹的mask为1

然后障碍物的mask再次合并,就变为(1

d.设置掩码mask(将需要互相碰撞的group掩码或进来(加进来也可以))

  • 设置障碍物的collider的mask为(1
  • 设置玩家A的collider的mask为(1
  • 设置玩家B的collider的mask为(1
  • 设置导弹的collider的mask为(1

如果导弹不能穿墙,需要更改mask为

  • 设置障碍物的collider的mask为(1
  • 设置导弹的collider的mask为(1

如果玩家之间互相碰撞,需要更改mask为

  • 设置玩家A的collider的mask为(1
  • 设置玩家B的collider的mask为(1

示例代码如下

        var c0 = blocks.getComponent(ColliderComponent);
        c0.setGroup(1 
五、物理材质
Cocos 3.0 3D物理系统
image.png

Cocos 3.0 3D物理系统
image.png

物理材质有摩擦系数,回弹系数。

目前物理材质以碰撞体为单位进行设置,每个 Collider 都具有一个 material 的属性(不设置时, Collider 将会引用物理系统中的默认物理材质)。 应用到 Collider 同样也分编辑器操作和代码操作两种方式。

编辑器内操作,只需要将资源拖入到cc.PhysicMaterial属性框中即可,如下图所示:

Cocos 3.0 3D物理系统
image.png

代码中操作:

const collider = this.node.getComponent(Collider);
collider.material = newPmtl;
六、物理事件

Cocos Creator 3.0 的物理事件包括 触发事件 和 碰撞事件,分别由 触发器 和 碰撞器 产生。

1.触发器和碰撞器
  • Is Trigger 属性为 true ,是触发器。当发生碰撞时,触发器不会产生碰撞效果,所以触发器只用于碰撞检测。
  • Is Trigger 属性为 false ,是碰撞器。当发生碰撞时,碰撞器会产生碰撞效果,所以碰撞器既可以进行碰撞检测,又可以产生物理效果。

两者的区别如下:

  • 触发器不会与其它触发器或者碰撞器做更精细的检测。
  • 碰撞器与碰撞器会做更精细的检测,并会产生碰撞数据,如碰撞点、法线等。
2.触发事件和碰撞事件区别
  • 触发事件由触发器生成,碰撞事件根据碰撞数据生成。
  • 触发事件可以由触发器和另一个触发器/碰撞器产生。
  • 碰撞事件需要由两个碰撞器产生,并且至少有一个是动力学刚体。

参考
《学Unity的猫》——第十章:Unity的物理碰撞,流浪喵星计划
碰撞器、触发器

触发器在生活有很多例子,假设进入到一些门口时,当我们踏入到一定范围,门会自动打开,这其实就是触发器在现实生活中的例子,游戏中依然也是,例如,人物走回家的时候会自动的恢复血量,这其实就是在使用触发器

3.触发事件
  • onTriggerEnter 触发开始
  • onTriggerStay 触发保持
  • onTriggerExit 触发结束

需要通过注册事件来添加相应的回调:

  • 通过this.getComponent(Collider)获取到 Collider
  • 通过 Collider 的 on 或者 once 方法注册相应事件的回调
  • 注:Collider 是所有碰撞组件的父类。

代码示例:

public start () {
    let Collider = this.getComponent(Collider);
    Collider.on('onTriggerStay', this.onTrigger, this);
}

private onTrigger (event: ITriggerEvent) {
    console.log(event.type, event);
}

经过实测,触发事件,仍然需要其中一个组件是刚体

4.碰撞事件
  • onCollisionEnter 碰撞开始
  • onCollisionStay 碰撞保持
  • onCollisionExit 碰撞结束

代码示例:

public start () {
    let Collider = this.getComponent(Collider);
    Collider.on('onCollisionStay', this.onCollision, this);
}

private onCollision (event: ICollisionEvent) {
    console.log(event.type, event);
}
七、射线检测

官方文档 射线检测
浅析射线检测 raycast 的使用 !Cocos Creator 3D !
首先,我们看到的视角是这样子的。假设我们点击其中屏幕中的一个位置(图中的红点点)。

Cocos 3.0 3D物理系统
image.png

因为这个视角是摄像机提供的,我们就把这个点点和摄像机组合一条射线。

Cocos 3.0 3D物理系统
image.png

接着,检查这条射线穿过了那些物体,这些物体中可能就有我们点击的对象。

也可以这么理解,你用眼睛看着一块区域,伸出手指。你可以看到手指头挡住了一点视线,从你的视线做经过手指这个点画一条射线,这个射线穿过的物体,就刚好是你想要点击的物体。

creator 3d 提供了三种检测方案,可以参考https://github.com/cocos-creator/test-cases-3d中的raycast示例:

1.基于物理碰撞器的射线检测:
onEnable () {
    systemEvent.on(SystemEventType.TOUCH_START, this.onTouchStart, this);
}

onDisable () {
    systemEvent.off(SystemEventType.TOUCH_START, this.onTouchStart, this);
}

onTouchStart (touch: Touch, event: EventTouch) {
    this.cameraCom.screenPointToRay(touch.getLocationX(), touch.getLocationY(), this._ray);
    if (PhysicsSystem.instance.raycast(this._ray)) {
        const r = PhysicsSystem.instance.raycastResults;
        for (let i = 0; i 
2.基于模型的射线检测:
onTouchStart(touch: Touch, event: EventTouch) {
    const point = touch.getLocation();
    this.cameraCom.screenPointToRay(point.x, point.y, this._ray);
    if (geometry.intersect.rayModel(this._ray, this.modelCom.model!)) {
        this.modelCom.material = this.rayMaterial;
    } else {
        this.modelCom.material = this.defaultMaterial;
    }
}
3.基于 UITransform 组件的射线检测:
onTouchStart(touch: Touch, event: EventTouch) {
    this.label.string = '点击文字测试射线检测';
    const point = touch.getLocation();
    this.canvas.cameraComponent!.screenPointToRay(point.x, point.y, this._ray);
    const uiTrans = this.label.getComponent(UITransform)!;
    uiTrans.getComputeAABB(this._aabb);
    if (geometry.intersect.rayAABB(this._ray, this._aabb)) {
        this.label.string = '检测成功';
    }
}
4.API
  • raycast: 射线可以碰撞所有的可以检测的物体(多个).
  • raycastClosest:射线碰到一个物体以后,停止检测,直接返回一个物体(一个).

/**
 * 检测所有的碰撞盒,并记录所有被检测到的结果,通过 PhysicsSystem.instance.raycastResults 访问结果。
 * @param worldRay 世界空间下的一条射线
 * @param mask 掩码,默认为 0xffffffff
 * @param maxDistance 最大检测距离,默认为 10000000,目前请勿传入 Infinity 或 Number.MAX_VALUE
 * @param queryTrigger 是否检测触发器
 * @return boolean 表示是否有检测到碰撞盒
 */
raycast(worldRay: geometry.Ray, mask?: number, maxDistance?: number, queryTrigger?: boolean): boolean;
/**
 * 检测所有的碰撞盒,并记录与射线距离最短的检测结果,通过 PhysicsSystem.instance.raycastClosestResult 访问结果。
 * @param worldRay 世界空间下的一条射线
 * @param mask 掩码,默认为 0xffffffff
 * @param maxDistance 最大检测距离,默认为 10000000,目前请勿传入 Infinity 或 Number.MAX_VALUE
 * @param queryTrigger 是否检测触发器
 * @return boolean 表示是否有检测到碰撞盒
 */
raycastClosest(worldRay: geometry.Ray, mask?: number, maxDistance?: number, queryTrigger?: boolean): boolean;
八、射箭案例
Cocos 3.0 3D物理系统
odir1-qes1f.gif
1.射箭与回收箭——运动学、动力学、事件

射箭的第一步是拉弓,箭需要完全跟随弹性绳骨骼一起运动,不希望箭受到物理规则的影响,此时应将箭的刚体设置为 Kinematic 类型;第二步是松开弹性绳发射箭,这时希望给箭设置初速度后,可以按照物理规则进行运动,因此将箭的刚体设置为 Dynamic 类型

回收箭的大致过程是在箭射出去后,一旦触碰到触发区域就将其还原到弓上。这可以通过制作监听区域来实现,首先利用碰撞体组件拼凑出区域,同时将碰撞体组件的 IsTrigger 勾选上。(下图中的蓝色地板为监听区域)

Cocos 3.0 3D物理系统
image.png

易误点:

  • 利用修改变换信息来操作动力学(Dynamic)类型的刚体,应当通过速度、力或冲量等物理层的数值
  • 利用静态(Static)类型的刚体来监听事件,静态刚体只会和带有类型为运动学或动力学的刚体产生事件,可以更改为运动学(Kinematic)类型,或者事件通过另一方进行注册
  • 监听事件时仅监听了触发开始(OnTriggerEnter),但是误以为包括了触发保持(OnTriggerStay)和结束(OnTriggerExit)
2.瞄准——碰撞矩阵(过滤检测)、射线检测、静态平面

瞄准是射箭前的步骤,准心处于箭头指向所在的射线上,在十字架前面加一个静态平面碰撞体,然后利用射线检测就可以得到准心的位置;

Cocos 3.0 3D物理系统
image.png

静态平面只是用来做射线检测,给它专门建立一个分组,并且不与箭、苹果等等物体进行检测,这是最通用的性能优化方法

Cocos 3.0 3D物理系统
image.png

调用射线检测方法时,设置传入掩码为仅和静态平面检测,即 0b10(二进制表示法)。

Cocos 3.0 3D物理系统
image.png

注:这里传入了mask参数,代码注释中描述得并不清楚:@param mask 掩码,默认为 0xffffffff。实际上,mask参数是指要检测的物理类型,比如此例中的RaycastPlane的index是1,即第2位,就要传0b10

易误点:

  • 分不清刚体组件上的分组和节点上的层。这两者的概念类似,但是使用者不同,分组的使用者是物理模块,层的使用者是渲染模块
  • 对掩码的理解不到位,不知传何值。这里提供一个小技巧,以一个能够筛选出Others的掩码举例,首先Others的index值为2,哪么只要让二进制掩码从右往左的顺序第2位为1,就能让Others通过筛选,也就是ob100(这里强烈建议不要随便更改分组的索引)
  • 误认为射线检测接口的返回值是击中的数据。获取结果有专门的接口,此处设计是为了强调这是个复用对象。为了减少垃圾内存,每次调用接口只会更新它们的数据,而不是重新生成新的(若需要持久记录,哪么可以克隆一份)
3.网格碰撞器组件(MeshCollider)
Cocos 3.0 3D物理系统
image.png
  • mesh 网格碰撞器引用的网格资源,用于初始化网格碰撞体
  • convex 是否使用网格的凸包近似,网格顶点数应尽量小于255(通过它可以支持任意凸类碰撞体和动力学刚体)

注:cannon.js对网格碰撞器组件支持程度很差,只允许与球碰撞器产生检测。 注:convex功能目前仅ammo.js后端支持。

4.射击苹果——静态网格、凸包、多步模拟(步长调整)
Cocos 3.0 3D物理系统
8v773-kzyln.gif

一般的苹果都带有凹面,处理好凹类或带连续平滑不规则曲面的模型都非常棘手,这是因为目前成熟的理论和技术都建立在离散、凸包的世界之上(微积分中用差分近似表示微分就是最典型的范例)。

在实时物理引擎中,对于这类物体只能支持到静态或运动学类型的刚体层级,对于动力学就束手无策了。然而不幸的是,真实的苹果运动表现强烈依赖动力学,这种情况只能给苹果填加凸包形式的网格碰撞体(需将 convex 勾选上),再加上一个动力学刚体,用近似物体去参与模拟

运动表现与模拟参数有非常大的关系,穿透是最具有代表性的现象,这可以通过缩减步长和增加步数来实现,调整步长有个小技巧:输入分式,即 1/Frame,其中 Frame 表示帧率

Cocos 3.0 3D物理系统
image.png

易误点:

  • 在带有未勾选 convex 的网格碰撞器上添加了的动力学刚体,与其它物体产生了穿透现象,或者说完全没有反应,这是典型的错误使用,只有勾上 convex 的才能支持动力学刚体

  • 对一个顶点数极多的模型开启了 convex,过多的顶点数会使凸包的面数增多,这对性能有很大的影响,而且实际上并不需要面数特别多的凸包,一般建议模型的顶点数应小于 255

  • 开启凸包后,模型的凹面处的接触不贴近,这是正常现象,现在的实时技术是将模型用多个凸包组合来解决,如下图所示

    Cocos 3.0 3D物理系统
    image.png
  • 只调整了步长,但未调整步数,这两者需要相互配合才有效果。小技巧是,步数可以随意设置较大的值,步长根据最大的速度值进行调整,值越大,步长应当越小

九、小车案例
Cocos 3.0 3D物理系统
image.png

上图结构也是通过真实车的结构简化而来的,设计好结构后,还需要调整每个部分的属性:

重心: 车的重心应该要低一些,否则可能会很容易翻车;

车身和车轮:车辆运动应该是很平稳的,可以把摩擦力系数都设置为 0,另外车轮要比车身低一些,这样在碰到障碍物后车辆会有晃动的效果,用来模拟避震;

挡板:因为车身摩檫力设置为 0 了,为了防止车滑起来,加一个摩檫力不为 0 的挡板;

刚体:默认质量为 10,这里可以改成 200;因为摩檫力都为 0,避免车一直滑动,将阻力(damping)设置为 0.9;角速度因子 x 轴向设置成 0.5,减低车在 x 轴向的旋转抖动。

十、关节

cocos creator 3D 3D怎么使用关节组件嘞?还是说没有丫,小白太难了

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。