天天看點

Unity Entity Component System --- JobComponentSystem

Automatic job dependency management

自動管理Job依賴。

管理Job的依賴是件很麻煩的事。而JobComponentSystem幫我們自動處理了。規則很簡單:不同系統的Jobs可以并行地通路同樣類型的IComponentData。但是如果有一個Job在向該資料寫操作,則這些Jobs不能并行執行,必須根據依賴排程Jobs。

public class RotationSpeedSystem : JobComponentSystem
{
    [BurstCompile]
    struct RotationSpeedRotation : IJobForEach<Rotation, RotationSpeed>
    {
        public float dt;

        public void Execute(ref Rotation rotation, [ReadOnly]ref RotationSpeed speed)
        {
            rotation.value = math.mul(math.normalize(rotation.value), quaternion.axisAngle(math.up(), speed.speed * dt));
        }
    }

    // Any previously scheduled jobs reading/writing from Rotation or writing to RotationSpeed 
    // will automatically be included in the inputDeps dependency.
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var job = new RotationSpeedRotation() { dt = Time.deltaTime };
        return job.Schedule(this, inputDeps);
    } 
}
           

How does this work?

所有這些Jobs和Systems聲明了它們要讀或寫的ComponentType,是以當JobComponentSystem傳回JobHandle時,它自動将對這些ComponentType的讀寫通路注冊到EntityManager中。

是以當一個系統向A寫操作,其它系統之後讀取A,那麼JobComponentSystem會檢查清單中的讀取操作,并将傳遞一個對第一個系統的依賴。

JobComponentSystem簡單地将Jobs按照依賴關系連接配接到一起,簡化了我們在主線程中的依賴關系管理。但是,如果一個非Job的ComponentSystem要通路這些資料呢?因為所有的資料通路時事先聲明好的,是以ComponentSystem會在與其它有共同依賴的component的所有的jobs完成後,再調用它的OnUpdate。

Dependency management is conservative & deterministic

依賴管理是保守且确定的

依賴管理傾向于保守。ComponentSystem簡單地跟蹤用到過的EntityQuery對象并記錄它們對元件類型的讀寫配置。

而且,當在一個System中排程多個jobs時,無論這些Jobs是否是依賴的,都要講依賴對象傳遞給它們。如果證明這導緻效率問題,那麼嘗試把該系統拆分成2個系統。

依賴管理被設計的保守,這樣能夠用簡單的API保證邏輯的确定性和正确性。

Sync points

所有對結構的改變,都會導緻“強制同步點”,如,CreateEntity,Instantiate,Destroy,AddComponent,RemoveComponent,SetSharedComponentData。這意味着這些調用發生時,之前通過JobComponentSystem排程的所有的Jobs都要完成。這是自動的。比如,在邏輯幀的執行中間,調用EntityManager.CreateEntity,會導緻邏輯停下來,等待之前的Jobs 完成。

可以通過EntityCommandBuffer來避免實體建立類操作導緻的Sync Points。

Multiple Worlds

每個World都有自己的EntityManager,以及互相獨立的JobHandle依賴管理。一個World的Hard Sync Point,不會對另一個World産生影響。是以,對于序列化和建立對象,一個有用的建議是,在一個World中建立對象,建立好後,在一幀的開始将他們移動到另一個World中。

可以參考System update order 以及 ExclusiveEntityTransaction來避免實體建立和序列化導緻的Sync Points。