ECS 简略版说明六:additional-entities-features

目录

Enableable components

Shared components

Cleanup components

Chunk components

Blob assets

Version numbers


Enableable components

继承于 IComponentData or IBufferElementData 的struct,也可以继承于IEnableableComponent. 添加该组件的实体可以被 enabled and disabled

当 entity 的组件是 disabled, queries 认为 entity 不含有该组件.EntityQuery. ToArchetypeChunkArray() 如果没查到实体,则是空的。

disabled component仅仅影响 queries,可以正常读取、修改

下列方法可以检查和设置实体组件的启用状态:

  • EntityManager
  • ComponentLookup
  • BufferLookup (for a dynamic buffer)
  • EnabledRefRW (used in a SystemAPI.Query foreach or an IJobEntity)
  • ArchetypeChunk

比如:EntityManager has these key methods:

Method Description
IsComponentEnabled() Returns true if an entity has a currently enabled T component.
SetComponentEnabled() Enables or disables an entity's enableable T component.
 NOTE
For the sake of the job safety checks, read or write access of a component's enabled state requires read or write access of the component type itself.

IJobChunk中 Execute 方法中的参数来决定chunk中的哪些实体匹配 :

  • 如果 useEnableMask = false, all entities in the chunk match the query.
  • 如果 useEnableMask = true, the bits of the chunkEnabledMask parameter signal which entities in the chunk match the query, factoring in all enableable component types of the query. Rather than check these mask bits manually, you can use a ChunkEntityEnumerator to more conveniently iterate through the matching entities.
 NOTE
The chunkEnabledMask is a composite of all the enabled states of the enableable components included in the query of the job. To check enabled states of individual components, use the IsComponentEnabled() and SetComponentEnabled() methods of the ArchetypeChunk.

Shared components

shared component type共享组件. 因此设置 shared component 的值,是一个  structural change

queries can filter for specific shared component values.

shared component 的值不是直接存储在 chunks中, world 把它们存储在一个数组中,chunks 仅存储它在数组中的索引. This means that each unique shared component value is stored only once within a world.

继承自ISharedComponentData 来实现一个SharedComponent. 如果结构包含任何托管类型字段,那么共享组件本身将是托管组件类型

The EntityManager has these key methods for shared components:

Method Description
AddComponent() Adds a T component to an entity, where T can be a shared component type.
AddSharedComponent() Adds an unmanaged shared component to an entity and sets its initial value.
AddSharedComponentManaged() Adds a managed shared component to an entity and sets its initial value.
RemoveComponent() Removes a T component from an entity, where T can be a shared component type.
HasComponent() Returns true if an entity currently has a T component, where type T can be a shared component type.
GetSharedComponent() Retrieves the value of an entity's unmanaged shared T component.
SetSharedComponent() Overwrites the value of an entity's unmanaged shared T component.
GetSharedComponentManaged() Retrieves the value of an entity's managed shared T component.
SetSharedComponentManaged() Overwrites the value of an entity's managed shared T component.

共享组件类型可以通过 实现 IEquatable.接口,由EntityManager进行相等性比较。

⚠ IMPORTANT
Because the EntityManager relies upon equality to identify unique and matching shared component values, you should avoid modifying any mutable objects referenced by shared components. For example, if you want to modify an array stored in a shared component of a particular entity, you should not modify the array directly but instead update the component of that entity to have a new, modified copy of the array.

如果 shared component type 实现了 IRefCounted, 就可以对其引用计数,比如实现 IRefCounted 接口的组件中包含了  NativeArray, 就可以在引用数为0时,dispose它

如果shared component 是unmanaged, the methods of IEquatable and IRefCounted can be Burst-compiled by adding the [BurstCompile] attribute to the methods and the struct itself.

⚠ IMPORTANT
Having too many unique shared component values may result in chunk fragmentation. 

Cleanup components

Cleanup components在两个方面是特别的:

  • 当一个有cleanup components的 entity 被销毁时, (不是cleanup的组件)non-cleanup components 会被移除,  但是entity 还存在,直到 cleanup components 也被销毁了。
  • When an entity is copied to another world, copied in serialization, or copied by the Instantiate method of EntityManager, any cleanup components of the original are not added to the new entity.

清理组件的主要用例是在实体创建后帮助初始化实体,或者在实体销毁后帮助清理实体 

  1. We can find all monster entities needing initialization by querying for all entities which have the Monster component but which do nothave a MonsterCleanup component. For all entities matching this query, we perform any required initialization and add MonsterCleanup.
  2. We can find all monster entities needing cleanup by querying for all entities which have the MonsterCleanup component but not the Monster component. For all entities matching this query, we perform any required cleanup and remove MonsterCleanup. Unless the entities have additional remaining cleanup components, this will destroy the entities.
 NOTE
In some case, you'll want to store information needed for cleanup in your cleanup components, but in many cases, an empty cleanup tag component is sufficient.

Cleanup components come in four varieties:

Kind of cleanup component Description
A struct implementing ICleanupComponentData The cleanup variant of an unmanaged IComponentData type.
A class implementing ICleanupComponentData The cleanup variant of a managed IComponentData type.
A struct implementing ICleanupBufferElementData The cleanup variant of a dynamic buffer type.
A struct implementing ICleanupSharedComponentData The cleanup variant of a shared component type.

Chunk components

与常规组件不同,块组件是属于整个块的单个值,而不是块中的任何实体

Just like a regular component, a chunk component is defined as a struct or class implementing IComponentData, but a chunk component is added, removed, get, and set with these EntityManager methods:

Method Description
AddChunkComponentData Adds a chunk component of type T to a chunk, where T is a managed or unmanaged IComponentData.
RemoveChunkComponentData Removes a chunk component of type T from a chunk, where T is a managed or unmanaged IComponentData.
HasChunkComponent Returns true if a chunk has a chunk component of type T.
GetChunkComponentData Retrieves the value of a chunk's chunk component of type T.
SetChunkComponentData Sets the value of a chunk's chunk component of type T.
 NOTE
Shared components  per chunk存储一个值,但是它是属于实体的,也就是为什么值变化,就会更改chunk, Chunk components 属于chunk,直接存储在chunk中

Blob assets

A Blob (Binary Large Object) asset is an immutable (unchanging), unmanaged piece of binary data stored in a contiguous block of bytes:

  • Blob assets 高效的 copy and load because they are fully relocatable: all internal pointers 表示为相对偏移量而不是绝对地址, so copying the whole Blob is as simple as copying every byte.
  • Although they are stored independently from entities, Blob assets may be referenced from entity components.
  • Because they're immutable, Blob assets are inherently safe to access from multiple threads.
 NOTE
a Blob asset 内存中的一段数据, 不是项目资产文件! However, Blob assets are efficiently and easily serializable into files on disk, so it makes some sense to call them "assets".

To create a Blob asset:

  1. Create a BlobBuilder.
  2. Call the builder's ConstructRoot to set the Blob's 'root' (a struct of type T).
  3. Call the builder's Allocate, Construct and SetPointer methods to fill in the rest of the Blob data (including BlobArray's, BlobString's, and BlobPtr).
  4. Call the builder's CreateBlobAssetReference, which copies all the data in the builder to create the actual Blob asset and returns a BlobAssetReference.
  5. Dispose the BlobBuilder.

当不再需要Blob资产时,应该调用BlobAssetReference.Dispose()释放它,

Blob assets referenced in a baked entity scene are serialized and loaded along with the scene. These Blob assets should not be manually disposed: they will be automatically disposed along with the scene.

⚠ IMPORTANT
包含内部指针的blob assets的所有部分必须始终通过引用访问. For example, the offset values in a BlobString struct are only correct relative to where the BlobString struct is stored inside the Blob; the offsets are not correct relative to copies of the struct.

Version numbers

A world, its systems, and its chunks maintain several 'version numbers' (numbers which are incremented by certain operations). 通过比较version number,您可以确定某些数据是否发生了更改

version numbers 是 32-bit 有符号整数,比较版本号的正确方法依赖于c#定义的微妙特性:

// true if VersionB is more recent than VersionA
// false if VersionB is equal or less than VersionA
bool changed = (VersionB - VersionA) > 0;
Version number Description
World.Version Increased every time the world adds or removes a system or system group.
EntityManager.GlobalSystemVersion Increased before every system update in the world.
SystemState.LastSystemVersion Assigned the value of the GlobalSystemVersion immediately after each time the system updates.
EntityManager.EntityOrderVersion Increased every time a structural change is made in the world.

每一个component type 也有自己的 version number, 当对该组件写入访问时递增 EntityManager.GetComponentOrderVersion.访问

每一个shared component value also has a version number ,当发生 structure changes的时候递增.

chunk stores a version number for each component type in the chunk. When a component type in a chunk is accessed for writing, its version number is assigned the value of EntityManager.GlobalSystemVersion, regardless of whether any component values are actually modified. These chunk version numbers can be retrieved by calling the ArchetypeChunk.GetChangeVersion method.

A chunk also stores a version number for each component type which is assigned the value of EntityManager.GlobalSystemVersion every time a structural change affects the chunk. These chunk version numbers can be retrieved by calling the ArchetypeChunk.GetOrderVersion method.

你可能感兴趣的:(ECS,unity)