Skip to content

Commit 536642b

Browse files
committed
Pure stateless, non generic approach for sending data through fastBufferReader
1 parent 015e384 commit 536642b

File tree

4 files changed

+60
-75
lines changed

4 files changed

+60
-75
lines changed

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3239,13 +3239,10 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
32393239
var bufferSerializer = new BufferSerializer<BufferSerializerReader>(new BufferSerializerReader(reader));
32403240

32413241
//Synchronize the instantiation data if needed
3242-
if (sceneObject.HasInstantiationData)
3243-
{
3244-
networkManager.PrefabHandler.ReadInstantiationData(sceneObject.Hash, ref bufferSerializer);
3245-
}
3242+
FastBufferReader instantiationDataReader = sceneObject.HasInstantiationData ? networkManager.PrefabHandler.GetInstantiationDataReader(sceneObject.Hash, ref bufferSerializer) : default;
32463243

32473244
//Attempt to create a local NetworkObject
3248-
var networkObject = networkManager.SpawnManager.CreateLocalNetworkObject(sceneObject);
3245+
var networkObject = networkManager.SpawnManager.CreateLocalNetworkObject(sceneObject, instantiationDataReader);
32493246

32503247
if (networkObject == null)
32513248
{

com.unity.netcode.gameobjects/Runtime/Spawning/INetworkPrefabInstanceHandlerWithData.cs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,25 @@ public interface INetworkPrefabInstanceHandlerWithData<T> where T : struct, INet
1717

1818
internal interface INetworkPrefabInstanceHandlerWithData : INetworkPrefabInstanceHandler
1919
{
20+
NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation, FastBufferReader reader);
2021
bool HandlesDataType<T>();
21-
void ReadInstantiationData<TReaderWriter>(ref BufferSerializer<TReaderWriter> serializer) where TReaderWriter : IReaderWriter;
2222
}
2323

2424
internal class HandlerWrapper<T> : INetworkPrefabInstanceHandlerWithData where T : struct, INetworkSerializable
2525
{
2626
private readonly INetworkPrefabInstanceHandlerWithData<T> _impl;
27-
private T _payload;
28-
27+
2928
public HandlerWrapper(INetworkPrefabInstanceHandlerWithData<T> impl) => _impl = impl;
30-
public bool HandlesDataType<U>() => typeof(T) == typeof(U);
31-
public void ReadInstantiationData<TReaderWriter>(ref BufferSerializer<TReaderWriter> serializer) where TReaderWriter : IReaderWriter => serializer.SerializeValue(ref _payload);
32-
public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) => _impl.Instantiate(ownerClientId, position, rotation, _payload);
33-
public void Destroy(NetworkObject networkObject) => _impl.Destroy(networkObject);
34-
}
3529

30+
public bool HandlesDataType<U>() => typeof(T) == typeof(U);
3631

37-
public static class INetworkPrefabInstanceHandlerWithDataExtensions
38-
{
39-
/// PLACEHOLDER: If this pattern is liked, i can move all the injection code to here instead of the PrefabHandler
40-
public static void InjectInstantiationData<T>(this INetworkPrefabInstanceHandlerWithData<T> handler, NetworkObject networkObject, T data) where T : struct, INetworkSerializable
32+
public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation, FastBufferReader reader)
4133
{
42-
NetworkManager.Singleton.PrefabHandler.InjectInstantiationData(networkObject, data);
34+
reader.ReadValueSafe(out T _payload);
35+
return _impl.Instantiate(ownerClientId, position, rotation, _payload);
4336
}
4437

45-
public static void SpawnWithData<T>(this INetworkPrefabInstanceHandlerWithData<T> handler, NetworkObject networkObject, T data) where T : struct, INetworkSerializable
46-
{
47-
InjectInstantiationData(handler, networkObject, data);
48-
networkObject.Spawn();
49-
}
38+
public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) => _impl.Instantiate(ownerClientId, position, rotation, default);
39+
public void Destroy(NetworkObject networkObject) => _impl.Destroy(networkObject);
5040
}
5141
}

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkPrefabHandler.cs

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -297,37 +297,20 @@ internal bool TryGetHandlerWithData(uint objectHash, out INetworkPrefabInstanceH
297297
/// <typeparam name="T"></typeparam>
298298
/// <param name="objectHash"></param>
299299
/// <param name="serializer"></param>
300-
internal void ReadInstantiationData<T>(uint objectHash, ref BufferSerializer<T> serializer) where T : IReaderWriter
300+
internal FastBufferReader GetInstantiationDataReader<T>(uint objectHash, ref BufferSerializer<T> serializer) where T : IReaderWriter
301301
{
302302
if (!serializer.IsReader || !TryGetHandlerWithData(objectHash, out INetworkPrefabInstanceHandlerWithData synchronizableHandler))
303303
{
304-
return;
304+
return default;
305305
}
306306

307307
FastBufferReader fastBufferReader = serializer.GetFastBufferReader();
308308
// Reads the expected size of the instantiation data
309309
fastBufferReader.ReadValueSafe(out int dataSize);
310310
int dataStartPos = fastBufferReader.Position;
311-
312-
try
313-
{
314-
synchronizableHandler.ReadInstantiationData(ref serializer);
315-
}
316-
catch (Exception ex)
317-
{
318-
// Skips the unread instantiation data bytes
319-
fastBufferReader.Seek(dataStartPos + dataSize);
320-
NetworkLog.LogError($"[InstantiationData] Handler failed during synchronization (Read): {ex.Message}");
321-
return;
322-
}
323-
324-
// Validates if expected number of bytes were read
325-
int dataEndPos = fastBufferReader.Position;
326-
if (dataEndPos != dataStartPos + dataSize)
327-
{
328-
NetworkLog.LogWarning($"[InstantiationData] Read {dataEndPos - dataStartPos} bytes, expected {dataSize}");
329-
fastBufferReader.Seek(dataStartPos + dataSize);
330-
}
311+
var result = new FastBufferReader(fastBufferReader, Collections.Allocator.Temp, dataSize, dataStartPos);
312+
fastBufferReader.Seek(dataStartPos + dataSize);
313+
return result;
331314
}
332315

333316
/// <summary>
@@ -359,23 +342,38 @@ internal uint GetSourceGlobalObjectIdHash(uint networkPrefabHash)
359342
/// <param name="position"></param>
360343
/// <param name="rotation"></param>
361344
/// <returns></returns>
362-
internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulong ownerClientId, Vector3 position, Quaternion rotation)
345+
internal NetworkObject HandleNetworkPrefabSpawn(uint networkPrefabAssetHash, ulong ownerClientId, Vector3 position, Quaternion rotation, FastBufferReader instantiationDataReader = default)
346+
{
347+
NetworkObject networkObjectInstance = instantiationDataReader.IsInitialized
348+
? InstantiateNetworkPrefabWithData(networkPrefabAssetHash, ownerClientId, position, rotation, instantiationDataReader)
349+
: InstantiateNetworkPrefabDefault(networkPrefabAssetHash, ownerClientId, position, rotation);
350+
//Now we must make sure this alternate PrefabAsset spawned in place of the prefab asset with the networkPrefabAssetHash (GlobalObjectIdHash)
351+
//is registered and linked to the networkPrefabAssetHash so during the HandleNetworkPrefabDestroy process we can identify the alternate prefab asset.
352+
if (networkObjectInstance != null)
353+
RegisterPrefabInstance(networkObjectInstance, networkPrefabAssetHash);
354+
return networkObjectInstance;
355+
}
356+
357+
private NetworkObject InstantiateNetworkPrefabDefault(uint networkPrefabAssetHash, ulong ownerClientId, Vector3 position, Quaternion rotation)
363358
{
364359
if (m_PrefabAssetToPrefabHandler.TryGetValue(networkPrefabAssetHash, out var prefabInstanceHandler))
365-
{
366-
var networkObjectInstance = prefabInstanceHandler.Instantiate(ownerClientId, position, rotation);
360+
return prefabInstanceHandler.Instantiate(ownerClientId, position, rotation);
361+
return null;
362+
}
367363

368-
//Now we must make sure this alternate PrefabAsset spawned in place of the prefab asset with the networkPrefabAssetHash (GlobalObjectIdHash)
369-
//is registered and linked to the networkPrefabAssetHash so during the HandleNetworkPrefabDestroy process we can identify the alternate prefab asset.
370-
if (networkObjectInstance != null && !m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstance.GlobalObjectIdHash))
371-
{
372-
m_PrefabInstanceToPrefabAsset.Add(networkObjectInstance.GlobalObjectIdHash, networkPrefabAssetHash);
373-
}
364+
private NetworkObject InstantiateNetworkPrefabWithData(uint networkPrefabAssetHash, ulong ownerClientId, Vector3 position, Quaternion rotation, FastBufferReader instantiationDataReader)
365+
{
366+
if (m_PrefabAssetToPrefabHandlerWithData.TryGetValue(networkPrefabAssetHash, out var prefabInstanceHandler))
367+
return prefabInstanceHandler.Instantiate(ownerClientId, position, rotation, instantiationDataReader);
368+
return null;
369+
}
374370

375-
return networkObjectInstance;
371+
private void RegisterPrefabInstance(NetworkObject networkObjectInstance, uint networkPrefabAssetHash)
372+
{
373+
if (networkObjectInstance != null && !m_PrefabInstanceToPrefabAsset.ContainsKey(networkObjectInstance.GlobalObjectIdHash))
374+
{
375+
m_PrefabInstanceToPrefabAsset.Add(networkObjectInstance.GlobalObjectIdHash, networkPrefabAssetHash);
376376
}
377-
378-
return null;
379377
}
380378

381379
/// <summary>

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -779,14 +779,14 @@ internal NetworkObject InstantiateAndSpawnNoParameterChecks(NetworkObject networ
779779
/// Gets the right NetworkObject prefab instance to spawn. If a handler is registered or there is an override assigned to the
780780
/// passed in globalObjectIdHash value, then that is what will be instantiated, spawned, and returned.
781781
/// </summary>
782-
internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ownerId, Vector3? position, Quaternion? rotation, bool isScenePlaced = false)
782+
internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ownerId, Vector3? position, Quaternion? rotation, bool isScenePlaced = false, FastBufferReader instantiationDataReader = default)
783783
{
784784
NetworkObject networkObject = null;
785785
// If the prefab hash has a registered INetworkPrefabInstanceHandler derived class
786786
if (NetworkManager.PrefabHandler.ContainsHandler(globalObjectIdHash))
787787
{
788788
// Let the handler spawn the NetworkObject
789-
networkObject = NetworkManager.PrefabHandler.HandleNetworkPrefabSpawn(globalObjectIdHash, ownerId, position ?? default, rotation ?? default);
789+
networkObject = NetworkManager.PrefabHandler.HandleNetworkPrefabSpawn(globalObjectIdHash, ownerId, position ?? default, rotation ?? default, instantiationDataReader);
790790
networkObject.NetworkManagerOwner = NetworkManager;
791791
}
792792
else
@@ -807,22 +807,22 @@ internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ow
807807
break;
808808
case NetworkPrefabOverride.Hash:
809809
case NetworkPrefabOverride.Prefab:
810+
{
811+
// When scene management is disabled and this is an in-scene placed NetworkObject, we want to always use the
812+
// SourcePrefabToOverride and not any possible prefab override as a user might want to spawn overrides dynamically
813+
// but might want to use the same source network prefab as an in-scene placed NetworkObject.
814+
// (When scene management is enabled, clients don't delete their in-scene placed NetworkObjects prior to dynamically
815+
// spawning them so the original prefab placed is preserved and this is not needed)
816+
if (inScenePlacedWithNoSceneManagement)
810817
{
811-
// When scene management is disabled and this is an in-scene placed NetworkObject, we want to always use the
812-
// SourcePrefabToOverride and not any possible prefab override as a user might want to spawn overrides dynamically
813-
// but might want to use the same source network prefab as an in-scene placed NetworkObject.
814-
// (When scene management is enabled, clients don't delete their in-scene placed NetworkObjects prior to dynamically
815-
// spawning them so the original prefab placed is preserved and this is not needed)
816-
if (inScenePlacedWithNoSceneManagement)
817-
{
818-
networkPrefabReference = networkPrefab.SourcePrefabToOverride ? networkPrefab.SourcePrefabToOverride : networkPrefab.Prefab;
819-
}
820-
else
821-
{
822-
networkPrefabReference = NetworkManager.NetworkConfig.Prefabs.NetworkPrefabOverrideLinks[globalObjectIdHash].OverridingTargetPrefab;
823-
}
824-
break;
818+
networkPrefabReference = networkPrefab.SourcePrefabToOverride ? networkPrefab.SourcePrefabToOverride : networkPrefab.Prefab;
825819
}
820+
else
821+
{
822+
networkPrefabReference = NetworkManager.NetworkConfig.Prefabs.NetworkPrefabOverrideLinks[globalObjectIdHash].OverridingTargetPrefab;
823+
}
824+
break;
825+
}
826826
}
827827
}
828828

@@ -875,7 +875,7 @@ internal NetworkObject InstantiateNetworkPrefab(GameObject networkPrefab, uint p
875875
/// For most cases this is client-side only, with the exception of when the server
876876
/// is spawning a player.
877877
/// </remarks>
878-
internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneObject)
878+
internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneObject, FastBufferReader instantiationDataReader = default)
879879
{
880880
NetworkObject networkObject = null;
881881
var globalObjectIdHash = sceneObject.Hash;
@@ -888,7 +888,7 @@ internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneO
888888
// If scene management is disabled or the NetworkObject was dynamically spawned
889889
if (!NetworkManager.NetworkConfig.EnableSceneManagement || !sceneObject.IsSceneObject)
890890
{
891-
networkObject = GetNetworkObjectToSpawn(sceneObject.Hash, sceneObject.OwnerClientId, position, rotation, sceneObject.IsSceneObject);
891+
networkObject = GetNetworkObjectToSpawn(sceneObject.Hash, sceneObject.OwnerClientId, position, rotation, sceneObject.IsSceneObject, instantiationDataReader);
892892
}
893893
else // Get the in-scene placed NetworkObject
894894
{

0 commit comments

Comments
 (0)