Просмотр исходного кода

UPM package version 3.4.6

tags/3.4.6
GitHub 1 год назад
Родитель
Сommit
a618e7d7a8
13 измененных файлов: 95 добавлений и 72 удалений
  1. +4
    -4
      CHANGELOG.md
  2. +5
    -0
      Core/ComponentTypeID.cs
  3. +6
    -5
      Core/ComponentTypeMap.cs
  4. +2
    -2
      Core/EnginesRoot.Engines.cs
  5. +2
    -2
      Core/EntityDescriptor/DynamicEntityDescriptor.cs
  6. +2
    -2
      Core/EntityReference/EnginesRoot.LocatorMap.cs
  7. +4
    -10
      Core/Groups/EntityDescriptorsWarmup.cs
  8. +4
    -1
      Core/Groups/GroupCompound.cs
  9. +15
    -10
      Core/Groups/GroupHashMap.cs
  10. +39
    -28
      Extensions/Unity/DOTS/UECS/DOTSOperationsForSvelto.cs
  11. +8
    -6
      Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs
  12. +2
    -0
      README.md
  13. +2
    -2
      package.json

+ 4
- 4
CHANGELOG.md Просмотреть файл

@@ -1,10 +1,10 @@
# Svelto.ECS Changelog
All notable changes to this project will be documented in this file. Changes are listed in random order of importance.

## [3.4.5] - 04-2023
* improved code after internal data refactoring and fixed some bugs
* Added static DynamicEntityDescriptor method to create a new DynamicEntityDescriptor without passing an array of components
* factory method to build entities without entity descriptor is now internal
## [3.4.6] - 05-2023
* SveltoOnDOTS bug fixes/improvements
* Comments and code cleanup

## [3.4.4] - 04-2023



+ 5
- 0
Core/ComponentTypeID.cs Просмотреть файл

@@ -20,6 +20,11 @@ namespace Svelto.ECS
get => _id.Data;
}

/// <summary>
/// c# Static constructors are guaranteed to be thread safe
/// The runtime guarantees that a static constructor is only called once. So even if a type is called by multiple threads at the same time,
/// the static constructor is always executed one time. To get a better understanding how this works, it helps to know what purpose it serves.
/// </summary>
static ComponentTypeID()
{
Init();


+ 6
- 5
Core/ComponentTypeMap.cs Просмотреть файл

@@ -1,18 +1,19 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using Svelto.DataStructures;

namespace Svelto.ECS
{
public static class ComponentTypeMap
static class ComponentTypeMap
{
static readonly FasterDictionary<RefWrapper<Type>, ComponentID> _componentTypeMap = new FasterDictionary<RefWrapper<Type>, ComponentID>();
static readonly FasterDictionary<ComponentID, Type> _reverseComponentTypeMap = new FasterDictionary<ComponentID, Type>();
static readonly ConcurrentDictionary<Type, ComponentID> _componentTypeMap = new ConcurrentDictionary<Type, ComponentID>();
static readonly ConcurrentDictionary<ComponentID, Type> _reverseComponentTypeMap = new ConcurrentDictionary<ComponentID, Type>();

public static void Add(Type type, ComponentID idData)
{
_componentTypeMap.Add(type, idData);
_reverseComponentTypeMap.Add(idData, type);
_componentTypeMap.TryAdd(type, idData);
_reverseComponentTypeMap.TryAdd(idData, type);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]


+ 2
- 2
Core/EnginesRoot.Engines.cs Просмотреть файл

@@ -16,8 +16,8 @@ namespace Svelto.ECS
{
static EnginesRoot()
{
EntityDescriptorsWarmup.Init();
GroupHashMap.Init();
EntityDescriptorsWarmup.WarmUp();
GroupHashMap.WarmUp();
//SharedDictonary.Init();
SerializationDescriptorMap.Init();



+ 2
- 2
Core/EntityDescriptor/DynamicEntityDescriptor.cs Просмотреть файл

@@ -45,7 +45,7 @@ namespace Svelto.ECS

public DynamicEntityDescriptor(IComponentBuilder[] extraEntityBuilders)
{
this = CreateDynamicEntityDescriptor();
this = DynamicEntityDescriptor<TType>.CreateDynamicEntityDescriptor();
var extraEntitiesLength = extraEntityBuilders.Length;

@@ -54,7 +54,7 @@ namespace Svelto.ECS

public DynamicEntityDescriptor(FasterList<IComponentBuilder> extraEntityBuilders)
{
this = CreateDynamicEntityDescriptor();
this = DynamicEntityDescriptor<TType>.CreateDynamicEntityDescriptor();
var extraEntities = extraEntityBuilders.ToArrayFast(out _);
var extraEntitiesLength = extraEntityBuilders.count;


+ 2
- 2
Core/EntityReference/EnginesRoot.LocatorMap.cs Просмотреть файл

@@ -173,10 +173,10 @@ namespace Svelto.ECS
public bool TryGetEGID(EntityReference reference, out EGID egid)
{
egid = default;
#if DEBUG && !PROFILE_SVELTO
if (reference == EntityReference.Invalid)
return false;
#endif
// Make sure we are querying for the current version of the locator.
// Otherwise the locator is pointing to a removed entity.
ref var entityReferenceMapElement = ref _entityReferenceMap[reference.index];


+ 4
- 10
Core/Groups/EntityDescriptorsWarmup.cs Просмотреть файл

@@ -5,13 +5,13 @@ using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public static class EntityDescriptorsWarmup
static class EntityDescriptorsWarmup
{
/// <summary>
/// c# Static constructors are guaranteed to be thread safe
/// Warmup all EntityDescriptors and ComponentTypeID classes to avoid huge overheads when they are first used
/// </summary>
internal static void Init()
internal static void WarmUp()
{
List<Assembly> assemblies = AssemblyUtility.GetCompatibleAssemblies();
foreach (Assembly assembly in assemblies)
@@ -30,10 +30,7 @@ namespace Svelto.ECS

System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup.TypeHandle);
}
catch (Exception e)
{
continue;
}
catch { }
}
}
@@ -51,10 +48,7 @@ namespace Svelto.ECS
//this warms up the component builder. There could be different implementation of components builders for the same component type in theory
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(componentType.TypeHandle);
}
catch (Exception e)
{
continue;
}
catch { }
}
}
}


+ 4
- 1
Core/Groups/GroupCompound.cs Просмотреть файл

@@ -27,7 +27,10 @@ namespace Svelto.ECS
{
static GroupCompound()
{
//avoid race conditions if compounds are using on multiple thread
//avoid race conditions if compounds are using on multiple thread. This shouldn't be necessary though since c# static constructors are guaranteed to be thread safe!
/// c# Static constructors are guaranteed to be thread safe
/// The runtime guarantees that a static constructor is only called once. So even if a type is called by multiple threads at the same time,
/// the static constructor is always executed one time. To get a better understanding how this works, it helps to know what purpose it serves.
if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 &&
GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value == false)
{


+ 15
- 10
Core/Groups/GroupHashMap.cs Просмотреть файл

@@ -10,8 +10,12 @@ namespace Svelto.ECS
{
/// <summary>
/// c# Static constructors are guaranteed to be thread safe
/// The runtime guarantees that a static constructor is only called once. So even if a type is called by multiple threads at the same time,
/// the static constructor is always executed one time. To get a better understanding how this works, it helps to know what purpose it serves.
///
/// Warmup the group hash map. This will call all the static constructors of the group types
/// </summary>
internal static void Init()
internal static void WarmUp()
{
List<Assembly> assemblies = AssemblyUtility.GetCompatibleAssemblies();
foreach (Assembly assembly in assemblies)
@@ -26,8 +30,8 @@ namespace Svelto.ECS
{
CheckForGroupCompounds(type);

if (type != null && type.IsClass && type.IsSealed &&
type.IsAbstract) //IsClass and IsSealed and IsAbstract means only static classes
//Search inside static types
if (type != null && type.IsClass && type.IsSealed && type.IsAbstract) //IsClass and IsSealed and IsAbstract means only static classes
{
var subClasses = type.GetNestedTypes();

@@ -40,8 +44,8 @@ namespace Svelto.ECS

foreach (var field in fields)
{
if (field.IsStatic
&& (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType)
if (field.IsStatic
&& (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType)
|| typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType)
|| typeOfExclusiveBuildGroup.IsAssignableFrom(field.FieldType)))
{
@@ -52,7 +56,8 @@ namespace Svelto.ECS
var group = (ExclusiveGroup)field.GetValue(null);
groupIDAndBitMask = ((ExclusiveGroupStruct)@group).ToIDAndBitmask();
}
else if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType))
else
if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType))
{
var group = (ExclusiveGroupStruct)field.GetValue(null);
groupIDAndBitMask = @group.ToIDAndBitmask();
@@ -94,7 +99,7 @@ namespace Svelto.ECS
{
if (typeof(ITouchedByReflection).IsAssignableFrom(type))
{
//this wil call the static constructor, but only once. Static constructors won't be called
//this calls the static constructor, but only once. Static constructors won't be called
//more than once with this
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.BaseType.TypeHandle);
}
@@ -107,7 +112,7 @@ namespace Svelto.ECS
/// <param name="exclusiveGroupStruct"></param>
/// <param name="name"></param>
/// <exception cref="ECSException"></exception>
public static void RegisterGroup(ExclusiveGroupStruct exclusiveGroupStruct, string name)
internal static void RegisterGroup(ExclusiveGroupStruct exclusiveGroupStruct, string name)
{
//Group already registered by another field referencing the same group, can happen because
//the group poked is a group compound which static constructor is already been called at this point
@@ -125,7 +130,7 @@ namespace Svelto.ECS
_hashByGroups.Add(exclusiveGroupStruct, nameHash);
}

internal static uint GetHashFromGroup(ExclusiveGroupStruct groupStruct)
public static uint GetHashFromGroup(ExclusiveGroupStruct groupStruct)
{
#if DEBUG && !PROFILE_SVELTO
if (_hashByGroups.ContainsKey(groupStruct) == false)
@@ -135,7 +140,7 @@ namespace Svelto.ECS
return _hashByGroups[groupStruct];
}

internal static ExclusiveGroupStruct GetGroupFromHash(uint groupHash)
public static ExclusiveGroupStruct GetGroupFromHash(uint groupHash)
{
#if DEBUG && !PROFILE_SVELTO
if (_groupsByHash.ContainsKey(groupHash) == false)


+ 39
- 28
Extensions/Unity/DOTS/UECS/DOTSOperationsForSvelto.cs Просмотреть файл

@@ -20,14 +20,14 @@ namespace Svelto.ECS.SveltoOnDOTS

public EntityArchetype CreateArchetype(params ComponentType[] types)
{
return _EManager.CreateArchetype(types);
return EManager.CreateArchetype(types);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetComponent<T>(Entity e, in T component)
where T : unmanaged, IComponentData
{
_EManager.SetComponentData(e, component);
EManager.SetComponentData(e, component);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -37,23 +37,23 @@ namespace Svelto.ECS.SveltoOnDOTS
#if UNITY_ECS_100
_EManager.SetSharedComponent(e, component);
#else
_EManager.SetSharedComponentData(e, component);
EManager.SetSharedComponentData(e, component);
#endif
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity CreateDOTSEntityOnSvelto(Entity prefabEntity, EGID egid)
{
Entity dotsEntity = _EManager.Instantiate(prefabEntity);
Entity dotsEntity = EManager.Instantiate(prefabEntity);

//SharedComponentData can be used to group the DOTS ECS entities exactly like the Svelto ones
#if UNITY_ECS_100
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
#else
_EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
#endif
_EManager.AddComponent<DOTSSveltoEGID>(dotsEntity);
_EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid));
EManager.AddComponent<DOTSSveltoEGID>(dotsEntity);
EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid));

return dotsEntity;
}
@@ -68,16 +68,16 @@ namespace Svelto.ECS.SveltoOnDOTS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity CreateDOTSEntityOnSvelto(EntityArchetype archetype, EGID egid)
{
Entity dotsEntity = _EManager.CreateEntity(archetype);
Entity dotsEntity = EManager.CreateEntity(archetype);

//SharedComponentData can be used to group the DOTS ECS entities exactly like the Svelto ones
#if UNITY_ECS_100
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
#else
_EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID));
#endif
_EManager.AddComponent<DOTSSveltoEGID>(dotsEntity);
_EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid));
EManager.AddComponent<DOTSSveltoEGID>(dotsEntity);
EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid));

return dotsEntity;
}
@@ -92,34 +92,34 @@ namespace Svelto.ECS.SveltoOnDOTS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity CreateDOTSEntity(EntityArchetype archetype)
{
return _EManager.CreateEntity(archetype);
return EManager.CreateEntity(archetype);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DestroyEntity(Entity e)
{
_EManager.DestroyEntity(e);
EManager.DestroyEntity(e);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveComponent<T>(Entity dotsEntity)
{
_EManager.RemoveComponent<T>(dotsEntity);
EManager.RemoveComponent<T>(dotsEntity);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddComponent<T>(Entity dotsEntity)
where T : unmanaged, IComponentData
{
_EManager.AddComponent<T>(dotsEntity);
EManager.AddComponent<T>(dotsEntity);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddComponent<T>(Entity dotsEntity, in T component)
where T : unmanaged, IComponentData
{
_EManager.AddComponent<T>(dotsEntity);
_EManager.SetComponentData(dotsEntity, component);
EManager.AddComponent<T>(dotsEntity);
EManager.SetComponentData(dotsEntity, component);
}
public T GetComponent<T>(Entity dotsEntity) where T : unmanaged, IComponentData
@@ -127,7 +127,7 @@ namespace Svelto.ECS.SveltoOnDOTS
#if UNITY_ECS_100
return _EManager.GetComponentData<T>(dotsEntity);
#else
return _EManager.GetComponentData<T>(dotsEntity);
return EManager.GetComponentData<T>(dotsEntity);
#endif
}

@@ -138,7 +138,7 @@ namespace Svelto.ECS.SveltoOnDOTS
#if UNITY_ECS_100
_EManager.AddSharedComponent(dotsEntity, component);
#else
_EManager.AddSharedComponentData(dotsEntity, component);
EManager.AddSharedComponentData(dotsEntity, component);
#endif
}

@@ -146,7 +146,7 @@ namespace Svelto.ECS.SveltoOnDOTS
public void AddBuffer<T>(Entity dotsEntity)
where T : unmanaged, IBufferElementData
{
_EManager.AddBuffer<T>(dotsEntity);
EManager.AddBuffer<T>(dotsEntity);
}
#if !(DEBUG && !PROFILE_SVELTO)
@@ -154,7 +154,7 @@ namespace Svelto.ECS.SveltoOnDOTS
#endif
public void SetDebugName(Entity dotsEntity, string name)
{
_EManager.SetName(dotsEntity, name);
EManager.SetName(dotsEntity, name);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -166,7 +166,7 @@ namespace Svelto.ECS.SveltoOnDOTS
#else
for (int i = 0; i < nativeArray.Length; i++)
{
_EManager.SetSharedComponentData(nativeArray[i], SCD);
EManager.SetSharedComponentData(nativeArray[i], SCD);
}
#endif
}
@@ -174,7 +174,7 @@ namespace Svelto.ECS.SveltoOnDOTS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddComponentBatched<T>(NativeArray<Entity> DOTSEntities)
{
_EManager.AddComponent<T>(DOTSEntities);
EManager.AddComponent<T>(DOTSEntities);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -186,14 +186,14 @@ namespace Svelto.ECS.SveltoOnDOTS
_jobHandle->Complete();

var count = (int)(range.rangeEnd - range.rangeStart);
var nativeArray = _EManager.Instantiate(prefab, count, _EManager.World.UpdateAllocator.ToAllocator);
var nativeArray = EManager.Instantiate(prefab, count, EManager.World.UpdateAllocator.ToAllocator);
#if UNITY_ECS_100
_EManager.AddSharedComponent(nativeArray, new DOTSSveltoGroupID(groupID));
#else
for (int i = 0; i < nativeArray.Length; i++)
{
_EManager.AddSharedComponentData(nativeArray[i], new DOTSSveltoGroupID(groupID));
EManager.AddSharedComponentData(nativeArray[i], new DOTSSveltoGroupID(groupID));
}
#endif
//Set Svelto DOTSEntityComponent dotsEntity field to the DOTS entity
@@ -220,14 +220,14 @@ namespace Svelto.ECS.SveltoOnDOTS
var count = (int)(range.rangeEnd - range.rangeStart);
//DOTS entities track Svelto entities through this component
_EManager.AddComponent<DOTSSveltoEGID>(nativeArray);
EManager.AddComponent<DOTSSveltoEGID>(nativeArray);

//set the DOTSSveltoEGID values
var setDOTSSveltoEGIDJob = new SetDOTSSveltoEGID
{
sveltoStartIndex = range.rangeStart,
createdEntities = nativeArray,
entityManager = _EManager,
entityManager = EManager,
ids = sveltoIds,
groupID = groupID
};
@@ -249,7 +249,7 @@ namespace Svelto.ECS.SveltoOnDOTS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DestroyEntitiesBatched(NativeArray<Entity> nativeArray)
{
_EManager.DestroyEntity(nativeArray);
EManager.DestroyEntity(nativeArray);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -298,6 +298,17 @@ namespace Svelto.ECS.SveltoOnDOTS
});
}
}
EntityManager EManager
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
DBC.ECS.Check.Require(_EManager != default, "EManager not initialized, did you forget to add the engine as submission engine?");
return _EManager;
}
}

readonly EntityManager _EManager;
[NativeDisableUnsafePtrRestriction] readonly unsafe JobHandle* _jobHandle;


+ 8
- 6
Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs Просмотреть файл

@@ -29,7 +29,7 @@ namespace Svelto.ECS.SveltoOnDOTS
public SveltoOnDOTSEntitiesSubmissionGroup(SimpleEntitiesSubmissionScheduler submissionScheduler)
{
_submissionScheduler = submissionScheduler;
_submissionEngines = new FasterList<ISveltoOnDOTSStructuralEngine>();
_structuralEngines = new FasterList<ISveltoOnDOTSStructuralEngine>();
}

public EntitiesDB entitiesDB { get; set; }
@@ -56,7 +56,7 @@ namespace Svelto.ECS.SveltoOnDOTS
//Submit Svelto Entities, calls Add/Remove/MoveTo that can be used by the DOTS ECSSubmissionEngines
_submissionScheduler.SubmitEntities();

foreach (var engine in _submissionEngines)
foreach (var engine in _structuralEngines)
engine.OnPostSubmission();

_dotsOperationsForSvelto.Complete();
@@ -65,8 +65,8 @@ namespace Svelto.ECS.SveltoOnDOTS

public void Add(ISveltoOnDOTSStructuralEngine engine)
{
_submissionEngines.Add(engine);
if (World != null)
_structuralEngines.Add(engine);
if (_isReady == true)
{
engine.DOTSOperations = _dotsOperationsForSvelto;
engine.OnOperationsReady();
@@ -79,9 +79,10 @@ namespace Svelto.ECS.SveltoOnDOTS
{
_jobHandle = (JobHandle*) MemoryUtilities.NativeAlloc((uint)MemoryUtilities.SizeOf<JobHandle>(), Allocator.Persistent);
_dotsOperationsForSvelto = new DOTSOperationsForSvelto(World.EntityManager, _jobHandle);
_isReady = true;
//initialise engines field while world was null
foreach (var engine in _submissionEngines)
foreach (var engine in _structuralEngines)
{
engine.DOTSOperations = _dotsOperationsForSvelto;
engine.OnOperationsReady();
@@ -104,9 +105,10 @@ namespace Svelto.ECS.SveltoOnDOTS
throw new NotSupportedException("if this is called something broke the original design");
}

readonly FasterList<ISveltoOnDOTSStructuralEngine> _submissionEngines;
readonly FasterList<ISveltoOnDOTSStructuralEngine> _structuralEngines;
readonly SimpleEntitiesSubmissionScheduler _submissionScheduler;
DOTSOperationsForSvelto _dotsOperationsForSvelto;
bool _isReady;
unsafe JobHandle* _jobHandle;
}
}

+ 2
- 0
README.md Просмотреть файл

@@ -85,6 +85,8 @@ While other frameworks typically limit user freedom to avoid exposing flaws in t

**GroupCompounds** build on this idea by allowing users to change the "state"/"set"/"group" according to tags that serve effectively as adjective or state identifiers.

Entities can change state moving between sets swapping them in groups explcitly, rather than changing archetype.

## Why using Svelto.ECS with Unity?
Svelto.ECS doens't use a traditional archetype model like DOTS ECS does. The novel hybrid approach based on groups instead than archetypes has been designed to allow the user to take the right decision when it comes to states management. Svelto.ECS doesn't allow archetypes to change dynamically, the user cannot add or remove components after the entity is created. Handling entities states with components can quickly lead to very intensive structural changes operations, so groups have been introduced to avoid the wild explosion of states permutations and let the user see explicitly the cost of their decisions.



+ 2
- 2
package.json Просмотреть файл

@@ -11,7 +11,7 @@
"url": "https://github.com/sebas77/Svelto.ECS.git"
},
"dependencies": {
"com.sebaslab.svelto.common": "3.4.2"
"com.sebaslab.svelto.common": "3.4.3"
},
"keywords": [
"svelto",
@@ -19,7 +19,7 @@
"svelto.ecs"
],
"name": "com.sebaslab.svelto.ecs",
"version": "3.4.5",
"version": "3.4.6",
"type": "library",
"unity": "2020.3"
}

Загрузка…
Отмена
Сохранить