Skip to content

Commit 9459200

Browse files
committed
[ECO-5624] Fixed UnityAdapter as per review comments
- Updated UnityAdapter to handle instance access for different unity versions - Fixed unity editmode and playmode tests for agent identifiers - Updated link.xml with exclusions for needed types
1 parent 6e539f9 commit 9459200

File tree

8 files changed

+71
-86
lines changed

8 files changed

+71
-86
lines changed

src/IO.Ably.Shared/IO.Ably.Shared.projitems

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@
178178
<Compile Include="$(MSBuildThisFileDirectory)Types\PresenceMessage.cs" />
179179
<Compile Include="$(MSBuildThisFileDirectory)Types\ProtocolMessage.cs" />
180180
<Compile Include="$(MSBuildThisFileDirectory)Types\SemanticVersion.cs" />
181+
<Compile Include="$(MSBuildThisFileDirectory)Unity\UnityAdapter.cs" />
182+
<Compile Include="$(MSBuildThisFileDirectory)Unity\UnityHelper.cs" />
181183
<Compile Include="$(MSBuildThisFileDirectory)Utils\ActionOnDispose.cs" />
182184
<Compile Include="$(MSBuildThisFileDirectory)Utils\ActionUtils.cs" />
183185
<Compile Include="$(MSBuildThisFileDirectory)Utils\ConnectionChangeAwaiter.cs" />

src/IO.Ably.Shared/Unity/UnityAdapter.cs

Lines changed: 28 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,37 @@ namespace IO.Ably.Unity
2020
/// - No link.xml preservation directives needed for UnityEngine.Application (it's always preserved)
2121
/// - Works across all Unity scripting backends: Mono, IL2CPP (iOS/Android/WebGL/Console)
2222
/// - Gracefully degrades in non-Unity environments (returns empty/default values)
23-
/// - Zero reflection overhead after first access due to Lazy<T> caching
24-
/// - Safe for AOT platforms: no runtime code generation, only metadata queries
23+
/// - Zero reflection overhead after first access due to Lazy caching
24+
/// - Safe for AOT platforms: no runtime code generation, only metadata queries.
2525
/// </summary>
2626
internal static class UnityAdapter
2727
{
2828
private static readonly Lazy<Type> _unityApplication =
2929
new Lazy<Type>(() => GetUnityApplication());
30-
30+
3131
private static readonly Lazy<string> _unityVersion =
3232
new Lazy<string>(() => GetUnityVersion());
33-
34-
private static readonly Lazy<int> _runtimePlatform =
35-
new Lazy<int>(() => GetRuntimePlatform());
33+
34+
private static readonly Lazy<string> _runtimePlatform =
35+
new Lazy<string>(() => GetRuntimePlatform());
3636

3737
/// <summary>
3838
/// Indicates whether Unity runtime is available.
3939
/// </summary>
4040
public static bool IsAvailable => _unityApplication.Value != null;
41-
41+
4242
/// <summary>
4343
/// Gets the cached Unity version string.
4444
/// The value is computed once on first access and cached for subsequent calls.
4545
/// </summary>
4646
public static string UnityVersion => _unityVersion.Value;
47-
47+
4848
/// <summary>
49-
/// Gets the cached runtime platform value.
49+
/// Gets the cached runtime platform string value.
5050
/// The value is computed once on first access and cached for subsequent calls.
5151
/// </summary>
52-
public static int RuntimePlatform => _runtimePlatform.Value;
53-
52+
public static string RuntimePlatform => _runtimePlatform.Value;
53+
5454
/// <summary>
5555
/// Gets the UnityEngine.Application type using reflection.
5656
/// </summary>
@@ -60,15 +60,13 @@ private static Type GetUnityApplication()
6060
try
6161
{
6262
// Attempt to load UnityEngine.Application type at runtime
63-
// This will succeed if UnityEngine.dll is available in the runtime
64-
return Type.GetType(
65-
"UnityEngine.Application, UnityEngine",
66-
throwOnError: false);
63+
// The UnityEngine.Application class has been located in the UnityEngine.CoreModule assembly since Unity 2017.1
64+
// Returns null if the class is not found in UnityEngine.CoreModule
65+
return Type.GetType("UnityEngine.Application, UnityEngine.CoreModule", throwOnError: false);
6766
}
6867
catch
6968
{
7069
// Silently fail - Unity is not available
71-
// This is expected in non-Unity environments
7270
return null;
7371
}
7472
}
@@ -88,17 +86,11 @@ private static string GetUnityVersion()
8886
try
8987
{
9088
// Get property info for unityVersion
91-
var unityVersionProperty = applicationType.GetProperty(
89+
var version = applicationType.GetProperty(
9290
"unityVersion",
93-
BindingFlags.Public | BindingFlags.Static);
91+
BindingFlags.Public | BindingFlags.Static)
92+
?.GetValue(null) as string;
9493

95-
if (unityVersionProperty == null)
96-
{
97-
return string.Empty;
98-
}
99-
100-
// Get static property value via reflection
101-
var version = unityVersionProperty.GetValue(null) as string;
10294
return version ?? string.Empty;
10395
}
10496
catch
@@ -109,43 +101,33 @@ private static string GetUnityVersion()
109101
}
110102

111103
/// <summary>
112-
/// Gets the runtime platform as an integer value using reflection.
104+
/// Gets the runtime platform as a string value using reflection.
113105
/// </summary>
114-
/// <returns>Platform integer value (maps to RuntimePlatform enum) or -1 if unavailable.</returns>
115-
private static int GetRuntimePlatform()
106+
/// <returns>Platform string value (e.g., "OSXEditor", "WindowsPlayer") or empty string if unavailable.</returns>
107+
private static string GetRuntimePlatform()
116108
{
117109
var applicationType = _unityApplication.Value;
118110
if (applicationType == null)
119111
{
120-
return -1;
112+
return string.Empty;
121113
}
122114

123115
try
124116
{
125-
// Get property info for platform
126-
var platformProperty = applicationType.GetProperty(
117+
// Get property info for platform and convert enum to string (e.g., "OSXEditor", "WindowsPlayer")
118+
var platform = applicationType.GetProperty(
127119
"platform",
128-
BindingFlags.Public | BindingFlags.Static);
129-
130-
if (platformProperty == null)
131-
{
132-
return -1;
133-
}
120+
BindingFlags.Public | BindingFlags.Static)
121+
?.GetValue(null)
122+
?.ToString();
134123

135-
// Get static property value via reflection
136-
var platformValue = platformProperty.GetValue(null);
137-
if (platformValue != null)
138-
{
139-
// RuntimePlatform is an enum, convert to int
140-
return (int)platformValue;
141-
}
124+
return platform ?? string.Empty;
142125
}
143126
catch
144127
{
145128
// Ignore reflection errors
129+
return string.Empty;
146130
}
147-
148-
return -1;
149131
}
150132
}
151133
}

src/IO.Ably.Shared/Unity/UnityHelper.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,55 +29,55 @@ internal static class UnityHelper
2929
public const string Xbox = "unity-xbox";
3030

3131
/// <summary>
32-
/// Constants representing UnityEngine.RuntimePlatform enum values.
33-
/// These integer values map to the RuntimePlatform enum without requiring a compile-time reference.
34-
/// Values are stable across Unity versions and documented in Unity's API reference.
32+
/// Constants representing UnityEngine.RuntimePlatform enum string values.
33+
/// These string values map to the RuntimePlatform enum names without requiring a compile-time reference.
34+
/// Using string values instead of integers provides stability across Unity versions.
3535
/// </summary>
3636
public static class RuntimePlatform
3737
{
3838
/// <summary>In the Unity editor on macOS.</summary>
39-
public const int OSXEditor = 0;
39+
public const string OSXEditor = "OSXEditor";
4040

4141
/// <summary>In the player on macOS.</summary>
42-
public const int OSXPlayer = 1;
42+
public const string OSXPlayer = "OSXPlayer";
4343

4444
/// <summary>In the player on Windows.</summary>
45-
public const int WindowsPlayer = 2;
45+
public const string WindowsPlayer = "WindowsPlayer";
4646

4747
/// <summary>In the Unity editor on Windows.</summary>
48-
public const int WindowsEditor = 7;
48+
public const string WindowsEditor = "WindowsEditor";
4949

5050
/// <summary>In the player on iPhone.</summary>
51-
public const int IPhonePlayer = 8;
51+
public const string IPhonePlayer = "IPhonePlayer";
5252

5353
/// <summary>In the player on Android.</summary>
54-
public const int Android = 11;
54+
public const string Android = "Android";
5555

5656
/// <summary>In the player on Linux.</summary>
57-
public const int LinuxPlayer = 13;
57+
public const string LinuxPlayer = "LinuxPlayer";
5858

5959
/// <summary>In the Unity editor on Linux.</summary>
60-
public const int LinuxEditor = 16;
60+
public const string LinuxEditor = "LinuxEditor";
6161

6262
/// <summary>In the player on WebGL.</summary>
63-
public const int WebGLPlayer = 17;
63+
public const string WebGLPlayer = "WebGLPlayer";
6464

6565
/// <summary>In the player on PS4.</summary>
66-
public const int PS4 = 19;
66+
public const string PS4 = "PS4";
6767

6868
/// <summary>In the player on Xbox One.</summary>
69-
public const int XboxOne = 21;
69+
public const string XboxOne = "XboxOne";
7070

7171
/// <summary>In the player on Apple TV.</summary>
72-
public const int tvOS = 31;
72+
public const string TvOS = "tvOS";
7373

7474
/// <summary>In the player on Nintendo Switch.</summary>
75-
public const int Switch = 32;
75+
public const string Switch = "Switch";
7676

7777
/// <summary>In the player on PS5.</summary>
78-
public const int PS5 = 34;
78+
public const string PS5 = "PS5";
7979
}
80-
80+
8181
/// <summary>
8282
/// Gets the cached Unity OS identifier string.
8383
/// The value is computed once on first access and cached for subsequent calls.
@@ -89,7 +89,7 @@ public static class RuntimePlatform
8989
/// The value is computed once on first access and cached for subsequent calls.
9090
/// </summary>
9191
public static string UnityIdentifier => _unityIdentifier.Value;
92-
92+
9393
/// <summary>
9494
/// Gets the Unity OS identifier string based on the current runtime platform.
9595
/// Uses reflection to detect Unity platform without compile-time dependency.
@@ -133,7 +133,7 @@ private static string GetOsIdentifier()
133133
return PS4;
134134
case RuntimePlatform.XboxOne:
135135
return Xbox;
136-
case RuntimePlatform.tvOS:
136+
case RuntimePlatform.TvOS:
137137
return TvOS;
138138
case RuntimePlatform.Switch:
139139
return Switch;
@@ -165,4 +165,3 @@ private static string GetUnityIdentifier()
165165
}
166166
}
167167
}
168-
4 KB
Binary file not shown.

unity/Assets/Ably/Plugins/link.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
<linker>
22
<assembly fullname="IO.Ably" preserve="all" />
3-
<assembly fullname="IO.Ably.DeltaCodec" preserve="all" />
4-
</linker>
3+
<assembly fullname="UnityEngine.CoreModule">
4+
<type fullname="UnityEngine.Application">
5+
<property name="unityVersion" />
6+
<property name="platform" />
7+
</type>
8+
</assembly>
9+
</linker>

unity/Assets/Tests/AblySandbox/AblyRealtimeExtensions.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
using System.Threading.Tasks;
33
using IO.Ably;
44
using IO.Ably.Realtime;
5-
using IO.Ably.Realtime.Workflow;
6-
using IO.Ably.Types;
75

86
namespace Assets.Tests.AblySandbox
97
{

unity/Assets/Tests/EditMode/AblyRealtimeSpecs.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
using System;
21
using System.Collections;
32
using System.Collections.Generic;
43
using System.Linq;
54
using System.Net;
65
using System.Net.Http;
7-
using System.Threading.Tasks;
8-
using System.Threading;
96
using Assets.Tests.AblySandbox;
107
using Cysharp.Threading.Tasks;
118
using IO.Ably;
129
using IO.Ably.Realtime;
10+
using IO.Ably.Unity;
1311
using NUnit.Framework;
1412
using UnityEngine.TestTools;
1513

@@ -224,18 +222,18 @@ public IEnumerator TestHttpUnityAgentHeader([ValueSource(nameof(_protocols))] Pr
224222
Assert.AreEqual(1, values.Length);
225223
string[] agentValues = values[0].Split(' ');
226224

227-
Assert.IsTrue(Agent.OsIdentifier().StartsWith("unity-"));
228-
Assert.IsTrue(Agent.UnityPlayerIdentifier().StartsWith("unity/"));
225+
Assert.IsTrue(Agent.OsIdentifier.StartsWith("unity-"));
226+
Assert.IsTrue(UnityHelper.UnityIdentifier.StartsWith("unity/"));
229227

230228
var keys = new List<string>()
231229
{
232230
"ably-dotnet/",
233-
Agent.DotnetRuntimeIdentifier(),
234-
Agent.UnityPlayerIdentifier(),
235-
Agent.OsIdentifier()
231+
Agent.DotnetRuntimeIdentifier,
232+
UnityHelper.UnityIdentifier,
233+
Agent.OsIdentifier
236234
};
237235

238-
Assert.AreEqual(2, Agent.DotnetRuntimeIdentifier().Split('/').Length);
236+
Assert.AreEqual(2, Agent.DotnetRuntimeIdentifier.Split('/').Length);
239237

240238
keys.RemoveAll(s => s.IsEmpty());
241239

unity/Assets/Tests/PlayMode/AblyRealtimeSpecs.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Cysharp.Threading.Tasks;
88
using IO.Ably;
99
using IO.Ably.Realtime;
10+
using IO.Ably.Unity;
1011
using NUnit.Framework;
1112
using UnityEngine.TestTools;
1213

@@ -221,18 +222,18 @@ public IEnumerator TestHttpUnityAgentHeader([ValueSource(nameof(_protocols))] Pr
221222
Assert.AreEqual(1, values.Length);
222223
string[] agentValues = values[0].Split(' ');
223224

224-
Assert.IsTrue(Agent.OsIdentifier().StartsWith("unity-"));
225-
Assert.IsTrue(Agent.UnityPlayerIdentifier().StartsWith("unity/"));
225+
Assert.IsTrue(Agent.OsIdentifier.StartsWith("unity-"));
226+
Assert.IsTrue(UnityHelper.UnityIdentifier.StartsWith("unity/"));
226227

227228
var keys = new List<string>()
228229
{
229230
"ably-dotnet/",
230-
Agent.DotnetRuntimeIdentifier(),
231-
Agent.UnityPlayerIdentifier(),
232-
Agent.OsIdentifier()
231+
Agent.DotnetRuntimeIdentifier,
232+
UnityHelper.UnityIdentifier,
233+
Agent.OsIdentifier
233234
};
234235

235-
Assert.AreEqual(2, Agent.DotnetRuntimeIdentifier().Split('/').Length);
236+
Assert.AreEqual(2, Agent.DotnetRuntimeIdentifier.Split('/').Length);
236237

237238
keys.RemoveAll(s => s.IsEmpty());
238239

0 commit comments

Comments
 (0)