From 3c2d04f4c0e6ee53650412e4ac59e44d3735f094 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 14 Aug 2024 12:57:32 -0400 Subject: [PATCH 01/13] asmdefs generated with dependencies mapped --- .../Scripts/Editor/AvatarTransformEditor.cs | 4 ++-- ...multiplayer.samples.socialhub.editor.asmdef | 16 ++++++++++++++++ ...player.samples.socialhub.editor.asmdef.meta | 7 +++++++ ...ltiplayer.samples.socialhub.gameplay.asmdef | 17 +++++++++++++++++ ...ayer.samples.socialhub.gameplay.asmdef.meta | 7 +++++++ .../Assets/Scripts/Input/AvatarInputs.cs | 4 +++- ....multiplayer.samples.socialhub.input.asmdef | 16 ++++++++++++++++ ...iplayer.samples.socialhub.input.asmdef.meta | 7 +++++++ .../Assets/Scripts/Player/AvatarTransform.cs | 7 +++---- ...multiplayer.samples.socialhub.player.asmdef | 18 ++++++++++++++++++ ...player.samples.socialhub.player.asmdef.meta | 7 +++++++ 11 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs index f2282a912..ab772c38b 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs @@ -1,10 +1,10 @@ -using com.unity.multiplayer.samples.distributed_authority.gameplay; +using com.unity.multiplayer.samples.socialhub.player; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; -namespace com.unity.multiplayer.samples.distributed_authority.editor +namespace com.unity.multiplayer.samples.socialhub.editor { [CustomEditor(typeof(AvatarTransform))] class DerivedComponentEditor : Editor diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef new file mode 100644 index 000000000..27f97af4c --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef @@ -0,0 +1,16 @@ +{ + "name": "com.unity.multiplayer.samples.socialhub.editor", + "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "references": [ + "GUID:8314b31eee3cc495ca4a4f078575802d" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta new file mode 100644 index 000000000..fb0b64c54 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6846e1cea5ff5448bb199c1d5674fd09 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef new file mode 100644 index 000000000..dd6ff4baa --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef @@ -0,0 +1,17 @@ +{ + "name": "com.unity.multiplayer.samples.socialhub.gameplay", + "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "references": [ + "GUID:1491147abca9d7d4bb7105af628b223e", + "GUID:c15e7f658578345fcb824b0a64d4dbe8" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta new file mode 100644 index 000000000..5700dc7bb --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9ff2150ce7d7c415a8af1fbff3dc3e6c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs index 4289c30dd..c04540d5d 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs @@ -1,7 +1,9 @@ +using System.Runtime.CompilerServices; using UnityEngine; using UnityEngine.InputSystem; -namespace com.unity.multiplayer.samples.distributed_authority.input +[assembly: InternalsVisibleTo("com.unity.multiplayer.samples.socialhub.player")] +namespace com.unity.multiplayer.samples.socialhub.input { class AvatarInputs : MonoBehaviour { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef new file mode 100644 index 000000000..c509405bd --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef @@ -0,0 +1,16 @@ +{ + "name": "com.unity.multiplayer.samples.socialhub.input", + "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "references": [ + "GUID:75469ad4d38634e559750d17036d5f7c" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta new file mode 100644 index 000000000..55aae09c1 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c15e7f658578345fcb824b0a64d4dbe8 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index b8ea334aa..4f81bc88e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -1,9 +1,8 @@ using Unity.Netcode.Components; using UnityEngine; -using UnityEngine.InputSystem; -using com.unity.multiplayer.samples.distributed_authority.input; +using com.unity.multiplayer.samples.socialhub.input; -namespace com.unity.multiplayer.samples.distributed_authority.gameplay +namespace com.unity.multiplayer.samples.socialhub.player { [RequireComponent(typeof(Rigidbody))] public class AvatarTransform : NetworkTransform @@ -11,7 +10,7 @@ public class AvatarTransform : NetworkTransform [SerializeField] Rigidbody m_Rigidbody; [SerializeField] - PlayerInput m_PlayerInput; + MonoBehaviour m_PlayerInput; [SerializeField] AvatarInputs m_AvatarInputs; [SerializeField] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef new file mode 100644 index 000000000..8a059e8ad --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef @@ -0,0 +1,18 @@ +{ + "name": "com.unity.multiplayer.samples.socialhub.player", + "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "references": [ + "GUID:1491147abca9d7d4bb7105af628b223e", + "GUID:c15e7f658578345fcb824b0a64d4dbe8", + "GUID:9ff2150ce7d7c415a8af1fbff3dc3e6c" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta new file mode 100644 index 000000000..88021ce08 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8314b31eee3cc495ca4a4f078575802d +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From ad2404d5426b5edf4e2613da2f656cb20e51b916 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 14 Aug 2024 13:11:29 -0400 Subject: [PATCH 02/13] one unnecessary dependency removed --- .../com.unity.multiplayer.samples.socialhub.gameplay.asmdef | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef index dd6ff4baa..e838cdd64 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef @@ -2,8 +2,7 @@ "name": "com.unity.multiplayer.samples.socialhub.gameplay", "rootNamespace": "com.unity.multiplayer.samples.socialhub", "references": [ - "GUID:1491147abca9d7d4bb7105af628b223e", - "GUID:c15e7f658578345fcb824b0a64d4dbe8" + "GUID:1491147abca9d7d4bb7105af628b223e" ], "includePlatforms": [], "excludePlatforms": [], From c7787f28725943ae7c4006ec9d778272858fe1a9 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 14 Aug 2024 13:52:49 -0400 Subject: [PATCH 03/13] renaming asmdefs & adding input assemblyinfo --- .../Assets/Scripts/Editor/AvatarTransformEditor.cs | 6 +++--- ...ef => Unity.Multiplayer.Samples.SocialHub.Editor.asmdef} | 4 ++-- ... Unity.Multiplayer.Samples.SocialHub.Editor.asmdef.meta} | 0 ... => Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef} | 4 ++-- ...nity.Multiplayer.Samples.SocialHub.Gameplay.asmdef.meta} | 0 .../Assets/Scripts/Input/AssemblyInfo.cs | 2 ++ .../Assets/Scripts/Input/AssemblyInfo.cs.meta | 2 ++ .../Assets/Scripts/Input/AvatarInputs.cs | 3 +-- ...def => Unity.Multiplayer.Samples.SocialHub.Input.asmdef} | 4 ++-- ...> Unity.Multiplayer.Samples.SocialHub.Input.asmdef.meta} | 0 .../Assets/Scripts/Player/AvatarTransform.cs | 4 ++-- ...ef => Unity.Multiplayer.Samples.SocialHub.Player.asmdef} | 4 ++-- ... Unity.Multiplayer.Samples.SocialHub.Player.asmdef.meta} | 0 13 files changed, 18 insertions(+), 15 deletions(-) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/{com.unity.multiplayer.samples.socialhub.editor.asmdef => Unity.Multiplayer.Samples.SocialHub.Editor.asmdef} (73%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/{com.unity.multiplayer.samples.socialhub.editor.asmdef.meta => Unity.Multiplayer.Samples.SocialHub.Editor.asmdef.meta} (100%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/{com.unity.multiplayer.samples.socialhub.gameplay.asmdef => Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef} (72%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/{com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta => Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef.meta} (100%) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs.meta rename Experimental/DistributedAuthoritySample/Assets/Scripts/Input/{com.unity.multiplayer.samples.socialhub.input.asmdef => Unity.Multiplayer.Samples.SocialHub.Input.asmdef} (73%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Input/{com.unity.multiplayer.samples.socialhub.input.asmdef.meta => Unity.Multiplayer.Samples.SocialHub.Input.asmdef.meta} (100%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Player/{com.unity.multiplayer.samples.socialhub.player.asmdef => Unity.Multiplayer.Samples.SocialHub.Player.asmdef} (77%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Player/{com.unity.multiplayer.samples.socialhub.player.asmdef.meta => Unity.Multiplayer.Samples.SocialHub.Player.asmdef.meta} (100%) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs index ab772c38b..578f9d4ad 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs @@ -1,13 +1,13 @@ -using com.unity.multiplayer.samples.socialhub.player; +using Unity.Multiplayer.Samples.SocialHub.Player; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; -namespace com.unity.multiplayer.samples.socialhub.editor +namespace Unity.Multiplayer.Samples.SocialHub.Editor { [CustomEditor(typeof(AvatarTransform))] - class DerivedComponentEditor : Editor + class DerivedComponentEditor : UnityEditor.Editor { public override VisualElement CreateInspectorGUI() { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef similarity index 73% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef index 27f97af4c..763c559da 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef @@ -1,6 +1,6 @@ { - "name": "com.unity.multiplayer.samples.socialhub.editor", - "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "name": "Unity.Multiplayer.Samples.SocialHub.Editor", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ "GUID:8314b31eee3cc495ca4a4f078575802d" ], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef.meta similarity index 100% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/com.unity.multiplayer.samples.socialhub.editor.asmdef.meta rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef similarity index 72% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef index e838cdd64..a09e1b725 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef @@ -1,6 +1,6 @@ { - "name": "com.unity.multiplayer.samples.socialhub.gameplay", - "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "name": "Unity.Multiplayer.Samples.SocialHub.Gameplay", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ "GUID:1491147abca9d7d4bb7105af628b223e" ], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef.meta similarity index 100% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/com.unity.multiplayer.samples.socialhub.gameplay.asmdef.meta rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs new file mode 100644 index 000000000..9b00a0c99 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Player")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs.meta new file mode 100644 index 000000000..dc8750969 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7c74f4c681bf048b5bb6df8e0126a2de \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs index c04540d5d..523078d25 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs @@ -2,8 +2,7 @@ using UnityEngine; using UnityEngine.InputSystem; -[assembly: InternalsVisibleTo("com.unity.multiplayer.samples.socialhub.player")] -namespace com.unity.multiplayer.samples.socialhub.input +namespace Unity.Multiplayer.Samples.SocialHub.Input { class AvatarInputs : MonoBehaviour { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/Unity.Multiplayer.Samples.SocialHub.Input.asmdef similarity index 73% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Input/Unity.Multiplayer.Samples.SocialHub.Input.asmdef index c509405bd..47acd6f34 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/Unity.Multiplayer.Samples.SocialHub.Input.asmdef @@ -1,6 +1,6 @@ { - "name": "com.unity.multiplayer.samples.socialhub.input", - "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "name": "Unity.Multiplayer.Samples.SocialHub.Input", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ "GUID:75469ad4d38634e559750d17036d5f7c" ], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/Unity.Multiplayer.Samples.SocialHub.Input.asmdef.meta similarity index 100% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Input/com.unity.multiplayer.samples.socialhub.input.asmdef.meta rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Input/Unity.Multiplayer.Samples.SocialHub.Input.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 4f81bc88e..90b14338c 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -1,8 +1,8 @@ using Unity.Netcode.Components; using UnityEngine; -using com.unity.multiplayer.samples.socialhub.input; +using Unity.Multiplayer.Samples.SocialHub.Input; -namespace com.unity.multiplayer.samples.socialhub.player +namespace Unity.Multiplayer.Samples.SocialHub.Player { [RequireComponent(typeof(Rigidbody))] public class AvatarTransform : NetworkTransform diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef similarity index 77% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef index 8a059e8ad..5a39c55fa 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef @@ -1,6 +1,6 @@ { - "name": "com.unity.multiplayer.samples.socialhub.player", - "rootNamespace": "com.unity.multiplayer.samples.socialhub", + "name": "Unity.Multiplayer.Samples.SocialHub.Player", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ "GUID:1491147abca9d7d4bb7105af628b223e", "GUID:c15e7f658578345fcb824b0a64d4dbe8", diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef.meta similarity index 100% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Player/com.unity.multiplayer.samples.socialhub.player.asmdef.meta rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef.meta From 609c59dfd9b506ac393307e77ced5786e39a69ab Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Thu, 15 Aug 2024 13:29:10 -0400 Subject: [PATCH 04/13] avatar-side pickup/toss of pickupable object --- .../Assets/Prefabs/Avatar.prefab | 92 ++++++- .../Assets/Scripts/Gameplay/AssemblyInfo.cs | 2 + .../Scripts/Gameplay/AssemblyInfo.cs.meta | 2 + .../Assets/Scripts/Gameplay/GameplayEvent.cs | 10 + .../Scripts/Gameplay/GameplayEvent.cs.meta | 2 + .../Gameplay/IGameplayEventInvokable.cs | 10 + .../Gameplay/IGameplayEventInvokable.cs.meta | 2 + .../Scripts/Gameplay/IOwnershipRequestable.cs | 11 + .../Gameplay/IOwnershipRequestable.cs.meta | 2 + .../Assets/Scripts/Input/AvatarInputs.cs | 60 ++++- .../Scripts/Player/AvatarInteractions.cs | 228 ++++++++++++++++++ .../Scripts/Player/AvatarInteractions.cs.meta | 2 + .../ProjectSettings/TagManager.asset | 2 +- 13 files changed, 414 insertions(+), 11 deletions(-) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index 5bac5aa18..46e760340 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -1,5 +1,58 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1 &2790727344451942854 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5714572371256472543} + - component: {fileID: 1819693744524683591} + m_Layer: 0 + m_Name: InteractCollider + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5714572371256472543 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2790727344451942854} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 378099091213283077} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &1819693744524683591 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2790727344451942854} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} --- !u!1 &2971605785670457434 GameObject: m_ObjectHideFlags: 0 @@ -212,6 +265,7 @@ GameObject: - component: {fileID: -8100831418301897270} - component: {fileID: 4903152183366241606} - component: {fileID: 8197190117666738524} + - component: {fileID: 6126152928325105854} m_Layer: 0 m_Name: Avatar m_TagString: Untagged @@ -233,6 +287,7 @@ Transform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 527982249900556139} + - {fileID: 5714572371256472543} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2864305741433477372 @@ -290,7 +345,6 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 - PropertiesVisible: 1 m_Rigidbody: {fileID: 4745766379562620470} m_PlayerInput: {fileID: 4903152183366241606} m_AvatarInputs: {fileID: 8197190117666738524} @@ -382,15 +436,35 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5478015027486214707} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 7e9f71718dd134b14b300e378e98c718, type: 3} m_Name: m_EditorClassIdentifier: - move: {x: 0, y: 0} - look: {x: 0, y: 0} - jump: 0 - sprint: 0 - analogMovement: 0 - cursorLocked: 1 - cursorInputForLook: 1 + m_InteractActionReference: {fileID: 1781555164194001046, guid: dcd1b4eb76b964f40afe6c0a3ca65c82, type: 3} + Move: {x: 0, y: 0} + Look: {x: 0, y: 0} + Jump: 0 + Sprint: 0 + AnalogMovement: 0 + CursorLocked: 1 + CursorInputForLook: 1 +--- !u!114 &6126152928325105854 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5478015027486214707} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b47efef44cef74d9ca00f4913607f988, type: 3} + m_Name: + m_EditorClassIdentifier: + m_MainCollider: {fileID: 817796967242824188} + m_AvatarInputs: {fileID: 8197190117666738524} + m_NetworkRigidbody: {fileID: -8100831418301897270} + m_HoldTransform: {fileID: 378099091213283077} + m_InteractCollider: {fileID: 1819693744524683591} + m_MinTossForce: 5 + m_MaxTossForce: 10 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs new file mode 100644 index 000000000..9b00a0c99 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Player")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs.meta new file mode 100644 index 000000000..b48cd6cd4 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3465502a3a2c6448b96874d02edbb908 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs new file mode 100644 index 000000000..b2e3aff99 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + enum GameplayEvent + { + Despawned, + OwnershipChange + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs.meta new file mode 100644 index 000000000..685a4d486 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/GameplayEvent.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 507a19fc89d974f28adddfe762c13eb7 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs new file mode 100644 index 000000000..94f0cc79c --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs @@ -0,0 +1,10 @@ +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + interface IGameplayEventInvokable + { + event System.Action OnGameplayEvent; + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs.meta new file mode 100644 index 000000000..f3be27c52 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IGameplayEventInvokable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0969e36952ce846e895b036088dd6afa diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs new file mode 100644 index 000000000..e61f52504 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs @@ -0,0 +1,11 @@ +using System; +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + interface IOwnershipRequestable + { + event Action OnNetworkObjectOwnershipRequestResponse; + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs.meta new file mode 100644 index 000000000..df8630127 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/IOwnershipRequestable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 071ac956e173f479691c6233c0f4fb2e \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs index 523078d25..c4abc9618 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs @@ -1,11 +1,15 @@ -using System.Runtime.CompilerServices; +using System; using UnityEngine; using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Interactions; namespace Unity.Multiplayer.Samples.SocialHub.Input { class AvatarInputs : MonoBehaviour { + [SerializeField] + InputActionReference m_InteractActionReference; + [Header("Character Input Values")] [SerializeField] internal Vector2 Move; @@ -26,6 +30,60 @@ class AvatarInputs : MonoBehaviour [SerializeField] internal bool CursorInputForLook = true; + internal event Action InteractTapped; + internal event Action InteractHeld; + + // tracking when a Hold interaction has started/ended + bool m_HoldingInteractionPerformed; + + void Start() + { + if (m_InteractActionReference == null) + { + Debug.LogWarning("Assign Interact InputActionReference to this MonoBehaviour!", this); + return; + } + + m_InteractActionReference.action.performed += OnInteractPerformed; + m_InteractActionReference.action.canceled += OnInteractCanceled; + m_InteractActionReference.action.Enable(); + } + + void OnDestroy() + { + if (m_InteractActionReference != null) + { + m_InteractActionReference.action.performed -= OnInteractPerformed; + m_InteractActionReference.action.canceled -= OnInteractCanceled; + m_InteractActionReference.action.Disable(); + } + } + + void OnInteractPerformed(InputAction.CallbackContext context) + { + switch (context.interaction) + { + case HoldInteraction: + m_HoldingInteractionPerformed = true; + break; + case TapInteraction: + InteractTapped?.Invoke(); + break; + } + } + + void OnInteractCanceled(InputAction.CallbackContext context) + { + if (context.interaction is HoldInteraction) + { + if (m_HoldingInteractionPerformed) + { + InteractHeld?.Invoke(context.duration); + } + m_HoldingInteractionPerformed = false; + } + } + #if ENABLE_INPUT_SYSTEM void OnMove(InputValue value) { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs new file mode 100644 index 000000000..e511bc6ca --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs @@ -0,0 +1,228 @@ +using System; +using Unity.Multiplayer.Samples.SocialHub.Gameplay; +using Unity.Multiplayer.Samples.SocialHub.Input; +using Unity.Netcode; +using Unity.Netcode.Components; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Player +{ + [RequireComponent(typeof(AvatarInputs))] + class AvatarInteractions : NetworkBehaviour + { + [SerializeField] + Collider m_MainCollider; + + [SerializeField] + AvatarInputs m_AvatarInputs; + + [SerializeField] + NetworkRigidbody m_NetworkRigidbody; + + [SerializeField] + Transform m_HoldTransform; + + [SerializeField] + Collider m_InteractCollider; + + [SerializeField] + float m_MinTossForce; + + [SerializeField] + float m_MaxTossForce; + + Collider[] m_Results = new Collider[1]; + + LayerMask m_PickupableLayerMask; + + NetworkRigidbody m_HoldingRigidbody; + + const float k_MinDurationHeld = 0f; + const float k_MaxDurationHeld = 2f; + + void Awake() + { + m_PickupableLayerMask = 1 << LayerMask.NameToLayer("Pickupable"); + } + + public override void OnNetworkSpawn() + { + if (!HasAuthority) + { + return; + } + + if (!m_AvatarInputs) + { + Debug.LogWarning("Assign AvatarInputs in the inspector!"); + return; + } + + m_AvatarInputs.InteractTapped += OnTapPerformed; + m_AvatarInputs.InteractHeld += OnHoldReleased; + } + + public override void OnNetworkDespawn() + { + if (m_AvatarInputs) + { + m_AvatarInputs.InteractTapped -= OnTapPerformed; + m_AvatarInputs.InteractHeld -= OnHoldReleased; + } + } + + void OnTapPerformed() + { + if (m_HoldingRigidbody != null) + { + ReleaseHeldObject(); + } + else + { + PickUp(); + } + } + + void OnHoldReleased(double holdDuration) + { + if (m_HoldingRigidbody != null) + { + Toss(holdDuration); + } + } + + void PickUp() + { + if (Physics.OverlapBoxNonAlloc(m_InteractCollider.transform.position, m_InteractCollider.bounds.extents, m_Results, Quaternion.identity, mask: m_PickupableLayerMask) > 0) + { + if (m_Results[0].TryGetComponent(out NetworkObject otherNetworkObject)) + { + // if NetworkObject is locked, nothing we can do but retry a pickup at another time + if (otherNetworkObject.IsOwnershipLocked) + { + return; + } + + // trivial case: other NetworkObject is owned by this client, we can attach to fixed joint + if (otherNetworkObject.HasAuthority) + { + AttachToFixedJoint(otherNetworkObject); + return; + } + + if (otherNetworkObject.IsOwnershipTransferable) + { + // can use change ownership directly + otherNetworkObject.ChangeOwnership(OwnerClientId); + + // we can attach it via FixedPoint now as we are now owning this NetworkObject + AttachToFixedJoint(otherNetworkObject); + } + else if (otherNetworkObject.IsOwnershipRequestRequired) + { + // if not transferable, we must request access to become owner + if (m_Results[0].TryGetComponent(out IOwnershipRequestable otherRequestable)) + { + var ownershipRequestStatus = otherNetworkObject.RequestOwnership(); + if (ownershipRequestStatus == NetworkObject.OwnershipRequestStatus.RequestSent) + { + otherRequestable.OnNetworkObjectOwnershipRequestResponse += OnOwnershipRequestResponse; + } + } + } + } + } + } + + void OnOwnershipRequestResponse(NetworkObject other, NetworkObject.OwnershipRequestResponseStatus status) + { + // unsubscribe + var ownershipRequestable = other.GetComponent(); + ownershipRequestable.OnNetworkObjectOwnershipRequestResponse -= OnOwnershipRequestResponse; + + if (status != NetworkObject.OwnershipRequestResponseStatus.Approved) + { + return; + } + + AttachToFixedJoint(other); + } + + void AttachToFixedJoint(NetworkObject other) + { + if (!other.TryGetComponent(out NetworkRigidbody otherNetworkRigidbody)) + { + return; + } + + var success = otherNetworkRigidbody.AttachToFixedJoint(m_NetworkRigidbody, m_HoldTransform.position, massScale: 0.00001f); + if (success) + { + m_HoldingRigidbody = otherNetworkRigidbody; + + // set ownership status to request required, now that this object is being held + m_HoldingRigidbody.NetworkObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.RequestRequired, clearAndSet: true); + + var gameplayEventInvokable = other.GetComponent(); + gameplayEventInvokable.OnGameplayEvent += OnGameplayEvent; + + // prevent collisions from this collider to the picked up object and vice-versa + Physics.IgnoreCollision(m_MainCollider, other.GetComponent(), true); + } + } + + void OnGameplayEvent(NetworkObject networkObject, GameplayEvent gameplayEvent) + { + switch (gameplayEvent) + { + case GameplayEvent.Despawned: + case GameplayEvent.OwnershipChange: + + // unsubscribe + var gameplayEventInvokable = networkObject.GetComponent(); + gameplayEventInvokable.OnGameplayEvent -= OnGameplayEvent; + + // revert collision + if (networkObject.TryGetComponent(out Collider otherCollider)) + { + Physics.IgnoreCollision(m_MainCollider, otherCollider, false); + } + + // don't have ownership of the item, thus we can't invoke DetachFromFixedJoint(), but we need to remove created FixedJoint component + if (networkObject.TryGetComponent(out FixedJoint fixedJoint)) + { + Destroy(fixedJoint); + } + + m_HoldingRigidbody = null; + + break; + default: + throw new Exception($"Unknown GameplayEvent {gameplayEvent}!"); + } + } + + void ReleaseHeldObject() + { + // set ownership status to request required, now that this object is being held + m_HoldingRigidbody.NetworkObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.Distributable, clearAndSet: true); + m_HoldingRigidbody.NetworkObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.Transferable); + + m_HoldingRigidbody.DetachFromFixedJoint(); + m_HoldingRigidbody.GetComponent().useGravity = true; + Physics.IgnoreCollision(m_MainCollider, m_HoldingRigidbody.GetComponent(), false); + m_HoldingRigidbody = null; + } + + void Toss(double holdDuration) + { + var heldRigidbody = m_HoldingRigidbody.GetComponent(); + ReleaseHeldObject(); + + // apply a force to the released object + float timeHeldClamped = Mathf.Clamp((float)holdDuration, k_MinDurationHeld, k_MaxDurationHeld); + float tossForce = Mathf.Lerp(m_MinTossForce, m_MaxTossForce, Mathf.Clamp(timeHeldClamped, 0f, 1f)); + heldRigidbody.AddForce(transform.forward * tossForce, ForceMode.Impulse); + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs.meta new file mode 100644 index 000000000..2981f7212 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b47efef44cef74d9ca00f4913607f988 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/ProjectSettings/TagManager.asset b/Experimental/DistributedAuthoritySample/ProjectSettings/TagManager.asset index 148ab95f6..8899010ff 100644 --- a/Experimental/DistributedAuthoritySample/ProjectSettings/TagManager.asset +++ b/Experimental/DistributedAuthoritySample/ProjectSettings/TagManager.asset @@ -12,8 +12,8 @@ TagManager: - - Water - UI - - '[Empty Slot]' - Ground + - Pickupable - - - From d7e70f81d75dac1c85e2cac91090f3cce5e0d4e9 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Thu, 15 Aug 2024 14:37:48 -0400 Subject: [PATCH 05/13] adding a pickupable object, EnvironmentTransform, to scene with a spawner --- .../InputSystem/AvatarActions.inputactions | 4 +- .../Assets/NetworkPrefabs.asset | 7 +- .../Assets/Prefabs/Avatar.prefab | 2 +- .../DistributableTransferableObject.prefab | 211 +++++++++ ...istributableTransferableObject.prefab.meta | 7 + .../SessionOwnerNetworkObjectSpawner.prefab | 71 +++ ...ssionOwnerNetworkObjectSpawner.prefab.meta | 7 + .../Assets/Scenes/HubScene.unity | 420 ++++++++++++++++++ .../Scripts/Gameplay/EnvironmentTransform.cs | 54 +++ .../Gameplay/EnvironmentTransform.cs.meta | 2 + .../SessionOwnerNetworkObjectSpawner.cs | 27 ++ .../SessionOwnerNetworkObjectSpawner.cs.meta | 2 + .../Assets/Scripts/Player/AvatarTransform.cs | 1 + 13 files changed, 811 insertions(+), 4 deletions(-) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab create mode 100644 Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab create mode 100644 Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/InputSystem/AvatarActions.inputactions b/Experimental/DistributedAuthoritySample/Assets/InputSystem/AvatarActions.inputactions index 05274d353..513fc5005 100644 --- a/Experimental/DistributedAuthoritySample/Assets/InputSystem/AvatarActions.inputactions +++ b/Experimental/DistributedAuthoritySample/Assets/InputSystem/AvatarActions.inputactions @@ -36,9 +36,9 @@ "name": "Interact", "type": "Button", "id": "852140f2-7766-474d-8707-702459ba45f3", - "expectedControlType": "Button", + "expectedControlType": "", "processors": "", - "interactions": "Hold", + "interactions": "Hold,Tap", "initialStateCheck": false }, { diff --git a/Experimental/DistributedAuthoritySample/Assets/NetworkPrefabs.asset b/Experimental/DistributedAuthoritySample/Assets/NetworkPrefabs.asset index 63e14cc1b..ceae78d4c 100644 --- a/Experimental/DistributedAuthoritySample/Assets/NetworkPrefabs.asset +++ b/Experimental/DistributedAuthoritySample/Assets/NetworkPrefabs.asset @@ -13,4 +13,9 @@ MonoBehaviour: m_Name: NetworkPrefabs m_EditorClassIdentifier: IsDefault: 1 - List: [] + List: + - Override: 0 + Prefab: {fileID: 893974733110552042, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + SourcePrefabToOverride: {fileID: 0} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 0} diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index 46e760340..d4a198d0e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -464,7 +464,7 @@ MonoBehaviour: m_MainCollider: {fileID: 817796967242824188} m_AvatarInputs: {fileID: 8197190117666738524} m_NetworkRigidbody: {fileID: -8100831418301897270} - m_HoldTransform: {fileID: 378099091213283077} + m_HoldTransform: {fileID: 5714572371256472543} m_InteractCollider: {fileID: 1819693744524683591} m_MinTossForce: 5 m_MaxTossForce: 10 diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab new file mode 100644 index 000000000..0872489ec --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -0,0 +1,211 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &893974733110552042 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2736246462863405418} + - component: {fileID: 7532867373889483769} + - component: {fileID: 6167276273388148193} + - component: {fileID: 7690746213975220858} + - component: {fileID: 5499784127695994160} + - component: {fileID: -7368379283164171724} + - component: {fileID: 6039897070700006726} + - component: {fileID: 6689110374311511483} + m_Layer: 7 + m_Name: DistributableTransferableObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2736246462863405418 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &7532867373889483769 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6167276273388148193 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &7690746213975220858 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &5499784127695994160 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2069120471 + InScenePlacedSourceGlobalObjectIdHash: 0 + DeferredDespawnTick: 0 + Ownership: 3 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 1 + AutoObjectParentSync: 1 +--- !u!54 &-7368379283164171724 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + serializedVersion: 4 + m_Mass: 1 + m_Drag: 0 + m_AngularDrag: 0.05 + m_CenterOfMass: {x: 0, y: 0, z: 0} + m_InertiaTensor: {x: 1, y: 1, z: 1} + m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ImplicitCom: 1 + m_ImplicitTensor: 1 + m_UseGravity: 1 + m_IsKinematic: 0 + m_Interpolate: 0 + m_Constraints: 0 + m_CollisionDetection: 0 +--- !u!114 &6039897070700006726 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54937e94f00ab46c8ae43b81027f342c, type: 3} + m_Name: + m_EditorClassIdentifier: + AuthorityMode: 1 + UseUnreliableDeltas: 0 + SyncPositionX: 1 + SyncPositionY: 1 + SyncPositionZ: 1 + SyncRotAngleX: 1 + SyncRotAngleY: 1 + SyncRotAngleZ: 1 + SyncScaleX: 0 + SyncScaleY: 0 + SyncScaleZ: 0 + PositionThreshold: 0.001 + RotAngleThreshold: 0.01 + ScaleThreshold: 0.01 + UseQuaternionSynchronization: 0 + UseQuaternionCompression: 0 + UseHalfFloatPrecision: 0 + InLocalSpace: 0 + Interpolate: 1 + SlerpPosition: 0 +--- !u!114 &6689110374311511483 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3} + m_Name: + m_EditorClassIdentifier: + UseRigidBodyForMotion: 1 + AutoUpdateKinematicState: 1 + AutoSetKinematicOnDespawn: 1 diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab.meta b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab.meta new file mode 100644 index 000000000..747c7c3d7 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab new file mode 100644 index 000000000..2fd5ad46b --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab @@ -0,0 +1,71 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4843296344903462454 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1258953842080244886} + - component: {fileID: 1499607153087855347} + - component: {fileID: 8817259292813230997} + m_Layer: 0 + m_Name: SessionOwnerNetworkObjectSpawner + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1258953842080244886 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4843296344903462454} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1499607153087855347 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4843296344903462454} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 433160265 + InScenePlacedSourceGlobalObjectIdHash: 0 + DeferredDespawnTick: 0 + Ownership: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 1 + AutoObjectParentSync: 1 +--- !u!114 &8817259292813230997 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4843296344903462454} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: eea4e07da167d4da7beddb67532a15f2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_NetworkObjectToSpawn: {fileID: 0} diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab.meta b/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab.meta new file mode 100644 index 000000000..75da0b74d --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/SessionOwnerNetworkObjectSpawner.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e54d55fa193a2495ea1270535da81837 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scenes/HubScene.unity b/Experimental/DistributedAuthoritySample/Assets/Scenes/HubScene.unity index 59c32d26d..a39ad0a8f 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scenes/HubScene.unity +++ b/Experimental/DistributedAuthoritySample/Assets/Scenes/HubScene.unity @@ -118,6 +118,144 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!1001 &43234386 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 3505677855 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner (1) + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} +--- !u!1001 &373304902 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: -2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 910008014 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner (3) + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} --- !u!1 &410087039 GameObject: m_ObjectHideFlags: 0 @@ -288,6 +426,75 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &961771512 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 3782993129 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner (4) + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} --- !u!1 &1305680749 GameObject: m_ObjectHideFlags: 0 @@ -332,6 +539,75 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1329704198 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 1417850551 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner (5) + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} --- !u!1 &1888825843 GameObject: m_ObjectHideFlags: 0 @@ -441,6 +717,75 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1947161561 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: -2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 2143928463 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} --- !u!1001 &2024073102 PrefabInstance: m_ObjectHideFlags: 0 @@ -498,6 +843,75 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: eb439f24fcad44d48b8231b7418345d0, type: 3} +--- !u!1001 &2029928583 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.x + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalPosition.z + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1258953842080244886, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: GlobalObjectIdHash + value: 4096214831 + objectReference: {fileID: 0} + - target: {fileID: 1499607153087855347, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 882396614 + objectReference: {fileID: 0} + - target: {fileID: 4843296344903462454, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_Name + value: SessionOwnerNetworkObjectSpawner (2) + objectReference: {fileID: 0} + - target: {fileID: 8817259292813230997, guid: e54d55fa193a2495ea1270535da81837, type: 3} + propertyPath: m_NetworkObjectToSpawn + value: + objectReference: {fileID: 5499784127695994160, guid: 1c6ec0a7b92244c349d83ba9b4a1c8ab, type: 3} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e54d55fa193a2495ea1270535da81837, type: 3} --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 @@ -507,3 +921,9 @@ SceneRoots: - {fileID: 2024073102} - {fileID: 1888825847} - {fileID: 1305680751} + - {fileID: 1947161561} + - {fileID: 43234386} + - {fileID: 2029928583} + - {fileID: 373304902} + - {fileID: 961771512} + - {fileID: 1329704198} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs new file mode 100644 index 000000000..17decbb41 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs @@ -0,0 +1,54 @@ +using System; +using Unity.Netcode; +using Unity.Netcode.Components; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + class EnvironmentTransform : NetworkTransform, IOwnershipRequestable, IGameplayEventInvokable + { + public event Action OnNetworkObjectOwnershipRequestResponse; + + public event Action OnGameplayEvent; + + public override void OnNetworkSpawn() + { + base.OnNetworkSpawn(); + + NetworkObject.OnOwnershipRequested += OnOwnershipRequested; + NetworkObject.OnOwnershipRequestResponse += OnOwnershipRequestResponse; + } + + public override void OnNetworkDespawn() + { + if (NetworkObject) + { + NetworkObject.OnOwnershipRequested -= OnOwnershipRequested; + NetworkObject.OnOwnershipRequestResponse -= OnOwnershipRequestResponse; + } + + OnGameplayEvent?.Invoke(NetworkObject, GameplayEvent.Despawned); + } + + protected override void OnOwnershipChanged(ulong previous, ulong current) + { + base.OnOwnershipChanged(previous, current); + + OnGameplayEvent?.Invoke(NetworkObject, GameplayEvent.OwnershipChange); + } + + // note: invoked on owning client + bool OnOwnershipRequested(ulong clientRequesting) + { + // defaulting all ownership requests to true, as is the default for all ownership requests + // here, you'd introduce game-based logic to deny/approve requests + return true; + } + + // note: invoked on requesting client + void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponse) + { + OnNetworkObjectOwnershipRequestResponse?.Invoke(NetworkObject, ownershipRequestResponse); + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta new file mode 100644 index 000000000..fa3a503d7 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 54937e94f00ab46c8ae43b81027f342c \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs new file mode 100644 index 000000000..f255bc0c9 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs @@ -0,0 +1,27 @@ +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + class SessionOwnerNetworkObjectSpawner : NetworkBehaviour + { + [SerializeField] + NetworkObject m_NetworkObjectToSpawn; + + NetworkVariable m_InitialSpawnComplete = new NetworkVariable(); + + public override void OnNetworkSpawn() + { + if (IsSessionOwner && !m_InitialSpawnComplete.Value) + { + Spawn(); + } + } + + void Spawn() + { + m_NetworkObjectToSpawn.InstantiateAndSpawn(NetworkManager, position: transform.position, rotation: transform.rotation); + m_InitialSpawnComplete.Value = true; + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs.meta new file mode 100644 index 000000000..50612e5bb --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/SessionOwnerNetworkObjectSpawner.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: eea4e07da167d4da7beddb67532a15f2 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 90b14338c..19aed92b3 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -52,6 +52,7 @@ public override void OnNetworkSpawn() } m_PlayerInput.enabled = true; + m_AvatarInputs.enabled = true; m_Rigidbody.isKinematic = false; // Freeze rotation on the x and z axes to prevent toppling From 301856bf5f690bd08862699989ca181ffab504c3 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Thu, 15 Aug 2024 16:00:58 -0400 Subject: [PATCH 06/13] adding explicitly inputsystem to player assembly --- .../Assets/Prefabs/Avatar.prefab | 17 ++++++++--------- .../Assets/Scripts/Player/AvatarTransform.cs | 4 +++- ....Multiplayer.Samples.SocialHub.Player.asmdef | 3 ++- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index 5bac5aa18..4bcfbc52e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -290,7 +290,6 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 - PropertiesVisible: 1 m_Rigidbody: {fileID: 4745766379562620470} m_PlayerInput: {fileID: 4903152183366241606} m_AvatarInputs: {fileID: 8197190117666738524} @@ -382,15 +381,15 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5478015027486214707} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 7e9f71718dd134b14b300e378e98c718, type: 3} m_Name: m_EditorClassIdentifier: - move: {x: 0, y: 0} - look: {x: 0, y: 0} - jump: 0 - sprint: 0 - analogMovement: 0 - cursorLocked: 1 - cursorInputForLook: 1 + Move: {x: 0, y: 0} + Look: {x: 0, y: 0} + Jump: 0 + Sprint: 0 + AnalogMovement: 0 + CursorLocked: 1 + CursorInputForLook: 1 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 90b14338c..7601e7640 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -1,6 +1,7 @@ using Unity.Netcode.Components; using UnityEngine; using Unity.Multiplayer.Samples.SocialHub.Input; +using UnityEngine.InputSystem; namespace Unity.Multiplayer.Samples.SocialHub.Player { @@ -10,7 +11,7 @@ public class AvatarTransform : NetworkTransform [SerializeField] Rigidbody m_Rigidbody; [SerializeField] - MonoBehaviour m_PlayerInput; + PlayerInput m_PlayerInput; [SerializeField] AvatarInputs m_AvatarInputs; [SerializeField] @@ -52,6 +53,7 @@ public override void OnNetworkSpawn() } m_PlayerInput.enabled = true; + m_AvatarInputs.enabled = true; m_Rigidbody.isKinematic = false; // Freeze rotation on the x and z axes to prevent toppling diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef index 5a39c55fa..ebff7a9ea 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef @@ -4,7 +4,8 @@ "references": [ "GUID:1491147abca9d7d4bb7105af628b223e", "GUID:c15e7f658578345fcb824b0a64d4dbe8", - "GUID:9ff2150ce7d7c415a8af1fbff3dc3e6c" + "GUID:9ff2150ce7d7c415a8af1fbff3dc3e6c", + "GUID:75469ad4d38634e559750d17036d5f7c" ], "includePlatforms": [], "excludePlatforms": [], From 985d6d61ad785de46f09906cec6b15016848ccc0 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 21 Aug 2024 12:27:48 -0400 Subject: [PATCH 07/13] destructible object created, physics scripts imported --- .../DistributableTransferableObject.prefab | 58 +- .../Editor/PhysicsObjectMotionEditor.cs | 80 +++ .../Editor/PhysicsObjectMotionEditor.cs.meta | 2 + ...ultiplayer.Samples.SocialHub.Editor.asmdef | 3 +- .../Scripts/Gameplay/DestructibleObject.cs | 44 ++ .../Gameplay/DestructibleObject.cs.meta | 2 + ...mentTransform.cs => TransferableObject.cs} | 3 +- ...orm.cs.meta => TransferableObject.cs.meta} | 0 ...tiplayer.Samples.SocialHub.Gameplay.asmdef | 3 +- .../Physics/BaseObjectMotionHandler.cs | 592 ++++++++++++++++++ .../Physics/BaseObjectMotionHandler.cs.meta | 11 + .../Scripts/Physics/CollisionMessageInfo.cs | 148 +++++ .../Physics/CollisionMessageInfo.cs.meta | 11 + .../Scripts/Physics/ICollisionHandler.cs | 19 + .../Scripts/Physics/ICollisionHandler.cs.meta | 11 + .../Scripts/Physics/PhysicsObjectMotion.cs | 469 ++++++++++++++ .../Physics/PhysicsObjectMotion.cs.meta | 11 + ...ltiplayer.Samples.SocialHub.Physics.asmdef | 16 + ...ayer.Samples.SocialHub.Physics.asmdef.meta | 7 + 19 files changed, 1471 insertions(+), 19 deletions(-) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs.meta rename Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/{EnvironmentTransform.cs => TransferableObject.cs} (93%) rename Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/{EnvironmentTransform.cs.meta => TransferableObject.cs.meta} (100%) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab index 0872489ec..7f4fb2deb 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -16,6 +16,8 @@ GameObject: - component: {fileID: -7368379283164171724} - component: {fileID: 6039897070700006726} - component: {fileID: 6689110374311511483} + - component: {fileID: 6961888493949678523} + - component: {fileID: 2700541251598630985} m_Layer: 7 m_Name: DistributableTransferableObject m_TagString: Untagged @@ -174,6 +176,47 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 54937e94f00ab46c8ae43b81027f342c, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &6689110374311511483 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3} + m_Name: + m_EditorClassIdentifier: + UseRigidBodyForMotion: 1 + AutoUpdateKinematicState: 1 + AutoSetKinematicOnDespawn: 1 +--- !u!114 &6961888493949678523 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 496a933d305aa4e1c926bd7d19b42f46, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Impacts: + m_InternalValue: 0 +--- !u!114 &2700541251598630985 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 893974733110552042} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3} + m_Name: + m_EditorClassIdentifier: AuthorityMode: 1 UseUnreliableDeltas: 0 SyncPositionX: 1 @@ -194,18 +237,3 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 ---- !u!114 &6689110374311511483 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 893974733110552042} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3} - m_Name: - m_EditorClassIdentifier: - UseRigidBodyForMotion: 1 - AutoUpdateKinematicState: 1 - AutoSetKinematicOnDespawn: 1 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs new file mode 100644 index 000000000..ef81dffcc --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs @@ -0,0 +1,80 @@ +using Unity.Multiplayer.Samples.SocialHub.Physics; +using UnityEngine; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace Unity.Multiplayer.Samples.SocialHub.Editor +{ + [CustomEditor(typeof(PhysicsObjectMotion))] + class PhysicsObjectMotionEditor : UnityEditor.Editor + { + public override VisualElement CreateInspectorGUI() + { + // Create a new VisualElement to be the root of the inspector UI + var root = new VisualElement(); + + // Generate default inspector for AvatarTransform + serializedObject.Update(); + SerializedProperty property = serializedObject.GetIterator(); + property.NextVisible(true); // Skip the script field + while (property.NextVisible(false)) + { + var propertyField = new PropertyField(property); + root.Add(propertyField); + } + + serializedObject.ApplyModifiedProperties(); + + return root; + } + } + + /*/// + /// The custom editor for the component. + /// + [CustomEditor(typeof(PhysicsObjectMotion), true)] + public class PhysicsObjectMotionEditor : BaseObjectMotionHandlerEditor + { + private SerializedProperty m_CollisionImpulseEntries; + private SerializedProperty m_MaxAngularVelocity; + private SerializedProperty m_MaxVelocity; + private SerializedProperty m_MinMaxStartingTorque; + private SerializedProperty m_MinMaxStartingForce; + + public override void OnEnable() + { + m_CollisionImpulseEntries = serializedObject.FindProperty(nameof(PhysicsObjectMotion.CollisionImpulseEntries)); + m_MaxAngularVelocity = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MaxAngularVelocity)); + m_MaxVelocity = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MaxVelocity)); + m_MinMaxStartingTorque = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MinMaxStartingTorque)); + m_MinMaxStartingForce = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MinMaxStartingForce)); + base.OnEnable(); + } + + public override void OnInspectorGUI() + { + var physicsObject = target as PhysicsObjectMotion; + + physicsObject.PhysicsObjectMotionPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(physicsObject.PhysicsObjectMotionPropertiesVisible, $"{nameof(PhysicsObjectMotion)} Properties"); + if (physicsObject.PhysicsObjectMotionPropertiesVisible) + { + // End the header group since m_MinMaxStartingTorque and m_MinMaxStartingForce both use header groups + EditorGUILayout.EndFoldoutHeaderGroup(); + EditorGUILayout.PropertyField(m_CollisionImpulseEntries); + EditorGUILayout.PropertyField(m_MaxAngularVelocity); + EditorGUILayout.PropertyField(m_MaxVelocity); + EditorGUILayout.PropertyField(m_MinMaxStartingTorque); + EditorGUILayout.PropertyField(m_MinMaxStartingForce); + } + else + { + EditorGUILayout.EndFoldoutHeaderGroup(); + } + + EditorGUILayout.Space(); + + base.OnInspectorGUI(); + } + }*/ +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs.meta new file mode 100644 index 000000000..199590052 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6513302c68bd64368883bcb638331607 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef index 763c559da..30de4dafc 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef @@ -2,7 +2,8 @@ "name": "Unity.Multiplayer.Samples.SocialHub.Editor", "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ - "GUID:8314b31eee3cc495ca4a4f078575802d" + "GUID:8314b31eee3cc495ca4a4f078575802d", + "GUID:ae1323dabfa6440b3956d4cc5239e361" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs new file mode 100644 index 000000000..9c655d2d2 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs @@ -0,0 +1,44 @@ +using System; +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Gameplay +{ + class DestructibleObject : NetworkBehaviour + { + [SerializeField] + NetworkVariable m_Impacts = new NetworkVariable(); + + public override void OnNetworkSpawn() + { + base.OnNetworkSpawn(); + + enabled = HasAuthority; + } + + public override void OnNetworkDespawn() + { + base.OnNetworkDespawn(); + } + + protected override void OnOwnershipChanged(ulong previous, ulong current) + { + Debug.Log($"previous {previous} current {current}"); + enabled = HasAuthority; + } + + void OnCollisionEnter(Collision collision) + { + if (!HasAuthority) + { + return; + } + + if (collision.gameObject.layer == gameObject.layer) + { + Debug.Log($"Hit {collision.gameObject.name} of owner {collision.gameObject.GetComponent().OwnerClientId} collision.impulse.magnitude {collision.impulse.magnitude}"); + m_Impacts.Value += 1; + } + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs.meta new file mode 100644 index 000000000..5975b7b17 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 496a933d305aa4e1c926bd7d19b42f46 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs similarity index 93% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs index 17decbb41..c0c62a4e5 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs @@ -1,11 +1,10 @@ using System; using Unity.Netcode; -using Unity.Netcode.Components; using UnityEngine; namespace Unity.Multiplayer.Samples.SocialHub.Gameplay { - class EnvironmentTransform : NetworkTransform, IOwnershipRequestable, IGameplayEventInvokable + class TransferableObject : NetworkBehaviour, IOwnershipRequestable, IGameplayEventInvokable { public event Action OnNetworkObjectOwnershipRequestResponse; diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs.meta similarity index 100% rename from Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta rename to Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef index a09e1b725..506fb058a 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/Unity.Multiplayer.Samples.SocialHub.Gameplay.asmdef @@ -2,7 +2,8 @@ "name": "Unity.Multiplayer.Samples.SocialHub.Gameplay", "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ - "GUID:1491147abca9d7d4bb7105af628b223e" + "GUID:1491147abca9d7d4bb7105af628b223e", + "GUID:ae1323dabfa6440b3956d4cc5239e361" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs new file mode 100644 index 000000000..07f6bcbd8 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs @@ -0,0 +1,592 @@ +using System; +using System.Runtime.CompilerServices; +using Unity.Netcode; +using Unity.Netcode.Components; +using UnityEngine; +using Random = UnityEngine.Random; +using System.Collections.Generic; + +/* +#if UNITY_EDITOR +using Unity.Netcode.Editor; +using UnityEditor; +/// +/// The custom editor for the component. +/// +[CustomEditor(typeof(BaseObjectMotionHandler), true)] +public class BaseObjectMotionHandlerEditor : NetworkTransformEditor +{ + private SerializedProperty m_IsPooled; + private SerializedProperty m_CollisionType; + private SerializedProperty m_CollisionDamage; + private SerializedProperty m_DebugCollisions; + private SerializedProperty m_DebugDamage; + private SerializedProperty m_EnableBoundary; + private SerializedProperty m_Colliders; + + public override void OnEnable() + { + m_IsPooled = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.IsPooled)); + m_Colliders = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.Colliders)); + m_CollisionType = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.CollisionType)); + m_CollisionDamage = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.CollisionDamage)); + m_DebugCollisions = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.DebugCollisions)); + m_DebugDamage = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.DebugDamage)); + m_EnableBoundary = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.EnableBoundary)); + + base.OnEnable(); + } + + public override void OnInspectorGUI() + { + var baseObject = target as BaseObjectMotionHandler; + baseObject.BaseObjectMotionHandlerPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.BaseObjectMotionHandlerPropertiesVisible, $"{nameof(BaseObjectMotionHandler)} Properties"); + if (baseObject.BaseObjectMotionHandlerPropertiesVisible) + { + // End the header group since m_Colliders is a header group + EditorGUILayout.EndFoldoutHeaderGroup(); + EditorGUILayout.PropertyField(m_IsPooled); + EditorGUILayout.PropertyField(m_Colliders); + EditorGUILayout.PropertyField(m_CollisionType); + EditorGUILayout.PropertyField(m_CollisionDamage); + EditorGUILayout.PropertyField(m_DebugCollisions); + EditorGUILayout.PropertyField(m_DebugDamage); + EditorGUILayout.PropertyField(m_EnableBoundary); + } + else + { + EditorGUILayout.EndFoldoutHeaderGroup(); + } + + EditorGUILayout.Space(); + + baseObject.NetworkTransformPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.NetworkTransformPropertiesVisible, $"{nameof(NetworkTransform)} Properties"); + if (baseObject.NetworkTransformPropertiesVisible) + { + base.OnInspectorGUI(); + } + else + { + serializedObject.ApplyModifiedProperties(); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + } +} +#endif +*/ + +/// +/// Projectiles will be owner driven +/// +public partial class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEventHandler +{ + +#if UNITY_EDITOR + public bool BaseObjectMotionHandlerPropertiesVisible = false; + public bool NetworkTransformPropertiesVisible = false; +#endif + private static GameObject WorldBoundary; + + // Defaults to 1024 but can be updated by adding a GameObject named WorldBoundary and adding a SphereCollider to that. + private static float WorldBoundaryRadius = 1024.0f; + + public bool IsPooled = true; + public CollisionTypes CollisionType; + public ushort CollisionDamage; + + public Action OnNetworkObjectDespawned; + + public bool DebugBoundaryCheck; + + protected CollisionMessageInfo CollisionMessage = new CollisionMessageInfo(); + private Rigidbody m_Rigidbody; + private NetworkRigidbody m_NetworkRigidbody; + + public Rigidbody Rigidbody => m_Rigidbody; + public NetworkRigidbody NetworkRigidbody => m_NetworkRigidbody; + + [Tooltip("Enables/Disables collision logging (based on per derived type)")] + public bool DebugCollisions; + + [Tooltip("Enables/Disables damage logging (based on per derived type)")] + public bool DebugDamage; + + [HideInInspector] + public bool IsPhysicsBody; + + [Tooltip("When enabled, all physics bodies will head back towards the center once they reach the boundary limits.")] + public bool EnableBoundary = true; + + [Tooltip("Add all colliders to this list that will be used to detect collisions (exclude triggers).")] + public List Colliders; + + private Dictionary ColliderScales = new Dictionary(); + + protected void EnableColliders(bool enable) + { + foreach (var collider in Colliders) + { + collider.enabled = enable; + } + } + + private const float k_BoundaryCheckFrequency = 0.06667f; + private const int k_BoundaryCheckDistributionRes = 10; + private static int s_BoundaryOffsetCount = 1; + private float m_NextBoundaryCheck; + + public Rigidbody GetRigidbody() { return m_Rigidbody; } + + protected virtual Vector3 OnGetObjectVelocity(bool getReference = false) + { + if (m_Rigidbody != null) + { +#if UNITY_2023_3_OR_NEWER + return m_Rigidbody.linearVelocity; +#else + return m_Rigidbody.velocity; +#endif + } + return Vector3.zero; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector3 GetObjectVelocity(bool getReference = false) + { + return OnGetObjectVelocity(getReference); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetObjectVelocity(Vector3 velocity) + { + if (m_Rigidbody != null) + { +#if UNITY_2023_3_OR_NEWER + m_Rigidbody.linearVelocity = velocity; +#else + m_Rigidbody.velocity = velocity; +#endif + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual Vector3 OnGetObjectAngularVelocity() + { + if (m_Rigidbody != null) + { + return m_Rigidbody.angularVelocity; + } + return Vector3.zero; + } + + public Vector3 GetObjectAngularVelocity() + { + return OnGetObjectAngularVelocity(); + } + + + protected void IgnoreCollision(GameObject objectA, GameObject objectB, bool shouldIgnore) + { + if (objectA == null || objectB == null) + { + return; + } + + var rootA = objectA.transform.root.gameObject; + var rootB = objectB.transform.root.gameObject; + + var collidersA = rootA.GetComponentsInChildren(); + var collidersB = rootB.GetComponentsInChildren(); + + foreach (var colliderA in collidersA) + { + foreach (var colliderB in collidersB) + { + Physics.IgnoreCollision(colliderA, colliderB, shouldIgnore); + } + } + } + + public override void OnNetworkDespawn() + { + base.OnNetworkDespawn(); + OnNetworkObjectDespawned?.Invoke(); + OnNetworkObjectDespawned = null; + + /*var fxObjects = GetComponentsInChildren(); + foreach (var fxObject in fxObjects) + { + fxObject.transform.SetParent(null); + }*/ + } + + /// + /// Override this method to make adjustments for wrapping + /// + protected virtual bool OnBoundaryReached() + { + return true; + } + + // Distribute the boundary check processing evenly amongst all instances + private void SetNextBoundaryCheck(float timeOffset = k_BoundaryCheckFrequency, bool init = false) + { + if (init) + { + s_BoundaryOffsetCount++; + m_NextBoundaryCheck = Time.realtimeSinceStartup + (timeOffset * (s_BoundaryOffsetCount % k_BoundaryCheckDistributionRes)); + } + else + { + m_NextBoundaryCheck = Time.realtimeSinceStartup + timeOffset; + } + } + + private void CheckBoundary() + { + if (Rigidbody == null || Rigidbody != null && Rigidbody.isKinematic) + { + return; + } + if (EnableBoundary && m_NextBoundaryCheck < Time.realtimeSinceStartup) + { + var distance = Vector3.Distance(Vector3.zero, transform.position); + // if we reached the maximum boundary, then reverse the velocity of the Rigidbody if it has one + if (distance >= WorldBoundaryRadius && OnBoundaryReached()) + { + + var dir = Vector3.zero - transform.position; + var velocity = GetObjectVelocity(); + velocity = velocity.magnitude * dir; + SetObjectVelocity(velocity); + } + else + { + SetNextBoundaryCheck(); + } + } + } + + protected override void Awake() + { + if (WorldBoundary == null) + { + WorldBoundary = GameObject.Find("WorldBoundary"); + if (WorldBoundary != null) + { + var sphereCollider = WorldBoundary.GetComponent(); + WorldBoundaryRadius = sphereCollider.radius; + } + } + + m_Rigidbody = GetComponent(); + m_NetworkRigidbody = GetComponent(); + + SetNextBoundaryCheck(init: true); + + base.Awake(); + } + + protected virtual void Start() + { + CollisionMessage.Damage = CollisionDamage; + CollisionMessage.SetFlag(true, (uint)CollisionType); + } + + /// + /// Invoked every network tick if this instance has sent a update. + /// + /// + protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) + { + CheckBoundary(); + base.OnAuthorityPushTransformState(ref networkTransformState); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static public GameObject GetRootParent(GameObject parent) + { + return parent.transform.root.gameObject; + } + + /// + /// This method provides the ability to make adjustments to the collision message as well as apply damage locally if needed + /// + /// + /// + protected virtual bool OnPrepareCollisionMessage(Vector3 averagedCollisionNormal, BaseObjectMotionHandler targetBaseObjectMotionHandler) + { + return true; + } + + protected virtual void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) + { + } + + public void HandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) + { + OnHandleCollision(collisionMessage, isLocal, applyImmediately); + // Hanlding is invoked before logging so logging can determine the end result. + if (DebugCollisions) + { + LogHandleCollision(collisionMessage); + } + } + + /// + /// Used to communicate collisions + /// + /// + /// + [Rpc(SendTo.Authority, RequireOwnership = false)] + public void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default) + { + // If authority changes while this message is in flight, forward it to the new authority + if (!HasAuthority) + { + LogMessage($"[HandleCollisionRpc][Not Owner][Routing Collision][{name}] Routing to Client-{OwnerClientId}"); + SendCollisionMessage(CollisionMessage); + return; + } + + CollisionMessage.SourceOwner = rpcParams.Receive.SenderClientId; + CollisionMessage.TargetOwner = OwnerClientId; + HandleCollision(collisionMessage); + } + + /// + /// Invoked by the owner of the object inflicting damage, this will handle the RPC routing + /// of the message to the appropriate targeted owner of the object taking damage + /// + /// + public void SendCollisionMessage(CollisionMessageInfo collisionMessage) + { + LogDamage(collisionMessage); + HandleCollisionRpc(collisionMessage); + } + + /// + /// Override this method if you have registerd the instance with and + /// want to customize collision. + /// + /// + /// Only automatically handles collisions. For an example of a customized contact event + /// handler look over . + /// + /// The average normal of the collisions contacts + /// The that collided with this object. + protected virtual void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + + } + + protected ulong LastEventId { get; private set; } + /// + /// Invoked from when a non-kinematic body collides + /// with another registered . + /// + /// The averaged normal of the collision + /// The this objects collided with + public void ContactEvent(ulong eventId, Vector3 averageNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + if (!IsSpawned) + { + return; + } + OnContactEvent(eventId, averageNormal, collidingBody, contactPoint, hasCollisionStay, averagedCollisionStayNormal); + LastEventId = eventId; + } + + + /// + /// Invoked this to send a collision message to the authoritative instance. + /// + /// + /// + protected void EventCollision(Vector3 averagedCollisionNormal, BaseObjectMotionHandler collidingBodyBaseObject) + { +#if DEBUG || UNITY_EDITOR + if (DebugCollisions) + { + LogCollision(ref collidingBodyBaseObject); + } +#endif + + if (OnPrepareCollisionMessage(averagedCollisionNormal, collidingBodyBaseObject)) + { + CollisionId++; + CollisionMessage.CollisionId = CollisionId; + CollisionMessage.Time = Time.realtimeSinceStartup; + CollisionMessage.Source = OwnerClientId; + CollisionMessage.SourceId = NetworkObjectId; + CollisionMessage.Destination = collidingBodyBaseObject.OwnerClientId; + CollisionMessage.DestNetworkObjId = collidingBodyBaseObject.NetworkObjectId; + CollisionMessage.DestBehaviourId = collidingBodyBaseObject.NetworkBehaviourId; + + // Otherwise, send the collision message to the owner of the object + collidingBodyBaseObject.SendCollisionMessage(CollisionMessage); + } + } + + #region DEBUG CONSOLE LOGGING METHODS + + /// + /// Override to handle local collisions generating an outbound message + /// + /// + /// + protected virtual string OnLogCollision(ref BaseObjectMotionHandler objectHit) + { + return "[LocalCollision-End]"; + } + + private static int CollisionId = 0; + private void LogCollision(ref BaseObjectMotionHandler objectHit) + { + if (!DebugCollisions) + { + return; + } + var distance = Vector3.Distance(transform.position, objectHit.transform.position); + /*NetworkManagerHelper.Instance.LogMessage($"[{Time.realtimeSinceStartup}][LocalCollision][{name}][collided with][{objectHit.name}][Collider:{name}][Distance: {distance}]" + + $"{OnLogCollision(ref objectHit)}.");*/ + } + + protected virtual string OnLogDamage(CollisionMessageInfo collisionMessage) + { + return string.Empty; + } + + protected void LogDamage(CollisionMessageInfo collisionMessage) + { + if (!DebugDamage || collisionMessage.Damage == 0) + { + return; + } + var additionalInfo = OnLogDamage(collisionMessage); + /*NetworkManagerHelper.Instance.LogMessage($"[{name}][++Damaged++][Client-{collisionMessage.TargetOwner}][{collisionMessage.GetCollisionType()}][Dmg:{collisionMessage.Damage}] {additionalInfo}");*/ + } + + /// + /// Override to log incoming collision messages + /// + /// + protected virtual string OnLogHandleCollision(ref CollisionMessageInfo collisionMessage) + { + return "[CollisionMessage-End]"; + } + + private void LogHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false) + { + var distance = -1.0f; + if (NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(collisionMessage.DestNetworkObjId)) + { + distance = Vector3.Distance(transform.position, NetworkManager.SpawnManager.SpawnedObjects[collisionMessage.DestNetworkObjId].transform.position); + } + var distStr = distance == -1.0f ? $"{collisionMessage.DestNetworkObjId} DNE!!" : $"Distance: {distance}"; + /*NetworkManagerHelper.Instance.LogMessage($"[{collisionMessage.CollisionId}][{collisionMessage.Time}][CollisionMessage][IsLocal: {isLocal}][{name}][Src:{collisionMessage.Source}][Dest:{collisionMessage.Destination}]" + + $"[NObjId:{collisionMessage.DestNetworkObjId}][NBvrId:{collisionMessage.DestBehaviourId}][{distStr}]{OnLogHandleCollision(ref collisionMessage)}.");*/ + } + + protected void LogMessage(string msg, bool forceMessage = false, float messageTime = 10.0f) + { + /*NetworkManagerHelper.Instance.LogMessage($"[{name}]{msg}", messageTime, forceMessage);*/ + } + + #endregion + + #region VECTOR AND EULER HELPER METHODS + /// + /// Enable this to get 6 decimal precision when logging Vector3 values + /// + private bool m_HigPrecisionDecimals = false; + protected string GetVector3Values(ref Vector3 vector3) + { + if (m_HigPrecisionDecimals) + { + return $"({vector3.x:F6},{vector3.y:F6},{vector3.z:F6})"; + } + else + { + return $"({vector3.x:F2},{vector3.y:F2},{vector3.z:F2})"; + } + } + + protected string GetVector3Values(Vector3 vector3) + { + return GetVector3Values(ref vector3); + } + + protected Vector3 GetRandomVector3(float min, float max, Vector3 baseLine, bool randomlyApplySign = false) + { + var retValue = new Vector3(baseLine.x * Random.Range(min, max), baseLine.y * Random.Range(min, max), baseLine.z * Random.Range(min, max)); + if (!randomlyApplySign) + { + return retValue; + } + + retValue.x *= Random.Range(1, 100) >= 50 ? -1 : 1; + retValue.y *= Random.Range(1, 100) >= 50 ? -1 : 1; + retValue.z *= Random.Range(1, 100) >= 50 ? -1 : 1; + return retValue; + } + + protected Vector3 GetRandomVector3(MinMaxVector2Physics minMax, Vector3 baseLine, bool randomlyApplySign = false) + { + return GetRandomVector3(minMax.Min, minMax.Max, baseLine, randomlyApplySign); + } + + private const float k_DefaultThreshold = 0.0025f; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool Approximately(float a, float b, float threshold = k_DefaultThreshold) + { + return Math.Round(Mathf.Abs(a - b), 4) <= threshold; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool Approximately(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) + { + return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool Approximately(Quaternion a, Quaternion b, float threshold = k_DefaultThreshold) + { + return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z) && Approximately(a.w, b.w); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected float EulerDelta(float a, float b) + { + return Mathf.DeltaAngle(a, b); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool ApproximatelyEuler(float a, float b, float threshold = k_DefaultThreshold) + { + return Mathf.Abs(EulerDelta(a, b)) <= threshold; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected bool ApproximatelyEuler(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) + { + return ApproximatelyEuler(a.x, b.x, threshold) && ApproximatelyEuler(a.y, b.y, threshold) && ApproximatelyEuler(a.z, b.z, threshold); + } + #endregion +} + +[Serializable] +public class MinMaxVector2Physics +{ + [Range(1.0f, 200.0f)] + public float Min; + [Range(1.0f, 200.0f)] + public float Max; + + public MinMaxVector2Physics(float min, float max) + { + Min = min; + Max = max; + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs.meta new file mode 100644 index 000000000..d016b1d61 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d97f2549555383847a36d4dc0a26a53f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs new file mode 100644 index 000000000..4e422440b --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs @@ -0,0 +1,148 @@ +using System.Runtime.CompilerServices; +using Unity.Netcode; +using UnityEngine; + +/// +/// Only 15 types are allowed. +/// Applied to the first byte of +/// +public enum CollisionTypes +{ + Laser = 0x01, + Missile = 0x02, + Mine = 0x03, + Asteroid = 0x04, + Ship = 0x05, + DebugCollision = 0x0F, + // Maximum value for collision types is 15 - 0x0E +} + +/// +/// Flags to be used with +/// 16, 32, 64, and 128 are used for flags +/// +public enum CollisionCategoryFlags +{ + // Four flags are reserved + Standard = 0x10, + CollisionForce = 0x20, + CollisionPoint = 0x40, +} + +public struct CollisionMessageInfo : INetworkSerializable +{ + /// + /// Flags are serialized and determine the collision type + /// + public byte Flags; + + /// + /// Damage is serialized and is set based on the type + /// + public ushort Damage; + + /// + /// Collision force is serialized only if the flags contains the + /// flag. + /// + public Vector3 CollisionForce; + + /// + /// Collision force is serialized only if the flags contains the + /// flag. + /// + public Vector3 CollisionPoint; + + /// + /// Never serialized, only used locally to determine if + /// we are + /// + public bool DebugCollisionEnabled; + + public int CollisionId; + public float Time; + public ulong Source; + public ulong Destination; + public ulong DestNetworkObjId; + public ushort DestBehaviourId; + + /// + /// Never serialized, only used locally + /// + public ulong SourceId; + + /// + /// Never serialized, only used locally + /// + public ulong SourceOwner; + + /// + /// Never serialized, only used locally + /// + public ulong TargetOwner; + + public CollisionTypes GetCollisionType() + { + return (CollisionTypes)(Flags & 0x0F); + } + + public bool HasCollisionForce() + { + return (Flags & (uint)CollisionCategoryFlags.CollisionForce) == (byte)CollisionCategoryFlags.CollisionForce; + } + + private bool DebugCollisionsEnabled + { + get + { + return GetFlag((uint)CollisionTypes.DebugCollision); + } + + set + { + SetFlag(value, (uint)CollisionTypes.DebugCollision); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetFlag(bool set, uint flag) + { + var flags = (uint)Flags; + if (set) { flags = flags | flag; } + else { flags = flags & ~flag; } + Flags = (byte)flags; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool GetFlag(uint flag) + { + var flags = (uint)Flags; + return (flags & flag) != 0; + } + + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter + { + serializer.SerializeValue(ref Flags); + serializer.SerializeValue(ref Damage); + // only if we have a collision force should we serialize it (read and write) + if (GetFlag((uint)CollisionCategoryFlags.CollisionForce)) + { + serializer.SerializeValue(ref CollisionForce); + } + + if (GetFlag((uint)CollisionCategoryFlags.CollisionPoint)) + { + serializer.SerializeValue(ref CollisionForce); + } + + if (DebugCollisionsEnabled) + { + serializer.SerializeValue(ref CollisionId); + serializer.SerializeValue(ref Time); + serializer.SerializeValue(ref Source); + serializer.SerializeValue(ref Destination); + serializer.SerializeValue(ref DestNetworkObjId); + serializer.SerializeValue(ref DestBehaviourId); + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs.meta new file mode 100644 index 000000000..dcd19bebc --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2fd728083c5b4740926d76679851317 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs new file mode 100644 index 000000000..46bf76df5 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs @@ -0,0 +1,19 @@ +using Unity.Netcode; + +public interface ICollisionHandler +{ + /// + /// Invoked by non-authority objects detecting a collision, this determines the + /// appropriate targeted authority of the object being collided with. If the local + /// instance is authority it handles collision locally + /// + void SendCollisionMessage(CollisionMessageInfo collisionMessage); + + /// + /// Authority instances receive collision messages from non-authority instances via this implemented method + /// + /// + /// + [Rpc(SendTo.Authority, DeferLocal = true)] + void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default); +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs.meta new file mode 100644 index 000000000..675c74f2c --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e77960601117fe644a32bd9dc9a9a34d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs new file mode 100644 index 000000000..7c4cf9385 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs @@ -0,0 +1,469 @@ +using System; +using System.Collections.Generic; +using Unity.Netcode; +using Unity.Netcode.Components; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Physics +{ + public partial class PhysicsObjectMotion : BaseObjectMotionHandler + { +#if UNITY_EDITOR + public bool PhysicsObjectMotionPropertiesVisible = false; +#endif + + [Serializable] + public struct CollisionImpulseMultiplierEntry + { + public CollisionTypes CollisionType; + public float MaxCollisionForce; + } + + public List CollisionImpulseEntries; + private Dictionary CollisionImpulseTable; + + public float MaxAngularVelocity = 30; + public float MaxVelocity = 30; + [HideInInspector] + public float StartingMass = 1.0f; + + public const float MaxMass = 5.0f; + public const float MinMass = 0.10f; + + public MinMaxVector2Physics MinMaxStartingTorque = new MinMaxVector2Physics(5.0f, 15.0f); + public MinMaxVector2Physics MinMaxStartingForce = new MinMaxVector2Physics(5.0f, 30.0f); + + protected NetworkVariable BeenInitialized = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + /// + /// All of the below values keep the physics objects synchronized between clients so when ownership changes the local Rigidbody can be configured to mirror + /// the last known physics related states. + /// + protected NetworkVariable Mass = new NetworkVariable(1.0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable AngularVelocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable Velocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable Torque = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable Force = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + + protected override void Awake() + { + base.Awake(); + CollisionImpulseTable = new Dictionary(); + foreach (var entry in CollisionImpulseEntries) + { + if (!CollisionImpulseTable.ContainsKey(entry.CollisionType)) + { + CollisionImpulseTable.Add(entry.CollisionType, entry); + } + else + { + Debug.LogWarning($"[Duplicate Entry] A duplicate {nameof(CollisionImpulseMultiplierEntry)} of type {entry.CollisionType} was detected! Ignoring entry."); + } + } + + StartingMass = Rigidbody.mass; + } + + protected override Vector3 OnGetObjectVelocity(bool getReference = false) + { + if (getReference) + { + return Velocity.Value; + } + + return base.OnGetObjectVelocity(getReference); + } + + protected override Vector3 OnGetObjectAngularVelocity() + { + return AngularVelocity.Value; + } + + protected void UpdateVelocity(Vector3 velocity, bool updateObjectVelocity = true) + { + if (HasAuthority) + { + if (updateObjectVelocity) + { + SetObjectVelocity(velocity); + } + + Velocity.Value = velocity; + } + } + + protected void UpdateAngularVelocity(Vector3 angularVelocity) + { + if (HasAuthority) + { + Rigidbody.angularVelocity = angularVelocity; + AngularVelocity.Value = angularVelocity; + } + } + + protected void UpdateTorque(Vector3 torque) + { + if (HasAuthority) + { + Rigidbody.AddTorque(torque); + Torque.Value = torque; + } + } + + protected void UpdateImpulseForce(Vector3 impulseForce) + { + if (HasAuthority) + { + Rigidbody.AddForce(impulseForce, ForceMode.Impulse); + Force.Value = impulseForce; + } + } + + protected void UpdateMass(float mass) + { + if (HasAuthority) + { + if (mass > MinMass && mass < MaxMass) + { + Rigidbody.mass = mass; + } + else + { + NetworkLog.LogWarningServer($"[{name}] Trying to assign mass of {mass} which is outside the mass boundary of {MinMass} to {MaxMass}! Clamping."); + Rigidbody.mass = Mathf.Clamp(mass, MinMass, MaxMass); + } + } + } + + /// + /// Invoked when authority pushes state, we keep track whether the most recent state + /// had rotation or position deltas. + /// + /// + /// This keeps track of angular and motion velocities in order to keep objects synchronized + /// when ownership changes. + /// + /// + protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) + { + // If we haven't already initialized for the first time or haven't initialized previous state values during spawn then exit early + if (!BeenInitialized.Value) + { + return; + } + + if (networkTransformState.HasRotAngleChange && !Rigidbody.isKinematic) + { + if (Vector3.Distance(GetObjectAngularVelocity(), Rigidbody.angularVelocity) > RotAngleThreshold) + { + UpdateAngularVelocity(Rigidbody.angularVelocity); + } + } + + if (networkTransformState.HasPositionChange && !Rigidbody.isKinematic) + { + var velocity = GetObjectVelocity(); + if (Vector3.Distance(GetObjectVelocity(true), velocity) > PositionThreshold) + { + UpdateVelocity(velocity, false); + } + } + + base.OnAuthorityPushTransformState(ref networkTransformState); + } + + public override void OnNetworkSpawn() + { + + // When creating customized NetworkTransform behaviors, you must always invoke the base OnNetworkSpawn + // method if you override it in any child derive generation (i.e. always assure the NetworkTransform.OnNetworkSpawn + // method is invoked) + base.OnNetworkSpawn(); + + IsPhysicsBody = true; + + // Assure all colliders are enabled (authority and non-authority) + EnableColliders(true); + + // Register for contact events (authority and non-authority) + RigidbodyContactEventManager.Instance.RegisterHandler(this); + + // Clamp the linear and angular velocities + Rigidbody.maxAngularVelocity = MaxAngularVelocity; + Rigidbody.maxLinearVelocity = MaxVelocity; + if (HasAuthority) + { + + // Assure we are not still in kinematic mode + NetworkRigidbody.SetIsKinematic(false); + + // Since state can be preserved during a CMB service connection when there are no clients connected, + // this section determines whether we need to initialize the physics object or just apply the last + // known velocities. +#if SESSION_STORE_ENABLED + if (!BeenInitialized.Value) +#endif + { + BeenInitialized.Value = true; + /*var torque = GetRandomVector3(MinMaxStartingTorque, Vector3.one, true); + Rigidbody.AddTorque(torque, ForceMode.Impulse); + UpdateTorque(torque); + var force = GetRandomVector3(MinMaxStartingForce, Vector3.one, true); + force.y = 0f; + Rigidbody.AddForce(force, ForceMode.Impulse); + UpdateImpulseForce(force);*/ + } +#if SESSION_STORE_ENABLED + else + { + Rigidbody.angularVelocity = Vector3.ClampMagnitude(GetObjectAngularVelocity(), MaxAngularVelocity); + SetObjectVelocity(Vector3.ClampMagnitude(GetObjectVelocity(), MaxVelocity)); + } +#endif + } + } + + public override void OnNetworkDespawn() + { + RigidbodyContactEventManager.Instance.RegisterHandler(this, false); + + // Invoke the base before applying any additional adjustments + base.OnNetworkDespawn(); + + // If we are pooled and not shutting down, then reset the physics object for re-use later + // ** Important to do this ** + if (IsPooled) + { + EnableColliders(false); + if (!Rigidbody.isKinematic) + { + Rigidbody.angularVelocity = Vector3.zero; + SetObjectVelocity(Vector3.zero); + NetworkRigidbody.SetIsKinematic(true); + } + + Rigidbody.mass = StartingMass; + BeenInitialized.Reset(); + AngularVelocity.Reset(); + Velocity.Reset(); + Torque.Reset(); + Force.Reset(); + Mass.Reset(); + } + } + + /// + /// When ownership changes, we apply the last known angular and motion velocities. + /// Otherwise, + /// + protected override void OnOwnershipChanged(ulong previous, ulong current) + { + if (NetworkManager.LocalClientId == current) + { + NetworkRigidbody.SetIsKinematic(false); + if (BeenInitialized.Value) + { + Rigidbody.angularVelocity = Vector3.ClampMagnitude(GetObjectAngularVelocity(), MaxAngularVelocity); + SetObjectVelocity(Vector3.ClampMagnitude(GetObjectVelocity(true), MaxVelocity)); + } + else + { + Rigidbody.AddTorque(Torque.Value, ForceMode.Impulse); + Rigidbody.AddForce(Force.Value, ForceMode.Impulse); + } + } + else + { + NetworkRigidbody.SetIsKinematic(true); + } + + base.OnOwnershipChanged(previous, current); + } + + private struct RemoteForce + { + public float EndOfLife; + public Vector3 TargetForce; + public Vector3 AppliedForce; + } + + private List m_RemoteAppliedForce = new List(); + private Dictionary m_CollisionLatency = new Dictionary(); + + /// + /// Handles queuing up incoming collisions (remote and local) to be processed + /// + protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) + { + if (collisionMessage.HasCollisionForce()) + { + AddForceDirect(collisionMessage.CollisionForce); + } + + base.OnHandleCollision(collisionMessage); + } + + public void AddForceDirect(Vector3 force) + { + var remoteForce = new RemoteForce() + { + TargetForce = force, + AppliedForce = Vector3.zero, + }; + + + m_RemoteAppliedForce.Add(remoteForce); + } + + protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + // TODO: Possibly come up with a better way to route contact events at this level. + // For now, since lasers are always kinematic and send damage messages we divert contact events to the LaserMotion child class + var collidingBaseObjectMotion = collidingBody.GetComponent(); + var collidingBodyPhys = collidingBaseObjectMotion as PhysicsObjectMotion; + + // If we don't have authority over either object or we are doing a second FixedUpdate pass, then exit early + if (eventId == LastEventId || collidingBaseObjectMotion == null || (!HasAuthority && !collidingBaseObjectMotion.HasAuthority)) + { + return; + } + + if (collidingBaseObjectMotion.CollisionType == CollisionTypes.Laser) + { + //var laserMotion = collidingBaseObjectMotion as LaserMotion; + //laserMotion.ContactEvent(eventId, averagedCollisionNormal, Rigidbody, contactPoint); + return; + } + + if (collidingBodyPhys == null) + { + return; + } + + var collisionNormal = hasCollisionStay ? averagedCollisionStayNormal : averagedCollisionNormal; + + var thisVelocity = (!Rigidbody.isKinematic ? Rigidbody.linearVelocity.sqrMagnitude : GetObjectVelocity().sqrMagnitude) * 0.5f; + var otherVelocity = (!collidingBody.isKinematic ? collidingBody.linearVelocity.sqrMagnitude : collidingBodyPhys.GetObjectVelocity().sqrMagnitude) * 0.5f; + var thisKineticForce = (Rigidbody.mass / collidingBody.mass) * -collisionNormal * thisVelocity; + var otherKineticForce = (collidingBody.mass / Rigidbody.mass) * collisionNormal * otherVelocity; + + if (!Rigidbody.isKinematic && collidingBody.isKinematic && thisVelocity > 0.01f) + { + CollisionMessage.CollisionForce = thisKineticForce; + CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); + if (DebugCollisions) + { + //NetworkManagerHelper.Instance.LogMessage($"[{name}][SecondBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {GetVector3Values(thisKineticForce)} to {collidingBody.name}."); + } + + // Send collision to owner of kinematic body + EventCollision(averagedCollisionNormal, collidingBodyPhys); + } + else if (Rigidbody.isKinematic && !collidingBody.isKinematic && otherVelocity > 0.01f) + { + collidingBodyPhys.CollisionMessage.CollisionForce = otherKineticForce; + collidingBodyPhys.CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); + collidingBodyPhys.EventCollision(averagedCollisionNormal, this); + if (DebugCollisions) + { + //NetworkManagerHelper.Instance.LogMessage($"[{collidingBodyPhys.name}][FirstBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {GetVector3Values(otherKineticForce)} to {name}."); + } + } + + base.OnContactEvent(eventId, averagedCollisionNormal, collidingBody, contactPoint); + } + + /// + /// Accumulatively apply the resultant collision force + /// + /// + private void ApplyCollisionForce(Vector3 force) + { + Rigidbody.AddForce(force, ForceMode.Impulse); + Rigidbody.AddTorque(force * 0.25f, ForceMode.Impulse); + } + + /// + /// Processes the queued collisions forces + /// + private void ProcessRemoteForces() + { + if (m_RemoteAppliedForce.Count == 0) + { + return; + } + + var accumulativeForce = Vector3.zero; + for (int i = m_RemoteAppliedForce.Count - 1; i >= 0; i--) + { + var remoteForce = m_RemoteAppliedForce[i]; + accumulativeForce += remoteForce.TargetForce; + if (Approximately(remoteForce.TargetForce, Vector3.zero)) + { + m_RemoteAppliedForce.RemoveAt(i); + } + else + { + m_RemoteAppliedForce[i] = remoteForce; + } + } + + ApplyCollisionForce(accumulativeForce); + m_RemoteAppliedForce.Clear(); + } + + /// + /// Hijack the FixedUpdate to assure physics simulation is always + /// taking into consideration the queued collisions to process + /// + /// + /// Override this method to apply additional forces to your physics object + /// + protected virtual void FixedUpdate() + { + if (!IsSpawned || !HasAuthority || Rigidbody != null && Rigidbody.isKinematic) + { + return; + } + + // Process any queued collisions + ProcessRemoteForces(); + } + + /// + /// When is enabled, this will log locally + /// generated collision info for the derived component + /// + /// the hit + /// log string + protected override string OnLogCollision(ref BaseObjectMotionHandler objectHit) + { + return $"[CF: {GetVector3Values(ref CollisionMessage.CollisionForce)}]-{base.OnLogCollision(ref objectHit)}"; + } + + /// + /// When is enabled, this will log remotely + /// received collision info for the derived component + /// + /// the message received + /// log string + protected override string OnLogHandleCollision(ref CollisionMessageInfo collisionMessage) + { + var sourceCollider = $"{collisionMessage.SourceOwner}"; + if (NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(collisionMessage.SourceOwner)) + { + sourceCollider = NetworkManager.SpawnManager.SpawnedObjects[collisionMessage.SourceOwner].name; + } + + var resLinearVel = string.Empty; + var resAngularVel = string.Empty; + if (Rigidbody != null) + { + resLinearVel = GetVector3Values(GetObjectVelocity()); + resAngularVel = GetVector3Values(Rigidbody.angularVelocity); + } + + return $"[**Collision-Info**][To: {name}][By:{sourceCollider}][Force:{GetVector3Values(ref collisionMessage.CollisionForce)}]" + + $"[LinVel: {resLinearVel}][AngVel: {resAngularVel}]-{base.OnLogHandleCollision(ref collisionMessage)}"; + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs.meta new file mode 100644 index 000000000..2785f4cca --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d3f561fb09787c42abad1ab0a51da2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef new file mode 100644 index 000000000..42291f412 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Unity.Multiplayer.Samples.SocialHub.Physics", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", + "references": [ + "GUID:1491147abca9d7d4bb7105af628b223e" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef.meta new file mode 100644 index 000000000..f4481a94b --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ae1323dabfa6440b3956d4cc5239e361 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 5f12e5c2c3f4881bfb145ad41fabe540726a3c34 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Mon, 26 Aug 2024 13:12:03 -0400 Subject: [PATCH 08/13] phyics base classes refactor & damage dealt to DestructibleObject --- .../Assets/Prefabs/Avatar.prefab | 48 +- .../DistributableTransferableObject.prefab | 38 +- .../Scripts/Editor/AvatarTransformEditor.cs | 2 +- .../Editor/DestructibleObjectEditor.cs | 32 + .../Editor/DestructibleObjectEditor.cs.meta | 2 + .../Editor/PhysicsObjectMotionEditor.cs | 48 -- ...ultiplayer.Samples.SocialHub.Editor.asmdef | 3 +- .../Assets/Scripts/Gameplay/AssemblyInfo.cs | 1 + .../Scripts/Gameplay/DestructibleObject.cs | 61 +- .../Scripts/Gameplay/TransferableObject.cs | 3 + .../Assets/Scripts/Input/AvatarInputs.cs | 10 +- .../Assets/Scripts/Physics/AssemblyInfo.cs | 4 + .../Scripts/Physics/AssemblyInfo.cs.meta | 2 + .../Physics/BaseObjectMotionHandler.cs | 725 ++++++------------ .../Scripts/Physics/CollisionMessageInfo.cs | 227 +++--- .../Scripts/Physics/ICollisionHandler.cs | 31 +- .../Scripts/Physics/PhysicsObjectMotion.cs | 197 ++--- .../Physics/PhysicsPlayerController.cs | 137 ++++ .../Physics/PhysicsPlayerController.cs.meta | 2 + .../PhysicsPlayerControllerSettings.cs | 27 + .../PhysicsPlayerControllerSettings.cs.meta | 2 + ...ltiplayer.Samples.SocialHub.Physics.asmdef | 3 +- .../Assets/Scripts/Player/AssemblyInfo.cs | 2 + .../Scripts/Player/AssemblyInfo.cs.meta | 2 + .../Scripts/Player/AvatarInteractions.cs | 12 +- .../Assets/Scripts/Player/AvatarTransform.cs | 152 +--- ...ultiplayer.Samples.SocialHub.Player.asmdef | 3 +- .../Assets/Scripts/Utils.meta | 8 + .../Assets/Scripts/Utils/AssemblyInfo.cs | 2 + .../Assets/Scripts/Utils/AssemblyInfo.cs.meta | 2 + .../Assets/Scripts/Utils/MathUtils.cs | 106 +++ .../Assets/Scripts/Utils/MathUtils.cs.meta | 2 + ...Multiplayer.Samples.SocialHub.Utils.asmdef | 14 + ...player.Samples.SocialHub.Utils.asmdef.meta | 7 + 34 files changed, 944 insertions(+), 973 deletions(-) create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef create mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index bf4bddabc..83e142cfd 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -213,6 +213,7 @@ GameObject: - component: {fileID: 4903152183366241606} - component: {fileID: 8197190117666738524} - component: {fileID: 539700041658036575} + - component: {fileID: 4655812346339390596} m_Layer: 0 m_Name: Avatar m_TagString: Untagged @@ -249,7 +250,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 3001504883 + GlobalObjectIdHash: 2473698027 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 0 @@ -292,18 +293,18 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 - m_Rigidbody: {fileID: 4745766379562620470} + m_CollisionType: 0 + m_CollisionDamage: 0 + m_DebugDamage: 0 + m_Colliders: + - {fileID: 817796967242824188} + CollisionImpulseEntries: [] + MaxAngularVelocity: 30 + MaxVelocity: 30 m_PlayerInput: {fileID: 4903152183366241606} m_AvatarInputs: {fileID: 8197190117666738524} - m_WalkSpeed: 6 - m_SprintSpeed: 10 - m_Acceleration: 50 - m_DragCoefficient: 4 - m_AirControlFactor: 0.5 - m_JumpImpusle: 7 - m_CustomGravityMultiplier: 2 - m_RotationSpeed: 700 - m_GroundCheckDistance: 1.1 + m_AvatarInteractions: {fileID: 539700041658036575} + m_PhysicsPlayerController: {fileID: 4655812346339390596} --- !u!54 &4745766379562620470 Rigidbody: m_ObjectHideFlags: 0 @@ -330,7 +331,7 @@ Rigidbody: m_IsKinematic: 1 m_Interpolate: 0 m_Constraints: 0 - m_CollisionDetection: 0 + m_CollisionDetection: 2 --- !u!114 &-8100831418301897270 MonoBehaviour: m_ObjectHideFlags: 0 @@ -358,8 +359,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 62899f850307741f2a39c98a8b639597, type: 3} m_Name: m_EditorClassIdentifier: - m_Actions: {fileID: -944628639613478452, guid: dcd1b4eb76b964f40afe6c0a3ca65c82, - type: 3} + m_Actions: {fileID: -944628639613478452, guid: dcd1b4eb76b964f40afe6c0a3ca65c82, type: 3} m_NotificationBehavior: 0 m_UIInputModule: {fileID: 0} m_DeviceLostEvent: @@ -389,15 +389,13 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 7e9f71718dd134b14b300e378e98c718, type: 3} m_Name: m_EditorClassIdentifier: + m_InteractActionReference: {fileID: 1781555164194001046, guid: dcd1b4eb76b964f40afe6c0a3ca65c82, type: 3} Move: {x: 0, y: 0} Look: {x: 0, y: 0} - Jump: 0 Sprint: 0 AnalogMovement: 0 CursorLocked: 1 CursorInputForLook: 1 - m_InteractActionReference: {fileID: 1781555164194001046, guid: dcd1b4eb76b964f40afe6c0a3ca65c82, - type: 3} --- !u!114 &539700041658036575 MonoBehaviour: m_ObjectHideFlags: 0 @@ -405,7 +403,7 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5478015027486214707} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: b47efef44cef74d9ca00f4913607f988, type: 3} m_Name: @@ -417,6 +415,20 @@ MonoBehaviour: m_InteractCollider: {fileID: 4881592427634173612} m_MinTossForce: 5 m_MaxTossForce: 10 +--- !u!114 &4655812346339390596 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5478015027486214707} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e222c86e1ae554b699fe6d68d3cf4ba9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Rigidbody: {fileID: 4745766379562620470} + m_PhysicsPlayerControllerSettings: {fileID: 11400000, guid: 1dd99ce80f3e54d03b20bf78d6ff2a40, type: 2} --- !u!1 &9009864878170659705 GameObject: m_ObjectHideFlags: 0 diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab index 7f4fb2deb..3706d2b5d 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -17,7 +17,6 @@ GameObject: - component: {fileID: 6039897070700006726} - component: {fileID: 6689110374311511483} - component: {fileID: 6961888493949678523} - - component: {fileID: 2700541251598630985} m_Layer: 7 m_Name: DistributableTransferableObject m_TagString: Untagged @@ -126,7 +125,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 2069120471 + GlobalObjectIdHash: 4270425062 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 3 @@ -145,7 +144,7 @@ Rigidbody: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 893974733110552042} serializedVersion: 4 - m_Mass: 1 + m_Mass: 100 m_Drag: 0 m_AngularDrag: 0.05 m_CenterOfMass: {x: 0, y: 0, z: 0} @@ -160,10 +159,10 @@ Rigidbody: m_ImplicitCom: 1 m_ImplicitTensor: 1 m_UseGravity: 1 - m_IsKinematic: 0 + m_IsKinematic: 1 m_Interpolate: 0 m_Constraints: 0 - m_CollisionDetection: 0 + m_CollisionDetection: 2 --- !u!114 &6039897070700006726 MonoBehaviour: m_ObjectHideFlags: 0 @@ -203,20 +202,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 496a933d305aa4e1c926bd7d19b42f46, type: 3} m_Name: m_EditorClassIdentifier: - m_Impacts: - m_InternalValue: 0 ---- !u!114 &2700541251598630985 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 893974733110552042} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3} - m_Name: - m_EditorClassIdentifier: AuthorityMode: 1 UseUnreliableDeltas: 0 SyncPositionX: 1 @@ -225,9 +210,9 @@ MonoBehaviour: SyncRotAngleX: 1 SyncRotAngleY: 1 SyncRotAngleZ: 1 - SyncScaleX: 0 - SyncScaleY: 0 - SyncScaleZ: 0 + SyncScaleX: 1 + SyncScaleY: 1 + SyncScaleZ: 1 PositionThreshold: 0.001 RotAngleThreshold: 0.01 ScaleThreshold: 0.01 @@ -237,3 +222,12 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 + m_CollisionType: 0 + m_CollisionDamage: 0 + m_DebugDamage: 0 + m_Colliders: + - {fileID: 7690746213975220858} + CollisionImpulseEntries: [] + MaxAngularVelocity: 30 + MaxVelocity: 30 + m_StartingHealth: 100 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs index 578f9d4ad..05c8f487a 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/AvatarTransformEditor.cs @@ -7,7 +7,7 @@ namespace Unity.Multiplayer.Samples.SocialHub.Editor { [CustomEditor(typeof(AvatarTransform))] - class DerivedComponentEditor : UnityEditor.Editor + class AvatarTransformEditor : UnityEditor.Editor { public override VisualElement CreateInspectorGUI() { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs new file mode 100644 index 000000000..0070c2487 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs @@ -0,0 +1,32 @@ +using Unity.Multiplayer.Samples.SocialHub.Gameplay; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Unity.Multiplayer.Samples.SocialHub.Editor +{ + [CustomEditor(typeof(DestructibleObject))] + class DestructibleObjectEditor : UnityEditor.Editor + { + public override VisualElement CreateInspectorGUI() + { + // Create a new VisualElement to be the root of the inspector UI + var root = new VisualElement(); + + // Generate default inspector for AvatarTransform + serializedObject.Update(); + SerializedProperty property = serializedObject.GetIterator(); + property.NextVisible(true); // Skip the script field + while (property.NextVisible(false)) + { + var propertyField = new PropertyField(property); + root.Add(propertyField); + } + + serializedObject.ApplyModifiedProperties(); + + return root; + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs.meta new file mode 100644 index 000000000..63681d1be --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/DestructibleObjectEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c4746eccfea8d4378a13a35effd619c1 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs index ef81dffcc..2393faeec 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/PhysicsObjectMotionEditor.cs @@ -29,52 +29,4 @@ public override VisualElement CreateInspectorGUI() return root; } } - - /*/// - /// The custom editor for the component. - /// - [CustomEditor(typeof(PhysicsObjectMotion), true)] - public class PhysicsObjectMotionEditor : BaseObjectMotionHandlerEditor - { - private SerializedProperty m_CollisionImpulseEntries; - private SerializedProperty m_MaxAngularVelocity; - private SerializedProperty m_MaxVelocity; - private SerializedProperty m_MinMaxStartingTorque; - private SerializedProperty m_MinMaxStartingForce; - - public override void OnEnable() - { - m_CollisionImpulseEntries = serializedObject.FindProperty(nameof(PhysicsObjectMotion.CollisionImpulseEntries)); - m_MaxAngularVelocity = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MaxAngularVelocity)); - m_MaxVelocity = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MaxVelocity)); - m_MinMaxStartingTorque = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MinMaxStartingTorque)); - m_MinMaxStartingForce = serializedObject.FindProperty(nameof(PhysicsObjectMotion.MinMaxStartingForce)); - base.OnEnable(); - } - - public override void OnInspectorGUI() - { - var physicsObject = target as PhysicsObjectMotion; - - physicsObject.PhysicsObjectMotionPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(physicsObject.PhysicsObjectMotionPropertiesVisible, $"{nameof(PhysicsObjectMotion)} Properties"); - if (physicsObject.PhysicsObjectMotionPropertiesVisible) - { - // End the header group since m_MinMaxStartingTorque and m_MinMaxStartingForce both use header groups - EditorGUILayout.EndFoldoutHeaderGroup(); - EditorGUILayout.PropertyField(m_CollisionImpulseEntries); - EditorGUILayout.PropertyField(m_MaxAngularVelocity); - EditorGUILayout.PropertyField(m_MaxVelocity); - EditorGUILayout.PropertyField(m_MinMaxStartingTorque); - EditorGUILayout.PropertyField(m_MinMaxStartingForce); - } - else - { - EditorGUILayout.EndFoldoutHeaderGroup(); - } - - EditorGUILayout.Space(); - - base.OnInspectorGUI(); - } - }*/ } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef index 30de4dafc..9bf630ba7 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Editor/Unity.Multiplayer.Samples.SocialHub.Editor.asmdef @@ -3,7 +3,8 @@ "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ "GUID:8314b31eee3cc495ca4a4f078575802d", - "GUID:ae1323dabfa6440b3956d4cc5239e361" + "GUID:ae1323dabfa6440b3956d4cc5239e361", + "GUID:9ff2150ce7d7c415a8af1fbff3dc3e6c" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs index 9b00a0c99..fe86031e5 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/AssemblyInfo.cs @@ -1,2 +1,3 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Player")] +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Editor")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs index 9c655d2d2..e0c7c413e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs @@ -1,19 +1,25 @@ using System; +using Unity.Multiplayer.Samples.SocialHub.Physics; using Unity.Netcode; using UnityEngine; namespace Unity.Multiplayer.Samples.SocialHub.Gameplay { - class DestructibleObject : NetworkBehaviour + class DestructibleObject : PhysicsObjectMotion { [SerializeField] - NetworkVariable m_Impacts = new NetworkVariable(); + float m_StartingHealth = 100f; + + NetworkVariable m_Initialized = new NetworkVariable(false); + + NetworkVariable m_Health = new NetworkVariable(0.0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); public override void OnNetworkSpawn() { + m_DebugCollisions = m_DebugDamage = true; base.OnNetworkSpawn(); - - enabled = HasAuthority; + InitializeDestructible(); + gameObject.name = $"[NetworkObjectId-{NetworkObjectId}]{name}"; } public override void OnNetworkDespawn() @@ -21,23 +27,54 @@ public override void OnNetworkDespawn() base.OnNetworkDespawn(); } - protected override void OnOwnershipChanged(ulong previous, ulong current) + void OnCollisionEnter(Collision other) { - Debug.Log($"previous {previous} current {current}"); - enabled = HasAuthority; + return; } - void OnCollisionEnter(Collision collision) + protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) { - if (!HasAuthority) + // perhaps add invincible frames? would be a neat showcase + Debug.Log(nameof(OnHandleCollision)); + + if (m_Health.Value == 0.0f || collisionMessage.GetCollisionType() == Physics.CollisionType.Avatar) { + base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); return; } + var currentHealth = Mathf.Max(0.0f, m_Health.Value - collisionMessage.Damage); + + if (currentHealth == 0.0f) + { + Rigidbody.isKinematic = true; + EnableColliders(false); + m_Health.Value = currentHealth; + NetworkObject.Despawn(); + // TODO: Spawn VFX locally + send VFX message + return; + } + else + { + m_Health.Value = currentHealth; + } + + base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); + } - if (collision.gameObject.layer == gameObject.layer) + void InitializeDestructible() + { + if (IsSessionOwner && !m_Initialized.Value) + { + InitializeDestructible(m_StartingHealth); + m_Initialized.Value = true; + } + } + + void InitializeDestructible(float health) + { + if (IsSpawned) { - Debug.Log($"Hit {collision.gameObject.name} of owner {collision.gameObject.GetComponent().OwnerClientId} collision.impulse.magnitude {collision.impulse.magnitude}"); - m_Impacts.Value += 1; + m_Health.Value = health; } } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs index c0c62a4e5..fc62bd8eb 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/TransferableObject.cs @@ -20,6 +20,7 @@ public override void OnNetworkSpawn() public override void OnNetworkDespawn() { + base.OnNetworkDespawn(); if (NetworkObject) { NetworkObject.OnOwnershipRequested -= OnOwnershipRequested; @@ -27,6 +28,8 @@ public override void OnNetworkDespawn() } OnGameplayEvent?.Invoke(NetworkObject, GameplayEvent.Despawned); + OnGameplayEvent = null; + OnNetworkObjectOwnershipRequestResponse = null; } protected override void OnOwnershipChanged(ulong previous, ulong current) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs index c4abc9618..86dea27ee 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Input/AvatarInputs.cs @@ -16,8 +16,6 @@ class AvatarInputs : MonoBehaviour [SerializeField] internal Vector2 Look; [SerializeField] - internal bool Jump; - [SerializeField] internal bool Sprint; [Header("Movement Settings")] @@ -30,6 +28,7 @@ class AvatarInputs : MonoBehaviour [SerializeField] internal bool CursorInputForLook = true; + internal event Action Jumped; internal event Action InteractTapped; internal event Action InteractHeld; @@ -100,7 +99,7 @@ void OnLook(InputValue value) void OnJump(InputValue value) { - JumpInput(value.isPressed); + Jumped?.Invoke(); } void OnSprint(InputValue value) @@ -119,11 +118,6 @@ void LookInput(Vector2 newLookDirection) Look = newLookDirection; } - void JumpInput(bool newJumpState) - { - Jump = newJumpState; - } - void SprintInput(bool newSprintState) { Sprint = newSprintState; diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs new file mode 100644 index 000000000..eea577a98 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Player")] +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Gameplay")] +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Editor")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs.meta new file mode 100644 index 000000000..0e540c0c2 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d3be452b8071c4c96bad702f8424c77f diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs index 07f6bcbd8..fc51949b4 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs @@ -3,590 +3,353 @@ using Unity.Netcode; using Unity.Netcode.Components; using UnityEngine; -using Random = UnityEngine.Random; using System.Collections.Generic; -/* -#if UNITY_EDITOR -using Unity.Netcode.Editor; -using UnityEditor; -/// -/// The custom editor for the component. -/// -[CustomEditor(typeof(BaseObjectMotionHandler), true)] -public class BaseObjectMotionHandlerEditor : NetworkTransformEditor +namespace Unity.Multiplayer.Samples.SocialHub.Physics { - private SerializedProperty m_IsPooled; - private SerializedProperty m_CollisionType; - private SerializedProperty m_CollisionDamage; - private SerializedProperty m_DebugCollisions; - private SerializedProperty m_DebugDamage; - private SerializedProperty m_EnableBoundary; - private SerializedProperty m_Colliders; - - public override void OnEnable() + class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEventHandler { - m_IsPooled = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.IsPooled)); - m_Colliders = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.Colliders)); - m_CollisionType = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.CollisionType)); - m_CollisionDamage = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.CollisionDamage)); - m_DebugCollisions = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.DebugCollisions)); - m_DebugDamage = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.DebugDamage)); - m_EnableBoundary = serializedObject.FindProperty(nameof(BaseObjectMotionHandler.EnableBoundary)); - - base.OnEnable(); - } - - public override void OnInspectorGUI() - { - var baseObject = target as BaseObjectMotionHandler; - baseObject.BaseObjectMotionHandlerPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.BaseObjectMotionHandlerPropertiesVisible, $"{nameof(BaseObjectMotionHandler)} Properties"); - if (baseObject.BaseObjectMotionHandlerPropertiesVisible) - { - // End the header group since m_Colliders is a header group - EditorGUILayout.EndFoldoutHeaderGroup(); - EditorGUILayout.PropertyField(m_IsPooled); - EditorGUILayout.PropertyField(m_Colliders); - EditorGUILayout.PropertyField(m_CollisionType); - EditorGUILayout.PropertyField(m_CollisionDamage); - EditorGUILayout.PropertyField(m_DebugCollisions); - EditorGUILayout.PropertyField(m_DebugDamage); - EditorGUILayout.PropertyField(m_EnableBoundary); - } - else - { - EditorGUILayout.EndFoldoutHeaderGroup(); - } - - EditorGUILayout.Space(); - - baseObject.NetworkTransformPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.NetworkTransformPropertiesVisible, $"{nameof(NetworkTransform)} Properties"); - if (baseObject.NetworkTransformPropertiesVisible) - { - base.OnInspectorGUI(); - } - else - { - serializedObject.ApplyModifiedProperties(); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - } -} -#endif -*/ - -/// -/// Projectiles will be owner driven -/// -public partial class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEventHandler -{ + protected bool m_IsPooled = true; -#if UNITY_EDITOR - public bool BaseObjectMotionHandlerPropertiesVisible = false; - public bool NetworkTransformPropertiesVisible = false; -#endif - private static GameObject WorldBoundary; - - // Defaults to 1024 but can be updated by adding a GameObject named WorldBoundary and adding a SphereCollider to that. - private static float WorldBoundaryRadius = 1024.0f; - - public bool IsPooled = true; - public CollisionTypes CollisionType; - public ushort CollisionDamage; + [SerializeField] + CollisionType m_CollisionType; + public CollisionType CollisionType => m_CollisionType; - public Action OnNetworkObjectDespawned; + [SerializeField] + ushort m_CollisionDamage; - public bool DebugBoundaryCheck; + protected CollisionMessageInfo m_CollisionMessage = new CollisionMessageInfo(); - protected CollisionMessageInfo CollisionMessage = new CollisionMessageInfo(); - private Rigidbody m_Rigidbody; - private NetworkRigidbody m_NetworkRigidbody; + protected Rigidbody Rigidbody { get; private set; } - public Rigidbody Rigidbody => m_Rigidbody; - public NetworkRigidbody NetworkRigidbody => m_NetworkRigidbody; + protected NetworkRigidbody NetworkRigidbody { get; private set; } - [Tooltip("Enables/Disables collision logging (based on per derived type)")] - public bool DebugCollisions; + [Tooltip("Enables/Disables collision logging (based on per derived type)")] + protected bool m_DebugCollisions; - [Tooltip("Enables/Disables damage logging (based on per derived type)")] - public bool DebugDamage; + [Tooltip("Enables/Disables damage logging (based on per derived type)")] + [SerializeField] + protected bool m_DebugDamage; - [HideInInspector] - public bool IsPhysicsBody; + [Tooltip("Add all colliders to this list that will be used to detect collisions (exclude triggers).")] + [SerializeField] + List m_Colliders; - [Tooltip("When enabled, all physics bodies will head back towards the center once they reach the boundary limits.")] - public bool EnableBoundary = true; + static int s_CollisionId = 0; - [Tooltip("Add all colliders to this list that will be used to detect collisions (exclude triggers).")] - public List Colliders; + protected ulong LastEventId { get; private set; } - private Dictionary ColliderScales = new Dictionary(); - - protected void EnableColliders(bool enable) - { - foreach (var collider in Colliders) + protected void EnableColliders(bool enable) { - collider.enabled = enable; + foreach (var collider in m_Colliders) + { + collider.enabled = enable; + } } - } - private const float k_BoundaryCheckFrequency = 0.06667f; - private const int k_BoundaryCheckDistributionRes = 10; - private static int s_BoundaryOffsetCount = 1; - private float m_NextBoundaryCheck; + public Rigidbody GetRigidbody() + { + return Rigidbody; + } - public Rigidbody GetRigidbody() { return m_Rigidbody; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected Vector3 GetObjectVelocity(bool getReference = false) + { + return OnGetObjectVelocity(getReference); + } - protected virtual Vector3 OnGetObjectVelocity(bool getReference = false) - { - if (m_Rigidbody != null) + protected virtual Vector3 OnGetObjectVelocity(bool getReference = false) { + if (Rigidbody != null) + { #if UNITY_2023_3_OR_NEWER - return m_Rigidbody.linearVelocity; + return Rigidbody.linearVelocity; #else return m_Rigidbody.velocity; #endif - } - return Vector3.zero; - } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3 GetObjectVelocity(bool getReference = false) - { - return OnGetObjectVelocity(getReference); - } + return Vector3.zero; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetObjectVelocity(Vector3 velocity) - { - if (m_Rigidbody != null) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected void SetObjectVelocity(Vector3 velocity) { + if (Rigidbody != null) + { #if UNITY_2023_3_OR_NEWER - m_Rigidbody.linearVelocity = velocity; + Rigidbody.linearVelocity = velocity; #else m_Rigidbody.velocity = velocity; #endif + } } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual Vector3 OnGetObjectAngularVelocity() - { - if (m_Rigidbody != null) + protected Vector3 GetObjectAngularVelocity() { - return m_Rigidbody.angularVelocity; + return OnGetObjectAngularVelocity(); } - return Vector3.zero; - } - public Vector3 GetObjectAngularVelocity() - { - return OnGetObjectAngularVelocity(); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected virtual Vector3 OnGetObjectAngularVelocity() + { + if (Rigidbody != null) + { + return Rigidbody.angularVelocity; + } + return Vector3.zero; + } - protected void IgnoreCollision(GameObject objectA, GameObject objectB, bool shouldIgnore) - { - if (objectA == null || objectB == null) + protected void IgnoreCollision(GameObject objectA, GameObject objectB, bool shouldIgnore) { - return; - } + if (objectA == null || objectB == null) + { + return; + } - var rootA = objectA.transform.root.gameObject; - var rootB = objectB.transform.root.gameObject; + var rootA = objectA.transform.root.gameObject; + var rootB = objectB.transform.root.gameObject; - var collidersA = rootA.GetComponentsInChildren(); - var collidersB = rootB.GetComponentsInChildren(); + var collidersA = rootA.GetComponentsInChildren(); + var collidersB = rootB.GetComponentsInChildren(); - foreach (var colliderA in collidersA) - { - foreach (var colliderB in collidersB) + foreach (var colliderA in collidersA) { - Physics.IgnoreCollision(colliderA, colliderB, shouldIgnore); + foreach (var colliderB in collidersB) + { + UnityEngine.Physics.IgnoreCollision(colliderA, colliderB, shouldIgnore); + } } } - } - public override void OnNetworkDespawn() - { - base.OnNetworkDespawn(); - OnNetworkObjectDespawned?.Invoke(); - OnNetworkObjectDespawned = null; - - /*var fxObjects = GetComponentsInChildren(); - foreach (var fxObject in fxObjects) + protected override void Awake() { - fxObject.transform.SetParent(null); - }*/ - } + Rigidbody = GetComponent(); + NetworkRigidbody = GetComponent(); - /// - /// Override this method to make adjustments for wrapping - /// - protected virtual bool OnBoundaryReached() - { - return true; - } + base.Awake(); + } - // Distribute the boundary check processing evenly amongst all instances - private void SetNextBoundaryCheck(float timeOffset = k_BoundaryCheckFrequency, bool init = false) - { - if (init) + protected virtual void Start() { - s_BoundaryOffsetCount++; - m_NextBoundaryCheck = Time.realtimeSinceStartup + (timeOffset * (s_BoundaryOffsetCount % k_BoundaryCheckDistributionRes)); + m_CollisionMessage.Damage = m_CollisionDamage; + m_CollisionMessage.SetFlag(true, (uint)m_CollisionType); } - else + + /// + /// Invoked every network tick if this instance has sent a update. + /// + /// + protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) { - m_NextBoundaryCheck = Time.realtimeSinceStartup + timeOffset; + base.OnAuthorityPushTransformState(ref networkTransformState); } - } - private void CheckBoundary() - { - if (Rigidbody == null || Rigidbody != null && Rigidbody.isKinematic) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static GameObject GetRootParent(GameObject parent) { - return; + return parent.transform.root.gameObject; } - if (EnableBoundary && m_NextBoundaryCheck < Time.realtimeSinceStartup) + + /// + /// This method provides the ability to make adjustments to the collision message as well as apply damage locally if needed + /// + /// + /// + protected virtual bool OnPrepareCollisionMessage(Vector3 averagedCollisionNormal, BaseObjectMotionHandler targetBaseObjectMotionHandler) + { + return true; + } + + protected virtual void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) { - var distance = Vector3.Distance(Vector3.zero, transform.position); - // if we reached the maximum boundary, then reverse the velocity of the Rigidbody if it has one - if (distance >= WorldBoundaryRadius && OnBoundaryReached()) - { - var dir = Vector3.zero - transform.position; - var velocity = GetObjectVelocity(); - velocity = velocity.magnitude * dir; - SetObjectVelocity(velocity); - } - else - { - SetNextBoundaryCheck(); - } } - } - protected override void Awake() - { - if (WorldBoundary == null) + void HandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) { - WorldBoundary = GameObject.Find("WorldBoundary"); - if (WorldBoundary != null) + OnHandleCollision(collisionMessage, isLocal, applyImmediately); + + // Handling is invoked before logging so logging can determine the end result. + if (m_DebugCollisions) { - var sphereCollider = WorldBoundary.GetComponent(); - WorldBoundaryRadius = sphereCollider.radius; + LogHandleCollision(collisionMessage); } } - m_Rigidbody = GetComponent(); - m_NetworkRigidbody = GetComponent(); - - SetNextBoundaryCheck(init: true); - - base.Awake(); - } - - protected virtual void Start() - { - CollisionMessage.Damage = CollisionDamage; - CollisionMessage.SetFlag(true, (uint)CollisionType); - } - - /// - /// Invoked every network tick if this instance has sent a update. - /// - /// - protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) - { - CheckBoundary(); - base.OnAuthorityPushTransformState(ref networkTransformState); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static public GameObject GetRootParent(GameObject parent) - { - return parent.transform.root.gameObject; - } - - /// - /// This method provides the ability to make adjustments to the collision message as well as apply damage locally if needed - /// - /// - /// - protected virtual bool OnPrepareCollisionMessage(Vector3 averagedCollisionNormal, BaseObjectMotionHandler targetBaseObjectMotionHandler) - { - return true; - } + /// + /// Used to communicate collisions + /// + /// + /// + [Rpc(SendTo.Authority, RequireOwnership = false)] + public void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default) + { + Debug.Log(nameof(HandleCollisionRpc)); - protected virtual void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) - { - } + // If authority changes while this message is in flight, forward it to the new authority + if (!HasAuthority) + { + LogMessage($"[HandleCollisionRpc][Not Owner][Routing Collision][{name}] Routing to Client-{OwnerClientId}"); + SendCollisionMessage(m_CollisionMessage); + return; + } - public void HandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) - { - OnHandleCollision(collisionMessage, isLocal, applyImmediately); - // Hanlding is invoked before logging so logging can determine the end result. - if (DebugCollisions) - { - LogHandleCollision(collisionMessage); + m_CollisionMessage.SourceOwner = rpcParams.Receive.SenderClientId; + m_CollisionMessage.TargetOwner = OwnerClientId; + HandleCollision(collisionMessage); } - } - /// - /// Used to communicate collisions - /// - /// - /// - [Rpc(SendTo.Authority, RequireOwnership = false)] - public void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default) - { - // If authority changes while this message is in flight, forward it to the new authority - if (!HasAuthority) + /// + /// Invoked by the owner of the object inflicting damage, this will handle the RPC routing + /// of the message to the appropriate targeted owner of the object taking damage + /// + /// + public void SendCollisionMessage(CollisionMessageInfo collisionMessage) { - LogMessage($"[HandleCollisionRpc][Not Owner][Routing Collision][{name}] Routing to Client-{OwnerClientId}"); - SendCollisionMessage(CollisionMessage); - return; + LogCollision(collisionMessage); + HandleCollisionRpc(collisionMessage); } - CollisionMessage.SourceOwner = rpcParams.Receive.SenderClientId; - CollisionMessage.TargetOwner = OwnerClientId; - HandleCollision(collisionMessage); - } + /// + /// Override this method if you have registered the instance with and + /// want to customize collision. + /// + /// + /// Only automatically handles collisions. + /// + /// + /// + /// The that collided with this object. + /// + /// + /// + protected virtual void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { - /// - /// Invoked by the owner of the object inflicting damage, this will handle the RPC routing - /// of the message to the appropriate targeted owner of the object taking damage - /// - /// - public void SendCollisionMessage(CollisionMessageInfo collisionMessage) - { - LogDamage(collisionMessage); - HandleCollisionRpc(collisionMessage); - } + } - /// - /// Override this method if you have registerd the instance with and - /// want to customize collision. - /// - /// - /// Only automatically handles collisions. For an example of a customized contact event - /// handler look over . - /// - /// The average normal of the collisions contacts - /// The that collided with this object. - protected virtual void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) - { + /// + /// Invoked from when a non-kinematic body collides + /// with another registered . + /// + /// + /// The averaged normal of the collision + /// The this objects collided with + /// + /// + /// + public void ContactEvent(ulong eventId, Vector3 averageNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + Debug.Log($"{nameof(OnContactEvent)} {gameObject.name} isKinematic {this.Rigidbody.isKinematic} collidingBody {collidingBody.gameObject.name} isKinematic {collidingBody.isKinematic}"); - } + if (!IsSpawned) + { + return; + } - protected ulong LastEventId { get; private set; } - /// - /// Invoked from when a non-kinematic body collides - /// with another registered . - /// - /// The averaged normal of the collision - /// The this objects collided with - public void ContactEvent(ulong eventId, Vector3 averageNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) - { - if (!IsSpawned) - { - return; + OnContactEvent(eventId, averageNormal, collidingBody, contactPoint, hasCollisionStay, averagedCollisionStayNormal); + LastEventId = eventId; } - OnContactEvent(eventId, averageNormal, collidingBody, contactPoint, hasCollisionStay, averagedCollisionStayNormal); - LastEventId = eventId; - } - - /// - /// Invoked this to send a collision message to the authoritative instance. - /// - /// - /// - protected void EventCollision(Vector3 averagedCollisionNormal, BaseObjectMotionHandler collidingBodyBaseObject) - { -#if DEBUG || UNITY_EDITOR - if (DebugCollisions) + /// + /// Invoked this to send a collision message to the authoritative instance. + /// + /// + /// + protected void EventCollision(Vector3 averagedCollisionNormal, BaseObjectMotionHandler collidingBodyBaseObject) { - LogCollision(ref collidingBodyBaseObject); - } +#if DEBUG || UNITY_EDITOR + if (m_DebugCollisions) + { + LogCollision(ref collidingBodyBaseObject); + } #endif - if (OnPrepareCollisionMessage(averagedCollisionNormal, collidingBodyBaseObject)) - { - CollisionId++; - CollisionMessage.CollisionId = CollisionId; - CollisionMessage.Time = Time.realtimeSinceStartup; - CollisionMessage.Source = OwnerClientId; - CollisionMessage.SourceId = NetworkObjectId; - CollisionMessage.Destination = collidingBodyBaseObject.OwnerClientId; - CollisionMessage.DestNetworkObjId = collidingBodyBaseObject.NetworkObjectId; - CollisionMessage.DestBehaviourId = collidingBodyBaseObject.NetworkBehaviourId; - - // Otherwise, send the collision message to the owner of the object - collidingBodyBaseObject.SendCollisionMessage(CollisionMessage); + if (OnPrepareCollisionMessage(averagedCollisionNormal, collidingBodyBaseObject)) + { + s_CollisionId++; + m_CollisionMessage.CollisionId = s_CollisionId; + m_CollisionMessage.Time = Time.realtimeSinceStartup; + m_CollisionMessage.Source = OwnerClientId; + m_CollisionMessage.SourceId = NetworkObjectId; + m_CollisionMessage.Destination = collidingBodyBaseObject.OwnerClientId; + m_CollisionMessage.DestinationNetworkObjId = collidingBodyBaseObject.NetworkObjectId; + m_CollisionMessage.DestinationBehaviourId = collidingBodyBaseObject.NetworkBehaviourId; + + // Otherwise, send the collision message to the owner of the object + collidingBodyBaseObject.SendCollisionMessage(m_CollisionMessage); + } } - } - - #region DEBUG CONSOLE LOGGING METHODS - /// - /// Override to handle local collisions generating an outbound message - /// - /// - /// - protected virtual string OnLogCollision(ref BaseObjectMotionHandler objectHit) - { - return "[LocalCollision-End]"; - } + #region DEBUG CONSOLE LOGGING METHODS - private static int CollisionId = 0; - private void LogCollision(ref BaseObjectMotionHandler objectHit) - { - if (!DebugCollisions) + /// + /// Override to handle local collisions generating an outbound message + /// + /// + /// + protected virtual string OnLogCollision(ref BaseObjectMotionHandler objectHit) { - return; + return "[LocalCollision-End]"; } - var distance = Vector3.Distance(transform.position, objectHit.transform.position); - /*NetworkManagerHelper.Instance.LogMessage($"[{Time.realtimeSinceStartup}][LocalCollision][{name}][collided with][{objectHit.name}][Collider:{name}][Distance: {distance}]" + - $"{OnLogCollision(ref objectHit)}.");*/ - } - protected virtual string OnLogDamage(CollisionMessageInfo collisionMessage) - { - return string.Empty; - } - - protected void LogDamage(CollisionMessageInfo collisionMessage) - { - if (!DebugDamage || collisionMessage.Damage == 0) + void LogCollision(ref BaseObjectMotionHandler objectHit) { - return; - } - var additionalInfo = OnLogDamage(collisionMessage); - /*NetworkManagerHelper.Instance.LogMessage($"[{name}][++Damaged++][Client-{collisionMessage.TargetOwner}][{collisionMessage.GetCollisionType()}][Dmg:{collisionMessage.Damage}] {additionalInfo}");*/ - } + if (!m_DebugCollisions) + { + return; + } - /// - /// Override to log incoming collision messages - /// - /// - protected virtual string OnLogHandleCollision(ref CollisionMessageInfo collisionMessage) - { - return "[CollisionMessage-End]"; - } + var distance = Vector3.Distance(transform.position, objectHit.transform.position); + Debug.Log($"[{Time.realtimeSinceStartup}][LocalCollision][{name}][collided with][{objectHit.name}][Collider:{name}][Distance: {distance}]" + + $"{OnLogCollision(ref objectHit)}."); + } - private void LogHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false) - { - var distance = -1.0f; - if (NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(collisionMessage.DestNetworkObjId)) + protected virtual string OnLogCollision(CollisionMessageInfo collisionMessage) { - distance = Vector3.Distance(transform.position, NetworkManager.SpawnManager.SpawnedObjects[collisionMessage.DestNetworkObjId].transform.position); + return string.Empty; } - var distStr = distance == -1.0f ? $"{collisionMessage.DestNetworkObjId} DNE!!" : $"Distance: {distance}"; - /*NetworkManagerHelper.Instance.LogMessage($"[{collisionMessage.CollisionId}][{collisionMessage.Time}][CollisionMessage][IsLocal: {isLocal}][{name}][Src:{collisionMessage.Source}][Dest:{collisionMessage.Destination}]" + - $"[NObjId:{collisionMessage.DestNetworkObjId}][NBvrId:{collisionMessage.DestBehaviourId}][{distStr}]{OnLogHandleCollision(ref collisionMessage)}.");*/ - } - protected void LogMessage(string msg, bool forceMessage = false, float messageTime = 10.0f) - { - /*NetworkManagerHelper.Instance.LogMessage($"[{name}]{msg}", messageTime, forceMessage);*/ - } + protected void LogCollision(CollisionMessageInfo collisionMessage) + { + if (!m_DebugDamage || collisionMessage.Damage == 0) + { + return; + } - #endregion + var additionalInfo = OnLogCollision(collisionMessage); + Debug.Log($"[{name}][++Damaged++][Client-{collisionMessage.TargetOwner}][{collisionMessage.GetCollisionType()}][Dmg:{collisionMessage.Damage}] {additionalInfo}"); + } - #region VECTOR AND EULER HELPER METHODS - /// - /// Enable this to get 6 decimal precision when logging Vector3 values - /// - private bool m_HigPrecisionDecimals = false; - protected string GetVector3Values(ref Vector3 vector3) - { - if (m_HigPrecisionDecimals) + /// + /// Override to log incoming collision messages + /// + /// + protected virtual string OnLogHandleCollision(ref CollisionMessageInfo collisionMessage) { - return $"({vector3.x:F6},{vector3.y:F6},{vector3.z:F6})"; + return "[CollisionMessage-End]"; } - else + + void LogHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false) { - return $"({vector3.x:F2},{vector3.y:F2},{vector3.z:F2})"; - } - } + var distance = -1.0f; + if (NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(collisionMessage.DestinationNetworkObjId)) + { + distance = Vector3.Distance(transform.position, NetworkManager.SpawnManager.SpawnedObjects[collisionMessage.DestinationNetworkObjId].transform.position); + } - protected string GetVector3Values(Vector3 vector3) - { - return GetVector3Values(ref vector3); - } + var distStr = distance == -1.0f ? $"{collisionMessage.DestinationNetworkObjId} DNE!!" : $"Distance: {distance}"; + Debug.Log($"[{collisionMessage.CollisionId}][{collisionMessage.Time}][CollisionMessage][IsLocal: {isLocal}][{name}][Src:{collisionMessage.Source}][Dest:{collisionMessage.Destination}]" + + $"[NObjId:{collisionMessage.DestinationNetworkObjId}][NBvrId:{collisionMessage.DestinationBehaviourId}][{distStr}]{OnLogHandleCollision(ref collisionMessage)}."); + } - protected Vector3 GetRandomVector3(float min, float max, Vector3 baseLine, bool randomlyApplySign = false) - { - var retValue = new Vector3(baseLine.x * Random.Range(min, max), baseLine.y * Random.Range(min, max), baseLine.z * Random.Range(min, max)); - if (!randomlyApplySign) + protected void LogMessage(string msg, bool forceMessage = false, float messageTime = 10.0f) { - return retValue; + Debug.Log($"[{name}]{msg} {messageTime} {forceMessage}"); } - retValue.x *= Random.Range(1, 100) >= 50 ? -1 : 1; - retValue.y *= Random.Range(1, 100) >= 50 ? -1 : 1; - retValue.z *= Random.Range(1, 100) >= 50 ? -1 : 1; - return retValue; - } - - protected Vector3 GetRandomVector3(MinMaxVector2Physics minMax, Vector3 baseLine, bool randomlyApplySign = false) - { - return GetRandomVector3(minMax.Min, minMax.Max, baseLine, randomlyApplySign); - } - - private const float k_DefaultThreshold = 0.0025f; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool Approximately(float a, float b, float threshold = k_DefaultThreshold) - { - return Math.Round(Mathf.Abs(a - b), 4) <= threshold; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool Approximately(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) - { - return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool Approximately(Quaternion a, Quaternion b, float threshold = k_DefaultThreshold) - { - return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z) && Approximately(a.w, b.w); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected float EulerDelta(float a, float b) - { - return Mathf.DeltaAngle(a, b); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool ApproximatelyEuler(float a, float b, float threshold = k_DefaultThreshold) - { - return Mathf.Abs(EulerDelta(a, b)) <= threshold; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool ApproximatelyEuler(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) - { - return ApproximatelyEuler(a.x, b.x, threshold) && ApproximatelyEuler(a.y, b.y, threshold) && ApproximatelyEuler(a.z, b.z, threshold); - } - #endregion -} - -[Serializable] -public class MinMaxVector2Physics -{ - [Range(1.0f, 200.0f)] - public float Min; - [Range(1.0f, 200.0f)] - public float Max; - - public MinMaxVector2Physics(float min, float max) - { - Min = min; - Max = max; + #endregion } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs index 4e422440b..348d08551 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/CollisionMessageInfo.cs @@ -2,147 +2,144 @@ using Unity.Netcode; using UnityEngine; -/// -/// Only 15 types are allowed. -/// Applied to the first byte of -/// -public enum CollisionTypes +namespace Unity.Multiplayer.Samples.SocialHub.Physics { - Laser = 0x01, - Missile = 0x02, - Mine = 0x03, - Asteroid = 0x04, - Ship = 0x05, - DebugCollision = 0x0F, - // Maximum value for collision types is 15 - 0x0E -} - -/// -/// Flags to be used with -/// 16, 32, 64, and 128 are used for flags -/// -public enum CollisionCategoryFlags -{ - // Four flags are reserved - Standard = 0x10, - CollisionForce = 0x20, - CollisionPoint = 0x40, -} - -public struct CollisionMessageInfo : INetworkSerializable -{ - /// - /// Flags are serialized and determine the collision type - /// - public byte Flags; - - /// - /// Damage is serialized and is set based on the type - /// - public ushort Damage; - - /// - /// Collision force is serialized only if the flags contains the - /// flag. - /// - public Vector3 CollisionForce; - /// - /// Collision force is serialized only if the flags contains the - /// flag. + /// Only 15 types are allowed. + /// Applied to the first byte of /// - public Vector3 CollisionPoint; - - /// - /// Never serialized, only used locally to determine if - /// we are - /// - public bool DebugCollisionEnabled; - - public int CollisionId; - public float Time; - public ulong Source; - public ulong Destination; - public ulong DestNetworkObjId; - public ushort DestBehaviourId; - - /// - /// Never serialized, only used locally - /// - public ulong SourceId; + enum CollisionType + { + Avatar = 0x01, + Destructible = 0x02, + DebugCollision = 0x0F, - /// - /// Never serialized, only used locally - /// - public ulong SourceOwner; + // Maximum value for collision types is 15 - 0x0E + } /// - /// Never serialized, only used locally + /// Flags to be used with + /// 16, 32, 64, and 128 are used for flags /// - public ulong TargetOwner; - - public CollisionTypes GetCollisionType() - { - return (CollisionTypes)(Flags & 0x0F); - } - - public bool HasCollisionForce() + enum CollisionCategoryFlags { - return (Flags & (uint)CollisionCategoryFlags.CollisionForce) == (byte)CollisionCategoryFlags.CollisionForce; + // Four flags are reserved + Standard = 0x10, + CollisionForce = 0x20, + CollisionPoint = 0x40, } - private bool DebugCollisionsEnabled + struct CollisionMessageInfo : INetworkSerializable { - get + /// + /// Flags are serialized and determine the collision type + /// + public byte Flags; + + /// + /// Damage is serialized and is set based on the type + /// + public ushort Damage; + + /// + /// Collision force is serialized only if the flags contains the + /// flag. + /// + public Vector3 CollisionForce; + + /// + /// Collision force is serialized only if the flags contains the + /// flag. + /// + public Vector3 CollisionPoint; + + /// + /// Never serialized, only used locally to determine if + /// we are + /// + public bool DebugCollisionEnabled; + + public int CollisionId; + public float Time; + public ulong Source; + public ulong Destination; + public ulong DestinationNetworkObjId; + public ushort DestinationBehaviourId; + + /// + /// Never serialized, only used locally + /// + public ulong SourceId; + + /// + /// Never serialized, only used locally + /// + public ulong SourceOwner; + + /// + /// Never serialized, only used locally + /// + public ulong TargetOwner; + + public CollisionType GetCollisionType() { - return GetFlag((uint)CollisionTypes.DebugCollision); + return (CollisionType)(Flags & 0x0F); } - set + public bool HasCollisionForce() { - SetFlag(value, (uint)CollisionTypes.DebugCollision); + return (Flags & (uint)CollisionCategoryFlags.CollisionForce) == (byte)CollisionCategoryFlags.CollisionForce; } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetFlag(bool set, uint flag) - { - var flags = (uint)Flags; - if (set) { flags = flags | flag; } - else { flags = flags & ~flag; } - Flags = (byte)flags; - } + private bool DebugCollisionsEnabled + { + get { return GetFlag((uint)CollisionType.DebugCollision); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool GetFlag(uint flag) - { - var flags = (uint)Flags; - return (flags & flag) != 0; - } + set { SetFlag(value, (uint)CollisionType.DebugCollision); } + } - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Flags); - serializer.SerializeValue(ref Damage); - // only if we have a collision force should we serialize it (read and write) - if (GetFlag((uint)CollisionCategoryFlags.CollisionForce)) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetFlag(bool set, uint flag) { - serializer.SerializeValue(ref CollisionForce); + var flags = (uint)Flags; + if (set) { flags = flags | flag; } + else { flags = flags & ~flag; } + + Flags = (byte)flags; } - if (GetFlag((uint)CollisionCategoryFlags.CollisionPoint)) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool GetFlag(uint flag) { - serializer.SerializeValue(ref CollisionForce); + var flags = (uint)Flags; + return (flags & flag) != 0; } - if (DebugCollisionsEnabled) + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { - serializer.SerializeValue(ref CollisionId); - serializer.SerializeValue(ref Time); - serializer.SerializeValue(ref Source); - serializer.SerializeValue(ref Destination); - serializer.SerializeValue(ref DestNetworkObjId); - serializer.SerializeValue(ref DestBehaviourId); + serializer.SerializeValue(ref Flags); + serializer.SerializeValue(ref Damage); + + // only if we have a collision force should we serialize it (read and write) + if (GetFlag((uint)CollisionCategoryFlags.CollisionForce)) + { + serializer.SerializeValue(ref CollisionForce); + } + + if (GetFlag((uint)CollisionCategoryFlags.CollisionPoint)) + { + serializer.SerializeValue(ref CollisionForce); + } + + if (DebugCollisionsEnabled) + { + serializer.SerializeValue(ref CollisionId); + serializer.SerializeValue(ref Time); + serializer.SerializeValue(ref Source); + serializer.SerializeValue(ref Destination); + serializer.SerializeValue(ref DestinationNetworkObjId); + serializer.SerializeValue(ref DestinationBehaviourId); + } } } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs index 46bf76df5..218f88b9e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/ICollisionHandler.cs @@ -1,19 +1,22 @@ using Unity.Netcode; -public interface ICollisionHandler +namespace Unity.Multiplayer.Samples.SocialHub.Physics { - /// - /// Invoked by non-authority objects detecting a collision, this determines the - /// appropriate targeted authority of the object being collided with. If the local - /// instance is authority it handles collision locally - /// - void SendCollisionMessage(CollisionMessageInfo collisionMessage); + interface ICollisionHandler + { + /// + /// Invoked by non-authority objects detecting a collision, this determines the + /// appropriate targeted authority of the object being collided with. If the local + /// instance is authority it handles collision locally + /// + void SendCollisionMessage(CollisionMessageInfo collisionMessage); - /// - /// Authority instances receive collision messages from non-authority instances via this implemented method - /// - /// - /// - [Rpc(SendTo.Authority, DeferLocal = true)] - void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default); + /// + /// Authority instances receive collision messages from non-authority instances via this implemented method + /// + /// + /// + [Rpc(SendTo.Authority, DeferLocal = true)] + void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default); + } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs index 7c4cf9385..d5d6810ee 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs @@ -3,71 +3,63 @@ using Unity.Netcode; using Unity.Netcode.Components; using UnityEngine; +using Unity.Multiplayer.Samples.SocialHub.Utils; namespace Unity.Multiplayer.Samples.SocialHub.Physics { - public partial class PhysicsObjectMotion : BaseObjectMotionHandler + class PhysicsObjectMotion : BaseObjectMotionHandler { -#if UNITY_EDITOR - public bool PhysicsObjectMotionPropertiesVisible = false; -#endif - [Serializable] public struct CollisionImpulseMultiplierEntry { - public CollisionTypes CollisionType; + public CollisionType CollisionType; public float MaxCollisionForce; } - public List CollisionImpulseEntries; - private Dictionary CollisionImpulseTable; - - public float MaxAngularVelocity = 30; - public float MaxVelocity = 30; - [HideInInspector] - public float StartingMass = 1.0f; + [SerializeField] + List m_CollisionImpulseEntries; + Dictionary m_CollisionImpulseTable; - public const float MaxMass = 5.0f; - public const float MinMass = 0.10f; + [SerializeField] + float m_MaxAngularVelocity = 30; + [SerializeField] + float m_MaxVelocity = 30; - public MinMaxVector2Physics MinMaxStartingTorque = new MinMaxVector2Physics(5.0f, 15.0f); - public MinMaxVector2Physics MinMaxStartingForce = new MinMaxVector2Physics(5.0f, 30.0f); + List m_RemoteAppliedForce = new List(); - protected NetworkVariable BeenInitialized = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_IsInitialized = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); /// /// All of the below values keep the physics objects synchronized between clients so when ownership changes the local Rigidbody can be configured to mirror /// the last known physics related states. /// - protected NetworkVariable Mass = new NetworkVariable(1.0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - protected NetworkVariable AngularVelocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - protected NetworkVariable Velocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - protected NetworkVariable Torque = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - protected NetworkVariable Force = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_Mass = new NetworkVariable(1.0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_AngularVelocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_Velocity = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_Torque = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + protected NetworkVariable m_Force = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); protected override void Awake() { base.Awake(); - CollisionImpulseTable = new Dictionary(); - foreach (var entry in CollisionImpulseEntries) + m_CollisionImpulseTable = new Dictionary(); + foreach (var entry in m_CollisionImpulseEntries) { - if (!CollisionImpulseTable.ContainsKey(entry.CollisionType)) + if (!m_CollisionImpulseTable.ContainsKey(entry.CollisionType)) { - CollisionImpulseTable.Add(entry.CollisionType, entry); + m_CollisionImpulseTable.Add(entry.CollisionType, entry); } else { Debug.LogWarning($"[Duplicate Entry] A duplicate {nameof(CollisionImpulseMultiplierEntry)} of type {entry.CollisionType} was detected! Ignoring entry."); } } - - StartingMass = Rigidbody.mass; } protected override Vector3 OnGetObjectVelocity(bool getReference = false) { if (getReference) { - return Velocity.Value; + return m_Velocity.Value; } return base.OnGetObjectVelocity(getReference); @@ -75,7 +67,7 @@ protected override Vector3 OnGetObjectVelocity(bool getReference = false) protected override Vector3 OnGetObjectAngularVelocity() { - return AngularVelocity.Value; + return m_AngularVelocity.Value; } protected void UpdateVelocity(Vector3 velocity, bool updateObjectVelocity = true) @@ -87,7 +79,7 @@ protected void UpdateVelocity(Vector3 velocity, bool updateObjectVelocity = true SetObjectVelocity(velocity); } - Velocity.Value = velocity; + m_Velocity.Value = velocity; } } @@ -96,7 +88,7 @@ protected void UpdateAngularVelocity(Vector3 angularVelocity) if (HasAuthority) { Rigidbody.angularVelocity = angularVelocity; - AngularVelocity.Value = angularVelocity; + m_AngularVelocity.Value = angularVelocity; } } @@ -105,7 +97,7 @@ protected void UpdateTorque(Vector3 torque) if (HasAuthority) { Rigidbody.AddTorque(torque); - Torque.Value = torque; + m_Torque.Value = torque; } } @@ -114,23 +106,7 @@ protected void UpdateImpulseForce(Vector3 impulseForce) if (HasAuthority) { Rigidbody.AddForce(impulseForce, ForceMode.Impulse); - Force.Value = impulseForce; - } - } - - protected void UpdateMass(float mass) - { - if (HasAuthority) - { - if (mass > MinMass && mass < MaxMass) - { - Rigidbody.mass = mass; - } - else - { - NetworkLog.LogWarningServer($"[{name}] Trying to assign mass of {mass} which is outside the mass boundary of {MinMass} to {MaxMass}! Clamping."); - Rigidbody.mass = Mathf.Clamp(mass, MinMass, MaxMass); - } + m_Force.Value = impulseForce; } } @@ -146,7 +122,7 @@ protected void UpdateMass(float mass) protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) { // If we haven't already initialized for the first time or haven't initialized previous state values during spawn then exit early - if (!BeenInitialized.Value) + if (!m_IsInitialized.Value) { return; } @@ -173,14 +149,11 @@ protected override void OnAuthorityPushTransformState(ref NetworkTransformState public override void OnNetworkSpawn() { - // When creating customized NetworkTransform behaviors, you must always invoke the base OnNetworkSpawn // method if you override it in any child derive generation (i.e. always assure the NetworkTransform.OnNetworkSpawn // method is invoked) base.OnNetworkSpawn(); - IsPhysicsBody = true; - // Assure all colliders are enabled (authority and non-authority) EnableColliders(true); @@ -188,11 +161,10 @@ public override void OnNetworkSpawn() RigidbodyContactEventManager.Instance.RegisterHandler(this); // Clamp the linear and angular velocities - Rigidbody.maxAngularVelocity = MaxAngularVelocity; - Rigidbody.maxLinearVelocity = MaxVelocity; + Rigidbody.maxAngularVelocity = m_MaxAngularVelocity; + Rigidbody.maxLinearVelocity = m_MaxVelocity; if (HasAuthority) { - // Assure we are not still in kinematic mode NetworkRigidbody.SetIsKinematic(false); @@ -203,14 +175,7 @@ public override void OnNetworkSpawn() if (!BeenInitialized.Value) #endif { - BeenInitialized.Value = true; - /*var torque = GetRandomVector3(MinMaxStartingTorque, Vector3.one, true); - Rigidbody.AddTorque(torque, ForceMode.Impulse); - UpdateTorque(torque); - var force = GetRandomVector3(MinMaxStartingForce, Vector3.one, true); - force.y = 0f; - Rigidbody.AddForce(force, ForceMode.Impulse); - UpdateImpulseForce(force);*/ + m_IsInitialized.Value = true; } #if SESSION_STORE_ENABLED else @@ -231,7 +196,7 @@ public override void OnNetworkDespawn() // If we are pooled and not shutting down, then reset the physics object for re-use later // ** Important to do this ** - if (IsPooled) + if (m_IsPooled) { EnableColliders(false); if (!Rigidbody.isKinematic) @@ -241,13 +206,12 @@ public override void OnNetworkDespawn() NetworkRigidbody.SetIsKinematic(true); } - Rigidbody.mass = StartingMass; - BeenInitialized.Reset(); - AngularVelocity.Reset(); - Velocity.Reset(); - Torque.Reset(); - Force.Reset(); - Mass.Reset(); + m_IsInitialized.Reset(); + m_AngularVelocity.Reset(); + m_Velocity.Reset(); + m_Torque.Reset(); + m_Force.Reset(); + m_Mass.Reset(); } } @@ -260,15 +224,15 @@ protected override void OnOwnershipChanged(ulong previous, ulong current) if (NetworkManager.LocalClientId == current) { NetworkRigidbody.SetIsKinematic(false); - if (BeenInitialized.Value) + if (m_IsInitialized.Value) { - Rigidbody.angularVelocity = Vector3.ClampMagnitude(GetObjectAngularVelocity(), MaxAngularVelocity); - SetObjectVelocity(Vector3.ClampMagnitude(GetObjectVelocity(true), MaxVelocity)); + Rigidbody.angularVelocity = Vector3.ClampMagnitude(GetObjectAngularVelocity(), m_MaxAngularVelocity); + SetObjectVelocity(Vector3.ClampMagnitude(GetObjectVelocity(true), m_MaxVelocity)); } else { - Rigidbody.AddTorque(Torque.Value, ForceMode.Impulse); - Rigidbody.AddForce(Force.Value, ForceMode.Impulse); + Rigidbody.AddTorque(m_Torque.Value, ForceMode.Impulse); + Rigidbody.AddForce(m_Force.Value, ForceMode.Impulse); } } else @@ -279,16 +243,6 @@ protected override void OnOwnershipChanged(ulong previous, ulong current) base.OnOwnershipChanged(previous, current); } - private struct RemoteForce - { - public float EndOfLife; - public Vector3 TargetForce; - public Vector3 AppliedForce; - } - - private List m_RemoteAppliedForce = new List(); - private Dictionary m_CollisionLatency = new Dictionary(); - /// /// Handles queuing up incoming collisions (remote and local) to be processed /// @@ -299,10 +253,10 @@ protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, AddForceDirect(collisionMessage.CollisionForce); } - base.OnHandleCollision(collisionMessage); + base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); } - public void AddForceDirect(Vector3 force) + void AddForceDirect(Vector3 force) { var remoteForce = new RemoteForce() { @@ -310,14 +264,11 @@ public void AddForceDirect(Vector3 force) AppliedForce = Vector3.zero, }; - m_RemoteAppliedForce.Add(remoteForce); } protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) { - // TODO: Possibly come up with a better way to route contact events at this level. - // For now, since lasers are always kinematic and send damage messages we divert contact events to the LaserMotion child class var collidingBaseObjectMotion = collidingBody.GetComponent(); var collidingBodyPhys = collidingBaseObjectMotion as PhysicsObjectMotion; @@ -327,13 +278,6 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN return; } - if (collidingBaseObjectMotion.CollisionType == CollisionTypes.Laser) - { - //var laserMotion = collidingBaseObjectMotion as LaserMotion; - //laserMotion.ContactEvent(eventId, averagedCollisionNormal, Rigidbody, contactPoint); - return; - } - if (collidingBodyPhys == null) { return; @@ -348,11 +292,13 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN if (!Rigidbody.isKinematic && collidingBody.isKinematic && thisVelocity > 0.01f) { - CollisionMessage.CollisionForce = thisKineticForce; - CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); - if (DebugCollisions) + // our non-kinematic Rigidbody is moving with physics and hit a still kinematic Rigidbody + + m_CollisionMessage.CollisionForce = thisKineticForce; + m_CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); + if (m_DebugCollisions) { - //NetworkManagerHelper.Instance.LogMessage($"[{name}][SecondBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {GetVector3Values(thisKineticForce)} to {collidingBody.name}."); + Debug.Log($"[{name}][SecondBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(thisKineticForce)} to {collidingBody.name}."); } // Send collision to owner of kinematic body @@ -360,23 +306,25 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN } else if (Rigidbody.isKinematic && !collidingBody.isKinematic && otherVelocity > 0.01f) { - collidingBodyPhys.CollisionMessage.CollisionForce = otherKineticForce; - collidingBodyPhys.CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); + // our still, kinematic Rigidbody was hit by a non-kinematic physics-moving Rigidbody + + collidingBodyPhys.m_CollisionMessage.CollisionForce = otherKineticForce; + collidingBodyPhys.m_CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); collidingBodyPhys.EventCollision(averagedCollisionNormal, this); - if (DebugCollisions) + if (m_DebugCollisions) { - //NetworkManagerHelper.Instance.LogMessage($"[{collidingBodyPhys.name}][FirstBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {GetVector3Values(otherKineticForce)} to {name}."); + Debug.Log($"[{collidingBodyPhys.name}][FirstBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(otherKineticForce)} to {name}."); } } - base.OnContactEvent(eventId, averagedCollisionNormal, collidingBody, contactPoint); + base.OnContactEvent(eventId, averagedCollisionNormal, collidingBody, contactPoint, hasCollisionStay, averagedCollisionStayNormal); } /// - /// Accumulatively apply the resultant collision force + /// Accumulative-ly apply the resultant collision force /// - /// - private void ApplyCollisionForce(Vector3 force) + /// s + void ApplyCollisionForce(Vector3 force) { Rigidbody.AddForce(force, ForceMode.Impulse); Rigidbody.AddTorque(force * 0.25f, ForceMode.Impulse); @@ -385,7 +333,7 @@ private void ApplyCollisionForce(Vector3 force) /// /// Processes the queued collisions forces /// - private void ProcessRemoteForces() + void ProcessRemoteForces() { if (m_RemoteAppliedForce.Count == 0) { @@ -397,7 +345,7 @@ private void ProcessRemoteForces() { var remoteForce = m_RemoteAppliedForce[i]; accumulativeForce += remoteForce.TargetForce; - if (Approximately(remoteForce.TargetForce, Vector3.zero)) + if (MathUtils.Approximately(remoteForce.TargetForce, Vector3.zero)) { m_RemoteAppliedForce.RemoveAt(i); } @@ -430,18 +378,18 @@ protected virtual void FixedUpdate() } /// - /// When is enabled, this will log locally + /// When is enabled, this will log locally /// generated collision info for the derived component /// /// the hit /// log string protected override string OnLogCollision(ref BaseObjectMotionHandler objectHit) { - return $"[CF: {GetVector3Values(ref CollisionMessage.CollisionForce)}]-{base.OnLogCollision(ref objectHit)}"; + return $"[CF: {MathUtils.GetVector3Values(ref m_CollisionMessage.CollisionForce)}]-{base.OnLogCollision(ref objectHit)}"; } /// - /// When is enabled, this will log remotely + /// When is enabled, this will log remotely /// received collision info for the derived component /// /// the message received @@ -458,12 +406,19 @@ protected override string OnLogHandleCollision(ref CollisionMessageInfo collisio var resAngularVel = string.Empty; if (Rigidbody != null) { - resLinearVel = GetVector3Values(GetObjectVelocity()); - resAngularVel = GetVector3Values(Rigidbody.angularVelocity); + resLinearVel = MathUtils.GetVector3Values(GetObjectVelocity()); + resAngularVel = MathUtils.GetVector3Values(Rigidbody.angularVelocity); } - return $"[**Collision-Info**][To: {name}][By:{sourceCollider}][Force:{GetVector3Values(ref collisionMessage.CollisionForce)}]" + + return $"[**Collision-Info**][To: {name}][By:{sourceCollider}][Force:{MathUtils.GetVector3Values(ref collisionMessage.CollisionForce)}]" + $"[LinVel: {resLinearVel}][AngVel: {resAngularVel}]-{base.OnLogHandleCollision(ref collisionMessage)}"; } } + + struct RemoteForce + { + public float EndOfLife; + public Vector3 TargetForce; + public Vector3 AppliedForce; + } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs new file mode 100644 index 000000000..c42468779 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs @@ -0,0 +1,137 @@ +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Physics +{ + [RequireComponent(typeof(Rigidbody))] + class PhysicsPlayerController : MonoBehaviour + { + [SerializeField] + Rigidbody m_Rigidbody; + + [SerializeField] + PhysicsPlayerControllerSettings m_PhysicsPlayerControllerSettings; + + // cached grounded check + bool m_IsGrounded; + RaycastHit[] m_RaycastHits = new RaycastHit[1]; + Ray m_Ray; + + Vector3 m_Movement; + bool m_Jump; + bool m_Sprint; + + void FixedUpdate() + { + if (m_Rigidbody != null && m_Rigidbody.isKinematic) + { + return; + } + + UpdateGroundedStatus(); + + ApplyMovement(); + + ApplyJump(); + + ApplyDrag(); + + ApplyCustomGravity(); + } + + void UpdateGroundedStatus() + { + m_IsGrounded = IsGrounded(); + } + + bool IsGrounded() + { + // Perform a raycast to check if the character is grounded + m_Ray.origin = m_Rigidbody.worldCenterOfMass; + m_Ray.direction = Vector3.down; + return UnityEngine.Physics.RaycastNonAlloc(m_Ray, m_RaycastHits, m_PhysicsPlayerControllerSettings.GroundCheckDistance) > 0; + } + + void ApplyMovement() + { + if (Mathf.Approximately(m_Movement.magnitude, 0f)) + { + return; + } + + var velocity = m_Rigidbody.linearVelocity; + var desiredVelocity = m_Movement * (m_Sprint ? m_PhysicsPlayerControllerSettings.SprintSpeed : m_PhysicsPlayerControllerSettings.WalkSpeed); + var targetVelocity = new Vector3(desiredVelocity.x, velocity.y, desiredVelocity.z); + var velocityChange = targetVelocity - velocity; + + if (m_IsGrounded) + { + // Apply force proportional to acceleration while grounded + var force = velocityChange * m_PhysicsPlayerControllerSettings.Acceleration; + m_Rigidbody.AddForce(force, ForceMode.Acceleration); + } + else + { + // Apply reduced force in the air for air control + var force = velocityChange * (m_PhysicsPlayerControllerSettings.Acceleration * m_PhysicsPlayerControllerSettings.AirControlFactor); + m_Rigidbody.AddForce(force, ForceMode.Acceleration); + } + + // maybe add magnitude check? + var targetAngle = Mathf.Atan2(m_Movement.x, m_Movement.z) * Mathf.Rad2Deg; + var targetRotation = Quaternion.Euler(0, targetAngle, 0); + var smoothRotation = Quaternion.Lerp(m_Rigidbody.rotation, targetRotation, Time.fixedDeltaTime * m_PhysicsPlayerControllerSettings.RotationSpeed); + m_Rigidbody.MoveRotation(smoothRotation); + + m_Movement = Vector3.zero; + } + + void ApplyJump() + { + if (m_Jump && m_IsGrounded) + { + m_Rigidbody.AddForce(Vector3.up * m_PhysicsPlayerControllerSettings.JumpImpusle, ForceMode.Impulse); + } + m_Jump = false; + } + + void ApplyDrag() + { + var groundVelocity = m_Rigidbody.linearVelocity; + groundVelocity.y = 0f; + if (groundVelocity.magnitude > 0f) + { + // Apply deceleration force to stop movement + var dragForce = -m_PhysicsPlayerControllerSettings.DragCoefficient * groundVelocity.magnitude * groundVelocity; + m_Rigidbody.AddForce(dragForce, ForceMode.Acceleration); + } + } + + void ApplyCustomGravity() + { + // custom gravity + if (!m_IsGrounded) + { + var customGravity = UnityEngine.Physics.gravity * (m_PhysicsPlayerControllerSettings.CustomGravityMultiplier - 1); + m_Rigidbody.AddForce(customGravity, ForceMode.Acceleration); + } + } + + public void SetMovement(Vector3 movement) + { + m_Movement = movement; + } + + public void SetJump(bool jump) + { + if (jump) + { + m_Jump = true; + } + } + + public void SetSprint(bool sprint) + { + m_Sprint = sprint; + } + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs.meta new file mode 100644 index 000000000..7598df3a1 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e222c86e1ae554b699fe6d68d3cf4ba9 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs new file mode 100644 index 000000000..2abc876f3 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace Unity.Multiplayer.Samples.SocialHub.Physics +{ + [CreateAssetMenu(fileName = "PhysicsPlayerControllerSettings", menuName = "ScriptableObjects/PhysicsPlayerControllerSettings", order = 1)] + class PhysicsPlayerControllerSettings : ScriptableObject + { + [SerializeField] + internal float WalkSpeed; + [SerializeField] + internal float SprintSpeed; + [SerializeField] + internal float Acceleration; + [SerializeField] + internal float DragCoefficient; + [SerializeField] + internal float AirControlFactor; + [SerializeField] + internal float JumpImpusle; + [SerializeField] + internal float CustomGravityMultiplier; + [SerializeField] + internal float RotationSpeed; + [SerializeField] + internal float GroundCheckDistance; + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs.meta new file mode 100644 index 000000000..b10dd2b41 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerControllerSettings.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 48976c2ba473849eab61b8e1398b8644 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef index 42291f412..d3213dc19 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/Unity.Multiplayer.Samples.SocialHub.Physics.asmdef @@ -2,7 +2,8 @@ "name": "Unity.Multiplayer.Samples.SocialHub.Physics", "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", "references": [ - "GUID:1491147abca9d7d4bb7105af628b223e" + "GUID:1491147abca9d7d4bb7105af628b223e", + "GUID:a469b04c8dd43463084f4a2b513f1284" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs new file mode 100644 index 000000000..ada318509 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Editor")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs.meta new file mode 100644 index 000000000..973e63c16 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 47327abb6038742b08c7675b13b1765f diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs index e511bc6ca..c1eb0d866 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs @@ -47,6 +47,7 @@ void Awake() public override void OnNetworkSpawn() { + base.OnNetworkSpawn(); if (!HasAuthority) { return; @@ -64,6 +65,7 @@ public override void OnNetworkSpawn() public override void OnNetworkDespawn() { + base.OnNetworkDespawn(); if (m_AvatarInputs) { m_AvatarInputs.InteractTapped -= OnTapPerformed; @@ -93,7 +95,7 @@ void OnHoldReleased(double holdDuration) void PickUp() { - if (Physics.OverlapBoxNonAlloc(m_InteractCollider.transform.position, m_InteractCollider.bounds.extents, m_Results, Quaternion.identity, mask: m_PickupableLayerMask) > 0) + if (UnityEngine.Physics.OverlapBoxNonAlloc(m_InteractCollider.transform.position, m_InteractCollider.bounds.extents, m_Results, Quaternion.identity, mask: m_PickupableLayerMask) > 0) { if (m_Results[0].TryGetComponent(out NetworkObject otherNetworkObject)) { @@ -167,7 +169,7 @@ void AttachToFixedJoint(NetworkObject other) gameplayEventInvokable.OnGameplayEvent += OnGameplayEvent; // prevent collisions from this collider to the picked up object and vice-versa - Physics.IgnoreCollision(m_MainCollider, other.GetComponent(), true); + UnityEngine.Physics.IgnoreCollision(m_MainCollider, other.GetComponent(), true); } } @@ -185,7 +187,7 @@ void OnGameplayEvent(NetworkObject networkObject, GameplayEvent gameplayEvent) // revert collision if (networkObject.TryGetComponent(out Collider otherCollider)) { - Physics.IgnoreCollision(m_MainCollider, otherCollider, false); + UnityEngine.Physics.IgnoreCollision(m_MainCollider, otherCollider, false); } // don't have ownership of the item, thus we can't invoke DetachFromFixedJoint(), but we need to remove created FixedJoint component @@ -210,7 +212,7 @@ void ReleaseHeldObject() m_HoldingRigidbody.DetachFromFixedJoint(); m_HoldingRigidbody.GetComponent().useGravity = true; - Physics.IgnoreCollision(m_MainCollider, m_HoldingRigidbody.GetComponent(), false); + UnityEngine.Physics.IgnoreCollision(m_MainCollider, m_HoldingRigidbody.GetComponent(), false); m_HoldingRigidbody = null; } @@ -222,7 +224,7 @@ void Toss(double holdDuration) // apply a force to the released object float timeHeldClamped = Mathf.Clamp((float)holdDuration, k_MinDurationHeld, k_MaxDurationHeld); float tossForce = Mathf.Lerp(m_MinTossForce, m_MaxTossForce, Mathf.Clamp(timeHeldClamped, 0f, 1f)); - heldRigidbody.AddForce(transform.forward * tossForce, ForceMode.Impulse); + heldRigidbody.AddForce(transform.forward * tossForce, ForceMode.VelocityChange); } } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 7601e7640..3f96cbfb2 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -1,45 +1,22 @@ -using Unity.Netcode.Components; +using System; using UnityEngine; using Unity.Multiplayer.Samples.SocialHub.Input; +using Unity.Multiplayer.Samples.SocialHub.Physics; using UnityEngine.InputSystem; namespace Unity.Multiplayer.Samples.SocialHub.Player { [RequireComponent(typeof(Rigidbody))] - public class AvatarTransform : NetworkTransform + class AvatarTransform : PhysicsObjectMotion { - [SerializeField] - Rigidbody m_Rigidbody; [SerializeField] PlayerInput m_PlayerInput; [SerializeField] AvatarInputs m_AvatarInputs; [SerializeField] - float m_WalkSpeed; - [SerializeField] - float m_SprintSpeed; - [SerializeField] - float m_Acceleration; - [SerializeField] - float m_DragCoefficient; - [SerializeField] - float m_AirControlFactor; - [SerializeField] - float m_JumpImpusle; - [SerializeField] - float m_CustomGravityMultiplier; + AvatarInteractions m_AvatarInteractions; [SerializeField] - float m_RotationSpeed; - [SerializeField] - float m_GroundCheckDistance; - - Vector3 m_Movement; - // grab jump state from input and clear after consumed - bool m_Jump; - // cached grounded check - bool m_IsGrounded; - RaycastHit[] m_RaycastHits = new RaycastHit[1]; - Ray m_Ray; + PhysicsPlayerController m_PhysicsPlayerController; public override void OnNetworkSpawn() { @@ -47,6 +24,8 @@ public override void OnNetworkSpawn() gameObject.name = $"[Client-{OwnerClientId}]{name}"; + m_DebugCollisions = m_DebugDamage = true; + if (!HasAuthority) { return; @@ -54,127 +33,50 @@ public override void OnNetworkSpawn() m_PlayerInput.enabled = true; m_AvatarInputs.enabled = true; - m_Rigidbody.isKinematic = false; + m_AvatarInputs.Jumped += OnJumped; + m_AvatarInteractions.enabled = true; + m_PhysicsPlayerController.enabled = true; + Rigidbody.isKinematic = false; // Freeze rotation on the x and z axes to prevent toppling - m_Rigidbody.freezeRotation = true; + Rigidbody.freezeRotation = true; var spawnPosition = new Vector3(0f, 1.5f, 0f); transform.SetPositionAndRotation(position: spawnPosition, rotation: Quaternion.identity); - m_Rigidbody.position = spawnPosition; - m_Rigidbody.linearVelocity = Vector3.zero; - } - - void Update() - { - if (!IsSpawned || !HasAuthority) - { - return; - } - - m_Movement = new Vector3(m_AvatarInputs.Move.x, 0, m_AvatarInputs.Move.y).normalized; - - // Handle rotation based on input direction - if (m_Movement.magnitude >= 0.1f) - { - var targetAngle = Mathf.Atan2(m_Movement.x, m_Movement.z) * Mathf.Rad2Deg; - var targetRotation = Quaternion.Euler(0, targetAngle, 0); - transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * m_RotationSpeed); - } - - if (IsGrounded() && m_AvatarInputs.Jump) - { - m_Jump = true; - m_AvatarInputs.Jump = false; - } - } - - void ApplyMovement() - { - if (Mathf.Approximately(m_Movement.magnitude, 0f)) - { - return; - } - - var velocity = m_Rigidbody.linearVelocity; - var desiredVelocity = m_Movement * (m_AvatarInputs.Sprint ? m_SprintSpeed : m_WalkSpeed); - var targetVelocity = new Vector3(desiredVelocity.x, velocity.y, desiredVelocity.z); - var velocityChange = targetVelocity - velocity; - - if (m_IsGrounded) - { - // Apply force proportional to acceleration while grounded - var force = velocityChange * m_Acceleration; - m_Rigidbody.AddForce(force, ForceMode.Acceleration); - } - else - { - // Apply reduced force in the air for air control - var force = velocityChange * (m_Acceleration * m_AirControlFactor); - m_Rigidbody.AddForce(force, ForceMode.Acceleration); - } + Rigidbody.position = spawnPosition; + Rigidbody.linearVelocity = Vector3.zero; } - void ApplyJump() + public override void OnNetworkDespawn() { - if (m_IsGrounded && m_Jump) + base.OnNetworkDespawn(); + if (m_AvatarInputs) { - m_Rigidbody.AddForce(Vector3.up * m_JumpImpusle, ForceMode.Impulse); - m_Jump = false; + m_AvatarInputs.Jumped -= OnJumped; } } - void UpdateGroundedStatus() - { - m_IsGrounded = IsGrounded(); - } - - bool IsGrounded() + void OnJumped() { - // Perform a raycast to check if the character is grounded - m_Ray.origin = m_Rigidbody.worldCenterOfMass; - m_Ray.direction = Vector3.down; - return Physics.RaycastNonAlloc(m_Ray, m_RaycastHits, m_GroundCheckDistance) > 0; + m_PhysicsPlayerController.SetJump(true); } - void FixedUpdate() + void Update() { - if (!IsSpawned || !HasAuthority || m_Rigidbody != null && m_Rigidbody.isKinematic) + if (!IsSpawned || !HasAuthority) { return; } - UpdateGroundedStatus(); - - ApplyMovement(); + var movement = new Vector3(m_AvatarInputs.Move.x, 0, m_AvatarInputs.Move.y).normalized; - ApplyJump(); - - ApplyDrag(); - - ApplyCustomGravity(); + m_PhysicsPlayerController.SetMovement(movement); + m_PhysicsPlayerController.SetSprint(m_AvatarInputs.Sprint); } - void ApplyDrag() + void OnCollisionEnter(Collision other) { - var groundVelocity = m_Rigidbody.linearVelocity; - groundVelocity.y = 0f; - if (groundVelocity.magnitude > 0f) - { - // Apply deceleration force to stop movement - var dragForce = -m_DragCoefficient * groundVelocity.magnitude * groundVelocity; - m_Rigidbody.AddForce(dragForce, ForceMode.Acceleration); - } - } - - void ApplyCustomGravity() - { - // custom gravity - if (!m_IsGrounded) - { - var customGravity = Physics.gravity * (m_CustomGravityMultiplier - 1); - m_Rigidbody.AddForce(customGravity, ForceMode.Acceleration); - } + return; } } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef index ebff7a9ea..bf25a23fa 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/Unity.Multiplayer.Samples.SocialHub.Player.asmdef @@ -5,7 +5,8 @@ "GUID:1491147abca9d7d4bb7105af628b223e", "GUID:c15e7f658578345fcb824b0a64d4dbe8", "GUID:9ff2150ce7d7c415a8af1fbff3dc3e6c", - "GUID:75469ad4d38634e559750d17036d5f7c" + "GUID:75469ad4d38634e559750d17036d5f7c", + "GUID:ae1323dabfa6440b3956d4cc5239e361" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils.meta new file mode 100644 index 000000000..398bb59c4 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b817bf16348b84528b3335a013608d3a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs new file mode 100644 index 000000000..c58534e17 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Unity.Multiplayer.Samples.SocialHub.Physics")] diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs.meta new file mode 100644 index 000000000..1a9ec85f1 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 639b9248aa1cd4519b7e04582490b53b diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs new file mode 100644 index 000000000..2e8a67d5b --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs @@ -0,0 +1,106 @@ +using System; +using System.Runtime.CompilerServices; +using UnityEngine; +using Random = UnityEngine.Random; + +namespace Unity.Multiplayer.Samples.SocialHub.Utils +{ + abstract class MathUtils + { + const float k_DefaultThreshold = 0.0025f; + + /// + /// + /// + /// + /// Enable this to get 6 decimal precision when logging Vector3 values + /// + internal static string GetVector3Values(ref Vector3 vector3, bool highPrecisionDecimals = false) + { + if (highPrecisionDecimals) + { + return $"({vector3.x:F6},{vector3.y:F6},{vector3.z:F6})"; + } + else + { + return $"({vector3.x:F2},{vector3.y:F2},{vector3.z:F2})"; + } + } + + internal static string GetVector3Values(Vector3 vector3, bool highPrecisionDecimals = false) + { + return GetVector3Values(ref vector3, highPrecisionDecimals); + } + + internal static Vector3 GetRandomVector3(float min, float max, Vector3 baseLine, bool randomlyApplySign = false) + { + var retValue = new Vector3(baseLine.x * Random.Range(min, max), baseLine.y * Random.Range(min, max), baseLine.z * Random.Range(min, max)); + if (!randomlyApplySign) + { + return retValue; + } + + retValue.x *= Random.Range(1, 100) >= 50 ? -1 : 1; + retValue.y *= Random.Range(1, 100) >= 50 ? -1 : 1; + retValue.z *= Random.Range(1, 100) >= 50 ? -1 : 1; + return retValue; + } + + internal static Vector3 GetRandomVector3(MinMaxVector2Physics minMax, Vector3 baseLine, bool randomlyApplySign = false) + { + return GetRandomVector3(minMax.Min, minMax.Max, baseLine, randomlyApplySign); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool Approximately(float a, float b, float threshold = k_DefaultThreshold) + { + return Math.Round(Mathf.Abs(a - b), 4) <= threshold; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool Approximately(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) + { + return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool Approximately(Quaternion a, Quaternion b, float threshold = k_DefaultThreshold) + { + return Approximately(a.x, b.x) && Approximately(a.y, b.y) && Approximately(a.z, b.z) && Approximately(a.w, b.w); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static float EulerDelta(float a, float b) + { + return Mathf.DeltaAngle(a, b); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool ApproximatelyEuler(float a, float b, float threshold = k_DefaultThreshold) + { + return Mathf.Abs(EulerDelta(a, b)) <= threshold; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool ApproximatelyEuler(Vector3 a, Vector3 b, float threshold = k_DefaultThreshold) + { + return ApproximatelyEuler(a.x, b.x, threshold) && ApproximatelyEuler(a.y, b.y, threshold) && ApproximatelyEuler(a.z, b.z, threshold); + } + + [Serializable] + internal class MinMaxVector2Physics + { + [Range(1.0f, 200.0f)] + public float Min; + [Range(1.0f, 200.0f)] + public float Max; + + MinMaxVector2Physics(float min, float max) + { + Min = min; + Max = max; + } + } + + } +} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs.meta new file mode 100644 index 000000000..34742ecac --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/MathUtils.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9889098b4101047349101dd918337bd3 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef new file mode 100644 index 000000000..9f56fb7f6 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Unity.Multiplayer.Samples.SocialHub.Utils", + "rootNamespace": "Unity.Multiplayer.Samples.SocialHub", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef.meta new file mode 100644 index 000000000..78a2858a4 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Utils/Unity.Multiplayer.Samples.SocialHub.Utils.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a469b04c8dd43463084f4a2b513f1284 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 726d1c40d5ee487e2485b2fa6f20c8d278149c97 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Mon, 26 Aug 2024 13:16:06 -0400 Subject: [PATCH 09/13] adding SO for player movement --- .../Assets/ScriptableObjects.meta | 8 +++++++ ...vatarPhysicsPlayerControllerSettings.asset | 23 +++++++++++++++++++ ...PhysicsPlayerControllerSettings.asset.meta | 8 +++++++ 3 files changed, 39 insertions(+) create mode 100644 Experimental/DistributedAuthoritySample/Assets/ScriptableObjects.meta create mode 100644 Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset create mode 100644 Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects.meta b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects.meta new file mode 100644 index 000000000..d66295912 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4e4c1f7517bb5d4293f1e3ad3e66d18 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset new file mode 100644 index 000000000..21ca127e4 --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset @@ -0,0 +1,23 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 48976c2ba473849eab61b8e1398b8644, type: 3} + m_Name: AvatarPhysicsPlayerControllerSettings + m_EditorClassIdentifier: + WalkSpeed: 6 + SprintSpeed: 10 + Acceleration: 50 + DragCoefficient: 4 + AirControlFactor: 0.5 + JumpImpusle: 7 + CustomGravityMultiplier: 2 + RotationSpeed: 10 + GroundCheckDistance: 1.1 diff --git a/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset.meta b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset.meta new file mode 100644 index 000000000..5f6fa669c --- /dev/null +++ b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1dd99ce80f3e54d03b20bf78d6ff2a40 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: From 32b1160ef39a4fd1834cc0a36d7efc5046f1addb Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Mon, 26 Aug 2024 13:28:21 -0400 Subject: [PATCH 10/13] prefabs updated post-merge, debug log removed --- .../Assets/Prefabs/Avatar.prefab | 10 +++++----- .../Prefabs/DistributableTransferableObject.prefab | 10 +++++----- .../Scripts/Gameplay/EnvironmentTransform.cs.meta | 2 +- .../Assets/Scripts/Physics/BaseObjectMotionHandler.cs | 2 -- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index 83e142cfd..ce218c123 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -250,7 +250,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 2473698027 + GlobalObjectIdHash: 3001504883 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 0 @@ -293,14 +293,14 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 - m_CollisionType: 0 + m_CollisionType: 1 m_CollisionDamage: 0 m_DebugDamage: 0 m_Colliders: - {fileID: 817796967242824188} - CollisionImpulseEntries: [] - MaxAngularVelocity: 30 - MaxVelocity: 30 + m_CollisionImpulseEntries: [] + m_MaxAngularVelocity: 30 + m_MaxVelocity: 30 m_PlayerInput: {fileID: 4903152183366241606} m_AvatarInputs: {fileID: 8197190117666738524} m_AvatarInteractions: {fileID: 539700041658036575} diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab index 3706d2b5d..2e0b8615e 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -125,7 +125,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 4270425062 + GlobalObjectIdHash: 2069120471 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 3 @@ -222,12 +222,12 @@ MonoBehaviour: InLocalSpace: 0 Interpolate: 1 SlerpPosition: 0 - m_CollisionType: 0 + m_CollisionType: 2 m_CollisionDamage: 0 m_DebugDamage: 0 m_Colliders: - {fileID: 7690746213975220858} - CollisionImpulseEntries: [] - MaxAngularVelocity: 30 - MaxVelocity: 30 + m_CollisionImpulseEntries: [] + m_MaxAngularVelocity: 30 + m_MaxVelocity: 30 m_StartingHealth: 100 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta index fa3a503d7..9deeceee3 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: 54937e94f00ab46c8ae43b81027f342c \ No newline at end of file +guid: e03d6beb668b4417984e204ab9e25342 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs index fc51949b4..0849ca816 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs @@ -242,8 +242,6 @@ protected virtual void OnContactEvent(ulong eventId, Vector3 averagedCollisionNo /// public void ContactEvent(ulong eventId, Vector3 averageNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) { - Debug.Log($"{nameof(OnContactEvent)} {gameObject.name} isKinematic {this.Rigidbody.isKinematic} collidingBody {collidingBody.gameObject.name} isKinematic {collidingBody.isKinematic}"); - if (!IsSpawned) { return; From c28ee1071dfbe0487a03b4ed31d3aa7c5fb6eb06 Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Wed, 28 Aug 2024 16:38:06 -0400 Subject: [PATCH 11/13] removing unused class, cooldown on damage, cleanup --- .../Assets/Prefabs/Avatar.prefab | 12 ++--- .../DistributableTransferableObject.prefab | 19 +++---- .../Scripts/Gameplay/DestructibleObject.cs | 30 +++++------ .../Scripts/Gameplay/EnvironmentTransform.cs | 54 ------------------- .../Gameplay/EnvironmentTransform.cs.meta | 2 - .../Physics/BaseObjectMotionHandler.cs | 13 ++--- .../Scripts/Physics/PhysicsObjectMotion.cs | 40 ++------------ .../Scripts/Player/AvatarInteractions.cs | 2 +- .../Assets/Scripts/Player/AvatarTransform.cs | 7 --- 9 files changed, 44 insertions(+), 135 deletions(-) delete mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs delete mode 100644 Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index ce218c123..622138b0a 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -190,7 +190,7 @@ CapsuleCollider: m_Bits: 0 m_LayerOverridePriority: 0 m_IsTrigger: 0 - m_ProvidesContacts: 0 + m_ProvidesContacts: 1 m_Enabled: 1 serializedVersion: 2 m_Radius: 0.5 @@ -295,12 +295,12 @@ MonoBehaviour: SlerpPosition: 0 m_CollisionType: 1 m_CollisionDamage: 0 + m_DebugCollisions: 0 m_DebugDamage: 0 m_Colliders: - {fileID: 817796967242824188} - m_CollisionImpulseEntries: [] - m_MaxAngularVelocity: 30 - m_MaxVelocity: 30 + m_MaxAngularVelocity: 10 + m_MaxVelocity: 10 m_PlayerInput: {fileID: 4903152183366241606} m_AvatarInputs: {fileID: 8197190117666738524} m_AvatarInteractions: {fileID: 539700041658036575} @@ -413,8 +413,8 @@ MonoBehaviour: m_NetworkRigidbody: {fileID: -8100831418301897270} m_HoldTransform: {fileID: 3820763517226122587} m_InteractCollider: {fileID: 4881592427634173612} - m_MinTossForce: 5 - m_MaxTossForce: 10 + m_MinTossForce: 500 + m_MaxTossForce: 1000 --- !u!114 &4655812346339390596 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab index 2e0b8615e..abd3c6426 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -108,7 +108,7 @@ BoxCollider: m_Bits: 0 m_LayerOverridePriority: 0 m_IsTrigger: 0 - m_ProvidesContacts: 0 + m_ProvidesContacts: 1 m_Enabled: 1 serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} @@ -125,7 +125,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 2069120471 + GlobalObjectIdHash: 4270425062 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 3 @@ -210,9 +210,9 @@ MonoBehaviour: SyncRotAngleX: 1 SyncRotAngleY: 1 SyncRotAngleZ: 1 - SyncScaleX: 1 - SyncScaleY: 1 - SyncScaleZ: 1 + SyncScaleX: 0 + SyncScaleY: 0 + SyncScaleZ: 0 PositionThreshold: 0.001 RotAngleThreshold: 0.01 ScaleThreshold: 0.01 @@ -223,11 +223,12 @@ MonoBehaviour: Interpolate: 1 SlerpPosition: 0 m_CollisionType: 2 - m_CollisionDamage: 0 + m_CollisionDamage: 5 + m_DebugCollisions: 0 m_DebugDamage: 0 m_Colliders: - {fileID: 7690746213975220858} - m_CollisionImpulseEntries: [] - m_MaxAngularVelocity: 30 - m_MaxVelocity: 30 + m_MaxAngularVelocity: 10 + m_MaxVelocity: 5 m_StartingHealth: 100 + m_IntangibleDurationAfterDamage: 2 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs index e0c7c413e..fe990d876 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs @@ -10,38 +10,37 @@ class DestructibleObject : PhysicsObjectMotion [SerializeField] float m_StartingHealth = 100f; - NetworkVariable m_Initialized = new NetworkVariable(false); + [SerializeField] + float m_IntangibleDurationAfterDamage; + + float m_LastDamageTime; + + NetworkVariable m_Initialized = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); NetworkVariable m_Health = new NetworkVariable(0.0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); public override void OnNetworkSpawn() { - m_DebugCollisions = m_DebugDamage = true; base.OnNetworkSpawn(); InitializeDestructible(); gameObject.name = $"[NetworkObjectId-{NetworkObjectId}]{name}"; } - public override void OnNetworkDespawn() - { - base.OnNetworkDespawn(); - } - - void OnCollisionEnter(Collision other) - { - return; - } - protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) { - // perhaps add invincible frames? would be a neat showcase - Debug.Log(nameof(OnHandleCollision)); - + // Avatars don't damage destructible objects if (m_Health.Value == 0.0f || collisionMessage.GetCollisionType() == Physics.CollisionType.Avatar) { base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); return; } + + if (Time.realtimeSinceStartup - m_LastDamageTime < m_IntangibleDurationAfterDamage) + { + base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); + return; + } + var currentHealth = Mathf.Max(0.0f, m_Health.Value - collisionMessage.Damage); if (currentHealth == 0.0f) @@ -56,6 +55,7 @@ protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, else { m_Health.Value = currentHealth; + m_LastDamageTime = Time.realtimeSinceStartup; } base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs deleted file mode 100644 index 17decbb41..000000000 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using Unity.Netcode; -using Unity.Netcode.Components; -using UnityEngine; - -namespace Unity.Multiplayer.Samples.SocialHub.Gameplay -{ - class EnvironmentTransform : NetworkTransform, IOwnershipRequestable, IGameplayEventInvokable - { - public event Action OnNetworkObjectOwnershipRequestResponse; - - public event Action OnGameplayEvent; - - public override void OnNetworkSpawn() - { - base.OnNetworkSpawn(); - - NetworkObject.OnOwnershipRequested += OnOwnershipRequested; - NetworkObject.OnOwnershipRequestResponse += OnOwnershipRequestResponse; - } - - public override void OnNetworkDespawn() - { - if (NetworkObject) - { - NetworkObject.OnOwnershipRequested -= OnOwnershipRequested; - NetworkObject.OnOwnershipRequestResponse -= OnOwnershipRequestResponse; - } - - OnGameplayEvent?.Invoke(NetworkObject, GameplayEvent.Despawned); - } - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - base.OnOwnershipChanged(previous, current); - - OnGameplayEvent?.Invoke(NetworkObject, GameplayEvent.OwnershipChange); - } - - // note: invoked on owning client - bool OnOwnershipRequested(ulong clientRequesting) - { - // defaulting all ownership requests to true, as is the default for all ownership requests - // here, you'd introduce game-based logic to deny/approve requests - return true; - } - - // note: invoked on requesting client - void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponse) - { - OnNetworkObjectOwnershipRequestResponse?.Invoke(NetworkObject, ownershipRequestResponse); - } - } -} diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta deleted file mode 100644 index 9deeceee3..000000000 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/EnvironmentTransform.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e03d6beb668b4417984e204ab9e25342 \ No newline at end of file diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs index 0849ca816..a31af7c96 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs @@ -13,7 +13,6 @@ class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEve [SerializeField] CollisionType m_CollisionType; - public CollisionType CollisionType => m_CollisionType; [SerializeField] ushort m_CollisionDamage; @@ -25,6 +24,7 @@ class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEve protected NetworkRigidbody NetworkRigidbody { get; private set; } [Tooltip("Enables/Disables collision logging (based on per derived type)")] + [SerializeField] protected bool m_DebugCollisions; [Tooltip("Enables/Disables damage logging (based on per derived type)")] @@ -186,8 +186,6 @@ void HandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false [Rpc(SendTo.Authority, RequireOwnership = false)] public void HandleCollisionRpc(CollisionMessageInfo collisionMessage, RpcParams rpcParams = default) { - Debug.Log(nameof(HandleCollisionRpc)); - // If authority changes while this message is in flight, forward it to the new authority if (!HasAuthority) { @@ -240,6 +238,9 @@ protected virtual void OnContactEvent(ulong eventId, Vector3 averagedCollisionNo /// /// /// + /// To enable this callback to be triggered, make sure you enable the Provides Contacts toggle on your + /// desired + /// public void ContactEvent(ulong eventId, Vector3 averageNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) { if (!IsSpawned) @@ -302,7 +303,7 @@ void LogCollision(ref BaseObjectMotionHandler objectHit) var distance = Vector3.Distance(transform.position, objectHit.transform.position); Debug.Log($"[{Time.realtimeSinceStartup}][LocalCollision][{name}][collided with][{objectHit.name}][Collider:{name}][Distance: {distance}]" + - $"{OnLogCollision(ref objectHit)}."); + $"{OnLogCollision(ref objectHit)}.", this); } protected virtual string OnLogCollision(CollisionMessageInfo collisionMessage) @@ -318,7 +319,7 @@ protected void LogCollision(CollisionMessageInfo collisionMessage) } var additionalInfo = OnLogCollision(collisionMessage); - Debug.Log($"[{name}][++Damaged++][Client-{collisionMessage.TargetOwner}][{collisionMessage.GetCollisionType()}][Dmg:{collisionMessage.Damage}] {additionalInfo}"); + Debug.Log($"[{name}][++Damaged++][Client-{collisionMessage.TargetOwner}][{collisionMessage.GetCollisionType()}][Dmg:{collisionMessage.Damage}] {additionalInfo}", this); } /// @@ -340,7 +341,7 @@ void LogHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = fa var distStr = distance == -1.0f ? $"{collisionMessage.DestinationNetworkObjId} DNE!!" : $"Distance: {distance}"; Debug.Log($"[{collisionMessage.CollisionId}][{collisionMessage.Time}][CollisionMessage][IsLocal: {isLocal}][{name}][Src:{collisionMessage.Source}][Dest:{collisionMessage.Destination}]" + - $"[NObjId:{collisionMessage.DestinationNetworkObjId}][NBvrId:{collisionMessage.DestinationBehaviourId}][{distStr}]{OnLogHandleCollision(ref collisionMessage)}."); + $"[NObjId:{collisionMessage.DestinationNetworkObjId}][NBvrId:{collisionMessage.DestinationBehaviourId}][{distStr}]{OnLogHandleCollision(ref collisionMessage)}.", this); } protected void LogMessage(string msg, bool forceMessage = false, float messageTime = 10.0f) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs index d5d6810ee..336cee59d 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs @@ -9,17 +9,6 @@ namespace Unity.Multiplayer.Samples.SocialHub.Physics { class PhysicsObjectMotion : BaseObjectMotionHandler { - [Serializable] - public struct CollisionImpulseMultiplierEntry - { - public CollisionType CollisionType; - public float MaxCollisionForce; - } - - [SerializeField] - List m_CollisionImpulseEntries; - Dictionary m_CollisionImpulseTable; - [SerializeField] float m_MaxAngularVelocity = 30; [SerializeField] @@ -38,23 +27,6 @@ public struct CollisionImpulseMultiplierEntry protected NetworkVariable m_Torque = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); protected NetworkVariable m_Force = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - protected override void Awake() - { - base.Awake(); - m_CollisionImpulseTable = new Dictionary(); - foreach (var entry in m_CollisionImpulseEntries) - { - if (!m_CollisionImpulseTable.ContainsKey(entry.CollisionType)) - { - m_CollisionImpulseTable.Add(entry.CollisionType, entry); - } - else - { - Debug.LogWarning($"[Duplicate Entry] A duplicate {nameof(CollisionImpulseMultiplierEntry)} of type {entry.CollisionType} was detected! Ignoring entry."); - } - } - } - protected override Vector3 OnGetObjectVelocity(bool getReference = false) { if (getReference) @@ -287,18 +259,16 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN var thisVelocity = (!Rigidbody.isKinematic ? Rigidbody.linearVelocity.sqrMagnitude : GetObjectVelocity().sqrMagnitude) * 0.5f; var otherVelocity = (!collidingBody.isKinematic ? collidingBody.linearVelocity.sqrMagnitude : collidingBodyPhys.GetObjectVelocity().sqrMagnitude) * 0.5f; - var thisKineticForce = (Rigidbody.mass / collidingBody.mass) * -collisionNormal * thisVelocity; - var otherKineticForce = (collidingBody.mass / Rigidbody.mass) * collisionNormal * otherVelocity; + var thisKineticForce = (Rigidbody.mass/* / collidingBody.mass*/) * -collisionNormal * thisVelocity; + var otherKineticForce = (collidingBody.mass/* / Rigidbody.mass*/) * collisionNormal * otherVelocity; if (!Rigidbody.isKinematic && collidingBody.isKinematic && thisVelocity > 0.01f) { - // our non-kinematic Rigidbody is moving with physics and hit a still kinematic Rigidbody - m_CollisionMessage.CollisionForce = thisKineticForce; m_CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); if (m_DebugCollisions) { - Debug.Log($"[{name}][SecondBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(thisKineticForce)} to {collidingBody.name}."); + Debug.Log($"[{name}][SecondBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(thisKineticForce)} to {collidingBody.name}.", this); } // Send collision to owner of kinematic body @@ -306,14 +276,14 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN } else if (Rigidbody.isKinematic && !collidingBody.isKinematic && otherVelocity > 0.01f) { - // our still, kinematic Rigidbody was hit by a non-kinematic physics-moving Rigidbody + // our kinematic Rigidbody was hit by a non-kinematic physics-moving Rigidbody collidingBodyPhys.m_CollisionMessage.CollisionForce = otherKineticForce; collidingBodyPhys.m_CollisionMessage.SetFlag(true, (uint)CollisionCategoryFlags.CollisionForce); collidingBodyPhys.EventCollision(averagedCollisionNormal, this); if (m_DebugCollisions) { - Debug.Log($"[{collidingBodyPhys.name}][FirstBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(otherKineticForce)} to {name}."); + Debug.Log($"[{collidingBodyPhys.name}][FirstBody][Collision Stay: {hasCollisionStay}] Sending impulse thrust {MathUtils.GetVector3Values(otherKineticForce)} to {name}.", this); } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs index c1eb0d866..e5daee9a8 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarInteractions.cs @@ -224,7 +224,7 @@ void Toss(double holdDuration) // apply a force to the released object float timeHeldClamped = Mathf.Clamp((float)holdDuration, k_MinDurationHeld, k_MaxDurationHeld); float tossForce = Mathf.Lerp(m_MinTossForce, m_MaxTossForce, Mathf.Clamp(timeHeldClamped, 0f, 1f)); - heldRigidbody.AddForce(transform.forward * tossForce, ForceMode.VelocityChange); + heldRigidbody.AddForce(transform.forward * tossForce, ForceMode.Impulse); } } } diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 3f96cbfb2..2b4405713 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -24,8 +24,6 @@ public override void OnNetworkSpawn() gameObject.name = $"[Client-{OwnerClientId}]{name}"; - m_DebugCollisions = m_DebugDamage = true; - if (!HasAuthority) { return; @@ -73,10 +71,5 @@ void Update() m_PhysicsPlayerController.SetMovement(movement); m_PhysicsPlayerController.SetSprint(m_AvatarInputs.Sprint); } - - void OnCollisionEnter(Collision other) - { - return; - } } } From 38e750a10d61f220755be4b09b19630b2f7f892f Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Thu, 29 Aug 2024 14:18:35 -0400 Subject: [PATCH 12/13] routing damage message for locally owned non-kinematic pairs --- .../Scripts/Gameplay/DestructibleObject.cs | 43 ++++++++++++++++--- .../Physics/BaseObjectMotionHandler.cs | 4 ++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs index fe990d876..3ae64d0fa 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Gameplay/DestructibleObject.cs @@ -26,10 +26,39 @@ public override void OnNetworkSpawn() gameObject.name = $"[NetworkObjectId-{NetworkObjectId}]{name}"; } + protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) + { + var collidingBaseObjectMotion = collidingBody.GetComponent(); + var collidingBodyPhys = collidingBaseObjectMotion as PhysicsObjectMotion; + + // overriding this method to catch when a physics collision happens between two non-kinematic objects + if (!Rigidbody.isKinematic && !collidingBody.isKinematic && collidingBodyPhys != null && HasAuthority && collidingBodyPhys.HasAuthority) + { + var collisionMessageInfo = new CollisionMessageInfo(); + collisionMessageInfo.Damage = collidingBodyPhys.CollisionDamage; + collisionMessageInfo.SetFlag(true, (uint)collidingBodyPhys.CollisionType); + + // apply damage to this non-kinematic object + OnHandleCollision(collisionMessageInfo); + + collisionMessageInfo.Damage = CollisionDamage; + collisionMessageInfo.SetFlag(true, (uint)CollisionType); + + // this can be reworked to an interface, but for now this routes damage directly to another destructible + var destructible = collidingBodyPhys.GetComponent(); + // apply damage to other non-kinematic object + destructible.OnHandleCollision(collisionMessageInfo); + } + else + { + base.OnContactEvent(eventId, averagedCollisionNormal, collidingBody, contactPoint, hasCollisionStay, averagedCollisionStayNormal); + } + } + protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, bool isLocal = false, bool applyImmediately = false) { // Avatars don't damage destructible objects - if (m_Health.Value == 0.0f || collisionMessage.GetCollisionType() == Physics.CollisionType.Avatar) + if (m_Health.Value == 0.0f || collisionMessage.GetCollisionType() == CollisionType.Avatar) { base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); return; @@ -41,7 +70,14 @@ protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, return; } - var currentHealth = Mathf.Max(0.0f, m_Health.Value - collisionMessage.Damage); + ApplyCollisionDamage(collisionMessage.Damage); + + base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); + } + + void ApplyCollisionDamage(float damage) + { + var currentHealth = Mathf.Max(0.0f, m_Health.Value - damage); if (currentHealth == 0.0f) { @@ -50,15 +86,12 @@ protected override void OnHandleCollision(CollisionMessageInfo collisionMessage, m_Health.Value = currentHealth; NetworkObject.Despawn(); // TODO: Spawn VFX locally + send VFX message - return; } else { m_Health.Value = currentHealth; m_LastDamageTime = Time.realtimeSinceStartup; } - - base.OnHandleCollision(collisionMessage, isLocal, applyImmediately); } void InitializeDestructible() diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs index a31af7c96..376188097 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/BaseObjectMotionHandler.cs @@ -14,9 +14,13 @@ class BaseObjectMotionHandler : NetworkTransform, ICollisionHandler, IContactEve [SerializeField] CollisionType m_CollisionType; + internal CollisionType CollisionType => m_CollisionType; + [SerializeField] ushort m_CollisionDamage; + internal ushort CollisionDamage => m_CollisionDamage; + protected CollisionMessageInfo m_CollisionMessage = new CollisionMessageInfo(); protected Rigidbody Rigidbody { get; private set; } From f589cc18bb7cee09b359a0319b5b68da2409dafa Mon Sep 17 00:00:00 2001 From: Fernando Cortez Date: Thu, 29 Aug 2024 23:28:51 -0400 Subject: [PATCH 13/13] networkupdateloop usage, masses reconfigured, gravity constantly applied --- .../Assets/Prefabs/Avatar.prefab | 2 +- .../DistributableTransferableObject.prefab | 22 ++++++------- ...vatarPhysicsPlayerControllerSettings.asset | 4 +-- .../Scripts/Physics/PhysicsObjectMotion.cs | 4 +-- .../Physics/PhysicsPlayerController.cs | 10 ++---- .../Assets/Scripts/Player/AvatarTransform.cs | 31 ++++++++++++++----- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab index 622138b0a..9d1ff17f0 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/Avatar.prefab @@ -313,7 +313,7 @@ Rigidbody: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5478015027486214707} serializedVersion: 4 - m_Mass: 1 + m_Mass: 10 m_Drag: 0 m_AngularDrag: 0.05 m_CenterOfMass: {x: 0, y: 0, z: 0} diff --git a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab index abd3c6426..66374b06a 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab +++ b/Experimental/DistributedAuthoritySample/Assets/Prefabs/DistributableTransferableObject.prefab @@ -123,9 +123,9 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} - m_Name: - m_EditorClassIdentifier: - GlobalObjectIdHash: 4270425062 + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2069120471 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 3 @@ -144,7 +144,7 @@ Rigidbody: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 893974733110552042} serializedVersion: 4 - m_Mass: 100 + m_Mass: 25 m_Drag: 0 m_AngularDrag: 0.05 m_CenterOfMass: {x: 0, y: 0, z: 0} @@ -173,8 +173,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 54937e94f00ab46c8ae43b81027f342c, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: --- !u!114 &6689110374311511483 MonoBehaviour: m_ObjectHideFlags: 0 @@ -185,8 +185,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: UseRigidBodyForMotion: 1 AutoUpdateKinematicState: 1 AutoSetKinematicOnDespawn: 1 @@ -200,8 +200,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 496a933d305aa4e1c926bd7d19b42f46, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: AuthorityMode: 1 UseUnreliableDeltas: 0 SyncPositionX: 1 @@ -229,6 +229,6 @@ MonoBehaviour: m_Colliders: - {fileID: 7690746213975220858} m_MaxAngularVelocity: 10 - m_MaxVelocity: 5 + m_MaxVelocity: 10 m_StartingHealth: 100 m_IntangibleDurationAfterDamage: 2 diff --git a/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset index 21ca127e4..fb00037ce 100644 --- a/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset +++ b/Experimental/DistributedAuthoritySample/Assets/ScriptableObjects/AvatarPhysicsPlayerControllerSettings.asset @@ -17,7 +17,7 @@ MonoBehaviour: Acceleration: 50 DragCoefficient: 4 AirControlFactor: 0.5 - JumpImpusle: 7 + JumpImpusle: 80 CustomGravityMultiplier: 2 - RotationSpeed: 10 + RotationSpeed: 13 GroundCheckDistance: 1.1 diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs index 336cee59d..dcfa701db 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsObjectMotion.cs @@ -259,8 +259,8 @@ protected override void OnContactEvent(ulong eventId, Vector3 averagedCollisionN var thisVelocity = (!Rigidbody.isKinematic ? Rigidbody.linearVelocity.sqrMagnitude : GetObjectVelocity().sqrMagnitude) * 0.5f; var otherVelocity = (!collidingBody.isKinematic ? collidingBody.linearVelocity.sqrMagnitude : collidingBodyPhys.GetObjectVelocity().sqrMagnitude) * 0.5f; - var thisKineticForce = (Rigidbody.mass/* / collidingBody.mass*/) * -collisionNormal * thisVelocity; - var otherKineticForce = (collidingBody.mass/* / Rigidbody.mass*/) * collisionNormal * otherVelocity; + var thisKineticForce = (Rigidbody.mass / collidingBody.mass) * -collisionNormal * thisVelocity; + var otherKineticForce = (collidingBody.mass / Rigidbody.mass) * collisionNormal * otherVelocity; if (!Rigidbody.isKinematic && collidingBody.isKinematic && thisVelocity > 0.01f) { diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs index c42468779..df68b2b8a 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Physics/PhysicsPlayerController.cs @@ -20,7 +20,7 @@ class PhysicsPlayerController : MonoBehaviour bool m_Jump; bool m_Sprint; - void FixedUpdate() + internal void OnFixedUpdate() { if (m_Rigidbody != null && m_Rigidbody.isKinematic) { @@ -108,12 +108,8 @@ void ApplyDrag() void ApplyCustomGravity() { - // custom gravity - if (!m_IsGrounded) - { - var customGravity = UnityEngine.Physics.gravity * (m_PhysicsPlayerControllerSettings.CustomGravityMultiplier - 1); - m_Rigidbody.AddForce(customGravity, ForceMode.Acceleration); - } + var customGravity = UnityEngine.Physics.gravity * (m_PhysicsPlayerControllerSettings.CustomGravityMultiplier - 1); + m_Rigidbody.AddForce(customGravity, ForceMode.Acceleration); } public void SetMovement(Vector3 movement) diff --git a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs index 2b4405713..67b9e2b17 100644 --- a/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs +++ b/Experimental/DistributedAuthoritySample/Assets/Scripts/Player/AvatarTransform.cs @@ -2,12 +2,13 @@ using UnityEngine; using Unity.Multiplayer.Samples.SocialHub.Input; using Unity.Multiplayer.Samples.SocialHub.Physics; +using Unity.Netcode; using UnityEngine.InputSystem; namespace Unity.Multiplayer.Samples.SocialHub.Player { [RequireComponent(typeof(Rigidbody))] - class AvatarTransform : PhysicsObjectMotion + class AvatarTransform : PhysicsObjectMotion, INetworkUpdateSystem { [SerializeField] PlayerInput m_PlayerInput; @@ -43,6 +44,9 @@ public override void OnNetworkSpawn() transform.SetPositionAndRotation(position: spawnPosition, rotation: Quaternion.identity); Rigidbody.position = spawnPosition; Rigidbody.linearVelocity = Vector3.zero; + + this.RegisterNetworkUpdate(updateStage: NetworkUpdateStage.Update); + this.RegisterNetworkUpdate(updateStage: NetworkUpdateStage.FixedUpdate); } public override void OnNetworkDespawn() @@ -52,6 +56,8 @@ public override void OnNetworkDespawn() { m_AvatarInputs.Jumped -= OnJumped; } + + this.UnregisterAllNetworkUpdates(); } void OnJumped() @@ -59,17 +65,28 @@ void OnJumped() m_PhysicsPlayerController.SetJump(true); } - void Update() + void OnTransformUpdate() { - if (!IsSpawned || !HasAuthority) - { - return; - } - var movement = new Vector3(m_AvatarInputs.Move.x, 0, m_AvatarInputs.Move.y).normalized; m_PhysicsPlayerController.SetMovement(movement); m_PhysicsPlayerController.SetSprint(m_AvatarInputs.Sprint); } + + public void NetworkUpdate(NetworkUpdateStage updateStage) + { + switch (updateStage) + { + case NetworkUpdateStage.Update: + OnTransformUpdate(); + break; + case NetworkUpdateStage.FixedUpdate: + m_PhysicsPlayerController.OnFixedUpdate(); + break; + default: + throw new ArgumentOutOfRangeException(nameof(updateStage), updateStage, null); + } + + } } }