最近DOTS發(fā)布了正式的版本,同時(shí)基于DOTS的理念實(shí)現(xiàn)了一套高性能的物理引擎,今天我們給大家分享和介紹一下這個(gè)物理引擎的碰撞事件處理以及核心相關(guān)概念。
Unity.Physics物理引擎的主要流程與Pipeline
?Unity.Physics物理引擎做仿真迭代計(jì)算的時(shí)候主要通過(guò)以下步驟來(lái)執(zhí)行:
???step1: 從entity里面的ECS組件中獲取我們當(dāng)前的物體的狀態(tài)數(shù)據(jù);
???step2: 做粗略的broadphase計(jì)算階段,遍歷物理世界里面所有的body, 通過(guò)AABB包圍計(jì)算,來(lái)快速的判斷哪些物體,可能相交;粗略計(jì)算,把不會(huì)相交的排除掉, 不會(huì)相交的就不會(huì)改變運(yùn)動(dòng)狀態(tài);
???step3: narrowphase階段: 把可能相交的物體,做進(jìn)一步的精確的計(jì)算;根據(jù)他們的物理形狀,計(jì)算出來(lái)準(zhǔn)確的碰撞點(diǎn)與相關(guān)的碰撞信息;
???step4: 基于這些碰撞信息, 我們的物理引擎會(huì)計(jì)算具體的碰撞信息,關(guān)節(jié),摩檫力,阻力等計(jì)算, 結(jié)合物理的原理,計(jì)算出來(lái)我們的物理剛體的速度,角速度等運(yùn)動(dòng)狀態(tài)。
???Step5: 根據(jù)基于全新的運(yùn)動(dòng)狀態(tài),把所有運(yùn)動(dòng)的物體,向前迭代計(jì)算(線性速度,角速度,摩擦力等),計(jì)算出這幀新的剛體的位置等信息;
???Step6: Unity Physic 通過(guò) ExportPhysicsWorld System 把物理剛體的位置速度等,同步給節(jié)點(diǎn)Entity的LocalTransform組件與PhysicVelocity等組件,這樣渲染的entity,就會(huì)跟著物理引擎的剛體同步移動(dòng);
??DOTS中基于System與SystemGroup 樹(shù)行結(jié)構(gòu)來(lái)決定DOTS中的迭代順序,這個(gè)是DOTS中很重要的一個(gè)概念。Unity Physics將上面步驟與邏輯基于ECS設(shè)計(jì)思想,分別設(shè)計(jì)了相關(guān)的System與System Group,結(jié)構(gòu)如下:
-->FixedStepSimulationSystemGroup:
?-->PhysicsSystemGroup
??????-->PhysicsInitializeGroup(System Group)
??????-->PhysicsSimulationGroup(SystemGroup)
??????????-->PhysicsCreateBodyPairsGroup
??????????-->PhysicsCreateContactsGroup
??????????-->PhysicsCreateJacobiansGroup
??????????-->PhysicsSolveAndIntegrateGroup
??????-->System: ExportPhysicsWorld
所有物理引擎的迭代計(jì)算都是基于FixedStepSimulationSystemGroup,即按照固定的時(shí)間間隔來(lái)迭代物理仿真,保持物理引擎的一致性與穩(wěn)定性。所有的物理引擎的仿真計(jì)算都放在PysicsSystemGroup下。PysicsSystemGroup包含PhysicsInitializeGroup?,PhysicsSimulationGroup 與一個(gè)ExportPhysicsWorld?System。上面提到的Step1,在PhysicsInitializeGroup階段完成, step2~step5在PhysicsSimulationGroup中完成,?PhysicsSimulationGroup完成后物理引擎的一幀的迭代計(jì)算完成,最后通過(guò)ExportPhysicsWorld的System把把物理引擎的內(nèi)部數(shù)據(jù)同步到Entity的PhysicsVelocity, LocalTransform等ECS組件。在PhysicsSimulationGroup又有4個(gè)subgroup,他們分別對(duì)應(yīng)step2~step5的執(zhí)行步驟。
Unity Physics碰撞檢測(cè)事件處理
當(dāng)PhysicsSimulationGroup的分組執(zhí)行完成以后,就完成了整個(gè)物理引擎的仿真與迭代計(jì)算。仿真過(guò)程中會(huì)產(chǎn)生一個(gè)PhysicsWorld,物理世界里面的所有的剛體等相關(guān)物理數(shù)據(jù)(位置,速度等)都可以通過(guò)PhysicsWorld得到,最后還被導(dǎo)出到Entity的ECS組件里面。在物理仿真中所有的事件都會(huì)被保存到Simulation對(duì)象中,這些事件包括了我們常見(jiàn)的碰撞事件與觸發(fā)器事件。傳統(tǒng)模式下我們是通過(guò)回調(diào)函數(shù)來(lái)處理的,DOTS模式下我們是在一個(gè)System環(huán)節(jié)內(nèi)統(tǒng)一來(lái)處理這些事件。物理引擎的碰撞與觸發(fā)事件處理流程如下:
??Step1: 編寫(xiě)一個(gè)System處理邏輯,來(lái)處理物理事件;
??Step2: 指定好System執(zhí)行的時(shí)機(jī),一定要在PhysicsSimulationGroup之前或者之后,這樣才能拿到碰撞事件的數(shù)據(jù);
??Step3: 通過(guò)編寫(xiě)Job,來(lái)遍歷當(dāng)前所有發(fā)生的碰撞事件,然后編寫(xiě)每個(gè)碰撞事件的處理邏輯;
??Step4: 獲取存儲(chǔ)事件的Simulation單例,傳遞給job來(lái)進(jìn)行具體執(zhí)行;
碰撞事件的處理:
??當(dāng)所有的模擬迭代計(jì)算完成后,會(huì)把過(guò)程中的所有碰撞事件對(duì)存放到Simulation對(duì)象中,我們可以通過(guò)(SystemBase|SystemAPI|EntityQuery).GetSingleton<SimulationSingleton>().AsSimulation()獲取Simulation對(duì)象。
要處理所有的碰撞事件,我們先編寫(xiě)一個(gè)System用來(lái)編寫(xiě)事件處理邏輯,然后編寫(xiě)一個(gè)Job,繼承自IcollisionEventsJob,這樣就可以在Job中遍歷所有的碰撞事件,每個(gè)碰撞事件都調(diào)用Job的Execute函數(shù),在它里面來(lái)處理每個(gè)碰撞事件的邏輯。代碼如下:
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(PhysicsSimulationGroup))] // We are updating before `PhysicsSimulationGroup` - this means that we will get the events of the previous frame
public?partial?struct?GetNumCollisionEventsSystem : ISystem
{
????[BurstCompile]
????public?partial?struct?CountNumCollisionEvents : ICollisionEventsJob
????{
????????public?NativeReference<int> NumCollisionEvents;
????????public?void?Execute(CollisionEvent collisionEvent)
????????{
????????????NumCollisionEvents.Value++;
????????}
????}
????[BurstCompile]
????public?void?OnUpdate(ref?SystemState state)
????{
????????NativeReference<int> numCollisionEvents = new?NativeReference<int>(0, Allocator.TempJob);
????????
????????state.Dependency = new?CountNumCollisionEvents
????????{
????????????NumCollisionEvents = numCollisionEvents
????????}.Schedule(SystemAPI.GetSingleton<SimulationSingleton>());
????????// ...
????}
}文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-800126.html
觸發(fā)器事件TriggerEvent處理:
??觸發(fā)器事件與碰撞事件類(lèi)似,我們只要編寫(xiě)一個(gè)ItriggerEventsJob就可以遍歷當(dāng)前所有的觸發(fā)器事件了,代碼如下:
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))] // We are updating after `PhysicsSimulationGroup` - this means that we will get the events of the current frame.
public?partial?struct?GetNumTriggerEventsSystem : ISystem
{
????[BurstCompile]
????public?partial?struct?CountNumTriggerEvents : ITriggerEventsJob
????{
????????public?NativeReference<int> NumTriggerEvents;
????????public?void?Execute(TriggerEvent collisionEvent)
????????{
????????????NumTriggerEvents.Value++;
????????}
????}
????[BurstCompile]
????public?void?OnUpdate(ref?SystemState state)
????{
????????NativeReference<int> numTriggerEvents = new?NativeReference<int>(0, Allocator.TempJob);
????????
????????state.Dependency = new?CountNumTriggerEvents
????????{
????????????NumTriggerEvents = numTriggerEvents
????????}.Schedule(SystemAPI.GetSingleton<SimulationSingleton>());
????????// ...
????}
}
今天的分享就到這里,文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-800126.html
到了這里,關(guān)于DOTS Unity.Physics物理引擎碰撞事件處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!