最近DOTS發(fā)布了正式的版本, 我們來分享一下System中如何基于SystemAPI.Query來迭代World中的數(shù)據(jù),方便大家上手學(xué)習(xí)掌握Unity DOTS開發(fā)。
SystemAPI.Query的使用
System有兩種,一種是Unmanaged 的ISystem,一種是managed 的SystemBase,這兩種System都可以通過SystemAPI.Query來迭代與遍歷,可以獲取World里面的組件與Entity。SystemAPI.Query是運(yùn)行在main thread的主線程上,SystemAPI.Query與C# 傳統(tǒng)的foreach語句結(jié)合起來,讓我們遍歷數(shù)據(jù)非常的方便。當(dāng)我們要遍歷一個(gè)World里面的entity數(shù)據(jù)的時(shí)候,我們需要根據(jù)數(shù)據(jù)類型來篩選出對(duì)應(yīng)的組件與Entity。函數(shù)SystemAPI.Query(),其中t1, t2就是我們需要的component data的類型,查詢的時(shí)候,會(huì)遍歷World 里面有這些組件的Entity,獲取組件的引用。Query中的類型T1,T2,可以是以下7中類型:
IAspect
IComponentData
ISharedComponentData
DynamicBuffer
RefRO
RefRW
EnabledRefRO where T : IEnableableComponent, IComponentData
EnabledRefRW where T : IEnableableComponent, IComponentData
以下是給的一個(gè)代碼示例,從World里面篩選出來有LocalTransform與RotationSpeed組件的Entity,并把它們的數(shù)據(jù)通過foreach來處理。示例代碼如下:
??public?partial?struct?MyRotationSpeedSystem?:?ISystem
??{
?
????[BurstCompile]
????public?void?OnUpdate(ref?SystemState?state)
????{
??????float?deltaTime?= SystemAPI.Time.DeltaTime;
?
??????foreach?(var?(transform,?speed)?in?SystemAPI.Query,?RefRO>())
????????transform.ValueRW?= transform.ValueRO.RotateY(speed.ValueRO.RadiansPerSecond?* deltaTime);
????}
??}
RefRW.ValueRW獲取組件的可讀寫權(quán)限的組件引用, RefRW.ValueRO只讀屬性的組件應(yīng)用, RefRO.ValueRO組件的只讀引用。如果你只要一個(gè)只讀之間,我們就可以單純的用組件的名字來Query就可以了。
????public?void?OnUpdate(ref?SystemState?state)
????{
??????#region query-data-alt
??????float?deltaTime?= SystemAPI.Time.DeltaTime;
?
??????foreach?(var?(transform,?speed)?in?SystemAPI.Query,?RotationSpeed>())
????????transform.ValueRW?= transform.ValueRO.RotateY(speed.RadiansPerSecond?* deltaTime);
??????#endregion
????}
其中RotaionSpeed為只讀的組件實(shí)例的引用。如果我們?cè)趕ystem里面迭代數(shù)據(jù)的時(shí)候,需要組件對(duì)應(yīng)的Entity,我們使用API函數(shù)WithEntityAcess,示例代碼如下:
?public?void?OnUpdate(ref?SystemState?state)
????{
??????float?deltaTime?= SystemAPI.Time.DeltaTime;
?
??????#region entity-access
??????foreach?(var?(transform,?speed,?entity)?in?SystemAPI.Query,?RefRO>().WithEntityAccess())
??????{
????????// Do stuff;
??????}
??????#endregion
????}
?
?
SystemAPI.Query的內(nèi)部實(shí)現(xiàn)
當(dāng)我們?cè)赟ystem代碼里面調(diào)用foreach+SystemAPI.Query的時(shí)候,我們的自動(dòng)代碼生成器會(huì)根據(jù)Query調(diào)用的時(shí)候傳遞的參數(shù)的類型來生成EntityQuery字段到當(dāng)前的System類里面(正因如此,我們?cè)诙x一個(gè)System類型的時(shí)候都要加partial)。同時(shí)替換掉SystemAPI.Query代碼。這樣運(yùn)行的時(shí)候使用EntityQuery字段來幫我們找到對(duì)應(yīng)的組件來進(jìn)行迭代處理。SystemAPI.Query也有它的一些局限性,使用SystemAPI.Query API的時(shí)候我們無法對(duì)Dynamic Buffer組件來做只讀的訪問權(quán)限,只能獲得可讀寫的訪問權(quán)限。我們不能夠保存foreach的結(jié)果,因?yàn)閒oreach是自動(dòng)代碼生成的時(shí)候,根據(jù)foreach在編譯的時(shí)候自動(dòng)生成的EntityQuery,沒有辦法去緩存EntityQuery的結(jié)果。
?
?
今天的?SystemAPI.Query如何使用,就到這里了,更多的DOTS系列,關(guān)注我,持續(xù)更新!
??
?
標(biāo)簽: