Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit 05ec260

Browse files
BryanJY-WongJamie Brynes
and
Jamie Brynes
authored
UTY-2661: Improve snapshot api (#1479)
Improve `Snapshot` API: - Added method to check if `EntityId` is valid - Improve search for next available `EntityId` - Throws exception when adding duplicate `EntityId` - Implement `IDisposable` to free native memory Co-authored-by: Jamie Brynes <[email protected]>
1 parent a9e1e7d commit 05ec260

File tree

5 files changed

+145
-8
lines changed

5 files changed

+145
-8
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
- The minimum supported version of Unity is now 2020.1. [#1459](https://github.com/spatialos/gdk-for-unity/pull/1459)
88
- Upgraded Unity Entities to 0.14.0-preview.18. [#1463](https://github.com/spatialos/gdk-for-unity/pull/1463)
99
- Projects now require the `Unity Web Request` built-in package to compile for iOS and Android.
10+
- Adding an entity to the `Snapshot` class with a duplicate entity ID now throws an exception. [#1479](https://github.com/spatialos/gdk-for-unity/pull/1479)
1011

1112
### Added
1213

1314
- Added `MeansImplicitUse` attribute to `RequireAttribute` to reduce warnings in Rider IDE. [#1462](https://github.com/spatialos/gdk-for-unity/pull/1462)
1415
- Added Event Tracing API. [#1452](https://github.com/spatialos/gdk-for-unity/pull/1452)
1516
- Added tooltips to the SpatialOS Project Settings. [#1470](https://github.com/spatialos/gdk-for-unity/pull/1470)
17+
- Added new features to the `Snapshot` class [#1479](https://github.com/spatialos/gdk-for-unity/pull/1479)
18+
- Added the `Contains(EntityId entityId)` method to check if snapshot already contains an `EntityId`
19+
- Improved the search for next available `EntityId`, it will no longer return already used `EntityId`s.
20+
- `Snapshot` now auto-adds `Persistence` when adding entities
21+
- `Snapshot` now implements `IDisposable`
1622

1723
### Changed
1824

workers/unity/Assets/Playground/Editor/SnapshotGenerator/SnapshotGenerator.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ public struct Arguments
1919
public static void Generate(Arguments arguments)
2020
{
2121
Debug.Log("Generating snapshot.");
22-
var snapshot = CreateSnapshot(arguments.NumberEntities);
23-
24-
Debug.Log($"Writing snapshot to: {arguments.OutputPath}");
25-
snapshot.WriteToFile(arguments.OutputPath);
22+
using (var snapshot = CreateSnapshot(arguments.NumberEntities))
23+
{
24+
Debug.Log($"Writing snapshot to: {arguments.OutputPath}");
25+
snapshot.WriteToFile(arguments.OutputPath);
26+
}
2627
}
2728

2829
private static Snapshot CreateSnapshot(int cubeCount)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Linq;
3+
using Improbable.Gdk.Core;
4+
using NUnit.Framework;
5+
6+
namespace Improbable.Gdk.EditmodeTests.Utility
7+
{
8+
[TestFixture]
9+
public class SnapshotTests
10+
{
11+
private Snapshot snapshot;
12+
13+
[SetUp]
14+
public void Initialize()
15+
{
16+
snapshot = new Snapshot();
17+
}
18+
19+
[Test]
20+
public void Contains_returns_true_if_entityId_exists()
21+
{
22+
var entityId = snapshot.GetNextEntityId();
23+
var template = GetTemplate();
24+
snapshot.AddEntity(entityId, template);
25+
Assert.IsTrue(snapshot.Contains(entityId));
26+
}
27+
28+
[Test]
29+
public void Contains_returns_false_if_entityId_does_not_exists()
30+
{
31+
var entityId = snapshot.GetNextEntityId();
32+
Assert.IsFalse(snapshot.Contains(entityId));
33+
}
34+
35+
[TestCase(10)]
36+
[TestCase(20)]
37+
[TestCase(40)]
38+
public void GetNextEntityId_will_return_valid_EntityIds(int size)
39+
{
40+
var entities = Enumerable.Range(1, size).Select(i => new EntityId(i));
41+
var template = new EntityTemplate();
42+
template.AddComponent(new Position.Snapshot());
43+
foreach (var entity in entities)
44+
{
45+
snapshot.AddEntity(entity, template);
46+
}
47+
48+
Assert.IsFalse(snapshot.Contains(snapshot.GetNextEntityId()));
49+
}
50+
51+
[TestCase(10)]
52+
[TestCase(20)]
53+
[TestCase(40)]
54+
public void Count_increases_on_adding_new_entity(int size)
55+
{
56+
var entityIds = Enumerable.Range(1, size).Select(i => new EntityId(i));
57+
var template = new EntityTemplate();
58+
template.AddComponent(new Position.Snapshot());
59+
foreach (var entityId in entityIds)
60+
{
61+
snapshot.AddEntity(entityId, template);
62+
}
63+
64+
Assert.AreEqual(size, snapshot.Count);
65+
}
66+
67+
[Test]
68+
public void AddEntity_throws_if_EntityId_exists()
69+
{
70+
var entityId = new EntityId(1);
71+
var template = GetTemplate();
72+
var template2 = GetTemplate(new Coordinates(1, 2, 3));
73+
snapshot.AddEntity(entityId, template);
74+
Assert.Throws<ArgumentException>(() => snapshot.AddEntity(entityId, template2));
75+
}
76+
77+
[TearDown]
78+
public void TearDown()
79+
{
80+
snapshot.Dispose();
81+
}
82+
83+
private static EntityTemplate GetTemplate(Coordinates pos = default)
84+
{
85+
var template = new EntityTemplate();
86+
template.AddComponent(new Position.Snapshot(pos));
87+
return template;
88+
}
89+
}
90+
}

workers/unity/Assets/Tests/EditmodeTests/Correctness/Utility/SnapshotTests.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workers/unity/Packages/io.improbable.gdk.core/Utility/Snapshot.cs

+41-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using Improbable.Worker.CInterop;
34
using UnityEngine;
@@ -7,12 +8,11 @@ namespace Improbable.Gdk.Core
78
/// <summary>
89
/// Convenience wrapper around the WorkerSDK Snapshot API.
910
/// </summary>
10-
public class Snapshot
11+
public sealed class Snapshot : IDisposable
1112
{
13+
private const int PersistenceComponentId = 55;
1214
private readonly Dictionary<EntityId, Entity> entities = new Dictionary<EntityId, Entity>();
13-
1415
public int Count => entities.Count;
15-
1616
private long nextEntityId = 1;
1717

1818
/// <summary>
@@ -21,9 +21,24 @@ public class Snapshot
2121
/// <returns>The next available entity ID.</returns>
2222
public EntityId GetNextEntityId()
2323
{
24+
while (Contains(new EntityId(nextEntityId)))
25+
{
26+
nextEntityId++;
27+
}
28+
2429
return new EntityId(nextEntityId++);
2530
}
2631

32+
/// <summary>
33+
/// Checks if the snapshot contains an entity ID
34+
/// </summary>
35+
/// <param name="entityId">The entity ID to check for</param>
36+
/// <returns> true if the snapshot contains the input entity ID, false otherwise </returns>
37+
public bool Contains(EntityId entityId)
38+
{
39+
return entities.ContainsKey(entityId);
40+
}
41+
2742
/// <summary>
2843
/// Adds an entity to the snapshot
2944
/// </summary>
@@ -50,7 +65,15 @@ public EntityId AddEntity(EntityTemplate entityTemplate)
5065
/// </remarks>
5166
public void AddEntity(EntityId entityId, EntityTemplate entityTemplate)
5267
{
53-
entities[entityId] = entityTemplate.GetEntity();
68+
if (entities.ContainsKey(entityId))
69+
{
70+
throw new ArgumentException($"EntityId {entityId} already exists in the snapshot");
71+
}
72+
73+
var entity = entityTemplate.GetEntity();
74+
// This is a no-op if the entity already has persistence.
75+
entity.Add(new ComponentData(PersistenceComponentId, SchemaComponentData.Create()));
76+
entities[entityId] = entity;
5477
}
5578

5679
/// <summary>
@@ -79,5 +102,19 @@ public void WriteToFile(string path)
79102
}
80103
}
81104
}
105+
106+
public void Dispose()
107+
{
108+
foreach (var entity in entities.Values)
109+
{
110+
foreach (var id in entity.GetComponentIds())
111+
{
112+
var componentData = entity.Get(id).Value;
113+
componentData.SchemaData?.Destroy();
114+
}
115+
}
116+
}
117+
118+
internal Entity this[EntityId entityId] => entities[entityId];
82119
}
83120
}

0 commit comments

Comments
 (0)