zoukankan      html  css  js  c++  java
  • 系统状态组件

    您可以使用SystemStateComponentData来跟踪系统内部的资源,并根据需要创建和销毁这些资源,而无需依赖单个回调。

    SystemStateComponentDataSystemStateSharedComponentData类似于ComponentDataSharedComponentData,但ECS不会SystemStateComponentData在实体销毁时删除

    当一个实体被销毁时,ECS通常会:

    1. 查找引用特定实体 ID 的所有组件。
    2. 删除那些组件。
    3. 回收实体 ID 以供重用。

    但是,如果SystemStateComponentData存在,ECS 不会回收 ID。这使系统有机会清理与实体 ID 关联的任何资源或状态。ECS 仅重用实体 ID 一次SystemStateComponentData删除。

    何时使用系统状态组件

    系统可能需要基于ComponentData例如,可能会分配资源。

    系统还需要能够将状态作为值进行管理,而其他系统可能会更改状态。例如,当组件中的值发生变化时,或者当相关组件被添加或删除时。

    “无回调”是 ECS 设计规则的一个重要元素。

    一般使用 SystemStateComponentData预期镜像用户组件,提供内部状态。

    例如,给定:

    • FooComponent ( ComponentData, 用户分配)
    • FooStateComponent ( SystemComponentData, 系统分配)

    检测何时添加组件

    创建组件时,系统状态组件不存在。系统更新对没有系统状态组件的组件的查询,并且可以推断它们已被添加。此时,系统会添加系统状态组件和任何所需的内部状态。

    检测组件何时被移除

    当您移除一个组件时,系统状态组件仍然存在。系统更新对没有组件的系统状态组件的查询,并且可以推断它们已被移除。此时,系统移除系统状态组件并修复任何需要的内部状态。

    检测实体何时被销毁

    DestroyEntity 是一个速记实用程序:

    • 查找引用给定实体 ID 的组件。
    • 删除找到的组件。
    • 回收实体 ID。

    但是,SystemStateComponentData在删除DestroyEntity最后一个组件之前不会删除,并且不会回收实体 ID。这使系统有机会以与删除组件完全相同的方式清理内部状态。

    系统状态组件

    ASystemStateComponentData类似于 a ComponentData

    struct FooStateComponent : ISystemStateComponentData
    {
    }
    

    a 的可见性SystemStateComponentData也以与组件相同的方式进行控制(使用privatepublicinternal) 但是,作为一般规则, aSystemStateComponentData将在ReadOnly创建它的系统之外。

    系统状态共享组件

    ASystemStateSharedComponentData类似于 a SharedComponentData

    struct FooStateSharedComponent : ISystemStateSharedComponentData
    {
      public int Value;
    }
    

    使用状态组件的示例系统

    以下示例显示了一个简化的系统,该系统说明了如何使用系统状态组件管理实体。该示例定义了一个通用 IComponentData 实例和一个系统状态 ISystemStateComponentData 实例。它还基于这些实体定义了三个查询:

    • m_newEntities选择具有通用但不具有系统状态组件的实体。此查询查找系统以前未见过的新实体。系统使用添加系统状态组件的新实体查询运行作业。
    • m_activeEntities选择具有通用和系统状态组件的实体。在实际应用中,其他系统可能是处理或销毁实体的系统。
    • m_destroyedEntities选择具有系统状态但不具有通用组件的实体。由于系统状态组件本身从未添加到实体中,因此该查询选择的实体必须已被该系统或其他系统删除。系统重用销毁的实体查询来运行作业并从实体中删除系统状态组件,这允许 ECS 代码回收实体标识符。
    笔记

    这个简化的例子不维护系统内的任何状态。系统状态组件的一个目的是跟踪何时需要分配或清理持久资源。

    
    using Unity.Entities;
    using Unity.Jobs;
    using Unity.Collections;
    
    public struct GeneralPurposeComponentA : IComponentData
    {
        public int Lifetime;
    }
    
    public struct StateComponentB : ISystemStateComponentData
    {
        public int State;
    }
    
    public partial class StatefulSystem : SystemBase
    {
        private EntityCommandBufferSystem ecbSource;
    
        protected override void OnCreate()
        {
            ecbSource = World.GetExistingSystem<EndSimulationEntityCommandBufferSystem>();
    
            // Create some test entities
            // This runs on the main thread, but it is still faster to use a command buffer
            EntityCommandBuffer creationBuffer = new EntityCommandBuffer(Allocator.Temp);
            EntityArchetype archetype = EntityManager.CreateArchetype(typeof(GeneralPurposeComponentA));
            for (int i = 0; i < 10000; i++)
            {
                Entity newEntity = creationBuffer.CreateEntity(archetype);
                creationBuffer.SetComponent<GeneralPurposeComponentA>
                (
                    newEntity,
                    new GeneralPurposeComponentA() { Lifetime = i }
                );
            }
            //Execute the command buffer
            creationBuffer.Playback(EntityManager);
        }
    
        protected override void OnUpdate()
        {
            EntityCommandBuffer.ParallelWriter parallelWriterECB = ecbSource.CreateCommandBuffer().AsParallelWriter();
    
            // Entities with GeneralPurposeComponentA but not StateComponentB
            Entities
                .WithNone<StateComponentB>()
                .ForEach(
                    (Entity entity, int entityInQueryIndex, in GeneralPurposeComponentA gpA) =>
                    {
                    // Add an ISystemStateComponentData instance
                    parallelWriterECB.AddComponent<StateComponentB>
                        (
                            entityInQueryIndex,
                            entity,
                            new StateComponentB() { State = 1 }
                        );
                    })
                .ScheduleParallel();
            ecbSource.AddJobHandleForProducer(this.Dependency);
    
            // Create new command buffer
            parallelWriterECB = ecbSource.CreateCommandBuffer().AsParallelWriter();
    
            // Entities with both GeneralPurposeComponentA and StateComponentB
            Entities
                .WithAll<StateComponentB>()
                .ForEach(
                    (Entity entity,
                     int entityInQueryIndex,
                     ref GeneralPurposeComponentA gpA) =>
                    {
                    // Process entity, in this case by decrementing the Lifetime count
                    gpA.Lifetime--;
    
                    // If out of time, destroy the entity
                    if (gpA.Lifetime <= 0)
                        {
                            parallelWriterECB.DestroyEntity(entityInQueryIndex, entity);
                        }
                    })
                .ScheduleParallel();
            ecbSource.AddJobHandleForProducer(this.Dependency);
    
            // Create new command buffer
            parallelWriterECB = ecbSource.CreateCommandBuffer().AsParallelWriter();
    
            // Entities with StateComponentB but not GeneralPurposeComponentA
            Entities
                .WithAll<StateComponentB>()
                .WithNone<GeneralPurposeComponentA>()
                .ForEach(
                    (Entity entity, int entityInQueryIndex) =>
                    {
                    // This system is responsible for removing any ISystemStateComponentData instances it adds
                    // Otherwise, the entity is never truly destroyed.
                    parallelWriterECB.RemoveComponent<StateComponentB>(entityInQueryIndex, entity);
                    })
                .ScheduleParallel();
            ecbSource.AddJobHandleForProducer(this.Dependency);
    
        }
    
        protected override void OnDestroy()
        {
            // Implement OnDestroy to cleanup any resources allocated by this system.
            // (This simplified example does not allocate any resources, so there is nothing to clean up.)
        }
    }
    

     

  • 相关阅读:
    打开一个网页,以html代码保存于txt文件中
    用C查看系统任务管理器中运行的程序
    常见两种LINK错误
    怎么把下载的dll和def生成lib,以用于编程
    建立一个不能打开的文件(占坑)C语言高级API调用
    [转]软件版本命名格式
    回调函数编写和注重点
    ubuntu linux mysql 开发模式与连接编译
    创建一个进程和两个管道,实现与进程通信
    hdoj 1115 Lifting the Stone (求多边形重心)
  • 原文地址:https://www.cnblogs.com/alps/p/15328216.html
Copyright © 2011-2022 走看看