Skip to content

Commit 9e39943

Browse files
authored
fix: GetSceneMapping final ulong -> int conversion (#3734)
* fix: GetSceneMapping final int->ulong conversion * Update CHANGELOG * Fix SceneMap serialization * Put things back * Fix yamato trigger
1 parent 4b99f27 commit 9e39943

File tree

8 files changed

+209
-41
lines changed

8 files changed

+209
-41
lines changed

.yamato/_triggers.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ pr_code_changes_checks:
8787
# Coverage on other standalone machines is present in Nightly job so it's enough to not run all of them for PRs
8888
# desktop_standalone_test and cmb_service_standalone_test are both reusing desktop_standalone_build dependency so we run those in the same configuration on PRs to reduce waiting time.
8989
# Note that our daily tests will anyway run both test configurations in "minimal supported" and "trunk" configurations
90-
- .yamato/desktop-standalone-tests.yml#desktop_standalone_test_testproject_ubuntu_il2cpp_trunk
91-
- .yamato/cmb-service-standalone-tests.yml#cmb_service_standalone_test_testproject_ubuntu_il2cpp_trunk
90+
91+
# TODO: Move these tests back to trunk once CMB Service has addressed https://jira.unity3d.com/browse/MTTB-1680
92+
- .yamato/desktop-standalone-tests.yml#desktop_standalone_test_testproject_ubuntu_il2cpp_6000.4
93+
- .yamato/cmb-service-standalone-tests.yml#cmb_service_standalone_test_testproject_ubuntu_il2cpp_6000.4
9294
triggers:
9395
expression: |-
9496
(pull_request.comment eq "ngo" OR

.yamato/project.metafile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ validation_editors:
162162
- 6000.0
163163
- 6000.2
164164
- 6000.3
165+
- 6000.4
165166
- trunk
166167
minimal:
167168
- 6000.0

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1111
### Added
1212

1313
- Added NetworkRigidbody documentation section. (#3664)
14+
- Added new fields to the `SceneMap` struct when using Unity 6.3 or higher. These fields allow referencing scene handles via the new `SceneHandle` struct. (#3734)
1415

1516
### Changed
1617

@@ -24,6 +25,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2425

2526
### Deprecated
2627

28+
- On Unity 6.5 some `SceneMap` fields that use an `int` to represent a `SceneHandle` are deprecated. (#3734)
2729

2830
### Removed
2931

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneHandle.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
3636
var reader = serializer.GetFastBufferReader();
3737
// DANGO-TODO Rust needs to be updated to either handle this ulong or to remove the scene store.
3838
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
39-
reader.ReadValue(out ulong rawData);
39+
reader.ReadValueSafe(out ulong rawData);
4040
m_Handle = SceneHandle.FromRawData(rawData);
4141
#elif SCENE_MANAGEMENT_SCENE_HANDLE_NO_INT_CONVERSION
4242
reader.ReadValueSafe(out int rawData);
@@ -92,8 +92,14 @@ internal NetworkSceneHandle(int handle, bool asMock)
9292
/// <summary>
9393
/// Implicit conversion from <see cref="SceneHandle"/> to <see cref="NetworkSceneHandle"/>.
9494
/// </summary>
95-
/// <param name="handle"></param>
95+
/// <param name="handle">The SceneHandle to covert</param>
9696
public static implicit operator NetworkSceneHandle(SceneHandle handle) => new(handle);
97+
98+
/// <summary>
99+
/// Implicit conversion from <see cref="NetworkSceneHandle"/> to <see cref="SceneHandle"/>.
100+
/// </summary>
101+
/// <param name="handle">The NetworkSceneHandle to convert</param>
102+
public static implicit operator SceneHandle(NetworkSceneHandle handle) => handle.m_Handle;
97103
#else
98104
/// <summary>
99105
/// Implicit conversion from <see langword="int"/> to <see cref="NetworkSceneHandle"/>.

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 124 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3115,19 +3115,101 @@ public struct SceneMap : INetworkSerializable
31153115
/// The name of the scene
31163116
/// </summary>
31173117
public string SceneName;
3118+
3119+
#if SCENE_MANAGEMENT_SCENE_HANDLE_NO_INT_CONVERSION
3120+
/// <summary>
3121+
/// The scene's server handle (a.k.a network scene handle)
3122+
/// </summary>
3123+
/// <remarks>
3124+
/// This is deprecated in favor of ServerSceneHandle
3125+
/// </remarks>
3126+
[Obsolete("Int representation of a SceneHandle is deprecated, please use SceneHandle instead.")]
3127+
#else
31183128
/// <summary>
31193129
/// The scene's server handle (a.k.a network scene handle)
31203130
/// </summary>
3131+
#endif
31213132
public int ServerHandle;
3133+
3134+
#if SCENE_MANAGEMENT_SCENE_HANDLE_NO_INT_CONVERSION
31223135
/// <summary>
31233136
/// The mapped handled. This could be the ServerHandle or LocalHandle depending upon context (client or server).
31243137
/// </summary>
3138+
/// <remarks>
3139+
/// This is deprecated in favor of MappedLocalSceneHandle
3140+
/// </remarks>
3141+
[Obsolete("Int representation of a SceneHandle is deprecated, please use SceneHandle instead.")]
3142+
#else
3143+
/// <summary>
3144+
/// The mapped handled. This could be the ServerHandle or LocalHandle depending upon context (client or server).
3145+
/// </summary>
3146+
#endif
31253147
public int MappedLocalHandle;
3148+
3149+
#if SCENE_MANAGEMENT_SCENE_HANDLE_NO_INT_CONVERSION
3150+
/// <summary>
3151+
/// The local handle of the scene.
3152+
/// </summary>
3153+
/// <remarks>
3154+
/// This is deprecated in favor of LocalSceneHandle
3155+
/// </remarks>
3156+
[Obsolete("Int representation of a SceneHandle is deprecated, please use SceneHandle instead.")]
3157+
#else
31263158
/// <summary>
31273159
/// The local handle of the scene.
31283160
/// </summary>
3161+
#endif
31293162
public int LocalHandle;
31303163

3164+
#if SCENE_MANAGEMENT_SCENE_HANDLE_AVAILABLE
3165+
/// <summary>
3166+
/// The scene's server handle (a.k.a network scene handle)
3167+
/// </summary>
3168+
public SceneHandle ServerSceneHandle;
3169+
/// <summary>
3170+
/// The mapped handled. This could be the ServerSceneHandle or LocalSceneHandle depending upon context (client or server).
3171+
/// </summary>
3172+
public SceneHandle MappedLocalSceneHandle;
3173+
/// <summary>
3174+
/// The local handle of the scene.
3175+
/// </summary>
3176+
public SceneHandle LocalSceneHandle;
3177+
#endif
3178+
3179+
private NetworkSceneHandle m_ServerHandle;
3180+
private NetworkSceneHandle m_MappedLocalHandle;
3181+
private NetworkSceneHandle m_LocalHandle;
3182+
3183+
internal SceneMap(MapTypes mapType, Scene scene, bool isScenePresent, NetworkSceneHandle serverHandle, NetworkSceneHandle mappedLocalHandle)
3184+
{
3185+
MapType = mapType;
3186+
Scene = scene;
3187+
ScenePresent = isScenePresent;
3188+
SceneName = isScenePresent ? scene.name : "Not Present";
3189+
3190+
m_ServerHandle = serverHandle;
3191+
m_MappedLocalHandle = mappedLocalHandle;
3192+
m_LocalHandle = new NetworkSceneHandle(scene.handle);
3193+
3194+
#if SCENE_MANAGEMENT_SCENE_HANDLE_AVAILABLE
3195+
ServerSceneHandle = serverHandle;
3196+
MappedLocalSceneHandle = mappedLocalHandle;
3197+
LocalSceneHandle = scene.handle;
3198+
#endif
3199+
3200+
#pragma warning disable CS0618 // Type or member is obsolete
3201+
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
3202+
ServerHandle = (int)m_ServerHandle.GetRawData();
3203+
MappedLocalHandle = (int)m_MappedLocalHandle.GetRawData();
3204+
LocalHandle = (int)m_LocalHandle.GetRawData();
3205+
#else
3206+
ServerHandle = m_ServerHandle.GetRawData();
3207+
MappedLocalHandle = m_MappedLocalHandle.GetRawData();
3208+
LocalHandle = m_LocalHandle.GetRawData();
3209+
#endif
3210+
#pragma warning restore CS0618 // Type or member is obsolete
3211+
}
3212+
31313213
/// <inheritdoc cref="INetworkSerializable.NetworkSerialize{T}(BufferSerializer{T})"/>
31323214
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
31333215
{
@@ -3140,11 +3222,45 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
31403222
if (ScenePresent)
31413223
{
31423224
serializer.SerializeValue(ref SceneName);
3225+
#pragma warning disable CS0618 // Type or member is obsolete
31433226
serializer.SerializeValue(ref LocalHandle);
3144-
31453227
}
31463228
serializer.SerializeValue(ref ServerHandle);
31473229
serializer.SerializeValue(ref MappedLocalHandle);
3230+
#pragma warning restore CS0618 // Type or member is obsolete
3231+
3232+
3233+
#if SCENE_MANAGEMENT_SCENE_HANDLE_AVAILABLE
3234+
// Ensure the SceneHandles are valid to be serialized
3235+
if (serializer.IsWriter)
3236+
{
3237+
if (m_LocalHandle.IsEmpty() && LocalSceneHandle != SceneHandle.None)
3238+
{
3239+
m_LocalHandle = LocalSceneHandle;
3240+
}
3241+
if (m_ServerHandle.IsEmpty() && ServerSceneHandle != SceneHandle.None)
3242+
{
3243+
m_ServerHandle = ServerSceneHandle;
3244+
}
3245+
if (m_MappedLocalHandle.IsEmpty() && MappedLocalSceneHandle != SceneHandle.None)
3246+
{
3247+
m_MappedLocalHandle = MappedLocalSceneHandle;
3248+
}
3249+
}
3250+
3251+
// Serialize the INetworkSerializable representations
3252+
serializer.SerializeValue(ref m_LocalHandle);
3253+
serializer.SerializeValue(ref m_ServerHandle);
3254+
serializer.SerializeValue(ref m_MappedLocalHandle);
3255+
3256+
// If we're reading, convert back into the raw SceneHandle
3257+
if (serializer.IsReader)
3258+
{
3259+
ServerSceneHandle = m_ServerHandle;
3260+
ServerSceneHandle = m_LocalHandle;
3261+
ServerSceneHandle = m_MappedLocalHandle;
3262+
}
3263+
#endif
31483264
}
31493265
}
31503266

@@ -3156,43 +3272,14 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
31563272
public List<SceneMap> GetSceneMapping(MapTypes mapType)
31573273
{
31583274
var mapping = new List<SceneMap>();
3159-
if (mapType == MapTypes.ServerToClient)
3160-
{
3161-
foreach (var entry in ServerSceneHandleToClientSceneHandle)
3162-
{
3163-
var scene = ScenesLoaded[entry.Value];
3164-
var sceneIsPresent = scene.IsValid() && scene.isLoaded;
3165-
var sceneMap = new SceneMap()
3166-
{
3167-
MapType = mapType,
3168-
ServerHandle = entry.Key.GetRawData(),
3169-
MappedLocalHandle = entry.Value.GetRawData(),
3170-
LocalHandle = new NetworkSceneHandle(scene.handle).GetRawData(),
3171-
Scene = scene,
3172-
ScenePresent = sceneIsPresent,
3173-
SceneName = sceneIsPresent ? scene.name : "NotPresent",
3174-
};
3175-
mapping.Add(sceneMap);
3176-
}
3177-
}
3178-
else
3275+
var map = mapType == MapTypes.ServerToClient ? ServerSceneHandleToClientSceneHandle : ClientSceneHandleToServerSceneHandle;
3276+
3277+
foreach (var entry in map)
31793278
{
3180-
foreach (var entry in ClientSceneHandleToServerSceneHandle)
3181-
{
3182-
var scene = ScenesLoaded[entry.Key];
3183-
var sceneIsPresent = scene.IsValid() && scene.isLoaded;
3184-
var sceneMap = new SceneMap()
3185-
{
3186-
MapType = mapType,
3187-
ServerHandle = entry.Key.GetRawData(),
3188-
MappedLocalHandle = entry.Value.GetRawData(),
3189-
LocalHandle = new NetworkSceneHandle(scene.handle).GetRawData(),
3190-
Scene = scene,
3191-
ScenePresent = sceneIsPresent,
3192-
SceneName = sceneIsPresent ? scene.name : "NotPresent",
3193-
};
3194-
mapping.Add(sceneMap);
3195-
}
3279+
var scene = ScenesLoaded[entry.Key];
3280+
var sceneIsPresent = scene.IsValid() && scene.isLoaded;
3281+
var sceneMap = new SceneMap(mapType, scene, sceneIsPresent, entry.Key, entry.Value);
3282+
mapping.Add(sceneMap);
31963283
}
31973284

31983285
return mapping;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using NUnit.Framework;
2+
using Unity.Collections;
3+
4+
namespace Unity.Netcode.EditorTests
5+
{
6+
internal class NetworkSceneHandleTests
7+
{
8+
[Test]
9+
public void NetworkSceneHandleSerializationTest()
10+
{
11+
var handle = new NetworkSceneHandle(1234, true);
12+
13+
using var writer = new FastBufferWriter(sizeof(ulong), Allocator.Temp);
14+
Assert.That(writer.Position, Is.EqualTo(0), "Writer position should be zero");
15+
16+
writer.WriteNetworkSerializable(handle);
17+
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
18+
Assert.That(writer.Position, Is.EqualTo(sizeof(ulong)), $"Writer position should not be beyond size! Expected: {sizeof(ulong)} Actual: {writer.Position}");
19+
#else
20+
Assert.That(writer.Position, Is.EqualTo(sizeof(int)), $"Writer position should not be beyond size! Expected: {sizeof(int)} Actual: {writer.Position}");
21+
#endif
22+
23+
var reader = new FastBufferReader(writer, Allocator.Temp);
24+
Assert.That(reader.Position, Is.EqualTo(0), "Reader position should be zero");
25+
reader.ReadNetworkSerializable(out NetworkSceneHandle deserializedHandle);
26+
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
27+
Assert.That(reader.Position, Is.EqualTo(sizeof(ulong)), $"Reader position should not be beyond size! Expected: {sizeof(ulong)} Actual: {reader.Position}");
28+
#else
29+
Assert.That(reader.Position, Is.EqualTo(sizeof(int)), $"Reader position should not be beyond size! Expected: {sizeof(int)} Actual: {reader.Position}");
30+
#endif
31+
32+
Assert.AreEqual(handle, deserializedHandle);
33+
34+
// Now serialize a list of SceneHandles
35+
var handles = new NetworkSceneHandle[] { handle, new NetworkSceneHandle(4567, true), new NetworkSceneHandle(7890, true) };
36+
37+
using var listWriter = new FastBufferWriter(1024, Allocator.Temp);
38+
39+
Assert.That(listWriter.Position, Is.EqualTo(0), "Writer position should be zero");
40+
41+
listWriter.WriteNetworkSerializable(handles);
42+
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
43+
var expectedSize = sizeof(int) + (sizeof(ulong) * handles.Length);
44+
#else
45+
var expectedSize = sizeof(int) + (sizeof(int) * handles.Length);
46+
#endif
47+
Assert.That(listWriter.Position, Is.EqualTo(expectedSize), $"Writer position should not be beyond size! Expected: {expectedSize} Actual: {listWriter.Position}");
48+
49+
var listReader = new FastBufferReader(listWriter, Allocator.Temp);
50+
Assert.That(listReader.Position, Is.EqualTo(0), "Reader position should be zero");
51+
listReader.ReadNetworkSerializable(out NetworkSceneHandle[] deserializedHandleList);
52+
Assert.That(listReader.Position, Is.EqualTo(expectedSize), $"Reader position should not be beyond expected size! Expected: {expectedSize} Actual: {listReader.Position}");
53+
54+
Assert.AreEqual(handles, deserializedHandleList);
55+
}
56+
}
57+
}

com.unity.netcode.gameobjects/Tests/Editor/Serialization/NetworkSceneHandleTests.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Tests/Editor/Unity.Netcode.Editor.Tests.asmdef

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@
4343
"name": "Unity",
4444
"expression": "6000.1.0a1",
4545
"define": "HOSTNAME_RESOLUTION_AVAILABLE"
46+
},
47+
{
48+
"name": "Unity",
49+
"expression": "6000.4.0a3",
50+
"define": "SCENE_MANAGEMENT_SCENE_HANDLE_NO_INT_CONVERSION"
51+
},
52+
{
53+
"name": "Unity",
54+
"expression": "6000.5.0a1",
55+
"define": "SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG"
4656
}
4757
],
4858
"noEngineReferences": false

0 commit comments

Comments
 (0)