@@ -1,7 +1,7 @@ | |||
# 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.1] - 03-2023 | |||
## [3.4.2] - 03-2023 | |||
* removed static caches used in performance critical paths as they were causing unexpected performance issues (the fetching of static data is slower than i imagined) | |||
* add Native prefix in front of the native memory utilities method names | |||
@@ -20,6 +20,17 @@ All notable changes to this project will be documented in this file. Changes are | |||
* Added ValueContainer, a simple int, Tvalue dictionary based on sparse set. It has very specific use cases at the moment. Mainly to be used for the new ECS OOP Abstraction resoruce manager | |||
* Added IReactOnSubmissionStarted interface | |||
### SveltoOnDOTS changes | |||
* update to DOTS 1.0 (but still compatible with 0.51, although slower) | |||
* Deprecated the use of EntityCommandBuffer since was very slow | |||
* added faster batched DOTS operations, new DOTS creation patterns introduced (old one still compatible as long as EntityCommandBuffer was not used) | |||
* ISveltoOnDOTSSubmission interface exists only to allow the user to submit entities On DOTS explicitly, use this instead of | |||
* SveltoOnDOTSHandleCreationEngine is no more, you want to use ISveltoOnDOTSStructuralEngine and its DOTSOperations instead wherever EntityManager was used before | |||
* ISveltoOnDOTSStructuralEngine is no more, you want to use ISveltoOnDOTSStructuralEngine and its DOTSOperations instead | |||
* in all the case above, if you were relying on Update you probably want to use OnPostSubmission instead | |||
* DOTSOperations new AddJobToComplete method will allow to register jobs from inside ISveltoOnDOTSStructuralEngines that will be completed at the end of the submission | |||
## [3.3.2] - 04-06-2022 | |||
* Internal refactoring to support future features. Currently it may translate to a small performance boost | |||
@@ -80,7 +80,7 @@ namespace Svelto.ECS | |||
// Getters of ValueReference must be refs, which would cause a failure on the common check. | |||
if (properties[j].CanRead == true && propertyType.IsByRef == false) | |||
{ | |||
ProcessError(MSG, entityComponentType, propertyType); | |||
ProcessError($"{MSG} Getters of ValueReference must be byref", entityComponentType, propertyType); | |||
} | |||
continue; | |||
@@ -174,8 +174,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]; | |||
@@ -190,13 +192,17 @@ namespace Svelto.ECS | |||
public EGID GetEGID(EntityReference reference) | |||
{ | |||
#if DEBUG && !PROFILE_SVELTO | |||
if (reference == EntityReference.Invalid) | |||
throw new ECSException("Invalid Reference"); | |||
#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]; | |||
#if DEBUG && !PROFILE_SVELTO | |||
if (entityReferenceMapElement.version != reference.version) | |||
throw new ECSException("outdated Reference"); | |||
#endif | |||
return entityReferenceMapElement.egid; | |||
} | |||
@@ -1,7 +1,6 @@ | |||
#if UNITY_ECS | |||
using System.Runtime.CompilerServices; | |||
using Svelto.DataStructures; | |||
using Svelto.DataStructures.Native; | |||
using Svelto.ECS.Internal; | |||
using Unity.Burst; | |||
using Unity.Collections; | |||
@@ -35,18 +34,26 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
public void SetSharedComponent<T>(Entity e, in T component) | |||
where T : unmanaged, ISharedComponentData | |||
{ | |||
#if UNITY_ECS_100 | |||
_EManager.SetSharedComponent(e, component); | |||
#else | |||
_EManager.SetSharedComponentData(e, component); | |||
#endif | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
internal Entity CreateDOTSEntityFromSvelto(Entity prefabEntity, ExclusiveGroupStruct groupID, EntityReference reference) | |||
public Entity CreateDOTSEntityOnSvelto(Entity prefabEntity, EGID egid) | |||
{ | |||
Entity dotsEntity = _EManager.Instantiate(prefabEntity); | |||
//SharedComponentData can be used to group the DOTS ECS entities exactly like the Svelto ones | |||
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(groupID)); | |||
_EManager.AddComponent<DOTSSveltoReference>(dotsEntity); | |||
_EManager.SetComponentData(dotsEntity, new DOTSSveltoReference(reference)); | |||
#if UNITY_ECS_100 | |||
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(egid.groupID)); | |||
#else | |||
_EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID)); | |||
#endif | |||
_EManager.AddComponent<DOTSSveltoEGID>(dotsEntity); | |||
_EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid)); | |||
return dotsEntity; | |||
} | |||
@@ -59,14 +66,18 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// <param name="egid"></param> | |||
/// <returns></returns> | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
internal Entity CreateDOTSEntityFromSvelto(EntityArchetype archetype, ExclusiveGroupStruct groupID, EntityReference reference) | |||
public Entity CreateDOTSEntityOnSvelto(EntityArchetype archetype, EGID egid) | |||
{ | |||
Entity dotsEntity = _EManager.CreateEntity(archetype); | |||
//SharedComponentData can be used to group the DOTS ECS entities exactly like the Svelto ones | |||
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(groupID)); | |||
_EManager.AddComponent<DOTSSveltoReference>(dotsEntity); | |||
_EManager.SetComponentData(dotsEntity, new DOTSSveltoReference(reference)); | |||
#if UNITY_ECS_100 | |||
_EManager.AddSharedComponent(dotsEntity, new DOTSSveltoGroupID(egid.groupID)); | |||
#else | |||
_EManager.AddSharedComponentData(dotsEntity, new DOTSSveltoGroupID(egid.groupID)); | |||
#endif | |||
_EManager.AddComponent<DOTSSveltoEGID>(dotsEntity); | |||
_EManager.SetComponentData(dotsEntity, new DOTSSveltoEGID(egid)); | |||
return dotsEntity; | |||
} | |||
@@ -79,7 +90,7 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// <param name="wireEgid"></param> | |||
/// <returns></returns> | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
internal Entity CreateDOTSEntity(EntityArchetype archetype) | |||
public Entity CreateDOTSEntity(EntityArchetype archetype) | |||
{ | |||
return _EManager.CreateEntity(archetype); | |||
} | |||
@@ -110,12 +121,25 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
_EManager.AddComponent<T>(dotsEntity); | |||
_EManager.SetComponentData(dotsEntity, component); | |||
} | |||
public T GetComponent<T>(Entity dotsEntity) where T : unmanaged, IComponentData | |||
{ | |||
#if UNITY_ECS_100 | |||
return _EManager.GetComponentData<T>(dotsEntity); | |||
#else | |||
return _EManager.GetComponentData<T>(dotsEntity); | |||
#endif | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public void AddSharedComponent<T>(Entity dotsEntity, in T component) | |||
where T : unmanaged, ISharedComponentData | |||
{ | |||
#if UNITY_ECS_100 | |||
_EManager.AddSharedComponent(dotsEntity, component); | |||
#else | |||
_EManager.AddSharedComponentData(dotsEntity, component); | |||
#endif | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
@@ -124,12 +148,27 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
{ | |||
_EManager.AddBuffer<T>(dotsEntity); | |||
} | |||
#if !(DEBUG && !PROFILE_SVELTO) | |||
[System.Diagnostics.Conditional("NO_SENSE")] | |||
#endif | |||
public void SetDebugName(Entity dotsEntity, string name) | |||
{ | |||
_EManager.SetName(dotsEntity, name); | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public void SetSharedComponentBatched<SharedComponentData>(NativeArray<Entity> nativeArray, SharedComponentData SCD) | |||
where SharedComponentData : unmanaged, ISharedComponentData | |||
{ | |||
#if UNITY_ECS_100 | |||
_EManager.SetSharedComponent(nativeArray, SCD); | |||
#else | |||
for (int i = 0; i < nativeArray.Length; i++) | |||
{ | |||
_EManager.SetSharedComponentData(nativeArray[i], SCD); | |||
} | |||
#endif | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
@@ -138,8 +177,9 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
_EManager.AddComponent<T>(DOTSEntities); | |||
} | |||
//can't support publicly the version without DOTSSveltoEGID now | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public NativeArray<Entity> CreateDOTSEntityFromSveltoBatched(Entity prefab, (uint rangeStart, uint rangeEnd) range, | |||
NativeArray<Entity> CreateDOTSEntityFromSveltoBatched(Entity prefab, (uint rangeStart, uint rangeEnd) range, | |||
ExclusiveGroupStruct groupID, NB<DOTSEntityComponent> DOSTEntityComponents) | |||
{ | |||
unsafe | |||
@@ -148,7 +188,15 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
var count = (int)(range.rangeEnd - range.rangeStart); | |||
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)); | |||
} | |||
#endif | |||
var setDOTSEntityComponentsJob = new SetDOTSEntityComponents | |||
{ | |||
@@ -164,25 +212,24 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public NativeArray<Entity> CreateDOTSEntityFromSveltoBatched(Entity prefab, (uint rangeStart, uint rangeEnd) range, | |||
ExclusiveGroupStruct groupID, NB<DOTSEntityComponent> DOSTEntityComponents, | |||
SharedSveltoDictionaryNative<uint, EntityReference> referenceMap, NativeEntityIDs sveltoIds, out JobHandle creationJob) | |||
ExclusiveGroupStruct groupID, NB<DOTSEntityComponent> DOSTEntityComponents, NativeEntityIDs sveltoIds, out JobHandle creationJob) | |||
{ | |||
var nativeArray = CreateDOTSEntityFromSveltoBatched(prefab, range, groupID, DOSTEntityComponents); | |||
unsafe | |||
{ | |||
var count = (int)(range.rangeEnd - range.rangeStart); | |||
_EManager.AddComponent<DOTSSveltoReference>(nativeArray); | |||
_EManager.AddComponent<DOTSSveltoEGID>(nativeArray); | |||
var SetDOTSSveltoReferenceJob = new SetDOTSSveltoReference | |||
var SetDOTSSveltoEGIDJob = new SetDOTSSveltoEGID | |||
{ | |||
sveltoStartIndex = range.rangeStart, | |||
createdEntities = nativeArray, | |||
entityManager = _EManager, | |||
ids = sveltoIds, | |||
entityReferenceMap = referenceMap, | |||
groupID = groupID | |||
}; | |||
creationJob = *_jobHandle = JobHandle.CombineDependencies(*_jobHandle, SetDOTSSveltoReferenceJob.ScheduleParallel(count, default)); | |||
creationJob = *_jobHandle = JobHandle.CombineDependencies(*_jobHandle, SetDOTSSveltoEGIDJob.ScheduleParallel(count, default)); | |||
return nativeArray; | |||
} | |||
@@ -229,13 +276,13 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
} | |||
[BurstCompile] | |||
public struct SetDOTSSveltoReference: IJobParallelFor | |||
public struct SetDOTSSveltoEGID: IJobParallelFor | |||
{ | |||
public uint sveltoStartIndex; | |||
[ReadOnly] public NativeArray<Entity> createdEntities; | |||
[NativeDisableParallelForRestriction] public EntityManager entityManager; | |||
public NativeEntityIDs ids; | |||
public SharedSveltoDictionaryNative<uint, EntityReference> entityReferenceMap; | |||
public ExclusiveGroupStruct groupID; | |||
public void Execute(int currentIndex) | |||
{ | |||
@@ -243,9 +290,9 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
var dotsEntity = createdEntities[currentIndex]; | |||
entityManager.SetComponentData( | |||
dotsEntity, new DOTSSveltoReference | |||
dotsEntity, new DOTSSveltoEGID | |||
{ | |||
entityReference = entityReferenceMap[ids[index]] | |||
egid = new EGID(ids[index], groupID) | |||
}); | |||
} | |||
} | |||
@@ -4,10 +4,7 @@ using Unity.Jobs; | |||
namespace Svelto.ECS.SveltoOnDOTS | |||
{ | |||
/// <summary> | |||
/// Note: we don't want implementations of ISveltoDOTSSubmission | |||
/// to be able to add directly Submission or HandleLifeTime engines as | |||
/// the implementation are not aware of EnginesRoot so cannot satisfy Engines | |||
/// that implement IEngine interfaces | |||
/// this interface exists to allow the user to submig entities explicitly | |||
/// </summary> | |||
public interface ISveltoOnDOTSSubmission | |||
{ | |||
@@ -30,16 +30,16 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// <summary> | |||
/// DOTS component to keep track of the associated Svelto.ECS entity | |||
/// </summary> | |||
public struct DOTSSveltoReference: IComponentData | |||
public struct DOTSSveltoEGID: IComponentData | |||
{ | |||
public EntityReference entityReference; | |||
public EGID egid; | |||
public DOTSSveltoReference(EntityReference eEntityReference) | |||
public DOTSSveltoEGID(EGID egid) | |||
{ | |||
entityReference = eEntityReference; | |||
this.egid = egid; | |||
} | |||
} | |||
/// <summary> | |||
/// DOTS component to be able to query all the DOTS entities found in a Svelto.ECS group | |||
/// </summary> | |||
@@ -10,7 +10,10 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
DOTSOperationsForSvelto DOTSOperations { get; set; } | |||
string name { get; } | |||
//use case is i.e. to create archetypes once | |||
void OnOperationsReady(); | |||
//use case is i.e. to operate once per submission on entities just created | |||
void OnPostSubmission(); | |||
} | |||
} |
@@ -39,6 +39,7 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// for the user to add pure DOTS ECS SystemBase/ISystem systems to the DOTS ECS world | |||
/// </summary> | |||
public World world { get; private set; } | |||
public ISveltoOnDOTSSubmission submitter => _sveltoDotsEntitiesSubmissionGroup; | |||
public JobHandle Execute(JobHandle inputDeps) | |||
{ | |||
@@ -62,7 +63,11 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
public void AddSveltoToDOTSSyncEngine(SyncSveltoToDOTSEngine engine) | |||
{ | |||
//it's a Svelto Engine/DOTS ECS SystemBase so it must be added in the DOTS ECS world AND svelto enginesRoot | |||
#if UNITY_ECS_100 | |||
world.AddSystemManaged(engine); | |||
#else | |||
world.AddSystem(engine); | |||
#endif | |||
_enginesRoot.AddEngine(engine); | |||
@@ -72,7 +77,11 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
public void AddDOTSToSveltoSyncEngine(SyncDOTSToSveltoEngine engine) | |||
{ | |||
//it's a Svelto Engine/DOTS ECS SystemBase so it must be added in the DOTS ECS world AND svelto enginesRoot | |||
#if UNITY_ECS_100 | |||
world.AddSystemManaged(engine); | |||
#else | |||
world.AddSystem(engine); | |||
#endif | |||
_enginesRoot.AddEngine(engine); | |||
_syncDotsToSveltoGroup.Add(engine); | |||
@@ -108,7 +117,11 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
_sveltoDotsEntitiesSubmissionGroup.Add(defaultSveltoOnDotsHandleLifeTimeEngine); | |||
enginesRoot.AddEngine(_sveltoDotsEntitiesSubmissionGroup); | |||
#if UNITY_ECS_100 | |||
world.AddSystemManaged(_sveltoDotsEntitiesSubmissionGroup); | |||
#else | |||
world.AddSystem(_sveltoDotsEntitiesSubmissionGroup); | |||
#endif | |||
//This is the group that handles the DOTS ECS sync systems that copy the svelto entities values to DOTS ECS entities | |||
_syncSveltoToDotsGroup = new SyncSveltoToDOTSGroup(); | |||
@@ -1,12 +1,11 @@ | |||
#if UNITY_ECS | |||
#if !UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD | |||
#if !UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD && !UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP | |||
#error SveltoOnDOTS required the user to take over the DOTS world control and explicitly create it. UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP must be defined | |||
#endif | |||
using System; | |||
using Svelto.Common; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Schedulers; | |||
using Unity.Collections.LowLevel.Unsafe; | |||
using Unity.Entities; | |||
using Unity.Jobs; | |||
@@ -25,7 +24,7 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// ISveltoOnDOTSStructuralEngine can use DOTSOperationsForSvelto in their add/remove/moove callbacks | |||
/// </summary> | |||
[DisableAutoCreation] | |||
public sealed partial class SveltoOnDOTSEntitiesSubmissionGroup: SystemBase, IQueryingEntitiesEngine, ISveltoOnDOTSSubmission | |||
public sealed partial class SveltoOnDOTSEntitiesSubmissionGroup: SystemBase, IQueryingEntitiesEngine, ISveltoOnDOTSSubmission | |||
{ | |||
public SveltoOnDOTSEntitiesSubmissionGroup(SimpleEntitiesSubmissionScheduler submissionScheduler) | |||
{ | |||
@@ -47,7 +46,11 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
using (profiler.Sample("Complete All Pending Jobs")) | |||
{ | |||
jobHandle.Complete(); //sync-point | |||
#if UNITY_ECS_100 | |||
EntityManager.CompleteAllTrackedJobs(); | |||
#else | |||
EntityManager.CompleteAllJobs(); | |||
#endif | |||
} | |||
//Submit Svelto Entities, calls Add/Remove/MoveTo that can be used by the DOTS ECSSubmissionEngines | |||
@@ -64,7 +67,10 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
{ | |||
_submissionEngines.Add(engine); | |||
if (World != null) | |||
{ | |||
engine.DOTSOperations = _dotsOperationsForSvelto; | |||
engine.OnOperationsReady(); | |||
} | |||
} | |||
protected override void OnCreate() | |||
@@ -76,7 +82,10 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
//initialise engines field while world was null | |||
foreach (var engine in _submissionEngines) | |||
{ | |||
engine.DOTSOperations = _dotsOperationsForSvelto; | |||
engine.OnOperationsReady(); | |||
} | |||
} | |||
} | |||
@@ -8,16 +8,17 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
/// Automatic Svelto Group -> DOTS archetype synchronization when necessary | |||
/// </summary> | |||
/// <typeparam name="DOTSEntityComponent"></typeparam> | |||
class SveltoOnDOTSHandleLifeTimeEngine<DOTSEntityComponent>: ISveltoOnDOTSStructuralEngine, IReactOnRemoveEx<DOTSEntityComponent>, | |||
public class SveltoOnDOTSHandleLifeTimeEngine<DOTSEntityComponent>: ISveltoOnDOTSStructuralEngine, IReactOnRemoveEx<DOTSEntityComponent>, | |||
IReactOnSwapEx<DOTSEntityComponent> where DOTSEntityComponent : unmanaged, IEntityComponentForDOTS | |||
{ | |||
public void Remove((uint start, uint end) rangeOfEntities, in EntityCollection<DOTSEntityComponent> entities, ExclusiveGroupStruct groupID) | |||
{ | |||
//todo burstify all of this if DOTS 1.0 is on | |||
var (buffer, _) = entities; | |||
var nativeArray = new NativeArray<Entity>((int)(rangeOfEntities.end - rangeOfEntities.start), Allocator.Temp); | |||
//todo this could be burstified or memcpied | |||
int counter = 0; | |||
for (uint i = rangeOfEntities.start; i < rangeOfEntities.end; i++) | |||
nativeArray[counter++] = buffer[i].dotsEntity; | |||
@@ -28,19 +29,25 @@ namespace Svelto.ECS.SveltoOnDOTS | |||
public void MovedTo((uint start, uint end) rangeOfEntities, in EntityCollection<DOTSEntityComponent> entities, | |||
ExclusiveGroupStruct _, ExclusiveGroupStruct toGroup) | |||
{ | |||
var (buffer, _) = entities; | |||
//todo burstify all of this if DOTS 1.0 is on | |||
var (buffer, ids, _) = entities; | |||
var nativeArray = new NativeArray<Entity>((int)(rangeOfEntities.end - rangeOfEntities.start), Allocator.Temp); | |||
//todo this could be burstified or memcpied | |||
int counter = 0; | |||
for (uint i = rangeOfEntities.start; i < rangeOfEntities.end; i++) | |||
nativeArray[counter++] = buffer[i].dotsEntity; | |||
DOTSOperations.SetSharedComponentBatched(nativeArray, new DOTSSveltoGroupID(toGroup)); | |||
counter = 0; | |||
for (uint i = rangeOfEntities.start; i < rangeOfEntities.end; i++) | |||
DOTSOperations.SetComponent(nativeArray[counter++], new DOTSSveltoEGID(new EGID(ids[i], toGroup))); | |||
} | |||
public void OnPostSubmission() { } | |||
public void OnOperationsReady() {} | |||
public void OnPostSubmission() {} | |||
public DOTSOperationsForSvelto DOTSOperations { get; set; } | |||
public string name => nameof(SveltoOnDOTSHandleLifeTimeEngine<DOTSEntityComponent>); | |||
@@ -19,7 +19,7 @@ | |||
"svelto.ecs" | |||
], | |||
"name": "com.sebaslab.svelto.ecs", | |||
"version": "3.4.1", | |||
"version": "3.4.2", | |||
"type": "library", | |||
"unity": "2020.3" | |||
} |
@@ -1,3 +1,3 @@ | |||
{ | |||
"version": "3.4.1" | |||
"version": "3.4.2" | |||
} |