From 230444a1cceb0117f4b4f7e4baae4a0710ee1480 Mon Sep 17 00:00:00 2001 From: FirstGearGames Date: Thu, 26 Sep 2024 19:48:16 -0400 Subject: [PATCH] 4.4.7 - Added several PreciseTick operators. - Added PreciseTick.Add/Subtract extensions. - Added PreciseTick.IsValid(); - Added TimeManager.TimeToPreciseTick. - Improved NetworkConnection.Kick sanity checks when trying to kick invalid connections. - Fixed SyncVar (Beta) not sending updates to reference times after calling DirtyAll, when the SyncVar was initialized in Awake and not changed aftwards. - Improved SyncVar write performance slightly. - Added UnloadSceneEventArgs.UnloadedScenesV2 to resolve issue (#783). - Fixed "cannot have it's parent changed" warning when spawning objects with nested NetworkObjects. - Fixed PrefabId 65535 is out of range error when spawning nested NetworkObjects which were not prefabs (#778). --- .../Prefabs/NetworkTransform Benchmark.prefab | 18 +-- .../ColliderRollback/Prefabs/Player.prefab | 76 ++++++----- .../HashGrid/Prefabs/HashGrid_Moving.prefab | 51 +++---- .../HashGrid/Prefabs/HashGrid_Static.prefab | 12 +- .../Prefabs/Player.prefab | 40 +++--- .../Additive Scenes/Prefabs/Player.prefab | 46 ++++--- .../Edgegap/Editor/EdgegapWindowMetadata.cs | 4 +- .../Connection/NetworkConnection.QOL.cs | 26 +++- .../Managing/Client/Object/ObjectCaching.cs | 15 ++- .../Runtime/Managing/NetworkManager.cs | 2 +- .../Object/ManagedObjects.Spawning.cs | 18 ++- .../Scened/Events/UnloadSceneEventArgs.cs | 11 +- .../Runtime/Managing/Scened/UnloadedScene.cs | 18 +++ .../Runtime/Managing/Timing/PreciseTick.cs | 124 +++++++++++++++++- .../Runtime/Managing/Timing/TimeManager.cs | 16 +++ .../Object/Synchronizing/Beta/SyncVar.cs | 43 +++--- .../GameKit/Dependencies/Utilities/Maths.cs | 16 ++- .../Transports/Multipass/Multipass.cs | 3 +- .../Utility/ChildTransformTickSmoother.cs | 10 +- Assets/FishNet/package.json | 2 +- 20 files changed, 368 insertions(+), 183 deletions(-) diff --git a/Assets/FishNet/Demos/Benchmarks/NetworkTransform/Prefabs/NetworkTransform Benchmark.prefab b/Assets/FishNet/Demos/Benchmarks/NetworkTransform/Prefabs/NetworkTransform Benchmark.prefab index 887033bd..27114730 100644 --- a/Assets/FishNet/Demos/Benchmarks/NetworkTransform/Prefabs/NetworkTransform Benchmark.prefab +++ b/Assets/FishNet/Demos/Benchmarks/NetworkTransform/Prefabs/NetworkTransform Benchmark.prefab @@ -51,9 +51,11 @@ MonoBehaviour: k__BackingField: 0 k__BackingField: {fileID: 0} k__BackingField: {fileID: 0} - NetworkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] + _networkBehaviours: + - {fileID: 0} + - {fileID: -5271135124957689192} + k__BackingField: {fileID: 0} + k__BackingField: [] _isNetworked: 1 _isSpawnable: 1 _isGlobal: 0 @@ -73,14 +75,14 @@ MonoBehaviour: _spectatorInterpolation: 2 _enableTeleport: 0 _teleportThreshold: 1 - k__BackingField: 65535 + k__BackingField: 26 k__BackingField: 0 k__BackingField: 14364260540862342890 k__BackingField: 0 SerializedTransformProperties: Position: {x: 0, y: 0, z: 0} - Rotation: {x: 0, y: 0, z: 0, w: 0} - LocalScale: {x: 0, y: 0, z: 0} + Rotation: {x: 0, y: 0, z: 0, w: 1} + LocalScale: {x: 1, y: 1, z: 1} --- !u!114 &6667641716399555817 MonoBehaviour: m_ObjectHideFlags: 0 @@ -114,9 +116,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 1 _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 4512293259955182956} _componentConfiguration: 0 _synchronizeParent: 0 _packing: diff --git a/Assets/FishNet/Demos/ColliderRollback/Prefabs/Player.prefab b/Assets/FishNet/Demos/ColliderRollback/Prefabs/Player.prefab index 38c9802f..3c599368 100644 --- a/Assets/FishNet/Demos/ColliderRollback/Prefabs/Player.prefab +++ b/Assets/FishNet/Demos/ColliderRollback/Prefabs/Player.prefab @@ -31,7 +31,6 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 2, z: -2} m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 @@ -48,40 +47,50 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} m_Name: m_EditorClassIdentifier: - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - k__BackingField: {fileID: 0} - NetworkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isSpawnable: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 NetworkObserver: {fileID: 0} + k__BackingField: 27 + k__BackingField: 0 + _scenePathHash: 0 + k__BackingField: 0 + k__BackingField: 7473726319608011331 + AdaptiveInterpolationValue: 4 + k__BackingField: 0 _enablePrediction: 0 _predictionType: 0 _graphicalObject: {fileID: 0} - _detachGraphicalObject: 0 _enableStateForwarding: 1 - _networkTransform: {fileID: 0} _ownerInterpolation: 1 - _ownerSmoothedProperties: 255 - _adaptiveInterpolation: 3 - _spectatorSmoothedProperties: 255 - _spectatorInterpolation: 2 _enableTeleport: 0 - _teleportThreshold: 1 - k__BackingField: 65535 - k__BackingField: 0 - k__BackingField: 7473726319608011331 - k__BackingField: 0 + _ownerTeleportThreshold: 1 + _spectatorAdaptiveInterpolation: 1 + _spectatorInterpolation: 1 + _adaptiveSmoothingType: 0 + _customSmoothingData: + InterpolationPercent: 1 + CollisionInterpolationPercent: 0.1 + InterpolationDecreaseStep: 1 + InterpolationIncreaseStep: 3 + _preconfiguredSmoothingDataPreview: + InterpolationPercent: 0.5 + CollisionInterpolationPercent: 0.05 + InterpolationDecreaseStep: 1 + InterpolationIncreaseStep: 2 + k__BackingField: 0 + k__BackingField: {fileID: 0} + _networkBehaviours: + - {fileID: 2759061792589502182} + - {fileID: 1348621277} + - {fileID: 1348621278} + k__BackingField: {fileID: 0} + k__BackingField: [] SerializedTransformProperties: Position: {x: 0, y: 0, z: 0} Rotation: {x: 0, y: 0, z: 0, w: 0} LocalScale: {x: 0, y: 0, z: 0} + _isNetworked: 1 + _isGlobal: 0 + _initializeOrder: 0 + _defaultDespawnType: 0 --- !u!114 &2759061792589502182 MonoBehaviour: m_ObjectHideFlags: 0 @@ -94,14 +103,15 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 9d3558aad46c24549bea48d0e3938264, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 0 _addedNetworkObject: {fileID: 8475222101369129519} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 8475222101369129519} _hitboxLayer: serializedVersion: 2 - m_Bits: 0 - _audio: {fileID: 0} - _muzzleFlashPrefab: {fileID: 0} + m_Bits: 32 + _audio: {fileID: 8300000, guid: 0330762d2b3c8d641bfe11ad89b7e196, type: 3} + _muzzleFlashPrefab: {fileID: 39148481766341303, guid: 4385a793e032d634bb912f84a23d6db1, + type: 3} --- !u!114 &1348621277 MonoBehaviour: m_ObjectHideFlags: 0 @@ -114,9 +124,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e6d656f377f37164d8d7431aa4e43cdb, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 1 _addedNetworkObject: {fileID: 8475222101369129519} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 8475222101369129519} --- !u!114 &1348621278 MonoBehaviour: m_ObjectHideFlags: 0 @@ -129,9 +139,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c718ab30626bbd648952910f74780a06, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 2 _addedNetworkObject: {fileID: 8475222101369129519} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 8475222101369129519} _moveRate: 3 --- !u!143 &5081159371976248031 CharacterController: diff --git a/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Moving.prefab b/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Moving.prefab index 35d6222b..78b57b77 100644 --- a/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Moving.prefab +++ b/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Moving.prefab @@ -134,37 +134,26 @@ MonoBehaviour: k__BackingField: 0 k__BackingField: 0 k__BackingField: {fileID: 0} - k__BackingField: {fileID: 0} - NetworkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] + _networkBehaviours: + - {fileID: 4670340455971777434} + - {fileID: 3019520109258855553} + k__BackingField: {fileID: 0} + k__BackingField: [] + SerializedTransformProperties: + Position: {x: 0, y: 0, z: 0} + Rotation: {x: 0, y: 0, z: 0, w: 0} + LocalScale: {x: 0, y: 0, z: 0} _isNetworked: 1 _isSpawnable: 1 _isGlobal: 0 _initializeOrder: 0 _defaultDespawnType: 0 NetworkObserver: {fileID: 0} - _enablePrediction: 0 - _predictionType: 0 - _graphicalObject: {fileID: 0} - _detachGraphicalObject: 0 - _enableStateForwarding: 1 - _networkTransform: {fileID: 0} - _ownerInterpolation: 1 - _ownerSmoothedProperties: 255 - _adaptiveInterpolation: 3 - _spectatorSmoothedProperties: 255 - _spectatorInterpolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - k__BackingField: 65535 + k__BackingField: 0 k__BackingField: 0 - k__BackingField: 11406911356865610645 + _scenePathHash: 0 k__BackingField: 0 - SerializedTransformProperties: - Position: {x: 0, y: 0, z: 0} - Rotation: {x: 0, y: 0, z: 0, w: 0} - LocalScale: {x: 0, y: 0, z: 0} + k__BackingField: 11406911356865610645 --- !u!114 &4670340455971777434 MonoBehaviour: m_ObjectHideFlags: 0 @@ -177,10 +166,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 10f399a5388d3b3459b7a8476ae13e6a, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 0 _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 0} - _renderer: {fileID: 0} + _networkObjectCache: {fileID: 4512293259955182956} + _renderer: {fileID: 2529588038898116402} --- !u!114 &3019520109258855553 MonoBehaviour: m_ObjectHideFlags: 0 @@ -193,9 +182,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 1 _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 4512293259955182956} _componentConfiguration: 0 _synchronizeParent: 0 _packing: @@ -204,10 +193,12 @@ MonoBehaviour: Scale: 0 _interpolation: 2 _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 + _enableTeleport: 1 + _teleportThreshold: 0.5 + _scaleThreshold: 1 _clientAuthoritative: 1 _sendToOwner: 1 + _enableNetworkLod: 1 _interval: 1 _synchronizePosition: 1 _positionSnapping: diff --git a/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Static.prefab b/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Static.prefab index f828ee1b..58a18627 100644 --- a/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Static.prefab +++ b/Assets/FishNet/Demos/HashGrid/Prefabs/HashGrid_Static.prefab @@ -153,17 +153,17 @@ MonoBehaviour: _ownerSmoothedProperties: 255 _adaptiveInterpolation: 3 _spectatorSmoothedProperties: 255 - _spectatorInterpolation: 2 + _spectatorInterpolation: 1 _enableTeleport: 0 _teleportThreshold: 1 - k__BackingField: 65535 + k__BackingField: 22 k__BackingField: 0 k__BackingField: 17472515426990886281 k__BackingField: 0 SerializedTransformProperties: Position: {x: 0, y: 0, z: 0} - Rotation: {x: 0, y: 0, z: 0, w: 0} - LocalScale: {x: 0, y: 0, z: 0} + Rotation: {x: 0, y: 0, z: 0, w: 1} + LocalScale: {x: 1, y: 1, z: 1} --- !u!114 &437322326027960749 MonoBehaviour: m_ObjectHideFlags: 0 @@ -176,6 +176,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8a6a39c46bf52104ba8efe3100bce3f7, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 0 _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 4512293259955182956} diff --git a/Assets/FishNet/Demos/SceneManager (Old Examples)/Prefabs/Player.prefab b/Assets/FishNet/Demos/SceneManager (Old Examples)/Prefabs/Player.prefab index 9e014cc5..10dda46a 100644 --- a/Assets/FishNet/Demos/SceneManager (Old Examples)/Prefabs/Player.prefab +++ b/Assets/FishNet/Demos/SceneManager (Old Examples)/Prefabs/Player.prefab @@ -218,10 +218,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 26e4f626a9ca9704f9befe7673a8dd15, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 0 _addedNetworkObject: {fileID: 611616139817875448} - _networkObjectCache: {fileID: 0} - _camera: {fileID: 0} + _networkObjectCache: {fileID: 611616139817875448} + _camera: {fileID: 5090726669533971462} _moveRate: 4 _clientAuth: 1 --- !u!54 &3514369712614123748 @@ -269,10 +269,15 @@ MonoBehaviour: k__BackingField: 0 k__BackingField: 0 k__BackingField: {fileID: 0} - k__BackingField: {fileID: 0} - NetworkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] + _networkBehaviours: + - {fileID: 5090726670223187108} + - {fileID: 6654616088585099699} + k__BackingField: {fileID: 0} + k__BackingField: [] + SerializedTransformProperties: + Position: {x: 0, y: 0, z: 0} + Rotation: {x: 0, y: 0, z: 0, w: 0} + LocalScale: {x: 0, y: 0, z: 0} _isNetworked: 1 _isSpawnable: 1 _isGlobal: 0 @@ -282,24 +287,15 @@ MonoBehaviour: _enablePrediction: 0 _predictionType: 0 _graphicalObject: {fileID: 0} - _detachGraphicalObject: 0 _enableStateForwarding: 1 - _networkTransform: {fileID: 0} _ownerInterpolation: 1 - _ownerSmoothedProperties: 255 - _adaptiveInterpolation: 3 - _spectatorSmoothedProperties: 255 - _spectatorInterpolation: 2 _enableTeleport: 0 _teleportThreshold: 1 - k__BackingField: 65535 + k__BackingField: 12 k__BackingField: 0 - k__BackingField: 12334122808499987737 + _scenePathHash: 0 k__BackingField: 0 - SerializedTransformProperties: - Position: {x: 0, y: 0, z: 0} - Rotation: {x: 0, y: 0, z: 0, w: 0} - LocalScale: {x: 0, y: 0, z: 0} + k__BackingField: 12334122808499987737 --- !u!114 &6420552185407096997 MonoBehaviour: m_ObjectHideFlags: 0 @@ -327,9 +323,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 1 _addedNetworkObject: {fileID: 611616139817875448} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 611616139817875448} _componentConfiguration: 0 _synchronizeParent: 0 _packing: @@ -340,8 +336,10 @@ MonoBehaviour: _extrapolation: 2 _enableTeleport: 0 _teleportThreshold: 1 + _scaleThreshold: 1 _clientAuthoritative: 1 _sendToOwner: 1 + _enableNetworkLod: 1 _interval: 1 _synchronizePosition: 1 _positionSnapping: diff --git a/Assets/FishNet/Demos/SceneManager/Additive Scenes/Prefabs/Player.prefab b/Assets/FishNet/Demos/SceneManager/Additive Scenes/Prefabs/Player.prefab index 90552d40..56293544 100644 --- a/Assets/FishNet/Demos/SceneManager/Additive Scenes/Prefabs/Player.prefab +++ b/Assets/FishNet/Demos/SceneManager/Additive Scenes/Prefabs/Player.prefab @@ -328,10 +328,15 @@ MonoBehaviour: k__BackingField: 0 k__BackingField: 0 k__BackingField: {fileID: 0} - k__BackingField: {fileID: 0} - NetworkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] + _networkBehaviours: + - {fileID: 6767263130208162619} + - {fileID: -7170926880071132319} + k__BackingField: {fileID: 0} + k__BackingField: [] + SerializedTransformProperties: + Position: {x: 0, y: 20, z: 0} + Rotation: {x: 0, y: 0, z: 0, w: 1} + LocalScale: {x: 1, y: 1, z: 1} _isNetworked: 1 _isSpawnable: 1 _isGlobal: 0 @@ -341,24 +346,15 @@ MonoBehaviour: _enablePrediction: 0 _predictionType: 0 _graphicalObject: {fileID: 0} - _detachGraphicalObject: 0 _enableStateForwarding: 1 - _networkTransform: {fileID: 0} _ownerInterpolation: 1 - _ownerSmoothedProperties: 255 - _adaptiveInterpolation: 3 - _spectatorSmoothedProperties: 255 - _spectatorInterpolation: 2 _enableTeleport: 0 _teleportThreshold: 1 - k__BackingField: 65535 + k__BackingField: 20 k__BackingField: 0 - k__BackingField: 5491988111533709812 + _scenePathHash: 0 k__BackingField: 0 - SerializedTransformProperties: - Position: {x: 0, y: 0, z: 0} - Rotation: {x: 0, y: 0, z: 0, w: 0} - LocalScale: {x: 0, y: 0, z: 0} + k__BackingField: 5491988111533709812 --- !u!114 &6767263130208162619 MonoBehaviour: m_ObjectHideFlags: 0 @@ -371,11 +367,11 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c8541d1cca4da7043b84a0d563939dea, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 0 _addedNetworkObject: {fileID: 8192566354860284824} - _networkObjectCache: {fileID: 0} - _ownerObjects: {fileID: 0} - _moveRate: 2 + _networkObjectCache: {fileID: 8192566354860284824} + _ownerObjects: {fileID: 6508211851680439895} + _moveRate: 3 --- !u!54 &-1062563901163859699 Rigidbody: m_ObjectHideFlags: 0 @@ -418,9 +414,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} m_Name: m_EditorClassIdentifier: - _componentIndexCache: 255 + _componentIndexCache: 1 _addedNetworkObject: {fileID: 8192566354860284824} - _networkObjectCache: {fileID: 0} + _networkObjectCache: {fileID: 8192566354860284824} _componentConfiguration: 0 _synchronizeParent: 0 _packing: @@ -430,9 +426,11 @@ MonoBehaviour: _interpolation: 2 _extrapolation: 2 _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 1 + _teleportThreshold: 0.5 + _scaleThreshold: 1 + _clientAuthoritative: 0 _sendToOwner: 1 + _enableNetworkLod: 1 _interval: 1 _synchronizePosition: 1 _positionSnapping: diff --git a/Assets/FishNet/Plugins/Edgegap/Editor/EdgegapWindowMetadata.cs b/Assets/FishNet/Plugins/Edgegap/Editor/EdgegapWindowMetadata.cs index 7047a458..7ef0217f 100644 --- a/Assets/FishNet/Plugins/Edgegap/Editor/EdgegapWindowMetadata.cs +++ b/Assets/FishNet/Plugins/Edgegap/Editor/EdgegapWindowMetadata.cs @@ -62,8 +62,8 @@ public enum LogLevel public const string EDGEGAP_GET_A_TOKEN_URL = "https://app.edgegap.com/?oneClick=true"; public const string EDGEGAP_ADD_MORE_GAME_SERVERS_URL = "https://edgegap.com/resources/contact"; public const string EDGEGAP_DOC_BTN_HOW_TO_LOGIN_VIA_CLI_URL = "https://docs.edgegap.com/docs/container/edgegap-container-registry/#getting-your-credentials"; - private const string DEFAULT_UTM_SOURCE_TAG = "partner_fishnet_assetstore_unity"; - // private const string DEFAULT_UTM_SOURCE_TAG = "partner_fishnet_source_unity"; + //private const string DEFAULT_UTM_SOURCE_TAG = "partner_fishnet_assetstore_unity"; + private const string DEFAULT_UTM_SOURCE_TAG = "partner_fishnet_source_unity"; private const string DEFAULT_UTM_MEDIUM_TAG = "servers_quickstart_plugin"; private const string DEFAULT_UTM_CONTENT_TAG = "plugin_button"; public const string DEFAULT_UTM_TAGS = "utm_source=" + DEFAULT_UTM_SOURCE_TAG + diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs index fd74ae6c..8b9e2e5a 100644 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs +++ b/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs @@ -3,16 +3,15 @@ using FishNet.Managing.Server; using FishNet.Serializing; using System; +using UnityEngine; namespace FishNet.Connection { - /// /// A container for a connected client used to perform actions on and gather information for the declared client. /// public partial class NetworkConnection { - #region Public. /// /// Returns true if this connection is a clientHost. @@ -46,10 +45,10 @@ public string GetAddress() /// Optional message to be debug logged. public void Kick(KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") { - NetworkManager.ServerManager.Kick(this, kickReason, loggingType, log); + if (CanKick()) + NetworkManager.ServerManager.Kick(this, kickReason, loggingType, log); } - /// /// Kicks a connection immediately while invoking OnClientKick. /// @@ -59,11 +58,24 @@ public void Kick(KickReason kickReason, LoggingType loggingType = LoggingType.Co /// Optional message to be debug logged. public void Kick(Reader reader, KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") { - NetworkManager.ServerManager.Kick(this, reader, kickReason, loggingType, log); + if (CanKick()) + NetworkManager.ServerManager.Kick(this, reader, kickReason, loggingType, log); } + private bool CanKick() + { + //Connection isn't valid, calling kick on an empty connection. + if (!IsValid) + return false; - } - + //Should never happen. + if (NetworkManager == null) + { + NetworkManager = InstanceFinder.NetworkManager; + NetworkManager.LogError($"NetworkManager was not set for connection {this.ToString()}. InstanceFinder has been used."); + } + return true; + } + } } \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs b/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs index e566dcbb..730bf76b 100644 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs +++ b/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs @@ -224,7 +224,7 @@ public void Iterate() //Nested. if (cnob.HasParent) { - bool nested = cnob.IsSerializedNested; + bool nested = cnob.IsInitializedNested; //It's not possible to be nested and have a parent. Set the Id to look for based on if nested or parented. int targetObjectId = cnob.ParentObjectId.Value; NetworkObject nob = GetSpawnedObject(targetObjectId); @@ -282,12 +282,13 @@ void ProcessObject(CachedNetworkObject cnob, bool spawn, int index) SetParentAndTransformProperties(cnob); } //Is nested in a prefab. - else if (cnob.IsSerializedNested) + else if (cnob.IsInitializedNested) { cnob.NetworkObject = _clientObjects.GetNestedNetworkObject(cnob); - SetParentAndTransformProperties(cnob); + //Do not try to set parent if initialized nested. + cnob.NetworkObject.transform.SetLocalPositionRotationAndScale(cnob.Position, cnob.Rotation, cnob.Scale); } - /* Not sceneObject or serializedNested. Could still be runtime + /* Not sceneObject or initializedNested. Could still be runtime * nested but this also requires instantiation. The instantiation process * handles parenting and position. */ else @@ -302,7 +303,7 @@ void ProcessObject(CachedNetworkObject cnob, bool spawn, int index) cnob.NetworkObject = _clientObjects.GetSpawnedNetworkObject(cnob); /* Do not log unless not nested. Nested nobs sometimes * could be destroyed if parent was first. */ - if (!_networkManager.IsHostStarted && cnob.NetworkObject == null && !cnob.IsSerializedNested) + if (!_networkManager.IsHostStarted && cnob.NetworkObject == null && !cnob.IsInitializedNested) _networkManager.Log($"NetworkObject for ObjectId of {cnob.ObjectId} was found null. Unable to despawn object. This may occur if a nested NetworkObject had it's parent object unexpectedly destroyed. This incident is often safe to ignore."); } @@ -550,9 +551,9 @@ public enum ActionType #endregion /// - /// True if cached object is nested. + /// True if cached object is nested during initialization. /// - public bool IsSerializedNested => (ComponentId > 0); + public bool IsInitializedNested => (ComponentId > 0); /// /// True if a scene object. diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.cs b/Assets/FishNet/Runtime/Managing/NetworkManager.cs index a99513a7..10ccda0f 100644 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.cs +++ b/Assets/FishNet/Runtime/Managing/NetworkManager.cs @@ -212,7 +212,7 @@ public static IReadOnlyList Instances /// /// Version of this release. /// - public const string FISHNET_VERSION = "4.4.6"; + public const string FISHNET_VERSION = "4.4.7"; /// /// Maximum framerate allowed. /// diff --git a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs index 95bd1471..9372547f 100644 --- a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs +++ b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs @@ -254,15 +254,25 @@ protected void WriteChangedTransformProperties(NetworkObject nob, bool sceneObje { /* Write changed transform properties. */ TransformPropertiesFlag tpf; - //If a scene object then get it from scene properties. - if (sceneObject) + /* If a scene object or nested during initialization then + * write changes compared to initialized values. */ + if (sceneObject || nob.InitializedParentNetworkBehaviour != null) { tpf = nob.GetTransformChanges(nob.SerializedTransformProperties); } else { - PrefabObjects po = NetworkManager.GetPrefabObjects(nob.SpawnableCollectionId, false); - tpf = nob.GetTransformChanges(po.GetObject(asServer: true, nob.PrefabId).gameObject); + //This should not be possible when spawning non-nested. + if (nob.PrefabId == NetworkObject.UNSET_PREFABID_VALUE) + { + NetworkManager.LogWarning($"NetworkObject {nob.ToString()} unexpectedly has an unset PrefabId while it's not nested. Please report this warning."); + tpf = TransformPropertiesFlag.Everything; + } + else + { + PrefabObjects po = NetworkManager.GetPrefabObjects(nob.SpawnableCollectionId, false); + tpf = nob.GetTransformChanges(po.GetObject(asServer: true, nob.PrefabId).gameObject); + } } headerWriter.WriteUInt8Unpacked((byte)tpf); diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs b/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs index e526fff8..ecf5b242 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs @@ -34,12 +34,21 @@ public struct SceneUnloadEndEventArgs /// Scenes which were successfully unloaded. /// This collection may be populated with empty scenes depending on engine version. /// + [Obsolete("Use UnloadedScenesV2.")] //Remove on V5. Rename UnloadedScenesV2 to UnloadedScenes. public List UnloadedScenes; - + /// + /// Scenes which were successfully unloaded. + /// This contains information of the scene unloaded but may not contain scene references as some Unity versions discard that information after a scene is unloaded. + /// + public List UnloadedScenesV2; + internal SceneUnloadEndEventArgs(UnloadQueueData sqd, List unloadedScenes, List newUnloadedScenes) { QueueData = sqd; +#pragma warning disable CS0618 // Type or member is obsolete UnloadedScenes = unloadedScenes; +#pragma warning restore CS0618 // Type or member is obsolete + UnloadedScenesV2 = newUnloadedScenes; } } diff --git a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs index a45f8ac8..65209601 100644 --- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs +++ b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs @@ -17,5 +17,23 @@ public UnloadedScene(string name, int handle) Name = name; Handle = handle; } + + /// + /// Returns a scene based on handle. + /// Result may not be valid as some Unity versions discard of the scene information after unloading. + /// + /// + public Scene GetScene() + { + int loadedScenes = UnityEngine.SceneManagement.SceneManager.sceneCount; + for (int i = 0; i < loadedScenes; i++) + { + Scene s = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i); + if (s.IsValid() && s.handle == Handle) + return s; + } + + return default; + } } } diff --git a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs b/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs index 9344752a..af504461 100644 --- a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs +++ b/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs @@ -1,23 +1,33 @@ -using FishNet.Serializing; +using System; +using FishNet.Serializing; using GameKit.Dependencies.Utilities; +using UnityEngine; namespace FishNet.Managing.Timing { - - public struct PreciseTick + public readonly struct PreciseTick : IEquatable { /// /// The current tick. /// - public uint Tick; + public readonly uint Tick; /// /// Percentage of the tick returned between 0d and 1d. /// - public double PercentAsDouble; + public readonly double PercentAsDouble; /// /// Percentage of the tick returned between 0 and 100. /// - public byte PercentAsByte; + public readonly byte PercentAsByte; + + /// + /// Maximum value a percent can be as a double. + /// + public const double MAXIMUM_DOUBLE_PERCENT = 1d; + /// + /// Maximum value a percent can be as a byte. + /// + public const byte MAXIMUM_BYTE_PERCENT = 100; /// /// Creates a precise tick where the percentage is a byte between 0 and 100. @@ -25,6 +35,8 @@ public struct PreciseTick public PreciseTick(uint tick, byte percentAsByte) { Tick = tick; + + percentAsByte = Maths.ClampByte(percentAsByte, 0, MAXIMUM_BYTE_PERCENT); PercentAsByte = percentAsByte; PercentAsDouble = (percentAsByte / 100d); } @@ -35,15 +47,113 @@ public PreciseTick(uint tick, byte percentAsByte) public PreciseTick(uint tick, double percent) { Tick = tick; - PercentAsByte = (byte)(percent * 100d); + percent = Maths.ClampDouble(percent, 0d, MAXIMUM_DOUBLE_PERCENT); + PercentAsByte = (byte)Math.Round(percent * 100d); PercentAsDouble = percent; } + public bool IsValid() => (Tick != TimeManager.UNSET_TICK); + /// /// Prints PreciseTick information as a string. /// /// public override string ToString() => $"Tick {Tick}, Percent {PercentAsByte.ToString("000")}"; + + public static bool operator ==(PreciseTick a, PreciseTick b) + { + return (a.Tick == b.Tick && a.PercentAsByte == b.PercentAsByte); + } + + public static bool operator !=(PreciseTick a, PreciseTick b) + { + return !(a == b); + } + + public static bool operator >=(PreciseTick a, PreciseTick b) + { + if (b.Tick > a.Tick) return false; + if (a.Tick > b.Tick) return true; + //If here ticks are the same. + return a.PercentAsByte >= b.PercentAsByte; + } + + public static bool operator <=(PreciseTick a, PreciseTick b) => (b >= a); + + public static bool operator >(PreciseTick a, PreciseTick b) + { + + if (b.Tick > a.Tick) return false; + if (a.Tick > b.Tick) return true; + //if here ticks are the same. + return a.PercentAsByte > b.PercentAsByte; + } + + public static bool operator <(PreciseTick a, PreciseTick b) => (b > a); + + public bool Equals(PreciseTick other) => (Tick == other.Tick && PercentAsByte == other.PercentAsByte); + + public override bool Equals(object obj)=> obj is PreciseTick other && Equals(other); + + public override int GetHashCode() => HashCode.Combine(Tick, PercentAsDouble, PercentAsByte); + + } + + public static class PreciseTickExtensions + { + /// + /// Adds value onto a PreciseTick. + /// + /// Value to add. + /// Tick delta. + /// + public static PreciseTick Add(this PreciseTick pt, PreciseTick value, double delta) + { + double percent = (pt.PercentAsDouble + value.PercentAsDouble); + ulong tick = ((ulong)pt.Tick + (ulong)value.Tick); + + if (percent > PreciseTick.MAXIMUM_DOUBLE_PERCENT) + { + tick++; + percent -= PreciseTick.MAXIMUM_DOUBLE_PERCENT; + } + + if (tick > uint.MaxValue) + { + tick = uint.MaxValue; + percent = 0d; + } + + return new PreciseTick((uint)tick, percent); + } + + /// + /// Subtracts value from a PreciseTick. + /// + /// Value to subtract. + /// Tick delta. + /// + public static PreciseTick Subtract(this PreciseTick pt, PreciseTick value, double delta) + { + double percent = (pt.PercentAsDouble - value.PercentAsDouble); + long tick = ((long)pt.Tick - (long)value.Tick); + + // Percentage is negative so subtract an additional tick and absolute percentage. + if (percent < 0d) + { + tick--; + percent *= -1d; + } + + if (tick < 0) + { + tick = 0; + percent = 0d; + } + + return new PreciseTick((uint)tick, percent); + } + } public static class PreciseTickSerializer diff --git a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs b/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs index e30b7f09..5e6a3e6e 100644 --- a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs +++ b/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs @@ -976,7 +976,23 @@ public uint TimeToTicks(double time, TickRounding rounding = TickRounding.RoundN else return (uint)Math.Ceiling(result); } + + /// + /// Converts time to a PreciseTick. + /// + /// Time to convert. + /// + public PreciseTick TimeToPreciseTick(double time) + { + double delta = TickDelta; + + uint ticks = (uint)Math.Floor(time / delta); + double percent = (time % delta); + + return new PreciseTick(ticks, percent); + } + /// /// Estimatedly converts a synchronized tick to what it would be for the local tick. /// diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/Beta/SyncVar.cs b/Assets/FishNet/Runtime/Object/Synchronizing/Beta/SyncVar.cs index ec2a2f3d..37bd741f 100644 --- a/Assets/FishNet/Runtime/Object/Synchronizing/Beta/SyncVar.cs +++ b/Assets/FishNet/Runtime/Object/Synchronizing/Beta/SyncVar.cs @@ -278,7 +278,7 @@ internal void SetValue(T nextValue, bool calledByUser, bool sendRpc = false) // T prev = _value; // if (Comparers.EqualityCompare(prev, nextValue)) // return; - + /* If also server do not update value. * Server side has say of the current value. */ /* Only update value if not server. We do not want @@ -288,7 +288,7 @@ internal void SetValue(T nextValue, bool calledByUser, bool sendRpc = false) UpdateValues(nextValue); T prev = _value; - + InvokeOnChange(prev, nextValue, asServer: false); } @@ -335,6 +335,9 @@ public void DirtyAll() if (!base.CanNetworkSetValues(true)) return; + //Also set that values have changed since the user is forcing a sync. + _valueSetAfterInitialized = true; + base.Dirty(); /* Invoke even if was unable to dirty. Dirtying only * becomes true if server is running, but also if there are @@ -405,22 +408,26 @@ internal protected override void WriteDelta(PooledWriter writer, bool resetSyncT [MakePublic] internal protected override void WriteFull(PooledWriter obj0) { - /* If a class then skip comparer check. - * InitialValue and Value will be the same reference. - * - * If a value then compare field changes, since the references - * will not be the same. */ - //Compare if a value type. - if (_isValueType) - { - if (Comparers.EqualityCompare(_initialValue, _value)) - return; - } - else - { - if (!_valueSetAfterInitialized) - return; - } + // /* If a class then skip comparer check. + // * InitialValue and Value will be the same reference. + // * + // * If a value then compare field changes, since the references + // * will not be the same. */ + // //Compare if a value type. + // if (_isValueType) + // { + // if (Comparers.EqualityCompare(_initialValue, _value)) + // return; + // } + // else + // { + // if (!_valueSetAfterInitialized) + // return; + // } + + if (!_valueSetAfterInitialized) + return; + /* SyncVars only hold latest value, so just * write current delta. */ WriteDelta(obj0, false); diff --git a/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Maths.cs b/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Maths.cs index ab8832ac..a82f37f9 100644 --- a/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Maths.cs +++ b/Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Maths.cs @@ -1,9 +1,7 @@ namespace GameKit.Dependencies.Utilities { - public static class Maths { - /// /// Returns a clamped SBytte. /// @@ -29,6 +27,18 @@ public static double ClampDouble(double value, double min, double max) else return value; } - } + /// + /// Returns a clamped byte. + /// + public static byte ClampByte(byte value, byte min, byte max) + { + if (value < min) + return min; + else if (value > max) + return max; + else + return value; + } + } } \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs index cfbc990b..1cc735b5 100644 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs +++ b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs @@ -6,7 +6,6 @@ using GameKit.Dependencies.Utilities; using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using UnityEngine; namespace FishNet.Transporting.Multipass @@ -102,7 +101,7 @@ public Transport ClientTransport /// /// Transports to use. /// - public IList Transports => _transports; + public IReadOnlyList Transports => _transports; #endregion #region Private. diff --git a/Assets/FishNet/Runtime/Utility/ChildTransformTickSmoother.cs b/Assets/FishNet/Runtime/Utility/ChildTransformTickSmoother.cs index 1eae853c..1b47374c 100644 --- a/Assets/FishNet/Runtime/Utility/ChildTransformTickSmoother.cs +++ b/Assets/FishNet/Runtime/Utility/ChildTransformTickSmoother.cs @@ -103,10 +103,6 @@ public TickTransformProperties(uint tick, TransformProperties tp) /// private float _movementMultiplier = 1f; /// - /// Ticks passed since the last reconcile. - /// - private uint _reconcileInterval = RECONCILE_INTERVAL_DEFAULT; - /// /// TransformProperties to move towards. /// private BasicQueue _transformProperties; @@ -396,7 +392,6 @@ public void OnPreReconcile() return; uint clientStateTick = _networkObject.PredictionManager.ClientStateTick; - _reconcileInterval = (clientStateTick - _lastReconcileTick); _lastReconcileTick = clientStateTick; UpdateInterpolation(clientStateTick); @@ -654,10 +649,10 @@ public void ResetState() if (_graphicalObject != null) { - if (_networkObject != null) + if (_rootTransform != null) { if (_detach) - _graphicalObject.SetParent(_networkObject.transform); + _graphicalObject.SetParent(_rootTransform); _graphicalObject.SetWorldProperties(GetNetworkObjectWorldPropertiesWithOffset()); _graphicalObject = null; } @@ -670,7 +665,6 @@ public void ResetState() _networkObject = null; _teleportedTick = TimeManager.UNSET_TICK; _lastReconcileTick = TimeManager.UNSET_TICK; - _reconcileInterval = RECONCILE_INTERVAL_DEFAULT; _movementMultiplier = 1f; CollectionCaches.StoreAndDefault(ref _transformProperties); _teleportThreshold = default; diff --git a/Assets/FishNet/package.json b/Assets/FishNet/package.json index 11ead87f..cd3da88e 100644 --- a/Assets/FishNet/package.json +++ b/Assets/FishNet/package.json @@ -1,6 +1,6 @@ { "name": "com.firstgeargames.fishnet", - "version": "4.4.6", + "version": "4.4.7", "displayName": "FishNet: Networking Evolved", "description": "A feature-rich Unity networking solution aimed towards reliability, ease of use, efficiency, and flexibility.", "unity": "2021.3",