From 64680f7280b9b97f5565deb51e95c675a4d2d50f Mon Sep 17 00:00:00 2001 From: in0finite Date: Sun, 3 Jan 2021 14:23:18 +0100 Subject: [PATCH 01/39] initial ragdoll stuff --- Assets/RagdollBuilder.cs | 6 ++-- Assets/Scripts/Behaviours/Ped/Ped.cs | 5 +++ Assets/Scripts/Behaviours/PedManager.cs | 5 +++ Assets/Scripts/Behaviours/PedModel.cs | 41 ++++++++++++++++++++++++- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/Assets/RagdollBuilder.cs b/Assets/RagdollBuilder.cs index d79f33c51..718dc1894 100644 --- a/Assets/RagdollBuilder.cs +++ b/Assets/RagdollBuilder.cs @@ -280,7 +280,7 @@ void Cleanup() } } - void BuildBodies() + public void BuildBodies() { foreach (BoneInfo bone in bones) { @@ -289,7 +289,7 @@ void BuildBodies() } } - void BuildJoints() + public void BuildJoints() { foreach (BoneInfo bone in bones) { @@ -335,7 +335,7 @@ void CalculateMassRecurse(BoneInfo bone) bone.summedMass = mass; } - void CalculateMass() + public void CalculateMass() { // Calculate allChildMass by summing all bodies CalculateMassRecurse(rootBone); diff --git a/Assets/Scripts/Behaviours/Ped/Ped.cs b/Assets/Scripts/Behaviours/Ped/Ped.cs index 53e26fac3..5fa842166 100644 --- a/Assets/Scripts/Behaviours/Ped/Ped.cs +++ b/Assets/Scripts/Behaviours/Ped/Ped.cs @@ -207,6 +207,11 @@ void OnEnable () void OnDisable () { s_allPeds.Remove (this); + + if (this.PlayerModel != null) + { + this.PlayerModel.DetachRagdoll(); + } } diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index a6c5ca384..d3f63fdf3 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -55,6 +55,11 @@ public class PedManager : MonoBehaviour public float pedSyncRate = 10; + [Header("Ragdoll")] + + public float ragdollMass = 100f; + public float ragdollLifetime = 30f; + void Awake () { diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 0ee55589b..0a9c7abff 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -100,6 +100,8 @@ private readonly Dictionary _loadedAnims readonly Dictionary m_damageLevelPerBones = new Dictionary(); + private RagdollBuilder m_ragdollBuilder; + public class FrameAnimData { public Vector3 pos; @@ -332,7 +334,7 @@ void SetupRagdoll() m_damageLevelPerBones.Clear(); - RagdollBuilder rb = new RagdollBuilder + RagdollBuilder rb = m_ragdollBuilder = new RagdollBuilder { pelvis = this.RootFrame.transform, leftHips = this.L_Thigh.transform, @@ -350,6 +352,8 @@ void SetupRagdoll() jaw = this.Jaw.transform, }; + rb.totalMass = PedManager.Instance.ragdollMass; + rb.PrepareBones(); rb.OnWizardCreate(); @@ -378,6 +382,41 @@ void SetupRagdoll() } + public Transform DetachRagdoll() + { + if (null == m_ragdollBuilder) + return null; + + if (null == this.RootFrame) + return null; + + m_ragdollBuilder.BuildBodies(); + m_ragdollBuilder.BuildJoints(); + m_ragdollBuilder.CalculateMass(); + + m_ragdollBuilder = null; + + var ragdollTransform = this.RootFrame.transform; + + ragdollTransform.SetParent(null); + + // add velocity to ragdoll based on current ped's velocity + foreach (var rb in ragdollTransform.GetComponentsInChildren()) + { + rb.velocity = m_ped.Velocity; + } + + // change layer + ragdollTransform.gameObject.SetLayerRecursive(0); + + + + + Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + + return ragdollTransform; + } + public float GetAmountOfDamageForBone(Transform boneTransform, float baseDamageValue) { if (m_damageLevelPerBones.TryGetValue(boneTransform, out int damageLevel)) From d6d5d660cf87dfc63d7db4c9806cf6a76a2b8022 Mon Sep 17 00:00:00 2001 From: in0finite Date: Mon, 4 Jan 2021 01:28:58 +0100 Subject: [PATCH 02/39] wip on ragdoll --- Assets/Prefabs/GameManager.prefab | 5 ++++ Assets/Scripts/Behaviours/GameManager.cs | 2 ++ Assets/Scripts/Behaviours/Ped/Ped.cs | 2 +- Assets/Scripts/Behaviours/Ped/Ped_Damage.cs | 5 ++++ .../Behaviours/Ped/States/BaseScriptState.cs | 1 + Assets/Scripts/Behaviours/PedManager.cs | 3 +++ Assets/Scripts/Behaviours/PedModel.cs | 27 +++++++++++++++---- Assets/Scripts/Behaviours/Weapon.cs | 2 ++ Assets/Scripts/Utilities/Damageable.cs | 6 ++++- Assets/Scripts/Utilities/F.cs | 9 +++++++ 10 files changed, 55 insertions(+), 7 deletions(-) diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index 53c3b02d4..bf7c460d8 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -171,6 +171,11 @@ MonoBehaviour: AIOutOfRangeTimeout: 5 AIOutOfRangeDistance: 250 pedSyncRate: 20 + ragdollMass: 100 + ragdollLifetime: 90 + ragdollDrag: 0.05 + ragdollMaxDepenetrationVelocity: -1 + ragdollDamageForce: 50 --- !u!114 &114560248511158306 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Behaviours/GameManager.cs b/Assets/Scripts/Behaviours/GameManager.cs index ff48159d8..6a6a250a3 100644 --- a/Assets/Scripts/Behaviours/GameManager.cs +++ b/Assets/Scripts/Behaviours/GameManager.cs @@ -25,6 +25,8 @@ public class GameManager : MonoBehaviour { [SerializeField] [Range(5, 100)] int m_defaultPhysicsUpdateRate = 30; [SerializeField] [Range(5, 100)] int m_defaultPhysicsUpdateRateOnMobile = 20; + public static int DefaultLayerIndex => 0; + public Vector2 cursorSensitivity = new Vector2(2f, 2f); diff --git a/Assets/Scripts/Behaviours/Ped/Ped.cs b/Assets/Scripts/Behaviours/Ped/Ped.cs index 5fa842166..8bfb52a64 100644 --- a/Assets/Scripts/Behaviours/Ped/Ped.cs +++ b/Assets/Scripts/Behaviours/Ped/Ped.cs @@ -210,7 +210,7 @@ void OnDisable () if (this.PlayerModel != null) { - this.PlayerModel.DetachRagdoll(); + this.PlayerModel.DetachRagdoll(this.KillingDamageInfo); } } diff --git a/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs b/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs index 5a74a8e21..b58216998 100644 --- a/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs +++ b/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs @@ -16,6 +16,11 @@ public partial class Ped { public Bar HealthBar { get; private set; } + /// + /// Damage info that killed the ped. + /// + public DamageInfo KillingDamageInfo { get; set; } + void AwakeForDamage () diff --git a/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs b/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs index 0df96b7dd..80ad046ed 100644 --- a/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs +++ b/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs @@ -318,6 +318,7 @@ public virtual void OnDamaged(DamageInfo damageInfo) if (m_ped.Health <= 0) { + m_ped.KillingDamageInfo = damageInfo; Object.Destroy(m_ped.gameObject); } diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index d3f63fdf3..bf9a6d2ae 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -59,6 +59,9 @@ public class PedManager : MonoBehaviour public float ragdollMass = 100f; public float ragdollLifetime = 30f; + public float ragdollDrag = 0.05f; + public float ragdollMaxDepenetrationVelocity = 10f; + public float ragdollDamageForce = 4f; void Awake () diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 0a9c7abff..5f046dd7a 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -382,12 +382,12 @@ void SetupRagdoll() } - public Transform DetachRagdoll() + public Transform DetachRagdoll(DamageInfo damageInfo) { if (null == m_ragdollBuilder) return null; - if (null == this.RootFrame) + if (null == this.UnnamedFrame) return null; m_ragdollBuilder.BuildBodies(); @@ -396,18 +396,35 @@ public Transform DetachRagdoll() m_ragdollBuilder = null; - var ragdollTransform = this.RootFrame.transform; + var ragdollTransform = this.UnnamedFrame.transform; ragdollTransform.SetParent(null); - // add velocity to ragdoll based on current ped's velocity foreach (var rb in ragdollTransform.GetComponentsInChildren()) { + rb.drag = PedManager.Instance.ragdollDrag; + if (PedManager.Instance.ragdollMaxDepenetrationVelocity >= 0) + rb.maxDepenetrationVelocity = PedManager.Instance.ragdollMaxDepenetrationVelocity; + + // add velocity to ragdoll based on current ped's velocity rb.velocity = m_ped.Velocity; } + // apply force to a collider that was hit by a weapon + if (damageInfo != null && damageInfo.raycastHitTransform != null && damageInfo.damageType == DamageType.Bullet) + { + var c = damageInfo.raycastHitTransform.GetComponent(); + if (c != null && c.attachedRigidbody != null) + { + c.attachedRigidbody.AddForceAtPosition( + damageInfo.hitDirection * damageInfo.amount.SqrtOrZero() * PedManager.Instance.ragdollDamageForce, + damageInfo.hitPoint, + ForceMode.Impulse); + } + } + // change layer - ragdollTransform.gameObject.SetLayerRecursive(0); + ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex); diff --git a/Assets/Scripts/Behaviours/Weapon.cs b/Assets/Scripts/Behaviours/Weapon.cs index fd8ed0428..bfc56d322 100644 --- a/Assets/Scripts/Behaviours/Weapon.cs +++ b/Assets/Scripts/Behaviours/Weapon.cs @@ -713,9 +713,11 @@ public virtual void FireProjectile (Vector3 firePos, Vector3 fireDir, WeaponAtta { amount = this.Damage, raycastHitTransform = hit.collider.transform, + hitDirection = fireDir, hitPoint = hit.point, hitNormal = hit.normal, attacker = m_ped, + damageType = DamageType.Bullet, }); } diff --git a/Assets/Scripts/Utilities/Damageable.cs b/Assets/Scripts/Utilities/Damageable.cs index 06c734bd2..9109caf8c 100644 --- a/Assets/Scripts/Utilities/Damageable.cs +++ b/Assets/Scripts/Utilities/Damageable.cs @@ -10,6 +10,7 @@ public class DamageInfo public float amount = 0f; public string damageType = null; public Transform raycastHitTransform = null; + public Vector3 hitDirection = Vector3.forward; public Vector3 hitPoint = Vector3.zero; public Vector3 hitNormal = Vector3.up; public object attacker = null; @@ -20,7 +21,10 @@ public static class DamageType { public static readonly string Bullet = "Bullet", - Explosion = "Explosion"; + Explosion = "Explosion", + Gas = "Gas", + Flame = "Flame", + Melee = "Melee"; } public class Damageable : MonoBehaviour diff --git a/Assets/Scripts/Utilities/F.cs b/Assets/Scripts/Utilities/F.cs index 809feb47d..683c2c20d 100644 --- a/Assets/Scripts/Utilities/F.cs +++ b/Assets/Scripts/Utilities/F.cs @@ -92,6 +92,15 @@ public static int RoundToInt(this float f) return Mathf.RoundToInt (f); } + public static float SqrtOrZero(this float f) + { + if (float.IsNaN(f)) + return 0f; + if (f <= 0f) + return 0f; + return Mathf.Sqrt(f); + } + public static double DateTimeToUnixTimestamp(this DateTime dateTime) { return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - From 9a224c0ecae9641840676fbad3bbf8960af4d951 Mon Sep 17 00:00:00 2001 From: in0finite Date: Mon, 4 Jan 2021 22:08:51 +0100 Subject: [PATCH 03/39] remove additionally added colliders from ragdoll (jaw, neck box) --- Assets/RagdollBuilder.cs | 15 ++++++++++++--- Assets/Scripts/Behaviours/PedModel.cs | 13 ++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Assets/RagdollBuilder.cs b/Assets/RagdollBuilder.cs index 718dc1894..81db8dd09 100644 --- a/Assets/RagdollBuilder.cs +++ b/Assets/RagdollBuilder.cs @@ -5,6 +5,7 @@ using UnityEngine; using System.Collections; using System; +using System.Collections.Generic; #pragma warning disable 649 @@ -45,7 +46,7 @@ public class RagdollBuilder Vector3 worldForward = Vector3.forward; public bool flipForward = false; - class BoneInfo + public class BoneInfo { public string name; @@ -68,9 +69,14 @@ class BoneInfo public float summedMass;// The mass of this and all children bodies } - ArrayList bones; + List bones; + public List Bones => bones; + BoneInfo rootBone; + public List AdditionalColliders = new List(); + + string CheckConsistency() { PrepareBones(); @@ -139,7 +145,7 @@ public void PrepareBones() worldForward = pelvis.TransformDirection(forward); } - bones = new ArrayList(); + bones = new List(); rootBone = new BoneInfo(); rootBone.name = "Pelvis"; @@ -519,6 +525,9 @@ void AddHeadCollider() newBox.size = new Vector3(radius * 0.65f, 0.75f * breastBox.size.y, 0.5f * breastBox.size.z); newBox.center = breastBox.center + Vector3.right * (breastBox.size.x * 0.5f + newBox.size.x * 0.5f); + + AdditionalColliders.Add(jawSphere); + AdditionalColliders.Add(newBox); } } } diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 5f046dd7a..5a28ceb18 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -387,17 +387,24 @@ public Transform DetachRagdoll(DamageInfo damageInfo) if (null == m_ragdollBuilder) return null; - if (null == this.UnnamedFrame) + if (null == this.RootFrame) return null; + var ragdollTransform = this.RootFrame.transform; + + // remove colliders which are not part of ragdoll + foreach (var c in m_ragdollBuilder.AdditionalColliders) + { + Debug.Log($"removing collider on {c.name} because it is not one of ragdoll bones"); + Object.Destroy(c); + } + m_ragdollBuilder.BuildBodies(); m_ragdollBuilder.BuildJoints(); m_ragdollBuilder.CalculateMass(); m_ragdollBuilder = null; - var ragdollTransform = this.UnnamedFrame.transform; - ragdollTransform.SetParent(null); foreach (var rb in ragdollTransform.GetComponentsInChildren()) From aa95d082d90e40979f5b4775d087d749f8a2a9f6 Mon Sep 17 00:00:00 2001 From: in0finite Date: Mon, 4 Jan 2021 22:11:55 +0100 Subject: [PATCH 04/39] use continuous dynamic CollisionDetectionMode for ragdoll --- Assets/Prefabs/GameManager.prefab | 1 + Assets/Scripts/Behaviours/PedManager.cs | 1 + Assets/Scripts/Behaviours/PedModel.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index bf7c460d8..2fa2ff276 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -176,6 +176,7 @@ MonoBehaviour: ragdollDrag: 0.05 ragdollMaxDepenetrationVelocity: -1 ragdollDamageForce: 50 + ragdollCollisionDetectionMode: 2 --- !u!114 &114560248511158306 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index bf9a6d2ae..c253475f8 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -62,6 +62,7 @@ public class PedManager : MonoBehaviour public float ragdollDrag = 0.05f; public float ragdollMaxDepenetrationVelocity = 10f; public float ragdollDamageForce = 4f; + public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; void Awake () diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 5a28ceb18..3e452f559 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -412,6 +412,7 @@ public Transform DetachRagdoll(DamageInfo damageInfo) rb.drag = PedManager.Instance.ragdollDrag; if (PedManager.Instance.ragdollMaxDepenetrationVelocity >= 0) rb.maxDepenetrationVelocity = PedManager.Instance.ragdollMaxDepenetrationVelocity; + rb.collisionDetectionMode = PedManager.Instance.ragdollCollisionDetectionMode; // add velocity to ragdoll based on current ped's velocity rb.velocity = m_ped.Velocity; From 988e250981f04f56368450d4bf762bfabf3a77f2 Mon Sep 17 00:00:00 2001 From: in0finite Date: Mon, 4 Jan 2021 23:32:28 +0100 Subject: [PATCH 05/39] ... --- Assets/Scripts/Behaviours/PedModel.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 3e452f559..a66c79fe4 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -390,12 +390,11 @@ public Transform DetachRagdoll(DamageInfo damageInfo) if (null == this.RootFrame) return null; - var ragdollTransform = this.RootFrame.transform; + Transform ragdollTransform = this.RootFrame.transform; // remove colliders which are not part of ragdoll foreach (var c in m_ragdollBuilder.AdditionalColliders) { - Debug.Log($"removing collider on {c.name} because it is not one of ragdoll bones"); Object.Destroy(c); } @@ -406,7 +405,9 @@ public Transform DetachRagdoll(DamageInfo damageInfo) m_ragdollBuilder = null; ragdollTransform.SetParent(null); + ragdollTransform.name = "dead body " + m_ped.name; + // setup rigid bodies foreach (var rb in ragdollTransform.GetComponentsInChildren()) { rb.drag = PedManager.Instance.ragdollDrag; @@ -434,10 +435,7 @@ public Transform DetachRagdoll(DamageInfo damageInfo) // change layer ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex); - - - - Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + Object.Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); return ragdollTransform; } From 3a5e237e06adf76ef1e52b5d46e5dd44f534c78c Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 03:09:45 +0100 Subject: [PATCH 06/39] add button to remove all dead bodies --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 22 +++++++++++++++++++ .../Scripts/Behaviours/Ped/DeadBody.cs.meta | 11 ++++++++++ Assets/Scripts/Behaviours/PedModel.cs | 3 +++ Assets/Scripts/UI/PedsWindow.cs | 20 ++++++++++++----- 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 Assets/Scripts/Behaviours/Ped/DeadBody.cs create mode 100644 Assets/Scripts/Behaviours/Ped/DeadBody.cs.meta diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs new file mode 100644 index 000000000..13ff9931d --- /dev/null +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace SanAndreasUnity.Behaviours.Peds +{ + public class DeadBody : MonoBehaviour + { + private static List _deadBodies = new List(); + public static IEnumerable DeadBodies => _deadBodies; + public static int NumDeadBodies => _deadBodies.Count; + + private void OnEnable() + { + _deadBodies.Add(this); + } + + private void OnDisable() + { + _deadBodies.Remove(this); + } + } +} diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs.meta b/Assets/Scripts/Behaviours/Ped/DeadBody.cs.meta new file mode 100644 index 000000000..95cb8b293 --- /dev/null +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52246fc08ef54f047800aa1a2be91fd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index a66c79fe4..2881eb889 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -5,6 +5,7 @@ using SanAndreasUnity.Importing.Animation; using UnityEngine; using System.Linq; +using SanAndreasUnity.Behaviours.Peds; using SanAndreasUnity.Utilities; namespace SanAndreasUnity.Behaviours @@ -437,6 +438,8 @@ public Transform DetachRagdoll(DamageInfo damageInfo) Object.Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + ragdollTransform.gameObject.AddComponent(); + return ragdollTransform; } diff --git a/Assets/Scripts/UI/PedsWindow.cs b/Assets/Scripts/UI/PedsWindow.cs index 963d9db88..2344f8177 100644 --- a/Assets/Scripts/UI/PedsWindow.cs +++ b/Assets/Scripts/UI/PedsWindow.cs @@ -5,6 +5,7 @@ using SanAndreasUnity.Importing.Items; using SanAndreasUnity.Importing.Items.Definitions; using System.Linq; +using SanAndreasUnity.Behaviours.Peds; namespace SanAndreasUnity.UI { @@ -62,10 +63,12 @@ protected override void OnWindowGUI () if (NetUtils.IsServer) { - // button to kill all peds - if (GUILayout.Button ("Kill all peds", GUILayout.Width (100))) { + if (GUILayout.Button ("Kill all peds", GUILayout.Width (100))) KillAllPeds (); - } + + if (GUILayout.Button ("Remove all dead bodies", GUILayout.Width (180))) + RemoveAllDeadBodies (); + GUILayout.Space (5); } @@ -159,11 +162,18 @@ private Rect GetLayoutRect (float height) private static void KillAllPeds () { - - foreach (var p in Ped.AllPeds) { + foreach (var p in Ped.AllPeds) + { Destroy (p.gameObject); } + } + private static void RemoveAllDeadBodies () + { + foreach (var db in DeadBody.DeadBodies.ToList()) + { + Destroy (db.gameObject); + } } } From 003442d5b7cd8bba0b72818c5d21a0365c50242d Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 03:10:00 +0100 Subject: [PATCH 07/39] add num dead bodies to Misc stats --- Assets/Scripts/Stats/MiscStats.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Assets/Scripts/Stats/MiscStats.cs b/Assets/Scripts/Stats/MiscStats.cs index d9a21756c..8c4395959 100644 --- a/Assets/Scripts/Stats/MiscStats.cs +++ b/Assets/Scripts/Stats/MiscStats.cs @@ -2,6 +2,7 @@ using System.Linq; using UnityEngine; using SanAndreasUnity.Behaviours; +using SanAndreasUnity.Behaviours.Peds; using SanAndreasUnity.Behaviours.Vehicles; using SanAndreasUnity.Utilities; @@ -22,6 +23,7 @@ void OnStatGUI() sb.AppendFormat("num peds: {0}\n", Ped.NumPeds); sb.AppendFormat("num vehicles: {0}\n", Vehicle.NumVehicles); + sb.AppendFormat("num dead bodies: {0}\n", DeadBody.NumDeadBodies); sb.AppendFormat("num ped state changes received: {0}\n", Ped.NumStateChangesReceived); sb.AppendLine(); From c50bff84cd0ec8970c789ed333166c3c2aa423f8 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 03:28:14 +0100 Subject: [PATCH 08/39] add setting for dead body lifetime --- Assets/Scripts/Settings/MiscSettings.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Assets/Scripts/Settings/MiscSettings.cs b/Assets/Scripts/Settings/MiscSettings.cs index fb926b93b..c99265126 100644 --- a/Assets/Scripts/Settings/MiscSettings.cs +++ b/Assets/Scripts/Settings/MiscSettings.cs @@ -109,6 +109,15 @@ public class MiscSettings : MonoBehaviour { setValue = (value) => { PedManager.Instance.pedTurnSpeed = value; }, persistType = OptionsWindow.InputPersistType.OnStart, }; + OptionsWindow.FloatInput m_deadBodyLifetime = new OptionsWindow.FloatInput + { + description = "Dead body lifetime", + minValue = 0.5f, + maxValue = 300f, + getValue = () => PedManager.Instance.ragdollLifetime, + setValue = (value) => { PedManager.Instance.ragdollLifetime = value; }, + persistType = OptionsWindow.InputPersistType.OnStart, + }; @@ -118,6 +127,7 @@ void Awake () m_runInBackgroundInput, m_drawLineFromGunInput, m_enableCamera, m_displayFpsInput, m_pausePlayerSpawning, m_playerSpawnInterval, m_vehicleDetachedPartLifetime, + m_deadBodyLifetime, m_projectileReloadTime, m_turnSpeedInput, }; From 59097a00f22e7229aa8bab3cb3c9b334965da3c1 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 04:20:46 +0100 Subject: [PATCH 09/39] apply force on dead body when it is hit by weapon --- Assets/Prefabs/GameManager.prefab | 1 + Assets/Scripts/Behaviours/PedManager.cs | 1 + Assets/Scripts/Behaviours/PedModel.cs | 3 ++ Assets/Scripts/Behaviours/PushableByDamage.cs | 52 +++++++++++++++++++ .../Behaviours/PushableByDamage.cs.meta | 11 ++++ 5 files changed, 68 insertions(+) create mode 100644 Assets/Scripts/Behaviours/PushableByDamage.cs create mode 100644 Assets/Scripts/Behaviours/PushableByDamage.cs.meta diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index 2fa2ff276..572d764ec 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -176,6 +176,7 @@ MonoBehaviour: ragdollDrag: 0.05 ragdollMaxDepenetrationVelocity: -1 ragdollDamageForce: 50 + ragdollDamageForceWhenDetached: 20 ragdollCollisionDetectionMode: 2 --- !u!114 &114560248511158306 MonoBehaviour: diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index c253475f8..aedd87ff0 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -62,6 +62,7 @@ public class PedManager : MonoBehaviour public float ragdollDrag = 0.05f; public float ragdollMaxDepenetrationVelocity = 10f; public float ragdollDamageForce = 4f; + public float ragdollDamageForceWhenDetached = 4f; public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 2881eb889..d7f0a6693 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -439,6 +439,9 @@ public Transform DetachRagdoll(DamageInfo damageInfo) Object.Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); ragdollTransform.gameObject.AddComponent(); + ragdollTransform.gameObject.AddComponent(); + var pushableByDamage = ragdollTransform.gameObject.AddComponent(); + pushableByDamage.forceMultiplier = PedManager.Instance.ragdollDamageForceWhenDetached; return ragdollTransform; } diff --git a/Assets/Scripts/Behaviours/PushableByDamage.cs b/Assets/Scripts/Behaviours/PushableByDamage.cs new file mode 100644 index 000000000..262daed1b --- /dev/null +++ b/Assets/Scripts/Behaviours/PushableByDamage.cs @@ -0,0 +1,52 @@ +using SanAndreasUnity.Utilities; +using UnityEngine; + +namespace SanAndreasUnity.Behaviours +{ + public class PushableByDamage : MonoBehaviour + { + //public Rigidbody rigidBodyToPush; + public float forceMultiplier = 1; + private Damageable _damageable; + + + private void Awake() + { + // if (null == this.rigidBodyToPush) + // this.rigidBodyToPush = this.GetComponentOrThrow(); + + _damageable = this.GetComponentOrThrow(); + _damageable.OnDamageEvent.AddListener(this.OnDamaged); + } + + void OnDamaged() + { + if (!NetUtils.IsServer) + return; + + // if (null == this.rigidBodyToPush) + // return; + + DamageInfo damageInfo = _damageable.LastDamageInfo; + + if (damageInfo.damageType != DamageType.Bullet) + return; + + if (null == damageInfo.raycastHitTransform) + return; + + var c = damageInfo.raycastHitTransform.GetComponent(); + if (null == c) + return; + + var rb = c.attachedRigidbody; + if (null == rb) + return; + + rb.AddForceAtPosition( + damageInfo.hitDirection * damageInfo.amount.SqrtOrZero() * this.forceMultiplier, + damageInfo.hitPoint, + ForceMode.Impulse); + } + } +} diff --git a/Assets/Scripts/Behaviours/PushableByDamage.cs.meta b/Assets/Scripts/Behaviours/PushableByDamage.cs.meta new file mode 100644 index 000000000..84dc1c077 --- /dev/null +++ b/Assets/Scripts/Behaviours/PushableByDamage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4dafeb77b323d57489cc5b15183dc41b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From acae61657d3ddf8bcf3c3fb18768bf15defe4152 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 04:26:17 +0100 Subject: [PATCH 10/39] cleanup --- .../{Behaviours => Utilities}/PushableByDamage.cs | 12 ++---------- .../PushableByDamage.cs.meta | 0 2 files changed, 2 insertions(+), 10 deletions(-) rename Assets/Scripts/{Behaviours => Utilities}/PushableByDamage.cs (76%) rename Assets/Scripts/{Behaviours => Utilities}/PushableByDamage.cs.meta (100%) diff --git a/Assets/Scripts/Behaviours/PushableByDamage.cs b/Assets/Scripts/Utilities/PushableByDamage.cs similarity index 76% rename from Assets/Scripts/Behaviours/PushableByDamage.cs rename to Assets/Scripts/Utilities/PushableByDamage.cs index 262daed1b..b7b0388d8 100644 --- a/Assets/Scripts/Behaviours/PushableByDamage.cs +++ b/Assets/Scripts/Utilities/PushableByDamage.cs @@ -1,20 +1,15 @@ -using SanAndreasUnity.Utilities; -using UnityEngine; +using UnityEngine; -namespace SanAndreasUnity.Behaviours +namespace SanAndreasUnity.Utilities { public class PushableByDamage : MonoBehaviour { - //public Rigidbody rigidBodyToPush; public float forceMultiplier = 1; private Damageable _damageable; private void Awake() { - // if (null == this.rigidBodyToPush) - // this.rigidBodyToPush = this.GetComponentOrThrow(); - _damageable = this.GetComponentOrThrow(); _damageable.OnDamageEvent.AddListener(this.OnDamaged); } @@ -24,9 +19,6 @@ void OnDamaged() if (!NetUtils.IsServer) return; - // if (null == this.rigidBodyToPush) - // return; - DamageInfo damageInfo = _damageable.LastDamageInfo; if (damageInfo.damageType != DamageType.Bullet) diff --git a/Assets/Scripts/Behaviours/PushableByDamage.cs.meta b/Assets/Scripts/Utilities/PushableByDamage.cs.meta similarity index 100% rename from Assets/Scripts/Behaviours/PushableByDamage.cs.meta rename to Assets/Scripts/Utilities/PushableByDamage.cs.meta From 17f6aaeedada660c455d1760efb45b5b901e5ca1 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 05:18:47 +0100 Subject: [PATCH 11/39] peds are killed with a separate function ; ragdoll is detached only when peds are killed, not destroyed --- Assets/Scripts/Behaviours/Ped/Ped.cs | 5 ----- Assets/Scripts/Behaviours/Ped/Ped_Damage.cs | 22 +++++++++++++++++++ .../Behaviours/Ped/States/BaseScriptState.cs | 2 +- Assets/Scripts/UI/PedsWindow.cs | 2 +- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/Ped.cs b/Assets/Scripts/Behaviours/Ped/Ped.cs index 8bfb52a64..53e26fac3 100644 --- a/Assets/Scripts/Behaviours/Ped/Ped.cs +++ b/Assets/Scripts/Behaviours/Ped/Ped.cs @@ -207,11 +207,6 @@ void OnEnable () void OnDisable () { s_allPeds.Remove (this); - - if (this.PlayerModel != null) - { - this.PlayerModel.DetachRagdoll(this.KillingDamageInfo); - } } diff --git a/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs b/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs index b58216998..cc2a139d1 100644 --- a/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs +++ b/Assets/Scripts/Behaviours/Ped/Ped_Damage.cs @@ -21,6 +21,8 @@ public partial class Ped { /// public DamageInfo KillingDamageInfo { get; set; } + private bool m_alreadyKilled = false; + void AwakeForDamage () @@ -130,6 +132,26 @@ public void DisplayInflictedDamageMessage(float damageAmount) msg.Text = damageAmount.ToString(); } + public void Kill() + { + F.RunExceptionSafe(this.KillInternal); + } + + void KillInternal() + { + if (m_alreadyKilled) + return; + + m_alreadyKilled = true; + + if (this.PlayerModel != null) + { + this.PlayerModel.DetachRagdoll(this.KillingDamageInfo); + } + + Object.Destroy(this.gameObject); + } + } } diff --git a/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs b/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs index 80ad046ed..e904a19e2 100644 --- a/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs +++ b/Assets/Scripts/Behaviours/Ped/States/BaseScriptState.cs @@ -319,7 +319,7 @@ public virtual void OnDamaged(DamageInfo damageInfo) if (m_ped.Health <= 0) { m_ped.KillingDamageInfo = damageInfo; - Object.Destroy(m_ped.gameObject); + m_ped.Kill(); } // notify clients diff --git a/Assets/Scripts/UI/PedsWindow.cs b/Assets/Scripts/UI/PedsWindow.cs index 2344f8177..e2ebf6611 100644 --- a/Assets/Scripts/UI/PedsWindow.cs +++ b/Assets/Scripts/UI/PedsWindow.cs @@ -164,7 +164,7 @@ private static void KillAllPeds () { foreach (var p in Ped.AllPeds) { - Destroy (p.gameObject); + p.Kill(); } } From 75d9ca5f354998ddb84284c39306e007cc0a791e Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 05:56:39 +0100 Subject: [PATCH 12/39] when vehicle explodes, all peds inside are killed - this also fixes Unity crash --- Assets/Scripts/Behaviours/Vehicles/Vehicle_Damage.cs | 8 ++++++++ Assets/Scripts/Utilities/ExplosionForce.cs | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Behaviours/Vehicles/Vehicle_Damage.cs b/Assets/Scripts/Behaviours/Vehicles/Vehicle_Damage.cs index 7e3b6cc49..c49d5904c 100644 --- a/Assets/Scripts/Behaviours/Vehicles/Vehicle_Damage.cs +++ b/Assets/Scripts/Behaviours/Vehicles/Vehicle_Damage.cs @@ -207,6 +207,14 @@ private void ExplodeInternal() // assign explosion sound F.RunExceptionSafe(() => AssignExplosionSound(explosionGo)); + // kill all peds inside + foreach (Ped ped in this.Seats + .Select(s => s.OccupyingPed) + .Where(p => p != null) + .ToList()) + { + ped.Kill(); + } } public void DetachFrameDuringExplosion(string frameName, float mass, GameObject parentGo) diff --git a/Assets/Scripts/Utilities/ExplosionForce.cs b/Assets/Scripts/Utilities/ExplosionForce.cs index 7e629d6d7..b895b505a 100644 --- a/Assets/Scripts/Utilities/ExplosionForce.cs +++ b/Assets/Scripts/Utilities/ExplosionForce.cs @@ -16,8 +16,7 @@ public class ExplosionForce : MonoBehaviour private IEnumerator Start() { - // wait one frame because some explosions instantiate debris which should then - // be pushed by physics force + // wait one frame because some objects can be spawned right after the explosion yield return null; float multiplier = this.explosionMultiplier; From 8469f188626d33358dcf2b582d1bb09b0139ec93 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 18:21:57 +0100 Subject: [PATCH 13/39] use prefab to spawn dead body --- Assets/Prefabs/DeadBody.prefab | 95 +++++++++++++++++++++++ Assets/Prefabs/DeadBody.prefab.meta | 7 ++ Assets/Prefabs/GameManager.prefab | 2 + Assets/Scripts/Behaviours/Ped/DeadBody.cs | 10 +++ Assets/Scripts/Behaviours/PedManager.cs | 1 + Assets/Scripts/Behaviours/PedModel.cs | 17 ++-- 6 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 Assets/Prefabs/DeadBody.prefab create mode 100644 Assets/Prefabs/DeadBody.prefab.meta diff --git a/Assets/Prefabs/DeadBody.prefab b/Assets/Prefabs/DeadBody.prefab new file mode 100644 index 000000000..b7aca257f --- /dev/null +++ b/Assets/Prefabs/DeadBody.prefab @@ -0,0 +1,95 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2141754834917738923 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4130636948537856663} + - component: {fileID: 4038138864584441180} + - component: {fileID: 3458215582039164093} + - component: {fileID: 3928823046603185135} + - component: {fileID: 7017421174877670493} + m_Layer: 0 + m_Name: DeadBody + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4130636948537856663 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141754834917738923} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &4038138864584441180 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141754834917738923} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3} + m_Name: + m_EditorClassIdentifier: + serverOnly: 0 + localPlayerAuthority: 0 + m_AssetId: + m_SceneId: 3719402579 +--- !u!114 &3458215582039164093 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141754834917738923} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 52246fc08ef54f047800aa1a2be91fd2, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &3928823046603185135 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141754834917738923} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 62374ff6df2c74f9699075492ef7fdb9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_health: 0 + m_onDamage: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &7017421174877670493 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141754834917738923} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4dafeb77b323d57489cc5b15183dc41b, type: 3} + m_Name: + m_EditorClassIdentifier: + forceMultiplier: 1 diff --git a/Assets/Prefabs/DeadBody.prefab.meta b/Assets/Prefabs/DeadBody.prefab.meta new file mode 100644 index 000000000..40b4f910e --- /dev/null +++ b/Assets/Prefabs/DeadBody.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 14d22e60f4926f64cbd36f393fe11b9a +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index 572d764ec..b9e6f8e8c 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -171,6 +171,8 @@ MonoBehaviour: AIOutOfRangeTimeout: 5 AIOutOfRangeDistance: 250 pedSyncRate: 20 + ragdollPrefab: {fileID: 2141754834917738923, guid: 14d22e60f4926f64cbd36f393fe11b9a, + type: 3} ragdollMass: 100 ragdollLifetime: 90 ragdollDrag: 0.05 diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 13ff9931d..596a9599e 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using SanAndreasUnity.Utilities; using UnityEngine; namespace SanAndreasUnity.Behaviours.Peds @@ -9,6 +10,15 @@ public class DeadBody : MonoBehaviour public static IEnumerable DeadBodies => _deadBodies; public static int NumDeadBodies => _deadBodies.Count; + public PushableByDamage PushableByDamage { get; private set; } + + + private void Awake() + { + this.PushableByDamage = this.GetComponentOrThrow(); + this.PushableByDamage.forceMultiplier = PedManager.Instance.ragdollDamageForceWhenDetached; + } + private void OnEnable() { _deadBodies.Add(this); diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index aedd87ff0..0c5256a1d 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -57,6 +57,7 @@ public class PedManager : MonoBehaviour [Header("Ragdoll")] + public GameObject ragdollPrefab; public float ragdollMass = 100f; public float ragdollLifetime = 30f; public float ragdollDrag = 0.05f; diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index d7f0a6693..89e32f082 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -383,7 +383,7 @@ void SetupRagdoll() } - public Transform DetachRagdoll(DamageInfo damageInfo) + public GameObject DetachRagdoll(DamageInfo damageInfo) { if (null == m_ragdollBuilder) return null; @@ -406,7 +406,6 @@ public Transform DetachRagdoll(DamageInfo damageInfo) m_ragdollBuilder = null; ragdollTransform.SetParent(null); - ragdollTransform.name = "dead body " + m_ped.name; // setup rigid bodies foreach (var rb in ragdollTransform.GetComponentsInChildren()) @@ -436,14 +435,16 @@ public Transform DetachRagdoll(DamageInfo damageInfo) // change layer ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex); - Object.Destroy(ragdollTransform.gameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + GameObject ragdollGameObject = Object.Instantiate(PedManager.Instance.ragdollPrefab); + Object.Destroy(ragdollGameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + ragdollGameObject.name = "dead body " + m_ped.name; + ragdollTransform.SetParent(ragdollGameObject.transform); + ragdollGameObject.GetComponentOrThrow(); - ragdollTransform.gameObject.AddComponent(); - ragdollTransform.gameObject.AddComponent(); - var pushableByDamage = ragdollTransform.gameObject.AddComponent(); - pushableByDamage.forceMultiplier = PedManager.Instance.ragdollDamageForceWhenDetached; + if (Net.NetStatus.IsServer) + Net.NetManager.Spawn(ragdollGameObject); - return ragdollTransform; + return ragdollGameObject; } public float GetAmountOfDamageForBone(Transform boneTransform, float baseDamageValue) From 5c36e129ada8676591375cd4504494c3e0a76d45 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 19:29:03 +0100 Subject: [PATCH 14/39] add dead body to list of spawnable objects --- Assets/Prefabs/NetworkManager.prefab | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/Prefabs/NetworkManager.prefab b/Assets/Prefabs/NetworkManager.prefab index d8da275f0..3242b3d70 100644 --- a/Assets/Prefabs/NetworkManager.prefab +++ b/Assets/Prefabs/NetworkManager.prefab @@ -68,6 +68,7 @@ MonoBehaviour: - {fileID: 100010, guid: 2894e2899fe860745afbc810459e2cc2, type: 3} - {fileID: 100010, guid: 4f8c6e508a3f69243ab7b8813398b7ed, type: 3} - {fileID: 8038540346792760480, guid: 858b1226127ef9f4e8d16c9610e691b6, type: 3} + - {fileID: 2141754834917738923, guid: 14d22e60f4926f64cbd36f393fe11b9a, type: 3} --- !u!114 &4862460140142645991 MonoBehaviour: m_ObjectHideFlags: 0 From f9e320ce23dee8018002fc26a0f2b629ac270474 Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 19:30:14 +0100 Subject: [PATCH 15/39] move creation of dead body to it's own class --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 18 ++++++++++++++++++ Assets/Scripts/Behaviours/PedModel.cs | 11 +---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 596a9599e..08b0a36a7 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -28,5 +28,23 @@ private void OnDisable() { _deadBodies.Remove(this); } + + public static DeadBody Create(Transform ragdollTransform, Ped ped) + { + NetStatus.ThrowIfNotOnServer(); + + GameObject ragdollGameObject = Object.Instantiate(PedManager.Instance.ragdollPrefab); + DeadBody deadBody = ragdollGameObject.GetComponentOrThrow(); + + Object.Destroy(ragdollGameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); + + ragdollGameObject.name = "dead body " + ped.name; + + ragdollTransform.SetParent(ragdollGameObject.transform); + + NetManager.Spawn(ragdollGameObject); + + return deadBody; + } } } diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index 89e32f082..c8ec68da8 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -435,16 +435,7 @@ public GameObject DetachRagdoll(DamageInfo damageInfo) // change layer ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex); - GameObject ragdollGameObject = Object.Instantiate(PedManager.Instance.ragdollPrefab); - Object.Destroy(ragdollGameObject, PedManager.Instance.ragdollLifetime * Random.Range(0.85f, 1.15f)); - ragdollGameObject.name = "dead body " + m_ped.name; - ragdollTransform.SetParent(ragdollGameObject.transform); - ragdollGameObject.GetComponentOrThrow(); - - if (Net.NetStatus.IsServer) - Net.NetManager.Spawn(ragdollGameObject); - - return ragdollGameObject; + return DeadBody.Create(ragdollTransform, m_ped).gameObject; } public float GetAmountOfDamageForBone(Transform boneTransform, float baseDamageValue) From 8d400bfceb81d49d0b213e0c14b3ea4d2455d08a Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 21:09:25 +0100 Subject: [PATCH 16/39] syncing works --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 124 +++++++++++++++++++++- Assets/Scripts/Behaviours/PedModel.cs | 4 +- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 08b0a36a7..1e6a10f6e 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -1,10 +1,19 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using Mirror; +using SanAndreasUnity.Importing.Conversion; +using SanAndreasUnity.Importing.Items; +using SanAndreasUnity.Importing.Items.Definitions; +using SanAndreasUnity.Net; using SanAndreasUnity.Utilities; using UnityEngine; +using Object = UnityEngine.Object; +using Random = UnityEngine.Random; namespace SanAndreasUnity.Behaviours.Peds { - public class DeadBody : MonoBehaviour + public class DeadBody : NetworkBehaviour { private static List _deadBodies = new List(); public static IEnumerable DeadBodies => _deadBodies; @@ -12,6 +21,18 @@ public class DeadBody : MonoBehaviour public PushableByDamage PushableByDamage { get; private set; } + private Dictionary m_framesDict = new Dictionary(); + + [SyncVar] private int m_net_modelId; + + private class SyncDictionaryIntVector3 : SyncDictionary + { + } + + private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3(); + private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3(); + + private void Awake() { @@ -29,6 +50,67 @@ private void OnDisable() _deadBodies.Remove(this); } + public override void OnStartClient() + { + if (NetStatus.IsServer) + return; + + F.RunExceptionSafe(this.InitialClientOnlySetup); + } + + private void InitialClientOnlySetup() + { + // load ped model + + // apply initial bones sync data (because not all bones have rigid bodies) + + // apply initial ragdoll (rigid bodies) sync data - this should be done AFTER applying bones sync data + + + + + var def = Item.GetDefinition(m_net_modelId); + if (null == def) + { + Debug.LogError($"Failed to initialize dead body: ped definition not found by id {m_net_modelId}"); + return; + } + + this.gameObject.name = $"dead body {m_net_modelId} {def.ModelName}"; + + var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName); + var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default); + m_framesDict = frames.ToDictionary(f => f.BoneId, f => f.transform); + + // apply initial transformation data to bones (at the moment when ragdoll was detached) - this is needed because not all bones have rigid bodies + // attached, and so will not be moved/rotated by physics engine + + foreach (var pair in m_framesDict) + { + if (m_syncDictionaryBonePositions.TryGetValue(pair.Key, out Vector3 pos)) + pair.Value.localPosition = pos; + if (m_syncDictionaryBoneRotations.TryGetValue(pair.Key, out Vector3 rotation)) + pair.Value.localRotation = Quaternion.Euler(rotation); + } + + // register to dictionary callbacks + RegisterDictionaryCallback( + m_syncDictionaryBonePositions, + (tr, pos) => tr.localPosition = pos); + RegisterDictionaryCallback( + m_syncDictionaryBoneRotations, + (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); + } + + private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) + { + dict.Callback += (op, key, item) => F.RunExceptionSafe(() => + { + if (m_framesDict.TryGetValue(key, out Transform tr)) + action(tr, item); + }); + } + public static DeadBody Create(Transform ragdollTransform, Ped ped) { NetStatus.ThrowIfNotOnServer(); @@ -42,9 +124,47 @@ public static DeadBody Create(Transform ragdollTransform, Ped ped) ragdollTransform.SetParent(ragdollGameObject.transform); + deadBody.m_framesDict = ragdollTransform.GetComponentsInChildren() + .ToDictionary(f => f.BoneId, f => f.transform); + + deadBody.InitSyncVarsOnServer(ped); + NetManager.Spawn(ragdollGameObject); return deadBody; } + + private void InitSyncVarsOnServer(Ped ped) + { + m_net_modelId = ped.PedDef.Id; + + // assign initial bones transformations + foreach (var pair in m_framesDict) + { + m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.localPosition); + m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.localRotation.eulerAngles); + } + } + + private void Update() + { + if (NetStatus.IsServer) + { + foreach (var pair in m_framesDict) + { + Vector3 pos = pair.Value.localPosition; + Vector3 rotation = pair.Value.localRotation.eulerAngles; + + if (m_syncDictionaryBonePositions[pair.Key] != pos) + m_syncDictionaryBonePositions[pair.Key] = pos; + if (m_syncDictionaryBoneRotations[pair.Key] != rotation) + m_syncDictionaryBoneRotations[pair.Key] = rotation; + } + } + else + { + + } + } } } diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index c8ec68da8..e56fe36c9 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -383,7 +383,7 @@ void SetupRagdoll() } - public GameObject DetachRagdoll(DamageInfo damageInfo) + public DeadBody DetachRagdoll(DamageInfo damageInfo) { if (null == m_ragdollBuilder) return null; @@ -435,7 +435,7 @@ public GameObject DetachRagdoll(DamageInfo damageInfo) // change layer ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex); - return DeadBody.Create(ragdollTransform, m_ped).gameObject; + return DeadBody.Create(ragdollTransform, m_ped); } public float GetAmountOfDamageForBone(Transform boneTransform, float baseDamageValue) From 20100a34aa4ba7282922ccd15bbd1d1adcdb4d6e Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 21:32:20 +0100 Subject: [PATCH 17/39] add "dead body sync rate" setting --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 7 +++++++ Assets/Scripts/Behaviours/PedManager.cs | 1 + Assets/Scripts/Settings/NetSettings.cs | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 1e6a10f6e..0bd8d8d99 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -38,6 +38,8 @@ private void Awake() { this.PushableByDamage = this.GetComponentOrThrow(); this.PushableByDamage.forceMultiplier = PedManager.Instance.ragdollDamageForceWhenDetached; + + this.RefreshSyncRate(); } private void OnEnable() @@ -166,5 +168,10 @@ private void Update() } } + + public void RefreshSyncRate() + { + this.syncInterval = 1.0f / PedManager.Instance.ragdollSyncRate; + } } } diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index 0c5256a1d..d1e6899bd 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -65,6 +65,7 @@ public class PedManager : MonoBehaviour public float ragdollDamageForce = 4f; public float ragdollDamageForceWhenDetached = 4f; public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; + [Range(1, 60)] public float ragdollSyncRate = 20f; void Awake () diff --git a/Assets/Scripts/Settings/NetSettings.cs b/Assets/Scripts/Settings/NetSettings.cs index 80334aa69..a18208066 100644 --- a/Assets/Scripts/Settings/NetSettings.cs +++ b/Assets/Scripts/Settings/NetSettings.cs @@ -1,4 +1,5 @@ using SanAndreasUnity.Behaviours; +using SanAndreasUnity.Behaviours.Peds; using SanAndreasUnity.Behaviours.Vehicles; using SanAndreasUnity.UI; using SanAndreasUnity.Utilities; @@ -14,6 +15,15 @@ public class NetSettings : MonoBehaviour setValue = (value) => { ApplyPedSyncRate(value); }, persistType = OptionsWindow.InputPersistType.OnStart }; + OptionsWindow.FloatInput m_deadBodySyncRate = new OptionsWindow.FloatInput + { + description = "Dead body sync rate", + minValue = 1, + maxValue = 60, + getValue = () => PedManager.Instance.ragdollSyncRate, + setValue = ApplyDeadBodySyncRate, + persistType = OptionsWindow.InputPersistType.OnStart, + }; OptionsWindow.FloatInput m_vehicleSyncRate = new OptionsWindow.FloatInput ("Vehicle sync rate", 1, 60) { isAvailable = () => VehicleManager.Instance != null, @@ -69,6 +79,7 @@ private void Awake() { OptionsWindow.RegisterInputs ("NET", m_pedSyncRate, + m_deadBodySyncRate, m_vehicleSyncRate, m_syncVehicleTransformUsingSyncVars, m_syncVehiclesLinearVelocity, @@ -86,6 +97,13 @@ static void ApplyPedSyncRate(float syncRate) ped.ApplySyncRate(syncRate); } + static void ApplyDeadBodySyncRate(float syncRate) + { + PedManager.Instance.ragdollSyncRate = syncRate; + foreach (var deadBody in DeadBody.DeadBodies) + deadBody.RefreshSyncRate(); + } + static void ApplyVehicleSyncRate(float syncRate) { VehicleManager.Instance.vehicleSyncRate = syncRate; From 68413a5c37fab91b2efc7f24bafaab9cb820a7bd Mon Sep 17 00:00:00 2001 From: in0finite Date: Tue, 5 Jan 2021 22:58:47 +0100 Subject: [PATCH 18/39] sync velocity --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 32 ++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 0bd8d8d99..c0efd26fc 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -23,6 +23,8 @@ public class DeadBody : NetworkBehaviour private Dictionary m_framesDict = new Dictionary(); + private Dictionary m_rigidBodiesDict = new Dictionary(); + [SyncVar] private int m_net_modelId; private class SyncDictionaryIntVector3 : SyncDictionary @@ -31,6 +33,7 @@ private class SyncDictionaryIntVector3 : SyncDictionary private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3(); private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3(); + private SyncDictionaryIntVector3 m_syncDictionaryBoneVelocities = new SyncDictionaryIntVector3(); @@ -82,6 +85,7 @@ private void InitialClientOnlySetup() var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName); var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default); + m_framesDict = frames.ToDictionary(f => f.BoneId, f => f.transform); // apply initial transformation data to bones (at the moment when ragdoll was detached) - this is needed because not all bones have rigid bodies @@ -129,6 +133,13 @@ public static DeadBody Create(Transform ragdollTransform, Ped ped) deadBody.m_framesDict = ragdollTransform.GetComponentsInChildren() .ToDictionary(f => f.BoneId, f => f.transform); + foreach (var pair in deadBody.m_framesDict) + { + var rb = pair.Value.GetComponent(); + if (rb != null) + deadBody.m_rigidBodiesDict.Add(pair.Key, rb); + } + deadBody.InitSyncVarsOnServer(ped); NetManager.Spawn(ragdollGameObject); @@ -146,6 +157,12 @@ private void InitSyncVarsOnServer(Ped ped) m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.localPosition); m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.localRotation.eulerAngles); } + + // assign initial velocities + foreach (var pair in m_rigidBodiesDict) + { + m_syncDictionaryBoneVelocities.Add(pair.Key, pair.Value.velocity); + } } private void Update() @@ -162,10 +179,23 @@ private void Update() if (m_syncDictionaryBoneRotations[pair.Key] != rotation) m_syncDictionaryBoneRotations[pair.Key] = rotation; } + + foreach (var pair in m_rigidBodiesDict) + { + Vector3 velocity = pair.Value.velocity; + if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) + m_syncDictionaryBoneVelocities[pair.Key] = velocity; + } } else { - + // apply velocity on clients + foreach (var pair in m_syncDictionaryBoneVelocities) + { + int boneId = pair.Key; + if (m_framesDict.TryGetValue(boneId, out Transform tr)) + tr.position += pair.Value * Time.deltaTime; + } } } From 34175971ae6d8e7b92249232775c3444b14cd286 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 15:26:11 +0100 Subject: [PATCH 19/39] syncing is finally decent enough --- Assets/Prefabs/GameManager.prefab | 3 + Assets/Scripts/Behaviours/Ped/DeadBody.cs | 68 ++++++++++++++++++----- Assets/Scripts/Behaviours/PedManager.cs | 2 + Assets/Scripts/Behaviours/PedModel.cs | 1 + 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index b9e6f8e8c..8e5365e8d 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -180,6 +180,9 @@ MonoBehaviour: ragdollDamageForce: 50 ragdollDamageForceWhenDetached: 20 ragdollCollisionDetectionMode: 2 + ragdollSyncRate: 10 + ragdollPositionLerpFactor: 1 + ragdollRotationLerpFactor: 1 --- !u!114 &114560248511158306 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index c0efd26fc..22d16c913 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -83,10 +83,24 @@ private void InitialClientOnlySetup() this.gameObject.name = $"dead body {m_net_modelId} {def.ModelName}"; - var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName); - var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default); + // var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName); + // var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default); + var model = this.gameObject.GetOrAddComponent(); + model.Load(m_net_modelId); + + // build character joints - we need them to constraint the bones + model.RagdollBuilder.BuildBodies(); + foreach (var rb in this.transform.GetComponentsInChildren()) + { + rb.isKinematic = true; + rb.interpolation = RigidbodyInterpolation.Extrapolate; + } + model.RagdollBuilder.BuildJoints(); + + m_framesDict = model.Frames.ToDictionary(f => f.BoneId, f => f.transform); - m_framesDict = frames.ToDictionary(f => f.BoneId, f => f.transform); + Object.Destroy(model.AnimComponent); + Object.Destroy(model); // apply initial transformation data to bones (at the moment when ragdoll was detached) - this is needed because not all bones have rigid bodies // attached, and so will not be moved/rotated by physics engine @@ -100,12 +114,15 @@ private void InitialClientOnlySetup() } // register to dictionary callbacks + // RegisterDictionaryCallback( + // m_syncDictionaryBonePositions, + // (tr, pos) => tr.localPosition = pos); + // RegisterDictionaryCallback( + // m_syncDictionaryBoneRotations, + // (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); RegisterDictionaryCallback( - m_syncDictionaryBonePositions, - (tr, pos) => tr.localPosition = pos); - RegisterDictionaryCallback( - m_syncDictionaryBoneRotations, - (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); + m_syncDictionaryBoneVelocities, + (tr, velocity) => tr.GetComponent().velocity = tr.TransformVector(velocity)); } private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) @@ -182,20 +199,45 @@ private void Update() foreach (var pair in m_rigidBodiesDict) { - Vector3 velocity = pair.Value.velocity; + Vector3 velocity = pair.Value.transform.InverseTransformVector(pair.Value.velocity); if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) m_syncDictionaryBoneVelocities[pair.Key] = velocity; } } else { - // apply velocity on clients - foreach (var pair in m_syncDictionaryBoneVelocities) + foreach (var pair in m_framesDict) { int boneId = pair.Key; - if (m_framesDict.TryGetValue(boneId, out Transform tr)) - tr.position += pair.Value * Time.deltaTime; + Transform tr = pair.Value; + + // position + if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) + { + Vector3 targetPos = pos; + // if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 velocity)) + // { + // if (boneId == 0) // only root bone + // targetPos += velocity * this.syncInterval; + // } + + // lerp toward target position + tr.localPosition = Vector3.Lerp(tr.localPosition, targetPos, PedManager.Instance.ragdollPositionLerpFactor); + } + + // rotation + if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) + tr.localRotation = Quaternion.Lerp(tr.localRotation, Quaternion.Euler(rotation), PedManager.Instance.ragdollRotationLerpFactor); + } + + // apply velocity on clients + // foreach (var pair in m_syncDictionaryBoneVelocities) + // { + // int boneId = pair.Key; + // if (m_framesDict.TryGetValue(boneId, out Transform tr)) + // tr.position += pair.Value * Time.deltaTime; + // } } } diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index d1e6899bd..dceb659ba 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -66,6 +66,8 @@ public class PedManager : MonoBehaviour public float ragdollDamageForceWhenDetached = 4f; public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; [Range(1, 60)] public float ragdollSyncRate = 20f; + [Range(0, 1)] public float ragdollPositionLerpFactor = 0.8f; + [Range(0, 1)] public float ragdollRotationLerpFactor = 0.8f; void Awake () diff --git a/Assets/Scripts/Behaviours/PedModel.cs b/Assets/Scripts/Behaviours/PedModel.cs index e56fe36c9..54dd08152 100644 --- a/Assets/Scripts/Behaviours/PedModel.cs +++ b/Assets/Scripts/Behaviours/PedModel.cs @@ -102,6 +102,7 @@ private readonly Dictionary _loadedAnims readonly Dictionary m_damageLevelPerBones = new Dictionary(); private RagdollBuilder m_ragdollBuilder; + public RagdollBuilder RagdollBuilder => m_ragdollBuilder; public class FrameAnimData { From 506bca3fafbd7f6b784dff8911abc185620bf813 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 15:43:56 +0100 Subject: [PATCH 20/39] cleanup --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 9 +++++---- Assets/Scripts/Behaviours/PedManager.cs | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 22d16c913..ee123ecec 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -215,23 +215,24 @@ private void Update() if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) { Vector3 targetPos = pos; + + // predict position based on velocity and sync interval // if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 velocity)) // { // if (boneId == 0) // only root bone // targetPos += velocity * this.syncInterval; // } - // lerp toward target position - tr.localPosition = Vector3.Lerp(tr.localPosition, targetPos, PedManager.Instance.ragdollPositionLerpFactor); + tr.localPosition = targetPos; } // rotation if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - tr.localRotation = Quaternion.Lerp(tr.localRotation, Quaternion.Euler(rotation), PedManager.Instance.ragdollRotationLerpFactor); + tr.localRotation = Quaternion.Euler(rotation); } - // apply velocity on clients + // apply velocity on clients - this is done by rigid bodies ? // foreach (var pair in m_syncDictionaryBoneVelocities) // { // int boneId = pair.Key; diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index dceb659ba..d1e6899bd 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -66,8 +66,6 @@ public class PedManager : MonoBehaviour public float ragdollDamageForceWhenDetached = 4f; public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; [Range(1, 60)] public float ragdollSyncRate = 20f; - [Range(0, 1)] public float ragdollPositionLerpFactor = 0.8f; - [Range(0, 1)] public float ragdollRotationLerpFactor = 0.8f; void Awake () From a9e70bf7cc9e4fc50f5a0e59aa8145b87a9dee4b Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 16:51:30 +0100 Subject: [PATCH 21/39] cleanup --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 48 +++++++++++++++++------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index ee123ecec..d5878cf1e 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -122,7 +122,7 @@ private void InitialClientOnlySetup() // (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); RegisterDictionaryCallback( m_syncDictionaryBoneVelocities, - (tr, velocity) => tr.GetComponent().velocity = tr.TransformVector(velocity)); + (tr, receivedVelocity) => tr.GetComponent().velocity = GetReceivedVelocityAsWorld(tr, receivedVelocity)); } private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) @@ -178,7 +178,7 @@ private void InitSyncVarsOnServer(Ped ped) // assign initial velocities foreach (var pair in m_rigidBodiesDict) { - m_syncDictionaryBoneVelocities.Add(pair.Key, pair.Value.velocity); + m_syncDictionaryBoneVelocities.Add(pair.Key, GetVelocityForSending(pair.Value)); } } @@ -199,7 +199,7 @@ private void Update() foreach (var pair in m_rigidBodiesDict) { - Vector3 velocity = pair.Value.transform.InverseTransformVector(pair.Value.velocity); + Vector3 velocity = GetVelocityForSending(pair.Value); if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) m_syncDictionaryBoneVelocities[pair.Key] = velocity; } @@ -211,33 +211,40 @@ private void Update() int boneId = pair.Key; Transform tr = pair.Value; - // position + // rotation + if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) + tr.localRotation = Quaternion.Euler(rotation); + + // after rotation is applied, transform velocity to local space and predict position based on it if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) { Vector3 targetPos = pos; // predict position based on velocity and sync interval - // if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 velocity)) + // if (boneId == 0) // only for root bone // { - // if (boneId == 0) // only root bone - // targetPos += velocity * this.syncInterval; + // if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) + // { + // Vector3 localVelocity = GetReceivedVelocityAsLocal(tr, receivedVelocity); + // targetPos += localVelocity * this.syncInterval; + // } // } tr.localPosition = targetPos; } - // rotation - if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - tr.localRotation = Quaternion.Euler(rotation); - } // apply velocity on clients - this is done by rigid bodies ? // foreach (var pair in m_syncDictionaryBoneVelocities) // { // int boneId = pair.Key; + // Vector3 receivedVelocity = pair.Value; // if (m_framesDict.TryGetValue(boneId, out Transform tr)) - // tr.position += pair.Value * Time.deltaTime; + // { + // Vector3 localVelocity = GetReceivedVelocityAsLocal(tr, receivedVelocity); + // tr.localPosition += localVelocity * Time.deltaTime; + // } // } } } @@ -246,5 +253,22 @@ public void RefreshSyncRate() { this.syncInterval = 1.0f / PedManager.Instance.ragdollSyncRate; } + + private static Vector3 GetVelocityForSending(Rigidbody rb) + { + // it's better to send local velocity, because rotation of ragdoll can change very fast, and so + // will the world velocity + return rb.transform.InverseTransformVector(rb.velocity); + } + + private static Vector3 GetReceivedVelocityAsLocal(Transform tr, Vector3 receivedVelocity) + { + return receivedVelocity; + } + + private static Vector3 GetReceivedVelocityAsWorld(Transform tr, Vector3 receivedVelocity) + { + return tr.TransformVector(receivedVelocity); + } } } From 2d5d67fc55d2c6d13b6579df97624ada5f0d160a Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 17:44:47 +0100 Subject: [PATCH 22/39] cleanup --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index d5878cf1e..11fc11bbb 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Mirror; -using SanAndreasUnity.Importing.Conversion; using SanAndreasUnity.Importing.Items; using SanAndreasUnity.Importing.Items.Definitions; using SanAndreasUnity.Net; @@ -65,15 +63,6 @@ public override void OnStartClient() private void InitialClientOnlySetup() { - // load ped model - - // apply initial bones sync data (because not all bones have rigid bodies) - - // apply initial ragdoll (rigid bodies) sync data - this should be done AFTER applying bones sync data - - - - var def = Item.GetDefinition(m_net_modelId); if (null == def) { @@ -83,8 +72,6 @@ private void InitialClientOnlySetup() this.gameObject.name = $"dead body {m_net_modelId} {def.ModelName}"; - // var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName); - // var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default); var model = this.gameObject.GetOrAddComponent(); model.Load(m_net_modelId); @@ -102,9 +89,7 @@ private void InitialClientOnlySetup() Object.Destroy(model.AnimComponent); Object.Destroy(model); - // apply initial transformation data to bones (at the moment when ragdoll was detached) - this is needed because not all bones have rigid bodies - // attached, and so will not be moved/rotated by physics engine - + // apply initial transformation data to bones foreach (var pair in m_framesDict) { if (m_syncDictionaryBonePositions.TryGetValue(pair.Key, out Vector3 pos)) From 6b3e656ed7294e0f1077da551650b67145053dbc Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 17:47:45 +0100 Subject: [PATCH 23/39] extract SetVelocity() method --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 11fc11bbb..eff4a29b6 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -107,7 +107,7 @@ private void InitialClientOnlySetup() // (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); RegisterDictionaryCallback( m_syncDictionaryBoneVelocities, - (tr, receivedVelocity) => tr.GetComponent().velocity = GetReceivedVelocityAsWorld(tr, receivedVelocity)); + SetVelocity); } private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) @@ -255,5 +255,10 @@ private static Vector3 GetReceivedVelocityAsWorld(Transform tr, Vector3 received { return tr.TransformVector(receivedVelocity); } + + private static void SetVelocity(Transform tr, Vector3 receivedVelocity) + { + tr.GetComponent().velocity = GetReceivedVelocityAsWorld(tr, receivedVelocity); + } } } From 31d7d3c5dd99d8ad18b2b50294bdef80700cc325 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 17:50:58 +0100 Subject: [PATCH 24/39] apply initial velocities --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index eff4a29b6..0512cb701 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -89,13 +89,18 @@ private void InitialClientOnlySetup() Object.Destroy(model.AnimComponent); Object.Destroy(model); - // apply initial transformation data to bones + // apply initial sync data foreach (var pair in m_framesDict) { - if (m_syncDictionaryBonePositions.TryGetValue(pair.Key, out Vector3 pos)) - pair.Value.localPosition = pos; - if (m_syncDictionaryBoneRotations.TryGetValue(pair.Key, out Vector3 rotation)) - pair.Value.localRotation = Quaternion.Euler(rotation); + int boneId = pair.Key; + Transform tr = pair.Value; + + if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) + tr.localPosition = pos; + if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) + tr.localRotation = Quaternion.Euler(rotation); + if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) + SetVelocity(tr, receivedVelocity); } // register to dictionary callbacks From 38d3035044618e07fd171e53b36c2b519aeee9ea Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 18:32:59 +0100 Subject: [PATCH 25/39] use struct for storing info about bones --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 45 +++++++++++++++-------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 0512cb701..e6af8aeea 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -19,7 +19,19 @@ public class DeadBody : NetworkBehaviour public PushableByDamage PushableByDamage { get; private set; } - private Dictionary m_framesDict = new Dictionary(); + private struct BoneInfo + { + public BoneInfo(Transform transform) + { + this.Transform = transform; + this.Rigidbody = transform.GetComponent(); + } + + public Transform Transform { get; set; } + public Rigidbody Rigidbody { get; set; } + } + + private Dictionary m_framesDict = new Dictionary(); private Dictionary m_rigidBodiesDict = new Dictionary(); @@ -84,7 +96,7 @@ private void InitialClientOnlySetup() } model.RagdollBuilder.BuildJoints(); - m_framesDict = model.Frames.ToDictionary(f => f.BoneId, f => f.transform); + m_framesDict = model.Frames.ToDictionary(f => f.BoneId, f => new BoneInfo(f.transform)); Object.Destroy(model.AnimComponent); Object.Destroy(model); @@ -93,14 +105,15 @@ private void InitialClientOnlySetup() foreach (var pair in m_framesDict) { int boneId = pair.Key; - Transform tr = pair.Value; + BoneInfo boneInfo = pair.Value; + Transform tr = pair.Value.Transform; if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) tr.localPosition = pos; if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) tr.localRotation = Quaternion.Euler(rotation); if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) - SetVelocity(tr, receivedVelocity); + SetVelocity(boneInfo, receivedVelocity); } // register to dictionary callbacks @@ -115,12 +128,12 @@ private void InitialClientOnlySetup() SetVelocity); } - private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) + private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) { dict.Callback += (op, key, item) => F.RunExceptionSafe(() => { - if (m_framesDict.TryGetValue(key, out Transform tr)) - action(tr, item); + if (m_framesDict.TryGetValue(key, out BoneInfo boneInfo)) + action(boneInfo, item); }); } @@ -138,11 +151,11 @@ public static DeadBody Create(Transform ragdollTransform, Ped ped) ragdollTransform.SetParent(ragdollGameObject.transform); deadBody.m_framesDict = ragdollTransform.GetComponentsInChildren() - .ToDictionary(f => f.BoneId, f => f.transform); + .ToDictionary(f => f.BoneId, f => new BoneInfo(f.transform)); foreach (var pair in deadBody.m_framesDict) { - var rb = pair.Value.GetComponent(); + var rb = pair.Value.Rigidbody; if (rb != null) deadBody.m_rigidBodiesDict.Add(pair.Key, rb); } @@ -161,8 +174,8 @@ private void InitSyncVarsOnServer(Ped ped) // assign initial bones transformations foreach (var pair in m_framesDict) { - m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.localPosition); - m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.localRotation.eulerAngles); + m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.Transform.localPosition); + m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.Transform.localRotation.eulerAngles); } // assign initial velocities @@ -178,8 +191,8 @@ private void Update() { foreach (var pair in m_framesDict) { - Vector3 pos = pair.Value.localPosition; - Vector3 rotation = pair.Value.localRotation.eulerAngles; + Vector3 pos = pair.Value.Transform.localPosition; + Vector3 rotation = pair.Value.Transform.localRotation.eulerAngles; if (m_syncDictionaryBonePositions[pair.Key] != pos) m_syncDictionaryBonePositions[pair.Key] = pos; @@ -199,7 +212,7 @@ private void Update() foreach (var pair in m_framesDict) { int boneId = pair.Key; - Transform tr = pair.Value; + Transform tr = pair.Value.Transform; // rotation if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) @@ -261,9 +274,9 @@ private static Vector3 GetReceivedVelocityAsWorld(Transform tr, Vector3 received return tr.TransformVector(receivedVelocity); } - private static void SetVelocity(Transform tr, Vector3 receivedVelocity) + private static void SetVelocity(BoneInfo boneInfo, Vector3 receivedVelocity) { - tr.GetComponent().velocity = GetReceivedVelocityAsWorld(tr, receivedVelocity); + boneInfo.Rigidbody.velocity = GetReceivedVelocityAsWorld(boneInfo.Transform, receivedVelocity); } } } From 7990d25ed5d243cd1378e7c94fe73a39a9d4e58c Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 18:48:02 +0100 Subject: [PATCH 26/39] extract SetPosition() and SetRotation() --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index e6af8aeea..b1f4583bf 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -106,12 +106,11 @@ private void InitialClientOnlySetup() { int boneId = pair.Key; BoneInfo boneInfo = pair.Value; - Transform tr = pair.Value.Transform; if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) - tr.localPosition = pos; + SetPosition(boneInfo, pos); if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - tr.localRotation = Quaternion.Euler(rotation); + SetRotation(boneInfo, rotation); if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) SetVelocity(boneInfo, receivedVelocity); } @@ -212,11 +211,12 @@ private void Update() foreach (var pair in m_framesDict) { int boneId = pair.Key; - Transform tr = pair.Value.Transform; + BoneInfo boneInfo = pair.Value; + Transform tr = boneInfo.Transform; // rotation if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - tr.localRotation = Quaternion.Euler(rotation); + SetRotation(boneInfo, rotation); // after rotation is applied, transform velocity to local space and predict position based on it if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) @@ -233,7 +233,7 @@ private void Update() // } // } - tr.localPosition = targetPos; + SetPosition(boneInfo, targetPos); } } @@ -274,6 +274,16 @@ private static Vector3 GetReceivedVelocityAsWorld(Transform tr, Vector3 received return tr.TransformVector(receivedVelocity); } + private static void SetPosition(BoneInfo boneInfo, Vector3 receivedPosition) + { + boneInfo.Transform.localPosition = receivedPosition; + } + + private static void SetRotation(BoneInfo boneInfo, Vector3 receivedRotation) + { + boneInfo.Transform.localRotation = Quaternion.Euler(receivedRotation); + } + private static void SetVelocity(BoneInfo boneInfo, Vector3 receivedVelocity) { boneInfo.Rigidbody.velocity = GetReceivedVelocityAsWorld(boneInfo.Transform, receivedVelocity); From 2051451095b64507826290097bddde3c10e3bf90 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 20:59:36 +0100 Subject: [PATCH 27/39] fix commented code --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index b1f4583bf..07f738391 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -243,10 +243,13 @@ private void Update() // { // int boneId = pair.Key; // Vector3 receivedVelocity = pair.Value; - // if (m_framesDict.TryGetValue(boneId, out Transform tr)) + // if (m_framesDict.TryGetValue(boneId, out BoneInfo boneInfo)) // { - // Vector3 localVelocity = GetReceivedVelocityAsLocal(tr, receivedVelocity); - // tr.localPosition += localVelocity * Time.deltaTime; + // if (null == boneInfo.Rigidbody) // only for bones which don't have rigid body + // { + // Vector3 localVelocity = GetReceivedVelocityAsLocal(boneInfo.Transform, receivedVelocity); + // boneInfo.Transform.localPosition += localVelocity * Time.deltaTime; + // } // } // } } From de8439ad311718bcb91cb66c674c851b1aefb42c Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 21:00:02 +0100 Subject: [PATCH 28/39] add extension method --- Assets/Scripts/Utilities/F.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Assets/Scripts/Utilities/F.cs b/Assets/Scripts/Utilities/F.cs index 683c2c20d..1d5cf0d29 100644 --- a/Assets/Scripts/Utilities/F.cs +++ b/Assets/Scripts/Utilities/F.cs @@ -539,6 +539,14 @@ public static T RandomElement (this IList list) return list [UnityEngine.Random.Range(0, list.Count)]; } + public static void ForEach(this IEnumerable enumerable, System.Action action) + { + foreach (var element in enumerable) + { + action(element); + } + } + public static int RemoveDeadObjects (this List list) where T : UnityEngine.Object { return list.RemoveAll(item => null == item); From 9267660a9753da402d2b9d4f6b8fc672a9bb4699 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 21:02:12 +0100 Subject: [PATCH 29/39] configure interpolation in Inspector --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 2 +- Assets/Scripts/Behaviours/PedManager.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 07f738391..0dde7f81b 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -92,7 +92,7 @@ private void InitialClientOnlySetup() foreach (var rb in this.transform.GetComponentsInChildren()) { rb.isKinematic = true; - rb.interpolation = RigidbodyInterpolation.Extrapolate; + rb.interpolation = PedManager.Instance.ragdollInterpolationMode; } model.RagdollBuilder.BuildJoints(); diff --git a/Assets/Scripts/Behaviours/PedManager.cs b/Assets/Scripts/Behaviours/PedManager.cs index d1e6899bd..54b997df8 100644 --- a/Assets/Scripts/Behaviours/PedManager.cs +++ b/Assets/Scripts/Behaviours/PedManager.cs @@ -66,6 +66,7 @@ public class PedManager : MonoBehaviour public float ragdollDamageForceWhenDetached = 4f; public CollisionDetectionMode ragdollCollisionDetectionMode = CollisionDetectionMode.Discrete; [Range(1, 60)] public float ragdollSyncRate = 20f; + public RigidbodyInterpolation ragdollInterpolationMode = RigidbodyInterpolation.Extrapolate; void Awake () From 34b961378218267dc1d9278abe867ad94154fe8e Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 21:35:14 +0100 Subject: [PATCH 30/39] don't set rigid body to kinematic - it behaves a little better with high velocity --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 0dde7f81b..dacc526d0 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -91,7 +91,8 @@ private void InitialClientOnlySetup() model.RagdollBuilder.BuildBodies(); foreach (var rb in this.transform.GetComponentsInChildren()) { - rb.isKinematic = true; + rb.useGravity = false; + rb.detectCollisions = false; rb.interpolation = PedManager.Instance.ragdollInterpolationMode; } model.RagdollBuilder.BuildJoints(); From dcc65fa8c5e6bbda455bf2f06f70a39453940165 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 21:43:03 +0100 Subject: [PATCH 31/39] tried to use MovePosition()/MoveRotation(), but it doesn't work --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index dacc526d0..42bfddbc2 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -280,11 +280,22 @@ private static Vector3 GetReceivedVelocityAsWorld(Transform tr, Vector3 received private static void SetPosition(BoneInfo boneInfo, Vector3 receivedPosition) { + // if (boneInfo.Rigidbody != null) + // boneInfo.Rigidbody.MovePosition(boneInfo.Transform.TransformVector(receivedPosition)); + // else + // boneInfo.Transform.localPosition = receivedPosition; + boneInfo.Transform.localPosition = receivedPosition; } private static void SetRotation(BoneInfo boneInfo, Vector3 receivedRotation) { + // Quaternion localRotation = Quaternion.Euler(receivedRotation); + // if (boneInfo.Rigidbody != null) + // boneInfo.Rigidbody.MoveRotation(boneInfo.Transform.TransformRotation(localRotation)); + // else + // boneInfo.Transform.localRotation = localRotation; + boneInfo.Transform.localRotation = Quaternion.Euler(receivedRotation); } From c8b44837af541beb460470caae19a821e640d054 Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 22:16:51 +0100 Subject: [PATCH 32/39] fix comments --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 42bfddbc2..f4f024b4a 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -239,18 +239,15 @@ private void Update() } - // apply velocity on clients - this is done by rigid bodies ? + // apply velocity on clients - this is not done by kinematic rigid bodies // foreach (var pair in m_syncDictionaryBoneVelocities) // { // int boneId = pair.Key; // Vector3 receivedVelocity = pair.Value; // if (m_framesDict.TryGetValue(boneId, out BoneInfo boneInfo)) // { - // if (null == boneInfo.Rigidbody) // only for bones which don't have rigid body - // { // Vector3 localVelocity = GetReceivedVelocityAsLocal(boneInfo.Transform, receivedVelocity); // boneInfo.Transform.localPosition += localVelocity * Time.deltaTime; - // } // } // } } From 38e205efc43c3bbc8d0d1ece16f5be626f70b95b Mon Sep 17 00:00:00 2001 From: in0finite Date: Thu, 7 Jan 2021 23:21:28 +0100 Subject: [PATCH 33/39] found almost perfect solution --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index f4f024b4a..e28f9bb4a 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -89,13 +89,15 @@ private void InitialClientOnlySetup() // build character joints - we need them to constraint the bones model.RagdollBuilder.BuildBodies(); + //model.Frames.ForEach(f => f.gameObject.GetOrAddComponent()); foreach (var rb in this.transform.GetComponentsInChildren()) { rb.useGravity = false; rb.detectCollisions = false; + rb.maxAngularVelocity = 0; rb.interpolation = PedManager.Instance.ragdollInterpolationMode; } - model.RagdollBuilder.BuildJoints(); + //model.RagdollBuilder.BuildJoints(); m_framesDict = model.Frames.ToDictionary(f => f.BoneId, f => new BoneInfo(f.transform)); @@ -117,12 +119,12 @@ private void InitialClientOnlySetup() } // register to dictionary callbacks - // RegisterDictionaryCallback( - // m_syncDictionaryBonePositions, - // (tr, pos) => tr.localPosition = pos); - // RegisterDictionaryCallback( - // m_syncDictionaryBoneRotations, - // (tr, rotation) => tr.localRotation = Quaternion.Euler(rotation)); + RegisterDictionaryCallback( + m_syncDictionaryBonePositions, + SetPosition); + RegisterDictionaryCallback( + m_syncDictionaryBoneRotations, + SetRotation); RegisterDictionaryCallback( m_syncDictionaryBoneVelocities, SetVelocity); @@ -194,21 +196,24 @@ private void Update() Vector3 pos = pair.Value.Transform.localPosition; Vector3 rotation = pair.Value.Transform.localRotation.eulerAngles; - if (m_syncDictionaryBonePositions[pair.Key] != pos) + //if (m_syncDictionaryBonePositions[pair.Key] != pos) m_syncDictionaryBonePositions[pair.Key] = pos; - if (m_syncDictionaryBoneRotations[pair.Key] != rotation) + //if (m_syncDictionaryBoneRotations[pair.Key] != rotation) m_syncDictionaryBoneRotations[pair.Key] = rotation; } foreach (var pair in m_rigidBodiesDict) { Vector3 velocity = GetVelocityForSending(pair.Value); - if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) + //if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) m_syncDictionaryBoneVelocities[pair.Key] = velocity; } + + this.SetDirtyBit(ulong.MaxValue); } else { + /* foreach (var pair in m_framesDict) { int boneId = pair.Key; @@ -238,6 +243,7 @@ private void Update() } } + */ // apply velocity on clients - this is not done by kinematic rigid bodies // foreach (var pair in m_syncDictionaryBoneVelocities) From 4b20f5de34b118339899aba278799f0b3f871635 Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 00:18:46 +0100 Subject: [PATCH 34/39] ... --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index e28f9bb4a..6e4058627 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -87,9 +87,8 @@ private void InitialClientOnlySetup() var model = this.gameObject.GetOrAddComponent(); model.Load(m_net_modelId); - // build character joints - we need them to constraint the bones + // add rigid bodies - syncing looks smoother with them model.RagdollBuilder.BuildBodies(); - //model.Frames.ForEach(f => f.gameObject.GetOrAddComponent()); foreach (var rb in this.transform.GetComponentsInChildren()) { rb.useGravity = false; From 2451514db1d04aaba6d358b45ce31d9d7c8d506c Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 02:40:45 +0100 Subject: [PATCH 35/39] use custom serialization --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 159 ++++++++++++++-------- Assets/Scripts/Utilities/F.cs | 12 ++ 2 files changed, 112 insertions(+), 59 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 6e4058627..1c691e98e 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -35,15 +35,31 @@ public BoneInfo(Transform transform) private Dictionary m_rigidBodiesDict = new Dictionary(); - [SyncVar] private int m_net_modelId; + private int m_net_modelId; - private class SyncDictionaryIntVector3 : SyncDictionary + // private class SyncDictionaryIntVector3 : SyncDictionary + // { + // } + + // private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3(); + // private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3(); + // private SyncDictionaryIntVector3 m_syncDictionaryBoneVelocities = new SyncDictionaryIntVector3(); + + private struct BoneSyncData { + public byte boneId; + public Vector3 position; + public Vector3 rotation; + public Vector3 velocity; } - private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3(); - private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3(); - private SyncDictionaryIntVector3 m_syncDictionaryBoneVelocities = new SyncDictionaryIntVector3(); + // private class SyncListBoneData : SyncList + // { + // } + // + // private SyncListBoneData m_bonesSyncData = new SyncListBoneData(); + + private List m_bonesSyncData = new List(); @@ -104,29 +120,19 @@ private void InitialClientOnlySetup() Object.Destroy(model); // apply initial sync data - foreach (var pair in m_framesDict) - { - int boneId = pair.Key; - BoneInfo boneInfo = pair.Value; - - if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) - SetPosition(boneInfo, pos); - if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - SetRotation(boneInfo, rotation); - if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) - SetVelocity(boneInfo, receivedVelocity); - } + // first sync should've been done before calling this function + this.UpdateBonesAfterDeserialization((byte)m_bonesSyncData.Count); + + // foreach (var boneData in m_bonesSyncData) + // { + // if (m_framesDict.TryGetValue(boneData.boneId, out BoneInfo boneInfo)) + // { + // SetPosition(boneInfo, boneData.position); + // SetRotation(boneInfo, boneData.rotation); + // SetVelocity(boneInfo, boneData.velocity); + // } + // } - // register to dictionary callbacks - RegisterDictionaryCallback( - m_syncDictionaryBonePositions, - SetPosition); - RegisterDictionaryCallback( - m_syncDictionaryBoneRotations, - SetRotation); - RegisterDictionaryCallback( - m_syncDictionaryBoneVelocities, - SetVelocity); } private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) @@ -138,6 +144,72 @@ private void RegisterDictionaryCallback(SyncDictionary dict, System.A }); } + public override bool OnSerialize(NetworkWriter writer, bool initialState) + { + if (initialState) + writer.Write(m_net_modelId); + + writer.Write((byte)m_framesDict.Count); + + foreach (var pair in m_framesDict) + { + int boneId = pair.Key; + Transform tr = pair.Value.Transform; + + var boneSyncData = new BoneSyncData(); + boneSyncData.boneId = (byte)boneId; + boneSyncData.position = tr.localPosition; + boneSyncData.rotation = tr.localRotation.eulerAngles; + boneSyncData.velocity = m_rigidBodiesDict.TryGetValue(boneId, out Rigidbody rb) ? GetVelocityForSending(rb) : Vector3.zero; + + writer.Write(boneSyncData.boneId); + writer.Write(boneSyncData.position); + writer.Write(boneSyncData.rotation); + writer.Write(boneSyncData.velocity); + } + + return true; + } + + public override void OnDeserialize(NetworkReader reader, bool initialState) + { + if (initialState) + m_net_modelId = reader.ReadInt32(); + + byte count = reader.ReadByte(); + + m_bonesSyncData.EnsureCount(count); + + for (int i = 0; i < count; i++) + { + var boneSyncData = new BoneSyncData(); + boneSyncData.boneId = reader.ReadByte(); + boneSyncData.position = reader.ReadVector3(); + boneSyncData.rotation = reader.ReadVector3(); + boneSyncData.velocity = reader.ReadVector3(); + m_bonesSyncData[i] = boneSyncData; + } + + //Debug.Log($"deserialized, count {count}, initialState {initialState}, m_net_modelId {m_net_modelId}"); + + F.RunExceptionSafe(() => UpdateBonesAfterDeserialization(count)); + } + + private void UpdateBonesAfterDeserialization(byte count) + { + for (int i = 0; i < count; i++) + { + var boneSyncData = m_bonesSyncData[i]; + if (m_framesDict.TryGetValue(boneSyncData.boneId, out BoneInfo boneInfo)) + { + SetPosition(boneInfo, boneSyncData.position); + SetRotation(boneInfo, boneSyncData.rotation); + if (boneInfo.Rigidbody != null) + SetVelocity(boneInfo, boneSyncData.velocity); + } + } + } + public static DeadBody Create(Transform ragdollTransform, Ped ped) { NetStatus.ThrowIfNotOnServer(); @@ -171,44 +243,13 @@ public static DeadBody Create(Transform ragdollTransform, Ped ped) private void InitSyncVarsOnServer(Ped ped) { m_net_modelId = ped.PedDef.Id; - - // assign initial bones transformations - foreach (var pair in m_framesDict) - { - m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.Transform.localPosition); - m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.Transform.localRotation.eulerAngles); - } - - // assign initial velocities - foreach (var pair in m_rigidBodiesDict) - { - m_syncDictionaryBoneVelocities.Add(pair.Key, GetVelocityForSending(pair.Value)); - } } private void Update() { if (NetStatus.IsServer) { - foreach (var pair in m_framesDict) - { - Vector3 pos = pair.Value.Transform.localPosition; - Vector3 rotation = pair.Value.Transform.localRotation.eulerAngles; - - //if (m_syncDictionaryBonePositions[pair.Key] != pos) - m_syncDictionaryBonePositions[pair.Key] = pos; - //if (m_syncDictionaryBoneRotations[pair.Key] != rotation) - m_syncDictionaryBoneRotations[pair.Key] = rotation; - } - - foreach (var pair in m_rigidBodiesDict) - { - Vector3 velocity = GetVelocityForSending(pair.Value); - //if (m_syncDictionaryBoneVelocities[pair.Key] != velocity) - m_syncDictionaryBoneVelocities[pair.Key] = velocity; - } - - this.SetDirtyBit(ulong.MaxValue); + this.SetDirtyBit(1); } else { diff --git a/Assets/Scripts/Utilities/F.cs b/Assets/Scripts/Utilities/F.cs index 1d5cf0d29..9ffc74b75 100644 --- a/Assets/Scripts/Utilities/F.cs +++ b/Assets/Scripts/Utilities/F.cs @@ -532,6 +532,18 @@ public static bool AddIfNotPresent (this List list, T item) return false; } + public static void EnsureCount(this List list, int count) + { + if (list.Count < count) + { + int diff = count - list.Count; + for (int i = 0; i < diff; i++) + { + list.Add(default); + } + } + } + public static T RandomElement (this IList list) { if (list.Count < 1) From be97e40457d39ac2be8cd7b560168fb2683118ee Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 02:52:10 +0100 Subject: [PATCH 36/39] cleanup --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 82 ----------------------- 1 file changed, 82 deletions(-) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 1c691e98e..0fc56af37 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -37,14 +37,6 @@ public BoneInfo(Transform transform) private int m_net_modelId; - // private class SyncDictionaryIntVector3 : SyncDictionary - // { - // } - - // private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3(); - // private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3(); - // private SyncDictionaryIntVector3 m_syncDictionaryBoneVelocities = new SyncDictionaryIntVector3(); - private struct BoneSyncData { public byte boneId; @@ -53,12 +45,6 @@ private struct BoneSyncData public Vector3 velocity; } - // private class SyncListBoneData : SyncList - // { - // } - // - // private SyncListBoneData m_bonesSyncData = new SyncListBoneData(); - private List m_bonesSyncData = new List(); @@ -112,7 +98,6 @@ private void InitialClientOnlySetup() rb.maxAngularVelocity = 0; rb.interpolation = PedManager.Instance.ragdollInterpolationMode; } - //model.RagdollBuilder.BuildJoints(); m_framesDict = model.Frames.ToDictionary(f => f.BoneId, f => new BoneInfo(f.transform)); @@ -123,25 +108,6 @@ private void InitialClientOnlySetup() // first sync should've been done before calling this function this.UpdateBonesAfterDeserialization((byte)m_bonesSyncData.Count); - // foreach (var boneData in m_bonesSyncData) - // { - // if (m_framesDict.TryGetValue(boneData.boneId, out BoneInfo boneInfo)) - // { - // SetPosition(boneInfo, boneData.position); - // SetRotation(boneInfo, boneData.rotation); - // SetVelocity(boneInfo, boneData.velocity); - // } - // } - - } - - private void RegisterDictionaryCallback(SyncDictionary dict, System.Action action) - { - dict.Callback += (op, key, item) => F.RunExceptionSafe(() => - { - if (m_framesDict.TryGetValue(key, out BoneInfo boneInfo)) - action(boneInfo, item); - }); } public override bool OnSerialize(NetworkWriter writer, bool initialState) @@ -190,8 +156,6 @@ public override void OnDeserialize(NetworkReader reader, bool initialState) m_bonesSyncData[i] = boneSyncData; } - //Debug.Log($"deserialized, count {count}, initialState {initialState}, m_net_modelId {m_net_modelId}"); - F.RunExceptionSafe(() => UpdateBonesAfterDeserialization(count)); } @@ -251,52 +215,6 @@ private void Update() { this.SetDirtyBit(1); } - else - { - /* - foreach (var pair in m_framesDict) - { - int boneId = pair.Key; - BoneInfo boneInfo = pair.Value; - Transform tr = boneInfo.Transform; - - // rotation - if (m_syncDictionaryBoneRotations.TryGetValue(boneId, out Vector3 rotation)) - SetRotation(boneInfo, rotation); - - // after rotation is applied, transform velocity to local space and predict position based on it - if (m_syncDictionaryBonePositions.TryGetValue(boneId, out Vector3 pos)) - { - Vector3 targetPos = pos; - - // predict position based on velocity and sync interval - // if (boneId == 0) // only for root bone - // { - // if (m_syncDictionaryBoneVelocities.TryGetValue(boneId, out Vector3 receivedVelocity)) - // { - // Vector3 localVelocity = GetReceivedVelocityAsLocal(tr, receivedVelocity); - // targetPos += localVelocity * this.syncInterval; - // } - // } - - SetPosition(boneInfo, targetPos); - } - - } - */ - - // apply velocity on clients - this is not done by kinematic rigid bodies - // foreach (var pair in m_syncDictionaryBoneVelocities) - // { - // int boneId = pair.Key; - // Vector3 receivedVelocity = pair.Value; - // if (m_framesDict.TryGetValue(boneId, out BoneInfo boneInfo)) - // { - // Vector3 localVelocity = GetReceivedVelocityAsLocal(boneInfo.Transform, receivedVelocity); - // boneInfo.Transform.localPosition += localVelocity * Time.deltaTime; - // } - // } - } } public void RefreshSyncRate() From ebaa36fb1af4ccac78a5311acc777cda86dff6a2 Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 02:57:39 +0100 Subject: [PATCH 37/39] add "num bones in dead bodies" to misc stats --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 1 + Assets/Scripts/Stats/MiscStats.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index 0fc56af37..da57c4b36 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -32,6 +32,7 @@ public BoneInfo(Transform transform) } private Dictionary m_framesDict = new Dictionary(); + public int NumBones => m_framesDict.Count; private Dictionary m_rigidBodiesDict = new Dictionary(); diff --git a/Assets/Scripts/Stats/MiscStats.cs b/Assets/Scripts/Stats/MiscStats.cs index 8c4395959..45a090a7d 100644 --- a/Assets/Scripts/Stats/MiscStats.cs +++ b/Assets/Scripts/Stats/MiscStats.cs @@ -24,6 +24,7 @@ void OnStatGUI() sb.AppendFormat("num peds: {0}\n", Ped.NumPeds); sb.AppendFormat("num vehicles: {0}\n", Vehicle.NumVehicles); sb.AppendFormat("num dead bodies: {0}\n", DeadBody.NumDeadBodies); + sb.AppendFormat("num bones in dead bodies: {0}\n", DeadBody.DeadBodies.Sum(db => db.NumBones)); sb.AppendFormat("num ped state changes received: {0}\n", Ped.NumStateChangesReceived); sb.AppendLine(); From b7ab28fedfda849b0d3d88b4abe802ac12385792 Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 03:00:03 +0100 Subject: [PATCH 38/39] add "num rigid bodies in dead bodies" to misc stats --- Assets/Scripts/Behaviours/Ped/DeadBody.cs | 1 + Assets/Scripts/Stats/MiscStats.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Assets/Scripts/Behaviours/Ped/DeadBody.cs b/Assets/Scripts/Behaviours/Ped/DeadBody.cs index da57c4b36..bcd51cf7b 100644 --- a/Assets/Scripts/Behaviours/Ped/DeadBody.cs +++ b/Assets/Scripts/Behaviours/Ped/DeadBody.cs @@ -35,6 +35,7 @@ public BoneInfo(Transform transform) public int NumBones => m_framesDict.Count; private Dictionary m_rigidBodiesDict = new Dictionary(); + public int NumRigidBodies => m_rigidBodiesDict.Count; private int m_net_modelId; diff --git a/Assets/Scripts/Stats/MiscStats.cs b/Assets/Scripts/Stats/MiscStats.cs index 45a090a7d..8553191aa 100644 --- a/Assets/Scripts/Stats/MiscStats.cs +++ b/Assets/Scripts/Stats/MiscStats.cs @@ -25,6 +25,7 @@ void OnStatGUI() sb.AppendFormat("num vehicles: {0}\n", Vehicle.NumVehicles); sb.AppendFormat("num dead bodies: {0}\n", DeadBody.NumDeadBodies); sb.AppendFormat("num bones in dead bodies: {0}\n", DeadBody.DeadBodies.Sum(db => db.NumBones)); + sb.AppendFormat("num rigid bodies in dead bodies: {0}\n", DeadBody.DeadBodies.Sum(db => db.NumRigidBodies)); sb.AppendFormat("num ped state changes received: {0}\n", Ped.NumStateChangesReceived); sb.AppendLine(); From 206c67bc8d1ac042d5116a487174dadb15e2a39b Mon Sep 17 00:00:00 2001 From: in0finite Date: Fri, 8 Jan 2021 04:44:56 +0100 Subject: [PATCH 39/39] "request suicide" button will kill ped --- Assets/Scripts/Networking/PlayerRequests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Networking/PlayerRequests.cs b/Assets/Scripts/Networking/PlayerRequests.cs index 3b94a6265..49fe162b6 100644 --- a/Assets/Scripts/Networking/PlayerRequests.cs +++ b/Assets/Scripts/Networking/PlayerRequests.cs @@ -115,8 +115,11 @@ public void RequestSuicide() [Command] void CmdRequestSuicide() { - if (m_player.OwnedPed != null) - Destroy(m_player.OwnedPed.gameObject); + F.RunExceptionSafe(() => + { + if (m_player.OwnedPed != null) + m_player.OwnedPed.Kill(); + }); } public void RequestToDestroyMyVehicles() => this.CmdRequestToDestroyMyVehicles();