Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 6 additions & 17 deletions sdks/csharp/src/SpacetimeDBClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ public abstract class DbConnectionBase<DbConnection, Tables, Reducer> : IDbConne
where DbConnection : DbConnectionBase<DbConnection, Tables, Reducer>, new()
where Tables : RemoteTablesBase
{
/// <remarks>
/// This isn't reset since [RuntimeInitializeOnLoadMethod] methods cannot be in generic types
/// We assume that the user will reset this if needed; Unity will give an error about this field not being reset.
/// One way we can get around this in the future is using <see href="https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Unity.Scripting.LifecycleManagement.AutoStaticsCleanupAttribute.html">AutoStaticsCleanup</see>
/// But that requires Unity 6.5
/// <remarks>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This closing tag should be </remarks>.

internal static bool IsTesting { get; set; } = false;

public static DbConnectionBuilder<DbConnection> Builder() => new();
Expand Down Expand Up @@ -292,23 +298,6 @@ internal struct ParsedMessage

private static readonly Status Committed = new Status.Committed(default);

#if UNITY_5_3_OR_NEWER
/// <summary>
/// Resets the static instance to prevent data persistence when Enter Play Mode Options (Disable Domain Reloading) is active.
/// RuntimeInitializeOnLoadMethod is used since it is supported in older versions of Unity.
/// AutoStaticsCleanup and NoAutoStaticsCleanup is only supported in Unity 6+
/// </summary>
/// <remarks>
/// See the <see href="https://docs.unity3d.com/6000.5/Documentation/Manual/domain-reloading.html">Unity Domain Reloading Manual</see>
/// and the <see href="https://docs.unity3d.com/6000.5/Documentation/ScriptReference/RuntimeInitializeOnLoadMethodAttribute.html">RuntimeInitializeOnLoadMethodAttribute API Docs</see> for details.
/// </remarks>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticFields()
{
IsTesting = false;
}
#endif

/// <summary>
/// Get a description of a message suitable for storing in the tracker metadata.
/// </summary>
Expand Down
66 changes: 48 additions & 18 deletions sdks/csharp/src/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,22 @@ public RemoteTableHandleBase(IDbConnection conn, bool isEventTable = false) : ba
{
IsEventTable = isEventTable;
}

#if UNITY_5_3_OR_NEWER
/// <summary>
/// Resets the static instance to prevent data persistence when Enter Play Mode Options (Disable Domain Reloading) is active.
/// RuntimeInitializeOnLoadMethod can't be used here since this is a generic class, so we have to handle it ourselves.
/// AutoStaticsCleanup and NoAutoStaticsCleanup is only supported in Unity 6+
/// </summary>
/// <remarks>
/// See the <see href="https://docs.unity3d.com/6000.5/Documentation/Manual/domain-reloading.html">Unity Domain Reloading Manual</see>
/// and the <see href="https://docs.unity3d.com/6000.5/Documentation/ScriptReference/RuntimeInitializeOnLoadMethodAttribute.html">RuntimeInitializeOnLoadMethodAttribute API Docs</see> for details.
/// </remarks>
static RemoteTableHandleBase()
{
RemoteTableHandleStaticReset.Register(() => _serializer = null);
}
#endif

// This method needs to be overridden by autogen.
protected virtual object? GetPrimaryKey(Row row) => null;
Expand Down Expand Up @@ -245,24 +261,6 @@ private static IReadWrite<Row> Serializer
}
}


#if UNITY_5_3_OR_NEWER
/// <summary>
/// Resets the static instance to prevent data persistence when Enter Play Mode Options (Disable Domain Reloading) is active.
/// RuntimeInitializeOnLoadMethod is used since it is supported in older versions of Unity.
/// AutoStaticsCleanup and NoAutoStaticsCleanup is only supported in Unity 6+
/// </summary>
/// <remarks>
/// See the <see href="https://docs.unity3d.com/6000.5/Documentation/Manual/domain-reloading.html">Unity Domain Reloading Manual</see>
/// and the <see href="https://docs.unity3d.com/6000.5/Documentation/ScriptReference/RuntimeInitializeOnLoadMethodAttribute.html">RuntimeInitializeOnLoadMethodAttribute API Docs</see> for details.
/// </remarks>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticFields()
{
_serializer = null;
}
#endif

// The function to use for decoding a type value.
Row DecodeValue(BinaryReader reader) => Serializer.Read(reader);

Expand Down Expand Up @@ -683,5 +681,37 @@ public abstract class RemoteEventTableHandle<EventContext, Row> : RemoteTableHan
{
protected RemoteEventTableHandle(IDbConnection conn) : base(conn, isEventTable: true) { }
}

#if UNITY_5_3_OR_NEWER
/// <summary>
/// Provides a mechanism for registering and invoking static reset callbacks
/// during Unity's subsystem registration phase.
/// This is because Unity's RuntimeInitializeOnLoadMethod can't be used in generic classes
/// One way we can get around this in the future is using <see href="https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Unity.Scripting.LifecycleManagement.AutoStaticsCleanupAttribute.html">AutoStaticsCleanup</see>
/// But that requires Unity 6.5
/// </summary>
/// <remarks>
/// Our generic static constructor doesn't necessarily execute for every table type before Unity's SubsystemRegistration callback runs
/// So this will only reset types that have already been initialized/registered. Which should be okay.
/// </remarks>
internal static class RemoteTableHandleStaticReset
{
private static readonly List<Action> Resets = new();

internal static void Register(Action reset)
{
Resets.Add(reset);
}

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Reset()
{
foreach (var reset in Resets)
{
reset();
}
}
}
#endif
}
#nullable disable