系统状态组件

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了系统状态组件脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

您可以使用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, 系统分配)
@H_1_126@检测何时添加组件

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

检测组件何时被移除

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

检测实体何时被销毁

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.)
    }
}

 

脚本宝典总结

以上是脚本宝典为你收集整理的系统状态组件全部内容,希望文章能够帮你解决系统状态组件所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。