Skip to content

Commit 2920dac

Browse files
committed
Version 0.12.5 Release [Bugfix]
Bugfix release
1 parent e5596fd commit 2920dac

File tree

8 files changed

+243
-14
lines changed

8 files changed

+243
-14
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ You can find changelogs for the individual modules in the [official Latios
1010
Framework Documentation
1111
repository](https://github.com/Dreaming381/Latios-Framework-Documentation).
1212

13+
## [0.12.5] – 2025-4-12
14+
15+
Officially supports Entities [1.3.9]
16+
17+
### Changed
18+
19+
- Updated Core to v0.12.5
20+
- Updated Psyshock to v0.12.5
21+
- Updated Unika to v0.12.5
22+
1323
## [0.12.4] – 2025-4-5
1424

1525
Officially supports Entities [1.3.9]

Core/Containers/CommandBuffers/AddComponentsCommandBuffer.cs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,171 @@ public enum AddComponentsDestroyedEntityResolution
1414
AddToNewEntityAndDestroy
1515
}
1616

17+
[BurstCompile]
18+
public struct AddComponentsCommandBuffer : INativeDisposable
19+
{
20+
#region Structure
21+
private EntityOperationCommandBuffer m_entityOperationCommandBuffer;
22+
private ComponentTypeSet m_typesToAdd;
23+
private AddComponentsDestroyedEntityResolution m_resolution;
24+
private NativeReference<bool> m_playedBack;
25+
#endregion
26+
27+
#region CreateDestroy
28+
/// <summary>
29+
/// Create an AddComponentsCommandBuffer which can be used to add default components to entities and play them back later.
30+
/// </summary>
31+
/// <param name="allocator">The type of allocator to use for allocating the buffer</param>
32+
/// <param name="resolution">What to do when an entity no longer exists</param>
33+
public AddComponentsCommandBuffer(AllocatorManager.AllocatorHandle allocator, AddComponentsDestroyedEntityResolution resolution)
34+
{
35+
m_entityOperationCommandBuffer = new EntityOperationCommandBuffer(allocator);
36+
m_typesToAdd = default;
37+
m_resolution = resolution;
38+
m_playedBack = new NativeReference<bool>(allocator);
39+
}
40+
41+
/// <summary>
42+
/// Disposes the AddComponentsCommandBuffer after the jobs which use it have finished.
43+
/// </summary>
44+
/// <param name="inputDeps">The JobHandle for any jobs previously using this AddComponentsCommandBuffer</param>
45+
/// <returns></returns>
46+
public JobHandle Dispose(JobHandle inputDeps)
47+
{
48+
var jh0 = m_entityOperationCommandBuffer.Dispose(inputDeps);
49+
var jh1 = m_playedBack.Dispose(inputDeps);
50+
return JobHandle.CombineDependencies(jh0, jh1);
51+
}
52+
53+
/// <summary>
54+
/// Disposes the AddComponentsCommandBuffer
55+
/// </summary>
56+
public void Dispose()
57+
{
58+
m_entityOperationCommandBuffer.Dispose();
59+
m_playedBack.Dispose();
60+
}
61+
#endregion
62+
63+
#region PublicAPI
64+
/// <summary>
65+
/// Adds an Entity to the AddComponentsCommandBuffer which should be have the components added to
66+
/// </summary>
67+
/// <param name="entity">The entity to add components too</param>
68+
/// <param name="sortKey">The sort key for deterministic playback if interleaving single and parallel writes</param>
69+
public void Add(Entity entity, int sortKey = int.MaxValue)
70+
{
71+
CheckDidNotPlayback();
72+
m_entityOperationCommandBuffer.Add(entity, sortKey);
73+
}
74+
75+
/// <summary>
76+
/// Plays back the AddComponentsCommandBuffer.
77+
/// </summary>
78+
/// <param name="entityManager">The EntityManager with which to play back the AddComponentsCommandBuffer</param>
79+
public unsafe void Playback(EntityManager entityManager)
80+
{
81+
CheckDidNotPlayback();
82+
Playbacker.Playback((AddComponentsCommandBuffer*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager));
83+
}
84+
85+
/// <summary>
86+
/// Get the number of entities stored in this InstantiateCommandBuffer. This method performs a summing operation on every invocation.
87+
/// </summary>
88+
/// <returns>The number of elements stored in this InstantiateCommandBuffer</returns>
89+
public int Count() => m_entityOperationCommandBuffer.Count();
90+
91+
/// <summary>
92+
/// Set additional component types to be added to the target entities. These components will be default-initialized.
93+
/// </summary>
94+
/// <param name="tags">The types to add to each target entity</param>
95+
public void SetComponentTags(ComponentTypeSet tags)
96+
{
97+
m_typesToAdd = tags;
98+
}
99+
100+
/// <summary>
101+
/// Gets the ParallelWriter for this AddComponentsCommandBuffer.
102+
/// </summary>
103+
/// <returns>The ParallelWriter which shares this AddComponentsCommandBuffer's backing storage.</returns>
104+
public ParallelWriter AsParallelWriter()
105+
{
106+
CheckDidNotPlayback();
107+
return new ParallelWriter(m_entityOperationCommandBuffer);
108+
}
109+
#endregion
110+
111+
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
112+
void CheckDidNotPlayback()
113+
{
114+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
115+
if (m_playedBack.Value == true)
116+
throw new System.InvalidOperationException(
117+
"The AddComponentsCommandBuffer has already been played back. You cannot write more commands to it or play it back again.");
118+
#endif
119+
}
120+
121+
#region PlaybackJobs
122+
[BurstCompile]
123+
static class Playbacker
124+
{
125+
[BurstCompile]
126+
public static unsafe void Playback(AddComponentsCommandBuffer* accb, EntityManager* em)
127+
{
128+
var targets = accb->m_entityOperationCommandBuffer.GetEntities(Allocator.Temp);
129+
int dst = 0;
130+
for (int src = 0; src < targets.Length; src++)
131+
{
132+
var e = targets[src];
133+
if (em->Exists(e))
134+
{
135+
targets[dst] = e;
136+
dst++;
137+
}
138+
else
139+
{
140+
if (accb->m_resolution == AddComponentsDestroyedEntityResolution.ThrowException)
141+
throw new System.InvalidOperationException($"Entity {e.ToFixedString()} in AddComponentsCommandBuffer has been destroyed.");
142+
else if (accb->m_resolution == AddComponentsDestroyedEntityResolution.AddToNewEntityAndDestroy)
143+
{
144+
e = em->CreateEntity();
145+
em->AddComponent(e, accb->m_typesToAdd);
146+
}
147+
}
148+
}
149+
targets.GetSubArray(0, dst);
150+
em->AddComponent(targets, in accb->m_typesToAdd);
151+
accb->m_playedBack.Value = true;
152+
}
153+
}
154+
#endregion
155+
156+
#region ParallelWriter
157+
/// <summary>
158+
/// The parallelWriter implementation of AddComponentsCommandBuffer. Use AsParallelWriter to obtain one from an AddComponentsCommandBuffer
159+
/// </summary>
160+
public struct ParallelWriter
161+
{
162+
private EntityOperationCommandBuffer.ParallelWriter m_entityOperationCommandBuffer;
163+
164+
internal ParallelWriter(EntityOperationCommandBuffer eocb)
165+
{
166+
m_entityOperationCommandBuffer = eocb.AsParallelWriter();
167+
}
168+
169+
/// <summary>
170+
/// Adds an Entity to the AddComponentsCommandBuffer which should have the components added
171+
/// </summary>
172+
/// <param name="entity">The entity to have the components added to</param>
173+
/// <param name="sortKey">The sort key for deterministic playback</param>
174+
public void Add(Entity entity, int sortKey)
175+
{
176+
m_entityOperationCommandBuffer.Add(entity, sortKey);
177+
}
178+
}
179+
#endregion
180+
}
181+
17182
/// <summary>
18183
/// A specialized variant of the EntityCommandBuffer exclusively for adding components to entities.
19184
/// This variant initializes the specified component type with specified values per instance.

Core/GameplayToolkit/DynamicHashMap.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using Latios.Unsafe;
45
using Unity.Collections;
56
using Unity.Collections.LowLevel.Unsafe;
67
using Unity.Entities;
@@ -9,7 +10,9 @@
910
namespace Latios
1011
{
1112
/// <summary>
12-
/// A wrapper type around a DynamicBuffer which provides HashMap capabilities while maintaining full serialization support.
13+
/// A wrapper type around a DynamicBuffer which provides HashMap capabilities while maintaining value serialization support.
14+
/// Key serialization requires explicit reconstruction for any remappable types (Entity, BlobAssetReference, ect). This can
15+
/// be done by calling ReconstructAfterRemap().
1316
/// </summary>
1417
/// <remarks>
1518
/// The general strategy of this map is that for a given power of two capacity, the first half is allocated for buckets,
@@ -206,6 +209,25 @@ public bool Remove(in TKey key)
206209
return false;
207210
}
208211

212+
/// <summary>
213+
/// Reorders the hashmap to adjust for entries whose hashcodes may have changed after a remap.
214+
/// </summary>
215+
public void ReconstructAfterRemap()
216+
{
217+
var length = count;
218+
using var allocator = ThreadStackAllocator.GetAllocator();
219+
var pairs = allocator.AllocateAsSpan<(TKey, TValue)>(length);
220+
int i = 0;
221+
foreach (var p in this)
222+
{
223+
pairs[i] = p;
224+
i++;
225+
}
226+
Clear();
227+
foreach (var p in pairs)
228+
TryAdd(p.Item1, p.Item2);
229+
}
230+
209231
public Enumerator GetEnumerator() => new Enumerator {
210232
m_enumerator = m_buffer.GetEnumerator()
211233
};

Core/Systems/_Essentials/SyncPointPlaybackSystem.cs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ enum PlaybackType
6565
Destroy,
6666
InstantiateNoData,
6767
InstantiateUntyped,
68+
AddComponentsNoData,
6869
AddComponentsUntyped,
6970
}
7071

@@ -80,6 +81,7 @@ struct PlaybackInstance
8081
NativeList<DestroyCommandBuffer> m_destroyCommandBuffers;
8182
NativeList<InstantiateCommandBuffer> m_instantiateCommandBuffersWithoutData;
8283
NativeList<InstantiateCommandBufferUntyped> m_instantiateCommandBuffersUntyped;
84+
NativeList<AddComponentsCommandBuffer> m_addComponentsCommandBuffersWithoutData;
8385
NativeList<AddComponentsCommandBufferUntyped> m_addComponentsCommandBuffersUntyped;
8486

8587
NativeList<JobHandle> m_jobHandles;
@@ -100,6 +102,7 @@ struct PlaybackInstance
100102
int m_destroyIndex;
101103
int m_instantiateNoDataIndex;
102104
int m_instantiateUntypedIndex;
105+
int m_addComponentsNoDataIndex;
103106
int m_addComponentsUntypedIndex;
104107

105108
internal NativeText.ReadOnly m_requestSystemNameForCurrentBuffer;
@@ -120,14 +123,15 @@ public void OnCreate(ref SystemState state)
120123
m_commandBufferAllocator = new AllocatorHelper<RewindableAllocator>(Allocator.Persistent);
121124
m_commandBufferAllocator.Allocator.Initialize(16 * 1024);
122125

123-
m_playbackInstances = new NativeList<PlaybackInstance>(Allocator.Persistent);
124-
m_entityCommandBuffers = new NativeList<EntityCommandBuffer>(Allocator.Persistent);
125-
m_enableCommandBuffers = new NativeList<EnableCommandBuffer>(Allocator.Persistent);
126-
m_disableCommandBuffers = new NativeList<DisableCommandBuffer>(Allocator.Persistent);
127-
m_destroyCommandBuffers = new NativeList<DestroyCommandBuffer>(Allocator.Persistent);
128-
m_instantiateCommandBuffersWithoutData = new NativeList<InstantiateCommandBuffer>(Allocator.Persistent);
129-
m_instantiateCommandBuffersUntyped = new NativeList<InstantiateCommandBufferUntyped>(Allocator.Persistent);
130-
m_addComponentsCommandBuffersUntyped = new NativeList<AddComponentsCommandBufferUntyped>(Allocator.Persistent);
126+
m_playbackInstances = new NativeList<PlaybackInstance>(Allocator.Persistent);
127+
m_entityCommandBuffers = new NativeList<EntityCommandBuffer>(Allocator.Persistent);
128+
m_enableCommandBuffers = new NativeList<EnableCommandBuffer>(Allocator.Persistent);
129+
m_disableCommandBuffers = new NativeList<DisableCommandBuffer>(Allocator.Persistent);
130+
m_destroyCommandBuffers = new NativeList<DestroyCommandBuffer>(Allocator.Persistent);
131+
m_instantiateCommandBuffersWithoutData = new NativeList<InstantiateCommandBuffer>(Allocator.Persistent);
132+
m_instantiateCommandBuffersUntyped = new NativeList<InstantiateCommandBufferUntyped>(Allocator.Persistent);
133+
m_addComponentsCommandBuffersWithoutData = new NativeList<AddComponentsCommandBuffer>(Allocator.Persistent);
134+
m_addComponentsCommandBuffersUntyped = new NativeList<AddComponentsCommandBufferUntyped>(Allocator.Persistent);
131135

132136
m_jobHandles = new NativeList<JobHandle>(Allocator.Persistent);
133137

@@ -152,6 +156,7 @@ public void OnDestroy(ref SystemState state)
152156
m_destroyCommandBuffers.Dispose();
153157
m_instantiateCommandBuffersWithoutData.Dispose();
154158
m_instantiateCommandBuffersUntyped.Dispose();
159+
m_addComponentsCommandBuffersWithoutData.Dispose();
155160
m_addComponentsCommandBuffersUntyped.Dispose();
156161

157162
m_externalSourceText.Dispose();
@@ -188,6 +193,7 @@ public void OnUpdate(ref SystemState state)
188193
case PlaybackType.Destroy: m_currentBufferTypeName = "DestroyCommandBuffer"; break;
189194
case PlaybackType.InstantiateNoData: m_currentBufferTypeName = "InstantiateCommandBuffer"; break;
190195
case PlaybackType.InstantiateUntyped: m_currentBufferTypeName = "InstantiateCommandBuffer"; break;
196+
case PlaybackType.AddComponentsNoData: m_currentBufferTypeName = "AddComponenstCommandBuffer"; break;
191197
case PlaybackType.AddComponentsUntyped: m_currentBufferTypeName = "AddComponentsCommandBuffer"; break;
192198
}
193199
if (state.WorldUnmanaged.IsSystemValid(instance.requestingSystem))
@@ -245,6 +251,13 @@ public void OnUpdate(ref SystemState state)
245251
icb.Playback(state.EntityManager);
246252
break;
247253
}
254+
case PlaybackType.AddComponentsNoData:
255+
{
256+
var accb = m_addComponentsCommandBuffersWithoutData[m_addComponentsNoDataIndex];
257+
m_addComponentsNoDataIndex++;
258+
accb.Playback(state.EntityManager);
259+
break;
260+
}
248261
case PlaybackType.AddComponentsUntyped:
249262
{
250263
var accb = m_addComponentsCommandBuffersUntyped[m_addComponentsUntypedIndex];
@@ -274,6 +287,7 @@ public void OnUpdate(ref SystemState state)
274287
m_destroyCommandBuffers.Clear();
275288
m_instantiateCommandBuffersWithoutData.Clear();
276289
m_instantiateCommandBuffersUntyped.Clear();
290+
m_addComponentsCommandBuffersWithoutData.Clear();
277291
m_addComponentsCommandBuffersUntyped.Clear();
278292

279293
m_entityIndex = 0;
@@ -282,6 +296,7 @@ public void OnUpdate(ref SystemState state)
282296
m_destroyIndex = 0;
283297
m_instantiateNoDataIndex = 0;
284298
m_instantiateUntypedIndex = 0;
299+
m_addComponentsNoDataIndex = 0;
285300
m_addComponentsUntypedIndex = 0;
286301

287302
m_commandBufferAllocator.Allocator.Rewind();
@@ -463,6 +478,23 @@ public InstantiateCommandBuffer<T0, T1, T2, T3, T4> CreateInstantiateCommandBuff
463478
return icb;
464479
}
465480

481+
/// <summary>
482+
/// Creates a new AddComponentsCommandBuffer that will be played back by this system.
483+
/// </summary>
484+
public AddComponentsCommandBuffer CreateAddComponentsCommandBuffer(AddComponentsDestroyedEntityResolution destroyedEntityResolution)
485+
{
486+
m_hasPendingJobHandlesToAcquire = true;
487+
var accb = new AddComponentsCommandBuffer(m_commandBufferAllocator.Allocator.Handle.ToAllocator, destroyedEntityResolution);
488+
var instance = new PlaybackInstance
489+
{
490+
type = PlaybackType.AddComponentsNoData,
491+
requestingSystem = m_world.m_impl->m_worldUnmanaged.GetCurrentlyExecutingSystem()
492+
};
493+
m_playbackInstances.Add(instance);
494+
m_addComponentsCommandBuffersWithoutData.Add(accb);
495+
return accb;
496+
}
497+
466498
/// <summary>
467499
/// Creates a new AddComponentsCommandBuffer that will be played back by this system.
468500
/// </summary>

PsyshockPhysics/Physics/Types/Colliders/TriMeshColliderPsyshock.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ public static unsafe BlobAssetReference<TriMeshColliderBlob> BuildBlob(ref BlobB
159159
{
160160
using ThreadStackAllocator tsa = ThreadStackAllocator.GetAllocator();
161161

162-
var bodiesCachePtr = tsa.Allocate<ColliderBody>(indices.Length / 3);
163-
var bodiesCache = CollectionHelper.ConvertExistingDataToNativeArray<ColliderBody>(bodiesCachePtr, indices.Length / 3, Allocator.None, true);
162+
var bodiesCachePtr = tsa.Allocate<ColliderBody>(indices.Length);
163+
var bodiesCache = CollectionHelper.ConvertExistingDataToNativeArray<ColliderBody>(bodiesCachePtr, indices.Length, Allocator.None, true);
164164
for (int i = 0; i < bodiesCache.Length; i++)
165165
{
166166
var tri = indices[i];

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![](https://github.com/Dreaming381/Latios-Framework-Documentation/blob/554a583e217bfe5bf38ece0ed65b22c33711afc6/media/bf2cb606139bb3ca01fe1c4c9f92cdf7.png)
22

3-
# Latios Framework for Unity ECS – [0.12.4]
3+
# Latios Framework for Unity ECS – [0.12.5]
44

55
The Latios Framework is a powerful suite of high-performance low-level APIs and
66
feature-sets for Unity’s ECS which aims to give you back control over your

Unika/Utilities/ScriptCast.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public static bool TryResolve(this ref ScriptRef scriptRef, in EntityScriptColle
119119
return false;
120120
}
121121

122-
if (math.clamp(scriptRef.m_cachedHeaderIndex, 0, allScripts.length) == scriptRef.m_cachedHeaderIndex)
122+
if (math.clamp(scriptRef.m_cachedHeaderIndex, 0, allScripts.length - 1) == scriptRef.m_cachedHeaderIndex)
123123
{
124124
var candidate = allScripts[scriptRef.m_cachedHeaderIndex];
125125
if (candidate.m_headerRO.instanceId == scriptRef.m_instanceId)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "com.latios.latiosframework",
33
"displayName": "Latios Framework for ECS",
4-
"version": "0.12.4",
4+
"version": "0.12.5",
55
"unity": "6000.0",
66
"description": "Latios Framework for ECS is a collection of tools, algorithms, and API extensions developed by a hardcore hobbyist game developer.\n\nThis package includes all of the following modules:\n\u25aa Core\n\u25aa QVVS Transforms\n\u25aa Psyshock Physics\n\u25aa Myri Audio\n\u25aa Kinemation Animation and Rendering\n\u25aa Caligraphics\n\u25aa LifeFX\n\u25aa Unika\n\nExamples: \n\u25aa Latios Space Shooter Sample - https://github.com/Dreaming381/lsss-wip \n\u25aa Mini Demos - https://github.com/Dreaming381/LatiosFrameworkMiniDemos \n\u25aa Free Parking - https://github.com/Dreaming381/Free-Parking",
77
"documentationURL": "https://github.com/Dreaming381/Latios-Framework-Documentation",

0 commit comments

Comments
 (0)