基于 PhysX 的 UE4 物理系统原理机制源码剖析

Viewed 5

说明

  • UE4 的物理系统包括 PhysX 和 Chaos,其中 PhysX 主要负责物理模拟部分(运动和碰撞等),Chaos 专注于破碎。 UE5 废弃了 PhysX ,所有物理模拟和破碎均用 Chaos 实现。
  • 本文主要对基于 PhysX 的 UE4 物理系统的原理机制源码进行分析、总结、记录和分享,包括但不限于基于 PhysX 物理系统的基础知识、在 UE4 里的配置和调用等及各自的源码解析。
  • 本文的另一个重要目的在于,希望能通过对相关原理机制和源码的剖析,对相关系统有更好的了解,最终能借此解决项目中的实际问题和需求。
  • 本文参阅了部分网上技术资料,尤其是 NVIDIA® 的 PhysX® SDK 文档(3.3.4版),感恩。部分链接放在文末,欢迎参考。

环境和调试

  • 欲要对基于 PhysX 的 UE4 物理系统进行分析或调试,最好先把环境准备好。因为 UE4 使用的 PhysX 是以库的形式存在的,默认情况下无法直接进入 PhysX SDK 源码调试。另一方面,可能有时候还需要进行可视化的调试分析。
  • 相关技术、工具和教程等,可以参考我的另一篇文章:UE4 物理系统的调试,此处不再赘述。主要是 PhysX 物理库的编译、调试及基于 PVD 对 PhysX 进行可视化调试。

PhysX

说明

  • 先介绍 PhysX 物理基础知识,主要是跟 UE4 关联比较密切的部分,更多可参考 PhysX SDK 文档(见附录)。

刚体(Rigid Body)

  • PhysX 使用分层刚体对象/参与者模型


ObjectModel.png

  • PxBase
  • 反射/查询对象类型。
  • PxActor
  • 继承于 PxBase,Actor 名称、actor 标志、主导地位(dominance)、clients、聚合(aggregates)、查询世界边界。
  • PxRigidActor
  • 继承于 PxActor,形状和变换。
  • PxRigidBody
  • 继承于 PxRigidActor,质量、惯性、速度、body 标志。
  • PxRigidStatic
  • 继承于 PxRigidActor,场景中静态物体的接口。 这种物体具有隐含的无限质量/惯性。
  • PxRigidDynamic
  • 继承于 PxRigidBody,场景中动态刚体的接口。 引入了对运动目标和对象休眠的支持。
  • PxArticulationLink
  • 继承于 PxRigidBody,PxArticulation 中动态刚体链接的接口。 引入了对查询关节和相邻链接的支持。
  • PxArticulation
  • 继承于 PxBase,定义 PxArticulation 的接口。 有效地包含引用多个 PxArticualtionLink 刚体。
  • 刚体管道涉及的主要类型之间的关系


RigidBodyOverview.png

几何体(Geometry)

  • 几何图形用于构建刚体的形状、碰撞触发器以及 PhysX 场景查询系统中的体积。PhysX 还提供独立功能,用于测试几何体之间的相交、针对它们进行光线投射以及将一个几何体扫过另一个几何体。
  • 几何图形是值类型,继承自公共基类 PxGeometry。每个几何类都定义具有固定位置和方向的体积或表面。变换(transform )指定解释几何图形的框架。对于平面和胶囊几何类型,PhysX 提供了辅助函数来根据常见的替代表示构建这些变换。
  • 几何形状分为两类:
  • 基元(PxBoxGeometry、PxSphereGeometry、PxCapsuleGeometry、PxPlaneGeometry),其中几何对象包含所有数据
  • 网格或高度场(PxConvexMeshGeometry、PxTriangleMeshGeometry、PxHeightFieldGeometry),其中几何对象包含指向更大对象的指针(分别为 PxConvexMesh、PxTriangleMesh、PxHeightField)。可以在引用它们的每个 PxGeometry 类型中使用具有不同比例的这些对象。较大的物体必须使用 cooking 过程来创建。
  • 几何类型
  • Spheres 球体
  • PxSphereGeometry 由一个属性(其半径)指定,并以原点为中心。


GeomTypeSphere.png

  • Capsules 胶囊体
  • PxCapsuleGeometry 以原点为中心。它由半径和半高值指定,其轴沿正负 X 轴延伸。


GeomTypeCapsule.png

  • Boxes 盒子
  • 一个 PxBoxGeometry 有三个属性,这三个属性的长度是边长的一半。


GeomTypeBox.png

  • Planes 平面
  • 平面将空间分为“上方”和“下方”。平面“下方”的所有物体都会与其碰撞。


GeomTypePlane.png

  • Convex Meshes 凸网格


GeomTypeConvex.png

  • 如果在一个形状内给定任意两点,该形状包含它们之间的连线,则该形状是凸的。PxConvexMesh是一个凸多面体,由一组顶点和多边形面表示。在PhysX中,凸网格的顶点数和面数限制为255。
  • 创建 PxConvexMesh 需要 cooking
  • Triangle Meshes 三角形网格


GeomTypeMesh.png

  • 与图形三角形网格一样,碰撞三角形网格由顶点和三角形索引的集合组成。三角形网格创建需要使用 cooking 库。
  • Height Fields 高度场


GeomTypeHeightField.png

  • 高度字段的局部空间轴为:
  • Row - X axis
  • Column - Z axis
  • Height - Y axis
  • 标志和材质指的是样本点下方和右侧的单元格,并指示沿哪条对角线将其分割成三角形,以及这些三角形的材料。特殊的预定义材质 PxHeightFieldMaterial::eHOLE 指定高度字段中的孔。有关更多详细信息,请参阅 PxHeightFieldSample 的参考文档。

关节(Joint)

  • 关节限制两个Actor相对移动的方式。关节的典型用途是对门铰链或角色的肩膀进行建模。
  • PhysX 支持六种不同的关节类型:
  • 固定(fixed )关节将方向和原点牢固地锁定在一起
  • 距离(distance)关节将原点保持在一定的距离范围内
  • 球形关节(spherical )(也称为球窝)将原点保持在一起,但允许方向自由变化。
  • 旋转关节(revolute )(也称为铰链)将框架的原点和 x 轴保持在一起,并允许围绕该公共轴自由旋转。
  • 棱柱形关节(prismatic )(也称为滑块)保持方向相同,但允许每个框架的原点沿着公共 x 轴自由滑动。
  • D6 关节是一种高度可配置的关节,允许指定各个自由度,以自由移动或锁定在一起。它可用于实现各种机械和解剖关节,但配置起来不如其他关节类型直观。
  • Fixed Joint 固定关节
  • 固定关节约束两个物体,使其约束框的位置和方向相同。


fixedJoint.png

  • Spherical Joint 球形关节
  • 球形关节将角色约束框架的原点限制为重合。


sphericalJoint.png

  • Revolute Joint 旋转关节
  • 旋转关节消除了两个物体除单个旋转自由度之外的所有自由度。两个主体旋转的轴由关节框架的公共原点及其公共 x 轴指定。理论上,沿旋转轴的所有原点都是等效的,但在实践中,当该点靠近物体最近的位置时,模拟稳定性最佳。


revoluteJoint.png

  • Prismatic Joint 棱柱形关节
  • 棱柱关节可防止所有旋转运动,但允许 actor1 的约束框架的原点沿着 actor0 的约束框架的 x 轴自由移动。棱柱关节支持两个约束框架原点之间的距离的上限和下限的单个限制


prismJoint.png

  • Distance Joint 距离关节
  • 距离关节将约束框的原点保持在一定的距离范围内。


distanceJoint.png

  • D6 Joint D6 关节
  • D6 关节是迄今为止最复杂的标准 PhysX 关节。在默认状态下,它的行为就像一个固定关节 - 也就是说,它严格固定其两个参与者的约束框架。然而,各个自由度可以被解锁以允许围绕x轴、y轴和z轴的旋转以及沿这些轴的平移的任意组合。

Physx 的多线程

  • Physx 的更新主要分为2个步骤:simulate 及 fetchResult 。
  • simulate
  • 物理帧模拟计算,涉及步骤如 BroadPhase(粗测) 、Narrow Phase(精测)、Solver Stage(解算)等。
  • 部分步骤对应的 PhysX API 如下
  • BroadPhase
  • physx::Sc::Scene::broadPhase
  • physx::Bp::SimpleAABBManager::updateAABBsAndBP
  • Narrow Phase
  • physx::Sc::Scene::rigidBodyNarrowPhase
  • Solver Stage
  • physx::Sc::Scene::solver

  • fetchResult

  • 结合 simulate 的数据 buffer 和用户更改后得到的数据 buffer,得到最终的物理模拟数据。
  • 默认情况下,PhysX 模拟是异步的。通过调用 scene->simulate(dt); 命令开始模拟。
  • 当此调用返回时,模拟步骤已在单独的线程中开始。当模拟运行时,我们仍然可以调用 API。如果这些调用影响模拟状态,则结果将被缓冲,并在模拟步骤完成时与模拟结果进行协调。
  • 要等待模拟完成,需要调用 scene->fetchResults(true);
  • fetchResults 的布尔参数表示调用是否应该等待模拟完成,或者立即返回当前完成状态。
  • 区分数据访问的两个时隙非常重要:


6qocgl7ffouoj9iuhrcrqpk94l.png

  • 在对 PxScene::fetchResults() 的调用返回之后和下一次 PxScene::simulate() 调用之前(参见下图,蓝色区域“1”)
  • 在对 PxScene::simulate() 的调用返回之后且在相应的 PxScene::fetchResults() 调用之前(参见下图,绿色区域“2”)。
  • 在第一个时隙中,模拟不运行,并且对读取或写入对象属性没有限制。例如,对象位置的更改会立即应用,下一个场景查询或模拟步骤将考虑新状态。
  • 在第二个时隙中,模拟正在运行,并在此过程中读取和更改对象的状态。用户的并发访问可能会破坏对象的状态或导致数据争用或模拟代码中的视图不一致。因此,模拟代码的对象视图受到保护,不会被 API 写入,并且模拟更新的任何属性都会被缓冲以允许 API 读取。
  • 请注意,simulate() 和 fetchResults() 是场景上的写入调用,因此在这些函数运行时访问场景中的任何对象都是非法的。

几何查询(GeometryQueries)

  • 几何查询主要有四种类型:
  • 光线投射(raycasts )(“光线投射查询”)针对几何对象测试光线。
  • 扫描(sweeps )(“扫描查询”)沿一条线移动一个几何对象以找到与另一个几何对象的第一个交点。
  • 重叠(overlaps)(“重叠查询”)确定两个几何对象是否相交。
  • 穿透深度计算(penetration depth computations)(“最小平移距离查询”,此处缩写为“MTD”)测试两个重叠的几何对象,以找到可以将它们分开最小距离的方向。
  • Raycasts 光线投射


GeomQueryRaycast.png

  • 光线投射查询沿着线段追踪点并记录与几何对象表面的交点。PhysX 支持所有几何类型的光线投射。
  • 针对 Heightfields 的光线投射
  • 高度场的处理与三角形网格不同 - 高度场始终被视为双面,这意味着将记录来自高度场表面上方和下方的光线的命中。
  • 命中法线将始终是三角形命中的法线,当厚度 <=0 时(在高度场的空间中)定向为 +y 方向,当厚度 >0 时定向为 -y 方向。
  • 未为照射高度场的光线设置 UV,并且 PxHitFlag::eUV 标志也未设置。
  • Sweeps 扫描


GeomQuerySweep.png

  • 扫描查询会在空间中追踪一个几何对象,以查找第二个几何对象上的撞击点,并在找到撞击点时报告有关撞击点的信息。PhysX 仅支持扫描查询,其中第一个几何对象(通过空间追踪的对象)是球体、盒子、胶囊或凸几何体。第二几何对象可以是任何类型。
  • 关于高度场的扫描查询
  • 高度字段被视为薄三角形表面而不是实体对象。
  • 厚度大小对初始重叠检测或影响点没有影响。
  • 对于单侧高度场,如果厚度 < 0,则命中的法线将面向 +y 局部空间方向;如果厚度 >0,则命中的法线将面向 -y。
  • 如果使用 eDOUBLE_SIDED 或 eMESH_BOTH_SIDES 标志之一,则高度字段将被视为双面。
  • 返回的碰撞法线将始终面向扫描方向。
  • eMESH_ANY 标志无效。ePRECISE_SWEEP 标志无效。
  • 使用扫描时需要注意一些陷阱
  • 由于数值精度问题,当对象的尺寸差异非常大时,可能会返回不正确的结果。
  • 由于算法不同,扫描查询可能检测到与重叠查询最初重叠的形状不同的一组形状。特别是,仅执行重叠检查不足以确定 PxHitFlag::eIGNORE_INITIAL_OVERLAP 标志的安全性。需要一致的重叠/扫描/穿透深度信息的应用程序应使用带有初始重叠测试和 PxHitFlag::eMTD 标志的扫描检查。
  • Overlaps 重叠


GeomQueryOverlap.png

  • 重叠查询只是检查两个几何对象是否重叠。其中一个几何形状必须是盒子、球体、胶囊或凸面,另一个可以是任何类型。
  • 高度场被视为按其厚度挤压的三角形表面。不与高度场表面相交但位于拉伸空间内的重叠几何图形将报告命中。
  • Penetration Depth 穿透深度


GeomQueryPenetration.png

  • 当两个对象相交时,PhysX可以计算出将对象分离所必须的最小距离和方向(这个量有时被称为MTD,表示最小平移距离,因为它是平移将形状分离的最小长度向量)。一个几何对象必须是盒子,球体,胶囊体或凸网格,而另一个可以是任何类型。

场景查询(Scene Queries)

  • PhysX 在 PxScene 中提供了对场景中的角色和附加形状执行碰撞查询的方法。查询分为三种类型:光线投射、扫描和重叠,每种查询都可以返回单个结果或多个结果。一般来说,每个查询都会遍历包含场景对象的剔除结构,使用 GeometryQuery 函数执行精确测试(请参阅几何查询),并累积结果。过滤可能发生在精确测试之前或之后。
  • 该场景使用两种不同的查询结构,一种用于 PxRigidStatic Actor,另一种用于 PxRigidBody Actor(PxRigidDynamic 和 PxArticulationLink)。这两个结构可以配置为根据所需的速度/空间特性使用不同的剔除实现(请参阅 PxPruningStructure。)
  • Raycasts 光线投射
  • PxScene::raycast() 查询使用户定义的光线与整个场景相交。raycast() 查询的最简单用例是沿着给定射线查找最近的命中
  • Sweeps 扫描
  • PxScene::sweep() 查询在几何上类似于 raycast():PxGeometry 形状从指定的初始姿势沿指定最大长度的方向 unitDir 扫描,以查找几何体与场景对象的影响点。扫描的最大距离必须在 [0, inf) 范围内,并将被限制在文件 PxScene.h 中定义的 PX_MAX_SWEEP_DISTANCE。
  • Overlaps 重叠
  • PxScene::overlap() 查询在指定形状包围的区域中搜索场景中任何重叠的对象。该区域被指定为变换后的盒子、球体、胶囊或凸几何体。

场景查询的阶段步骤

  • 场景查询分三个阶段进行:Broad phase、midphase 和 Narrow phase 。
  • Broad phase 遍历全局场景空间划分结构以找到中窄阶段的候选者。
  • midphase 遍历三角形网格和高度场内部剔除结构,以找到Broad-phase报告的网格中三角形的较小子集。
  • Narrow phase 执行精确相交测试(针对 raycast() 查询的光线测试,以及针对 swing() 和 Overlap() 查询的精确扫描形状测试或重叠测试)。
  • 要在查询中实现自定义过滤,可设置 PxQueryFlag::ePREFILTER 和/或 PxQueryFlag::ePOSTFILTER 标志以及具有所需过滤逻辑的 PxQueryFilterCallback 子类。
  • 预过滤发生在中间阶段和窄阶段之前,并允许在可能昂贵的精确碰撞测试之前有效地丢弃形状。对于三角形网格、高度场、凸面和大多数扫描,这些测试比仅涉及简单形状(例如球体、胶囊和盒子)的光线投射和重叠测试更昂贵。
  • 后过滤发生在 Narrow phase 测试之后,因此可以使用测试结果(例如 PxRaycastHit.position)来确定是否应丢弃命中。这些结果可以通过后过滤回调 (PxQueryFilterCallback::postFilter) 的 hit 输入参数来访问。使用例如 static_cast(hit),访问特定于光线投射查询的数据,对于重叠 (PxOverlapHit) 和扫描 (PxSweepHit) 也类似。

Broad-phase

  • 说明
  • PhysX 支持多种Broad-phase算法:
  • sweep-and-prune (SAP)清理和修剪 (SAP)
  • PxBroadPhaseType::eSAP 是 PhysX 3.2 之前使用的默认算法。当许多对象处于睡眠状态时,它是一个很好的通用选择,具有出色的性能。然而,当所有对象都在移动时,或者当大量对象被添加到广泛阶段或从广泛阶段中删除时,性能可能会显着下降。该算法不需要定义世界边界即可工作。
  • multi box pruning (MBP)多盒修剪(MBP)
  • PxBroadPhaseType::eMBP 是 PhysX 3.3 中引入的新算法。它是一种替代的Broad-phase算法,当所有对象都在移动或插入大量对象时,不会遇到与 eSAP 相同的性能问题。然而,当许多对象处于休眠状态时,其一般性能可能不如 eSAP,并且它需要用户定义世界边界才能工作。
  • 所需的Broad-phase算法由 PxSceneDesc 结构内的 PxBroadPhaseType 枚举控制。
  • UE 关联
  • 算法设置


7spiegiqiqqo4rj3o63hov8ihr.png


7uakn6s0ec5g3p9d2s23qav1de.png

  • 算法选择


3kc28k3kvvq5e5vlnp21pu8cpj.png

  • 算法调用
[PhysX3CHECKED_x64.dll] physx::Bp::BroadPhaseMBP::update(const unsigned int,physx::PxcScratchAllocator *,const physx::Bp::BroadPhaseUpdateData &,physx::PxBaseTask *,physx::PxBaseTask *) BpBroadPhaseMBP.cpp:3501
[PhysX3CHECKED_x64.dll] physx::Bp::SimpleAABBManager::finalizeUpdate(unsigned int,physx::PxcScratchAllocator *,physx::PxBaseTask *,physx::PxBaseTask *) BpSimpleAABBManager.cpp:2108
[PhysX3CHECKED_x64.dll] physx::Bp::FinalizeUpdateTask::runInternal() BpSimpleAABBManager.cpp:1885
[PhysX3CHECKED_x64.dll] physx::Cm::Task::run() CmTask.h:66
[UE4Editor-Engine-Win64-Debug.dll] FPhysXTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) PhysScene_PhysX.cpp:334
[UE4Editor-Engine-Win64-Debug.dll] TGraphTask<FPhysXTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886
[UE4Editor-Core-Win64-Debug.dll] FTaskThreadAnyThread::ProcessTasks() TaskGraph.cpp:1085
[UE4Editor-Core-Win64-Debug.dll] FTaskThreadAnyThread::ProcessTasksUntilQuit(int) TaskGraph.cpp:897
[UE4Editor-Core-Win64-Debug.dll] FTaskThreadBase::Run() TaskGraph.cpp:541
[UE4Editor-Core-Win64-Debug.dll] FTaskThreadAnyThread::Run() TaskGraph.cpp:985
[UE4Editor-Core-Win64-Debug.dll] FRunnableThreadWin::Run() WindowsRunnableThread.cpp:84
[UE4Editor-Core-Win64-Debug.dll] FRunnableThreadWin::GuardedRun() WindowsRunnableThread.cpp:27
[UE4Editor-Core-Win64-Debug.dll] FRunnableThreadWin::_ThreadProc(void *) WindowsRunnableThread.h:37
[kernel32.dll] <unknown> 0x00007ffe17ac7604
[ntdll.dll] <unknown> 0x00007ffe17ce26a1

连续碰撞检测(Continuous Collision Detection ,CCD)

  • 当连续碰撞检测(或 CCD)打开时,受影响的刚体将不会高速穿过其他物体(这个问题也称为隧道效应)。
  • 在 PhysX 3.3 中,在场景/场景中的所有物体上启用 CCD 应该相对高效,但即使场景中的所有物体移动相对较慢,它也会对性能产生一些影响。当物体缓慢移动时,这种额外的开销只占整个模拟时间的一小部分。随着物体速度的增加,CCD 开销也会增加,特别是当有大量高速物体靠近时。增加 CCD 遍数可能会使 CCD 更加昂贵,尽管如果不需要额外的遍数,CCD 将提前终止。

持续接触曲面(Persistent Contact Manifold ,PCM)

  • 说明
  • PhysX SDK 提供两种类型的碰撞检测:
  • 默认碰撞检测
  • 默认碰撞检测系统使用 SAT(分离轴定理)和基于距离的碰撞检测的混合来生成完全接触流形。它在一帧中生成所有潜在的接触,因此它更适合稳定的堆叠。此方法对于小接触偏移和静止偏移是稳定的,但在使用大偏移时可能无法生成正确的接触点,因为它通过平面移位来近似这些情况下的接触点。
  • Persistent Contact Manifold (PCM) 持续接触曲面 (PCM)
  • PCM 是一种完全基于距离的碰撞检测系统。当两个形状首次接触时,PCM 会产生完整的多种接触。它会回收并更新流形中前一帧中的现有接触,然后,如果形状相对于彼此移动超过阈值量或者如果接触从流形中丢失,则它会在后续帧中生成新的接触。如果由于框架中存在大量相对运动而从流形中丢弃了太多触点,则重新运行完整流形生成。这种方法在性能和内存方面非常有效。然而,由于 PCM 可能生成比默认碰撞检测更少的接触,因此在解算器迭代不足的情况下模拟高堆栈时,它可能会降低堆栈稳定性。由于这种方法是基于距离的,因此它将为任意接触偏移/静止偏移生成正确的接触点。

  • UE 关联

  • UE 中可通过 EnablePCM 开启基于 GJK 的距离碰撞检测系统。
  • 设置


3qra15l3ojp362udi399va4pjq.png


6g1stgpihh4u1sf9tkiv07eq81.png


3kh7mc4ak6el1ml5jq4f8d02tb.png

  • 调用(有截取)
[PhysX3CommonCHECKED_x64.dll] physx::Gu::gjk<physx::Gu::LocalConvex<physx::Gu::CapsuleV>,physx::Gu::LocalConvex<physx::Gu::ConvexHullV> >(const physx::Gu::LocalConvex<physx::Gu::CapsuleV> &,const physx::Gu::LocalConvex<physx::Gu::ConvexHullV> &,const __m128 &,const __m128 &,__m128 &,__m128 &,__m128 &,__m128 &) GuGJK.h:100
[PhysX3CommonCHECKED_x64.dll] intersectCapsuleConvex(const physx::PxCapsuleGeometry &,const physx::PxTransform &,const physx::Gu::ConvexMesh &,const physx::PxMeshScale &,const physx::PxTransform &,physx::PxVec3 *) GuOverlapTests.cpp:156
[PhysX3CommonCHECKED_x64.dll] GeomOverlapCallback_CapsuleConvex(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxGeometry &,const physx::PxTransform &,physx::Gu::TriggerCache *) GuOverlapTests.cpp:464
[Inlined] [PhysX3CHECKED_x64.dll] physx::Gu::overlap(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxGeometry &,const physx::PxTransform &,bool (*const (*__restrict)[8])(const physx::PxGeometry &, const physx::PxTransform &, const physx::PxGeometry &, const physx::PxTransform &, physx::Gu::TriggerCache *)) GuOverlapTests.h:116
[Inlined] [PhysX3CHECKED_x64.dll] GeomQueryAny<physx::PxOverlapHit>::geomHit(const physx::NpSceneQueries &,const physx::MultiQueryInput &,const physx::Gu::ShapeData &,const physx::PxGeometry &,const physx::PxTransform &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,unsigned int,physx::PxOverlapHit *,const float,physx::PxBounds3 *) NpSceneQueries.cpp:323
[PhysX3CHECKED_x64.dll] MultiQueryCallback<physx::PxOverlapHit>::invoke(float &,const physx::Sq::PrunerPayload &) NpSceneQueries.cpp:441
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeOverlap<physx::Gu::CapsuleAABBTest,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::Gu::CapsuleAABBTest &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:104
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::overlap(const physx::Gu::ShapeData &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:293
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxOverlapHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxOverlapHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:791
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::overlap(const physx::PxGeometry &,const physx::PxTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *) NpSceneQueries.cpp:104
[UE4Editor-Engine-Win64-Debug.dll] LowLevelOverlap(FPhysScene_PhysX &,const physx::PxGeometry &,const FTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:293
[UE4Editor-Engine-Win64-Debug.dll] <lambda_bc2b5caa79d4b1bb997e910417429f53>::operator()() SceneQuery.cpp:558

休眠

  • 当一个参与者在一段时间内不移动时,就假设它在未来也不会移动,直到有一些外力作用在它身上,使其失去平衡。在此之前,为了节省资源,不再进行模拟。这种状态称为睡眠。
  • UE 中的相关设置


image.png
UE4 的物理

初始化

场景初始化

  • 物理场景的创建
[PhysX3CHECKED_x64.dll] physx::NpScene::NpScene(const physx::PxSceneDesc &) NpScene.cpp:117
[PhysX3CHECKED_x64.dll] physx::NpPhysics::createScene(const physx::PxSceneDesc &) NpPhysics.cpp:323
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::InitPhysScene(const AWorldSettings *) PhysScene_PhysX.cpp:1970
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::FPhysScene_PhysX(const AWorldSettings *) PhysScene_PhysX.cpp:455
[UE4Editor-Engine-Win64-Debug.dll] UWorld::CreatePhysicsScene(const AWorldSettings *) World.cpp:4904
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitWorld(InitializationValues) World.cpp:1493
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::PostCreatePIEWorld(UWorld *) PlayLevel.cpp:2270
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::CreatePIEWorldByDuplication(FWorldContext &,UWorld *,FString &) PlayLevel.cpp:2257
[UE4Editor-Engine-Win64-Debug.dll] UGameInstance::InitializeForPlayInEditor(int,const FGameInstancePIEParameters &) GameInstance.cpp:289
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::CreateInnerProcessPIEGameInstance(FRequestPlaySessionParams &,const FGameInstancePIEParameters &,int) PlayLevel.cpp:2785
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::OnLoginPIEComplete_Deferred(int,bool,FString,FPieLoginStruct) PlayLevel.cpp:1502
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::CreateNewPlayInEditorInstance(FRequestPlaySessionParams &,const bool,EPlayNetMode) PlayLevel.cpp:1746
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::StartPlayInEditorSession(FRequestPlaySessionParams &) PlayLevel.cpp:2709
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::StartQueuedPlaySessionRequestImpl() PlayLevel.cpp:1103
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::StartQueuedPlaySessionRequest() PlayLevel.cpp:1015
[UE4Editor-UnrealEd-Win64-Debug.dll] UEditorEngine::Tick(float,bool) EditorEngine.cpp:1628
[UE4Editor-UnrealEd-Win64-Debug.dll] UUnrealEdEngine::Tick(float,bool) UnrealEdEngine.cpp:423
[UE4Editor-Win64-Debug.exe] FEngineLoop::Tick() LaunchEngineLoop.cpp:4915
[UE4Editor-Win64-Debug.exe] EngineTick() Launch.cpp:62
[UE4Editor-Win64-Debug.exe] GuardedMain(const wchar_t *) Launch.cpp:180
[UE4Editor-Win64-Debug.exe] LaunchWindowsStartup(HINSTANCE__ *,HINSTANCE__ *,char *,int,const wchar_t *) LaunchWindows.cpp:276
[UE4Editor-Win64-Debug.exe] WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) LaunchWindows.cpp:334
[Inlined] [UE4Editor-Win64-Debug.exe] invoke_main() 0x00007ff6663a1846
[UE4Editor-Win64-Debug.exe] __scrt_common_main_seh() 0x00007ff6663a1825
[kernel32.dll] <unknown> 0x00007ffcd55a7604
[ntdll.dll] <unknown> 0x00007ffcd68026a1
  • 物理事件注册


1caslp36jhed6d8aar6pmpgrjs.png

  • 高度场的场景查询函数的注册
[PhysX3CommonCHECKED_x64.dll] physx::Gu::registerHeightFields() GuOverlapTests.cpp:697
[PhysX3CHECKED_x64.dll] PxRegisterHeightFields(physx::PxPhysics &) NpPhysics.cpp:863
[UE4Editor-PhysicsCore-Win64-Debug.dll] InitGamePhysCore() PhysicsInitialization.cpp:83
[UE4Editor-Engine-Win64-Debug.dll] InitGamePhys() PhysLevel.cpp:268
[UE4Editor-Win64-Debug.exe] FEngineLoop::PreInitPreStartupScreen(const wchar_t *) LaunchEngineLoop.cpp:2459
[UE4Editor-Win64-Debug.exe] FEngineLoop::PreInit(const wchar_t *) LaunchEngineLoop.cpp:3649
[UE4Editor-Win64-Debug.exe] EnginePreInit(const wchar_t *) Launch.cpp:42
[UE4Editor-Win64-Debug.exe] GuardedMain(const wchar_t *) Launch.cpp:132
[UE4Editor-Win64-Debug.exe] LaunchWindowsStartup(HINSTANCE__ *,HINSTANCE__ *,char *,int,const wchar_t *) LaunchWindows.cpp:276
[UE4Editor-Win64-Debug.exe] WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) LaunchWindows.cpp:334
[Inlined] [UE4Editor-Win64-Debug.exe] invoke_main() 0x00007ff6663a1846
[UE4Editor-Win64-Debug.exe] __scrt_common_main_seh() 0x00007ff6663a1825
[kernel32.dll] <unknown> 0x00007ffcd55a7604
[ntdll.dll] <unknown> 0x00007ffcd68026a1

物体初始化

  • 添加动态刚体
[Inlined] [PhysX3CHECKED_x64.dll] physx::NpFactory::addRigidDynamic(physx::PxRigidDynamic *,bool) NpFactory.cpp:164
[PhysX3CHECKED_x64.dll] physx::NpFactory::createRigidDynamic(const physx::PxTransform &) NpFactory.cpp:919
[PhysX3CHECKED_x64.dll] physx::NpPhysics::createRigidDynamic(const physx::PxTransform &) NpPhysics.cpp:430
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsInterface_PhysX::CreateActor(const FActorCreationParams &,FPhysicsActorHandle_PhysX &) PhysicsInterfacePhysX.cpp:147
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateActor_AssumesLocked(FBodyInstance *,const FTransform &) BodyInstance.cpp:1212
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateShapesAndActors() BodyInstance.cpp:1337
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::InitBodies() BodyInstance.cpp:1373
[UE4Editor-Engine-Win64-Debug.dll] FBodyInstance::InitBody(UBodySetup *,const FTransform &,UPrimitiveComponent *,FPhysScene_PhysX *,const FInitBodySpawnParams &) BodyInstance.cpp:1525
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset_Internal(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,TFunctionRef<FTransform __cdecl(int)>,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:893
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:773
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InitArticulated(FPhysScene_PhysX *) SkeletalMeshComponentPhysics.cpp:747
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::OnCreatePhysicsState() SkeletalMeshComponentPhysics.cpp:1526
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::CreatePhysicsState(bool) ActorComponent.cpp:1476
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::ExecuteRegisterEvents(FRegisterComponentContext *) ActorComponent.cpp:1536
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::RegisterComponentWithWorld(UWorld *,FRegisterComponentContext *) ActorComponent.cpp:1220
[UE4Editor-Engine-Win64-Debug.dll] AActor::IncrementalRegisterComponents(int,FRegisterComponentContext *) Actor.cpp:4620
[UE4Editor-Engine-Win64-Debug.dll] ULevel::IncrementalUpdateComponents(int,bool,FRegisterComponentContext *) Level.cpp:1127
[UE4Editor-Engine-Win64-Debug.dll] ULevel::UpdateLevelComponents(bool,FRegisterComponentContext *) Level.cpp:966
[UE4Editor-Engine-Win64-Debug.dll] UWorld::UpdateWorldComponents(bool,bool,FRegisterComponentContext *) World.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitializeActorsForPlay(const FURL &,bool,FRegisterComponentContext *) World.cpp:4302
  • 添加静态刚体
[Inlined] [PhysX3CHECKED_x64.dll] physx::NpFactory::addRigidStatic(physx::PxRigidStatic *,bool) NpFactory.cpp:159
[PhysX3CHECKED_x64.dll] physx::NpFactory::createRigidStatic(const physx::PxTransform &) NpFactory.cpp:899
[PhysX3CHECKED_x64.dll] physx::NpPhysics::createRigidStatic(const physx::PxTransform &) NpPhysics.cpp:391
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsInterface_PhysX::CreateActor(const FActorCreationParams &,FPhysicsActorHandle_PhysX &) PhysicsInterfacePhysX.cpp:137
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateActor_AssumesLocked(FBodyInstance *,const FTransform &) BodyInstance.cpp:1208
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateShapesAndActors() BodyInstance.cpp:1337
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::InitBodies() BodyInstance.cpp:1373
[UE4Editor-Engine-Win64-Debug.dll] FBodyInstance::InitBody(UBodySetup *,const FTransform &,UPrimitiveComponent *,FPhysScene_PhysX *,const FInitBodySpawnParams &) BodyInstance.cpp:1520
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::OnCreatePhysicsState() PrimitiveComponent.cpp:799
[UE4Editor-Engine-Win64-Debug.dll] UStaticMeshComponent::OnCreatePhysicsState() StaticMeshComponent.cpp:607
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::CreatePhysicsState(bool) ActorComponent.cpp:1476
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::ExecuteRegisterEvents(FRegisterComponentContext *) ActorComponent.cpp:1536
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::RegisterComponentWithWorld(UWorld *,FRegisterComponentContext *) ActorComponent.cpp:1220
[UE4Editor-Engine-Win64-Debug.dll] AActor::IncrementalRegisterComponents(int,FRegisterComponentContext *) Actor.cpp:4580
[UE4Editor-Engine-Win64-Debug.dll] ULevel::IncrementalUpdateComponents(int,bool,FRegisterComponentContext *) Level.cpp:1127
[UE4Editor-Engine-Win64-Debug.dll] ULevel::UpdateLevelComponents(bool,FRegisterComponentContext *) Level.cpp:966
[UE4Editor-Engine-Win64-Debug.dll] UWorld::UpdateWorldComponents(bool,bool,FRegisterComponentContext *) World.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitializeActorsForPlay(const FURL &,bool,FRegisterComponentContext *) World.cpp:4302
  • 添加Actor
[PhysX3CHECKED_x64.dll] physx::NpAggregate::addActor(physx::PxActor &) NpAggregate.cpp:169
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsInterface_PhysX::AddActorToAggregate_AssumesLocked(const FPhysicsAggregateHandle_PhysX &,const FPhysicsActorHandle_PhysX &) PhysicsInterfacePhysX.cpp:795
[UE4Editor-Engine-Win64-Debug.dll] <lambda_06cbaf345d4feb383967480364227d85>::operator()() BodyInstance.cpp:1386
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefCaller<<lambda_06cbaf345d4feb383967480364227d85>,void __cdecl(void)>::Call(void *) Function.h:548
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefBase<UE4Function_Private::FFunctionRefStoragePolicy,void __cdecl(void)>::operator()() Function.h:676
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsCommand_PhysX::ExecuteWrite(FPhysScene_PhysX *,TFunctionRef<void __cdecl(void)>) PhysicsInterfacePhysX.cpp:662
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::InitBodies() BodyInstance.cpp:1375
[UE4Editor-Engine-Win64-Debug.dll] FBodyInstance::InitBody(UBodySetup *,const FTransform &,UPrimitiveComponent *,FPhysScene_PhysX *,const FInitBodySpawnParams &) BodyInstance.cpp:1525
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset_Internal(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,TFunctionRef<FTransform __cdecl(int)>,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:893
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:773
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InitArticulated(FPhysScene_PhysX *) SkeletalMeshComponentPhysics.cpp:747
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::OnCreatePhysicsState() SkeletalMeshComponentPhysics.cpp:1526
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::CreatePhysicsState(bool) ActorComponent.cpp:1476
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::ExecuteRegisterEvents(FRegisterComponentContext *) ActorComponent.cpp:1536
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::RegisterComponentWithWorld(UWorld *,FRegisterComponentContext *) ActorComponent.cpp:1220
[UE4Editor-Engine-Win64-Debug.dll] AActor::IncrementalRegisterComponents(int,FRegisterComponentContext *) Actor.cpp:4620
[UE4Editor-Engine-Win64-Debug.dll] ULevel::IncrementalUpdateComponents(int,bool,FRegisterComponentContext *) Level.cpp:1127
[UE4Editor-Engine-Win64-Debug.dll] ULevel::UpdateLevelComponents(bool,FRegisterComponentContext *) Level.cpp:966
[UE4Editor-Engine-Win64-Debug.dll] UWorld::UpdateWorldComponents(bool,bool,FRegisterComponentContext *) World.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitializeActorsForPlay(const FURL &,bool,FRegisterComponentContext *) World.cpp:4302
  • 附加图元
[PhysX3CHECKED_x64.dll] physx::NpShapeManager::attachShape(physx::NpShape &,physx::PxRigidActor &) NpShapeManager.cpp:92
[PhysX3CHECKED_x64.dll] physx::NpRigidActorTemplate<physx::PxRigidDynamic>::attachShape(physx::PxShape &) NpRigidActorTemplate.h:230
[PhysX3CHECKED_x64.dll] physx::NpRigidBodyTemplate<physx::PxRigidDynamic>::attachShape(physx::PxShape &) NpRigidBodyTemplate.h:216
[UE4Editor-Engine-Win64-Debug.dll] <lambda_667a34fe2dd88abed1dc5723c1de9620>::operator()(const physx::PxGeometry &,const physx::PxTransform &,const float,const float,const FPhysxUserData *,PxFlags<enum physx::PxShapeFlag::Enum,unsigned char>) PhysicsInterfacePhysX.cpp:869
[UE4Editor-Engine-Win64-Debug.dll] <lambda_9dc3437864dc8927c368aad4e5aecaa8>::operator()(const FKShapeElem &,const physx::PxGeometry &,const physx::PxTransform &,float,float) PhysicsInterfacePhysX.cpp:878
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefCaller<<lambda_9dc3437864dc8927c368aad4e5aecaa8>,void __cdecl(FKBoxElem const &,physx::PxBoxGeometry const &,physx::PxTransform const &,float,float)>::Call(void *,const FKBoxElem &,const physx::PxBoxGeometry &,const physx::PxTransform &,float &,float &) Function.h:548
[UE4Editor-Engine-Win64-Debug.dll] FBodySetupShapeIterator::ForEachShape<FKBoxElem,physx::PxBoxGeometry>(const TArrayView<FKBoxElem,int> &,TFunctionRef<void __cdecl(FKBoxElem const &,physx::PxBoxGeometry const &,physx::PxTransform const &,float,float)>) PhysicsGeometry.cpp:83
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsInterface_PhysX::AddGeometry(const FPhysicsActorHandle_PhysX &,const FGeometryAddParams &,TArray<FPhysicsShapeHandle_PhysX,TSizedDefaultAllocator<32> > *) PhysicsInterfacePhysX.cpp:901
[UE4Editor-Engine-Win64-Debug.dll] UBodySetup::AddShapesToRigidActor_AssumesLocked(FBodyInstance *,FVector &,UPhysicalMaterial *,TArray<UPhysicalMaterial *,TSizedDefaultAllocator<32> > &,TArray<FPhysicalMaterialMaskParams,TSizedDefaultAllocator<32> > &,const FBodyCollisionData &,const FTransform &,TArray<FPhysicsShapeHandle_PhysX,TSizedDefaultAllocator<32> > *) BodySetup.cpp:919
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateShapes_AssumesLocked(FBodyInstance *) BodyInstance.cpp:1241
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::CreateShapesAndActors() BodyInstance.cpp:1338
[UE4Editor-Engine-Win64-Debug.dll] FInitBodiesHelperBase::InitBodies() BodyInstance.cpp:1373
[UE4Editor-Engine-Win64-Debug.dll] FBodyInstance::InitBody(UBodySetup *,const FTransform &,UPrimitiveComponent *,FPhysScene_PhysX *,const FInitBodySpawnParams &) BodyInstance.cpp:1525
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset_Internal(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,TFunctionRef<FTransform __cdecl(int)>,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:893
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InstantiatePhysicsAsset(const UPhysicsAsset &,const FVector &,TArray<FBodyInstance *,TSizedDefaultAllocator<32> > &,TArray<FConstraintInstance *,TSizedDefaultAllocator<32> > &,FPhysScene_PhysX *,USkeletalMeshComponent *,int,const FPhysicsAggregateHandle_PhysX &) SkeletalMeshComponentPhysics.cpp:773
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::InitArticulated(FPhysScene_PhysX *) SkeletalMeshComponentPhysics.cpp:747
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::OnCreatePhysicsState() SkeletalMeshComponentPhysics.cpp:1526
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::CreatePhysicsState(bool) ActorComponent.cpp:1476
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::ExecuteRegisterEvents(FRegisterComponentContext *) ActorComponent.cpp:1536
[UE4Editor-Engine-Win64-Debug.dll] UActorComponent::RegisterComponentWithWorld(UWorld *,FRegisterComponentContext *) ActorComponent.cpp:1220
[UE4Editor-Engine-Win64-Debug.dll] AActor::IncrementalRegisterComponents(int,FRegisterComponentContext *) Actor.cpp:4620
[UE4Editor-Engine-Win64-Debug.dll] ULevel::IncrementalUpdateComponents(int,bool,FRegisterComponentContext *) Level.cpp:1127
[UE4Editor-Engine-Win64-Debug.dll] ULevel::UpdateLevelComponents(bool,FRegisterComponentContext *) Level.cpp:966
[UE4Editor-Engine-Win64-Debug.dll] UWorld::UpdateWorldComponents(bool,bool,FRegisterComponentContext *) World.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitializeActorsForPlay(const FURL &,bool,FRegisterComponentContext *) World.cpp:4302

更新

主流程


6su4j059bmhj8kei1tb4jblgrv.png
关键接口类为 FPhysScene_PhysX ,引擎通过其与 PhysX 交互。 通过引擎 tick (UWorld::Tick),调用 UWorld::RunTickGroup 执行各组物理更新 (如 TG_StartPhysics 、TG_DuringPhysics 等)。 * 见:LevelTick.cpp


5bj2ioeaiumlllm2chhkp2n2i9.png
关键步骤有 FStartPhysicsTickFunction::ExecuteTick 中通过 UWorld::StartPhysicsSim 触发的 FPhysScene_PhysX::StartFrame (其中主要执行 FPhysScene_PhysX::TickPhysScene (物理模拟主要接口))、FPhysScene_PhysX::WaitPhysScenes、FPhysScene_PhysX::SubstepSimulation (为避免更新阻塞而创建的子任务,可选开启)、FPhysScene_PhysX::ProcessPhysScene((fetchResults,刷新物理数据缓存) ) 及 UWorld::FinishPhysicsSim 执行的 FPhysScene_PhysX::EndFrame (再次 fetchResults 等)。 触发堆栈(部分)

[UE4Editor-Engine-Win64-Debug.dll] FTickFunctionTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TickTaskManager.cpp:284
[UE4Editor-Engine-Win64-Debug.dll] TGraphTask<FTickFunctionTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886

FPhysScene_PhysX::StartFrame


3lli66skmc0eg8bd9p3eggbkof.png

  • FPhysScene_PhysX::StartFrame 主要由引擎 tick FStartPhysicsTickFunction::ExecuteTick 触发,其主要调用 FPhysScene_PhysX::TickPhysScene
  • FPhysScene_PhysX::TickPhysScene 主要执行 UpdateKinematicsOnDeferredSkelMeshes 和 FPhysicsReplication::Tick
  • FPhysScene_PhysX::UpdateKinematicsOnDeferredSkelMeshes 处理任何延迟骨架网格物体的运动学更新
  • FPhysicsReplication::Tick 主要执行物理模拟,通过 FPhysicsReplication::OnTick 最终调用 nvidia::apex::ApexScene 的 simulate 和 physx::NpScene 的 simulateOrCollide
  • 这些 simulate 会通过各种 physx::Cm::Task 执行各种 Phase,如: physx::Sc::Scene::broadPhase (粗测)、physx::Sc::Scene::rigidBodyNarrowPhase (细测)及 physx::Sc::Scene::solver (解算)等。

FPhysScene_PhysX::ProcessPhysScene


2u4bsu2p1crfbefllb8bani04i.png

  • 通过 FPhysScene_PhysX::WaitPhysScenes 或 FTickTaskSequencer::ReleaseTickGroup (引擎 tick )触发 FPhysScene_PhysX::ProcessPhysScene - 通过 SyncComponentsToBodies_AssumesLocked 将场景中的组件同步到已更改的物理体。
  • 调用 ApexScene::fetchResults 、NpScene::fetchResults ,检查场景是否已完成模拟(可以选择阻止完成)。 更新 Actors 和 PxScene 的新状态。 如果模拟完成则返回 true。

FPhysScene_PhysX::EndFrame


2a9hic7vonb1qk260ialk6ahni.png

  • 在引擎 tick 的 FEndPhysicsTickFunction 中,通过 UWorld::FinishPhysicsSim 调用 FPhysScene_PhysX::EndFrame 。
  • FPhysScene_PhysX::EndFrame 中主要调用 FPhysScene_PhysX::DispatchPhysNotifications_AssumesLocked 派发各种物理事件,如 DispatchPhysicsCollisionHit 、DispatchWakeEvents、DispatchOnBroken 等。

SubstepSimulation 的更新流程


7u5s7jsluuvkpouf5sq09guhdc.png

  • substep simulation 主要目的在于在渲染帧数较低时通过substep进行多次物理tick达到追帧目的。
  • 默认关闭,可通过 ProjectSetting -> Engine -> Substepping 开启


7kjbb7vf5p1d4qn484thuml6oa.png

  • 主要异步调用 FPhysSubstepTask::StepSimulation 执行物理模拟(底层也是调用物理 simulate 和 fetchResults 等)

物理查询流程

  • UE 主要通过 SceneQueryLowLevel.cpp 与 PhysX 进行交互 (或者说调用 PhysX API 进行物理查询)
  • 注:此处堆栈未显示最底层,忽略了 PhysX 侧的部分更底层的调用。
  • Raycast
  • 接口为 SceneQueryLowLevel.cpp 的 LowLevelRaycast
  • 例:UWorld::LineTraceSingleByObjectType
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeRaycast<0,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::PxVec3 &,const physx::PxVec3 &,float &,const physx::PxVec3 &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:233
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::raycast(const physx::PxVec3 &,const physx::PxVec3 &,float &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:353
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxRaycastHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxRaycastHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:780
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::raycast(const physx::PxVec3 &,const physx::PxVec3 &,const float,physx::PxHitCallback<physx::PxRaycastHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,const physx::PxQueryCache *) NpSceneQueries.cpp:90
[UE4Editor-Engine-Win64-Debug.dll] LowLevelRaycast(FPhysScene_PhysX &,const FVector &,const FVector &,float,physx::PxHitCallback<physx::PxRaycastHit> &,EHitFlags,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:218
[UE4Editor-Engine-Win64-Debug.dll] TSQTraits<physx::PxRaycastHit,0,0>::SceneTrace<FRaycastSQAdditionalInputs,0>(FPhysScene_PhysX &,const FRaycastSQAdditionalInputs &,const FVector &,float,const FTransform &,PhysXInterface::FSingleHitBuffer<physx::PxRaycastHit> &,EHitFlags,EQueryFlags,const FCollisionFilterData &,const FCollisionQueryParams &,ICollisionQueryFilterCallbackBase *) SceneQuery.cpp:169
[UE4Editor-Engine-Win64-Debug.dll] TSceneCastCommon<TSQTraits<physx::PxRaycastHit,0,0>,FRaycastSQAdditionalInputs>(const UWorld *,FHitResult &,const FRaycastSQAdditionalInputs &,FVector,FVector,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:364
[UE4Editor-Engine-Win64-Debug.dll] FGenericPhysicsInterface::RaycastSingle(const UWorld *,FHitResult &,FVector,FVector,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:437
[UE4Editor-Engine-Win64-Debug.dll] UWorld::LineTraceSingleByObjectType(FHitResult &,const FVector &,const FVector &,const FCollisionObjectQueryParams &,const FCollisionQueryParams &) WorldCollision.cpp:167
[UE4Editor-Engine-Win64-Debug.dll] UKismetSystemLibrary::LineTraceSingleForObjects(const UObject *,FVector,FVector,const TArray<TEnumAsByte<enum EObjectTypeQuery>,TSizedDefaultAllocator<32> > &,bool,const TArray<AActor *,TSizedDefaultAllocator<32> > &,Type,FHitResult &,bool,FLinearColor,FLinearColor,float) KismetSystemLibrary.cpp:1605
  • Sweep
  • 接口为 SceneQueryLowLevel.cpp 的 LowLevelSweep
  • 例:UWorld::SweepSingleByChannel
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeRaycast<1,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::PxVec3 &,const physx::PxVec3 &,float &,const physx::PxVec3 &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:233
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::sweep(const physx::Gu::ShapeData &,const physx::PxVec3 &,float &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:337
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxSweepHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxSweepHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:810
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::sweep(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxVec3 &,const float,physx::PxHitCallback<physx::PxSweepHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,const physx::PxQueryCache *,const float) NpSceneQueries.cpp:145
[UE4Editor-Engine-Win64-Debug.dll] LowLevelSweep(FPhysScene_PhysX &,const physx::PxGeometry &,const FTransform &,const FVector &,float,physx::PxHitCallback<physx::PxSweepHit> &,EHitFlags,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:257
[UE4Editor-Engine-Win64-Debug.dll] TSceneCastCommon<TSQTraits<physx::PxSweepHit,1,0>,FGeomSQAdditionalInputs>(const UWorld *,FHitResult &,const FGeomSQAdditionalInputs &,FVector,FVector,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:364
[UE4Editor-Engine-Win64-Debug.dll] FGenericPhysicsInterface::GeomSweepSingle(const UWorld *,const FCollisionShape &,const FQuat &,FHitResult &,FVector,FVector,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:473
[UE4Editor-Engine-Win64-Debug.dll] UWorld::SweepSingleByChannel(FHitResult &,const FVector &,const FVector &,const FQuat &,ECollisionChannel,const FCollisionShape &,const FCollisionQueryParams &,const FCollisionResponseParams &) WorldCollision.cpp:113
  • 例:UWorld::ComponentSweepMulti
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeRaycast<1,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::PxVec3 &,const physx::PxVec3 &,float &,const physx::PxVec3 &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:233
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::sweep(const physx::Gu::ShapeData &,const physx::PxVec3 &,float &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:337
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxSweepHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxSweepHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:810
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::sweep(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxVec3 &,const float,physx::PxHitCallback<physx::PxSweepHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,const physx::PxQueryCache *,const float) NpSceneQueries.cpp:145
[UE4Editor-Engine-Win64-Debug.dll] LowLevelSweep(FPhysScene_PhysX &,const physx::PxGeometry &,const FTransform &,const FVector &,float,physx::PxHitCallback<physx::PxSweepHit> &,EHitFlags,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:257
[UE4Editor-Engine-Win64-Debug.dll] TSceneCastCommon<TSQTraits<physx::PxSweepHit,1,1>,FGeomCollectionSQAdditionalInputs>(const UWorld *,TArray<FHitResult,TSizedDefaultAllocator<32> > &,const FGeomCollectionSQAdditionalInputs &,FVector,FVector,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:364

  • Overlap
  • 接口为 SceneQueryLowLevel.cpp 的 LowLevelOverlap
  • 例:UWorld::OverlapBlockingTestByChannel
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeOverlap<physx::Gu::CapsuleAABBTest,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::Gu::CapsuleAABBTest &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:119
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::overlap(const physx::Gu::ShapeData &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:293
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxOverlapHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxOverlapHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:796
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::overlap(const physx::PxGeometry &,const physx::PxTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *) NpSceneQueries.cpp:104
[UE4Editor-Engine-Win64-Debug.dll] LowLevelOverlap(FPhysScene_PhysX &,const physx::PxGeometry &,const FTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:293
[UE4Editor-Engine-Win64-Debug.dll] <lambda_bc2b5caa79d4b1bb997e910417429f53>::operator()() SceneQuery.cpp:558

物理事件的执行流程

  • 举例对物理事件的执行流程做说明

OnComponentBeginOverlap

  • 说明
  • 以球掉到人身上触发 OnComponentBeginOverlap 事件为例,说明相关物理事件的执行流程
  • 流程
  • 注册
  • 注册对应的检测算法(非触发事件)
[PhysX3CommonCHECKED_x64.dll] physx::Gu::getOverlapFuncTable() GuOverlapTests.cpp:686
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::NpSceneQueries(const physx::PxSceneDesc &) NpScene.cpp:102
[PhysX3CHECKED_x64.dll] physx::NpScene::NpScene(const physx::PxSceneDesc &) NpScene.cpp:145
[PhysX3CHECKED_x64.dll] physx::NpPhysics::createScene(const physx::PxSceneDesc &) NpPhysics.cpp:323
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::InitPhysScene(const AWorldSettings *) PhysScene_PhysX.cpp:1970
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::FPhysScene_PhysX(const AWorldSettings *) PhysScene_PhysX.cpp:455
[UE4Editor-Engine-Win64-Debug.dll] UWorld::CreatePhysicsScene(const AWorldSettings *) World.cpp:4904
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitWorld(InitializationValues) World.cpp:1493
  • 基于 ComponentOverlapMulti 拿到 TArray Overlaps 放到 OverlapMultiResult ,底层会调用 GeomOverlapCallback_SphereCapsule 去执行 sphere 和 capsule 的 overlap 算法判定。
[PhysX3CommonCHECKED_x64.dll] GeomOverlapCallback_SphereCapsule(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxGeometry &,const physx::PxTransform &,physx::Gu::TriggerCache *) GuOverlapTests.cpp:252
[Inlined] [PhysX3CHECKED_x64.dll] physx::Gu::overlap(const physx::PxGeometry &,const physx::PxTransform &,const physx::PxGeometry &,const physx::PxTransform &,bool (*const (*__restrict)[8])(const physx::PxGeometry &, const physx::PxTransform &, const physx::PxGeometry &, const physx::PxTransform &, physx::Gu::TriggerCache *)) GuOverlapTests.h:116
[Inlined] [PhysX3CHECKED_x64.dll] GeomQueryAny<physx::PxOverlapHit>::geomHit(const physx::NpSceneQueries &,const physx::MultiQueryInput &,const physx::Gu::ShapeData &,const physx::PxGeometry &,const physx::PxTransform &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,unsigned int,physx::PxOverlapHit *,const float,physx::PxBounds3 *) NpSceneQueries.cpp:323
[PhysX3CHECKED_x64.dll] MultiQueryCallback<physx::PxOverlapHit>::invoke(float &,const physx::Sq::PrunerPayload &) NpSceneQueries.cpp:441
[PhysX3CHECKED_x64.dll] physx::Sq::AABBTreeOverlap<physx::Gu::SphereAABBTest,physx::Sq::AABBTree,physx::Sq::AABBTreeRuntimeNode>::operator()(const physx::Sq::PrunerPayload *,const physx::PxBounds3 *,const physx::Sq::AABBTree &,const physx::Gu::SphereAABBTest &,physx::Sq::PrunerCallback &) SqAABBTreeQuery.h:104
[PhysX3CHECKED_x64.dll] physx::Sq::AABBPruner::overlap(const physx::Gu::ShapeData &,physx::Sq::PrunerCallback &) SqAABBPruner.cpp:300
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::multiQuery<physx::PxOverlapHit>(const physx::MultiQueryInput &,physx::PxHitCallback<physx::PxOverlapHit> &,PxFlags<enum physx::PxHitFlag::Enum,unsigned short>,const physx::PxQueryCache *,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *,physx::BatchQueryFilterData *) NpSceneQueries.cpp:796
[PhysX3CHECKED_x64.dll] physx::NpSceneQueries::overlap(const physx::PxGeometry &,const physx::PxTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,const physx::PxQueryFilterData &,physx::PxQueryFilterCallback *) NpSceneQueries.cpp:104
[UE4Editor-Engine-Win64-Debug.dll] LowLevelOverlap(FPhysScene_PhysX &,const physx::PxGeometry &,const FTransform &,physx::PxHitCallback<physx::PxOverlapHit> &,FQueryFlags,const FCollisionFilterData &,const physx::PxQueryFilterData &,ICollisionQueryFilterCallbackBase *,const FQueryDebugParams &) SceneQueryLowLevel.cpp:293
[UE4Editor-Engine-Win64-Debug.dll] <lambda_a725cc02b6caf158ec4730b42e003b90>::operator()() SceneQuery.cpp:558
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefCaller<<lambda_a725cc02b6caf158ec4730b42e003b90>,void __cdecl(void)>::Call(void *) Function.h:548
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefBase<UE4Function_Private::FFunctionRefStoragePolicy,void __cdecl(void)>::operator()() Function.h:676
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsCommand_PhysX::ExecuteRead(FPhysScene_PhysX *,TFunctionRef<void __cdecl(void)>) PhysicsInterfacePhysX.cpp:604
[UE4Editor-Engine-Win64-Debug.dll] GeomOverlapMultiImp<0,FPhysicsGeometryCollection_PhysX>(const UWorld *,const physx::PxGeometry &,const FPhysicsGeometryCollection_PhysX &,const FTransform &,TArray<FOverlapResult,TSizedDefaultAllocator<32> > &,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:552
[UE4Editor-Engine-Win64-Debug.dll] FGenericPhysicsInterface::GeomOverlapMulti<FPhysicsGeometryCollection_PhysX>(const UWorld *,const FPhysicsGeometryCollection_PhysX &,const FVector &,const FQuat &,TArray<FOverlapResult,TSizedDefaultAllocator<32> > &,ECollisionChannel,const FCollisionQueryParams &,const FCollisionResponseParams &,const FCollisionObjectQueryParams &) SceneQuery.cpp:636
[UE4Editor-Engine-Win64-Debug.dll] <lambda_83796598905281753961d272e16af157>::operator()(const FPhysicsActorHandle_PhysX &) BodyInstance.cpp:3880


  • 注意这里还在AABB下一层,见 物理查询流程
  • 基于 OverlapMultiResult 填充 NewOverlappingComponentPtrs
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::UpdateOverlapsImpl(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) PrimitiveComponent.cpp:3258
[UE4Editor-Engine-Win64-Debug.dll] USceneComponent::UpdateOverlaps(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) SceneComponent.h:1926
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::UpdateOverlapsImpl(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) PrimitiveComponent.cpp:3360
[UE4Editor-Engine-Win64-Debug.dll] USceneComponent::UpdateOverlaps(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) SceneComponent.h:1926
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::MoveComponentImpl(const FVector &,const FQuat &,bool,FHitResult *,EMoveComponentFlags,ETeleportType) PrimitiveComponent.cpp:2390
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SyncComponentsToBodies_AssumesLocked() PhysScene_PhysX.cpp:1382
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::ProcessPhysScene() PhysScene_PhysX.cpp:1275
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SceneCompletionTask(Type,const TRefCountPtr<FGraphEvent> &) PhysScene_PhysX.cpp:1228
[UE4Editor-Engine-Win64-Debug.dll] TBaseRawMethodDelegateInstance<0,FPhysScene_PhysX,void __cdecl(enum ENamedThreads::Type,TRefCountPtr<FGraphEvent> const &),FDefaultDelegateUserPolicy>::ExecuteIfSafe(Type,const TRefCountPtr<FGraphEvent> &) DelegateInstancesImpl.h:467
[UE4Editor-Engine-Win64-Debug.dll] FDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1280

  • 基于 NewOverlappingComponentPtrs 执行 BeginComponentOverlap 最终触发业务回调
[UE4Editor-PhysTest-Win64-Debug.dll] APhysTestCharacter::OnComponentBeginOverlap(UPrimitiveComponent *,AActor *,UPrimitiveComponent *,int,bool,const FHitResult &) PhysTestCharacter.cpp:17
[UE4Editor-PhysTest-Win64-Debug.dll] APhysTestCharacter::execOnComponentBeginOverlap(UObject *,FFrame &,void *const) PhysTestCharacter.gen.cpp:47
[UE4Editor-CoreUObject-Win64-Debug.dll] UFunction::Invoke(UObject *,FFrame &,void *const) Class.cpp:5679
[UE4Editor-CoreUObject-Win64-Debug.dll] UObject::ProcessEvent(UFunction *,void *) ScriptCore.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] AActor::ProcessEvent(UFunction *,void *) Actor.cpp:863
[UE4Editor-Engine-Win64-Debug.dll] TScriptDelegate<FWeakObjectPtr>::ProcessDelegate<UObject>(void *) ScriptDelegates.h:247
[UE4Editor-Engine-Win64-Debug.dll] TMulticastScriptDelegate<FWeakObjectPtr>::ProcessMulticastDelegate<UObject>(void *) ScriptDelegates.h:493
[UE4Editor-Engine-Win64-Debug.dll] TSparseDynamicDelegate<FComponentBeginOverlapSignature_MCSignature,UPrimitiveComponent,FComponentBeginOverlapSignatureInfoGetter>::Broadcast<UPrimitiveComponent *,AActor *,UPrimitiveComponent *,enum <unnamed-enum-INDEX_NONE>,bool,FHitResult>(UPrimitiveComponent *,AActor *,UPrimitiveComponent *,(anonymous enum),bool,FHitResult) SparseDelegate.h:326
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::BeginComponentOverlap(const FOverlapInfo &,bool) PrimitiveComponent.cpp:2756
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::UpdateOverlapsImpl(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) PrimitiveComponent.cpp:3334
[UE4Editor-Engine-Win64-Debug.dll] USceneComponent::UpdateOverlaps(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) SceneComponent.h:1926
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::UpdateOverlapsImpl(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) PrimitiveComponent.cpp:3360
[UE4Editor-Engine-Win64-Debug.dll] USceneComponent::UpdateOverlaps(const TArrayView<FOverlapInfo const ,int> *,bool,const TArrayView<FOverlapInfo const ,int> *) SceneComponent.h:1926
[UE4Editor-Engine-Win64-Debug.dll] UPrimitiveComponent::MoveComponentImpl(const FVector &,const FQuat &,bool,FHitResult *,EMoveComponentFlags,ETeleportType) PrimitiveComponent.cpp:2390
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SyncComponentsToBodies_AssumesLocked() PhysScene_PhysX.cpp:1382
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::ProcessPhysScene() PhysScene_PhysX.cpp:1275
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SceneCompletionTask(Type,const TRefCountPtr<FGraphEvent> &) PhysScene_PhysX.cpp:1228
[UE4Editor-Engine-Win64-Debug.dll] TBaseRawMethodDelegateInstance<0,FPhysScene_PhysX,void __cdecl(enum ENamedThreads::Type,TRefCountPtr<FGraphEvent> const &),FDefaultDelegateUserPolicy>::ExecuteIfSafe(Type,const TRefCountPtr<FGraphEvent> &) DelegateInstancesImpl.h:467
[UE4Editor-Engine-Win64-Debug.dll] FDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1280

OnComponentHit

  • 说明
  • 以球掉到人身上触发 OnComponentHit 事件为例,说明相关物理事件的执行流程
  • 流程
  • 注册监听
  • 绑定 PSceneDesc.simulationEventCallback 到 FPhysXSimEventCallback ,其中包括 onContact 等事件回调。
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::InitPhysScene(const AWorldSettings *) PhysScene_PhysX.cpp:1865
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::FPhysScene_PhysX(const AWorldSettings *) PhysScene_PhysX.cpp:455
[UE4Editor-Engine-Win64-Debug.dll] UWorld::CreatePhysicsScene(const AWorldSettings *) World.cpp:4904
[UE4Editor-Engine-Win64-Debug.dll] UWorld::InitWorld(InitializationValues) World.cpp:1493
  • 添加到 PendingCollisionNotifies
[UE4Editor-Engine-Win64-Debug.dll] FPhysXSimEventCallback::onContact(const physx::PxContactPairHeader &,const physx::PxContactPair *,unsigned int) PhysXSupport.cpp:358
[ApexFrameworkCHECKED_x64.dll] nvidia::apex::ApexSceneUserNotify::onContact(const physx::PxContactPairHeader &,const physx::PxContactPair *,unsigned int) ApexSceneUserNotify.cpp:232
[PhysX3CHECKED_x64.dll] physx::Sc::Scene::fireQueuedContactCallbacks(bool) ScScene.cpp:4387
[Inlined] [PhysX3CHECKED_x64.dll] physx::Scb::Scene::fireQueuedContactCallbacks() ScbScene.h:265
[PhysX3CHECKED_x64.dll] physx::NpScene::fetchResults(bool,unsigned int *) NpScene.cpp:2341
[ApexFrameworkCHECKED_x64.dll] nvidia::apex::ApexScene::fetchResults(bool,unsigned int *) ApexScene.cpp:1366
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::ProcessPhysScene() PhysScene_PhysX.cpp:1266
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SceneCompletionTask(Type,const TRefCountPtr<FGraphEvent> &) PhysScene_PhysX.cpp:1228
[UE4Editor-Engine-Win64-Debug.dll] TBaseRawMethodDelegateInstance<0,FPhysScene_PhysX,void __cdecl(enum ENamedThreads::Type,TRefCountPtr<FGraphEvent> const &),FDefaultDelegateUserPolicy>::ExecuteIfSafe(Type,const TRefCountPtr<FGraphEvent> &) DelegateInstancesImpl.h:467
[UE4Editor-Engine-Win64-Debug.dll] FDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1280
[UE4Editor-Engine-Win64-Debug.dll] TGraphTask<FDelegateGraphTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886

  • 基于 PendingCollisionNotifies DispatchPhysicsCollisionHit
[UE4Editor-Engine-Win64-Debug.dll] AActor::DispatchPhysicsCollisionHit(const FRigidBodyCollisionInfo &,const FRigidBodyCollisionInfo &,const FCollisionImpactData &) Actor.cpp:4425
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::DispatchPhysNotifications_AssumesLocked() PhysScene_PhysX.cpp:1425
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::EndFrame(ULineBatchComponent *) PhysScene_PhysX.cpp:1571
[UE4Editor-Engine-Win64-Debug.dll] UWorld::FinishPhysicsSim() PhysLevel.cpp:172

  • 触发业务测的事件回调
[UE4Editor-PhysTest-Win64-Debug.dll] APhysTestCharacter::OnComponentHit(UPrimitiveComponent *,AActor *,UPrimitiveComponent *,FVector,const FHitResult &) PhysTestCharacter.cpp:38
[UE4Editor-PhysTest-Win64-Debug.dll] APhysTestCharacter::execOnComponentHit(UObject *,FFrame &,void *const) PhysTestCharacter.gen.cpp:36
[UE4Editor-CoreUObject-Win64-Debug.dll] UFunction::Invoke(UObject *,FFrame &,void *const) Class.cpp:5679
[UE4Editor-CoreUObject-Win64-Debug.dll] UObject::ProcessEvent(UFunction *,void *) ScriptCore.cpp:2017
[UE4Editor-Engine-Win64-Debug.dll] AActor::ProcessEvent(UFunction *,void *) Actor.cpp:863
[UE4Editor-Engine-Win64-Debug.dll] TScriptDelegate<FWeakObjectPtr>::ProcessDelegate<UObject>(void *) ScriptDelegates.h:247
[UE4Editor-Engine-Win64-Debug.dll] TMulticastScriptDelegate<FWeakObjectPtr>::ProcessMulticastDelegate<UObject>(void *) ScriptDelegates.h:493
[UE4Editor-Engine-Win64-Debug.dll] TSparseDynamicDelegate<FComponentHitSignature_MCSignature,UPrimitiveComponent,FComponentHitSignatureInfoGetter>::Broadcast<UPrimitiveComponent *,AActor *,UPrimitiveComponent *,FVector,FHitResult>(UPrimitiveComponent *,AActor *,UPrimitiveComponent *,FVector,FHitResult) SparseDelegate.h:326
[UE4Editor-Engine-Win64-Debug.dll] AActor::DispatchPhysicsCollisionHit(const FRigidBodyCollisionInfo &,const FRigidBodyCollisionInfo &,const FCollisionImpactData &) Actor.cpp:4425
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::DispatchPhysNotifications_AssumesLocked() PhysScene_PhysX.cpp:1425
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::EndFrame(ULineBatchComponent *) PhysScene_PhysX.cpp:1571
[UE4Editor-Engine-Win64-Debug.dll] UWorld::FinishPhysicsSim() PhysLevel.cpp:172

跟动画的关联

  • USkeletalMeshComponent::UpdateKinematicBonesToAnim
  • 迭代此网格物体的物理场中的每个物理体,并针对每个“运动学”(即如果所有者未进行模拟则为固定或默认),根据动画变换更新其变换。
[Inlined] [PhysX3CHECKED_x64.dll] physx::NpRigidDynamic::setKinematicTargetInternal(const physx::PxTransform &) NpRigidDynamic.cpp:106
[PhysX3CHECKED_x64.dll] physx::NpRigidDynamic::setKinematicTarget(const physx::PxTransform &) NpRigidDynamic.cpp:132
[UE4Editor-Engine-Win64-Debug.dll] FPhysScene_PhysX::SetKinematicTarget_AssumesLocked(FBodyInstance *,const FTransform &,bool) PhysScene_PhysX.cpp:651
[UE4Editor-Engine-Win64-Debug.dll] <lambda_1ce142ca88bea0e0ce8029516cc344ff>::operator()() PhysAnim.cpp:628
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefCaller<<lambda_1ce142ca88bea0e0ce8029516cc344ff>,void __cdecl(void)>::Call(void *) Function.h:548
[UE4Editor-Engine-Win64-Debug.dll] UE4Function_Private::TFunctionRefBase<UE4Function_Private::FFunctionRefStoragePolicy,void __cdecl(void)>::operator()() Function.h:676
[UE4Editor-Engine-Win64-Debug.dll] FPhysicsCommand_PhysX::ExecuteWrite(USkeletalMeshComponent *,TFunctionRef<void __cdecl(void)>) PhysicsInterfacePhysX.cpp:628
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::UpdateKinematicBonesToAnim(const TArray<FTransform,TSizedDefaultAllocator<32> > &,ETeleportType,bool,EAllowKinematicDeferral) PhysAnim.cpp:568
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::PostAnimEvaluation(FAnimationEvaluationContext &) SkeletalMeshComponent.cpp:2625
[UE4Editor-Engine-Win64-Debug.dll] USkeletalMeshComponent::CompleteParallelAnimationEvaluation(bool) SkeletalMeshComponent.cpp:3849
[UE4Editor-Engine-Win64-Debug.dll] FParallelAnimationCompletionTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) SkeletalMeshComponent.cpp:168
[UE4Editor-Engine-Win64-Debug.dll] TGraphTask<FParallelAnimationCompletionTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886

相关链接

**声明:**本文来自公众号:GameDevLearning,转载请附上原文链接(链接等公众号发文后补上。。)及本声明。

0 Answers