Browse Source

Svelto.ECS 3.4.6

pull/109/head
Sebastiano Mandala 1 year ago
parent
commit
79dd4f0022
14 changed files with 95 additions and 74 deletions
  1. +1
    -1
      com.sebaslab.svelto.common
  2. +4
    -4
      com.sebaslab.svelto.ecs/CHANGELOG.md
  3. +5
    -0
      com.sebaslab.svelto.ecs/Core/ComponentTypeID.cs
  4. +6
    -5
      com.sebaslab.svelto.ecs/Core/ComponentTypeMap.cs
  5. +2
    -2
      com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs
  6. +2
    -2
      com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs
  7. +2
    -2
      com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs
  8. +4
    -10
      com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs
  9. +4
    -1
      com.sebaslab.svelto.ecs/Core/Groups/GroupCompound.cs
  10. +15
    -10
      com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs
  11. +39
    -28
      com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/DOTSOperationsForSvelto.cs
  12. +8
    -6
      com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs
  13. +2
    -2
      com.sebaslab.svelto.ecs/package.json
  14. +1
    -1
      com.sebaslab.svelto.ecs/version.json

+ 1
- 1
com.sebaslab.svelto.common

@@ -1 +1 @@
Subproject commit b3b6ad7f922cfdac70d1ee5c28c580ddd451a1ff
Subproject commit 409d48a06c109b857b3da1699538d03f675d9192

+ 4
- 4
com.sebaslab.svelto.ecs/CHANGELOG.md View File

@@ -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
com.sebaslab.svelto.ecs/Core/ComponentTypeID.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/ComponentTypeMap.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs View File

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



+ 2
- 2
com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/Groups/GroupCompound.cs View File

@@ -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
com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs View File

@@ -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
com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/DOTSOperationsForSvelto.cs View File

@@ -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
com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs View File

@@ -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
- 2
com.sebaslab.svelto.ecs/package.json View File

@@ -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"
}

+ 1
- 1
com.sebaslab.svelto.ecs/version.json View File

@@ -1,3 +1,3 @@
{
"version": "3.4.5"
"version": "3.4.6"
}

Loading…
Cancel
Save