diff --git a/Assets/Prefabs/ActiveRagdollTemplate/ActiveRagdoll_Player.prefab b/Assets/Prefabs/ActiveRagdollTemplate/ActiveRagdoll_Player.prefab index 9bef08c..e548bbf 100644 --- a/Assets/Prefabs/ActiveRagdollTemplate/ActiveRagdoll_Player.prefab +++ b/Assets/Prefabs/ActiveRagdollTemplate/ActiveRagdoll_Player.prefab @@ -3168,44 +3168,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 67122c3deae63fc46aa427f277a4cf0c, type: 3} m_Name: m_EditorClassIdentifier: - RagdollDict: - keys: - - Root - - Body - - Head - - UpperRightArm - - LowerRightArm - - RightHand - - UpperLeftArm - - LowerLeftArm - - LeftHand - - UpperRightLeg - - LowerRightLeg - - RightFoot - - UpperLeftLeg - - LowerLeftLeg - - LeftFoot - values: - - {fileID: 4985531305610238155} - - {fileID: 2342578877390874844} - - {fileID: 8180284542250461611} - - {fileID: 5939825930290575603} - - {fileID: 2424591407695190332} - - {fileID: 7622080051543942553} - - {fileID: 1139281219103369986} - - {fileID: 2646510523600694781} - - {fileID: 5152617412082605911} - - {fileID: 6109431878821211215} - - {fileID: 6701170567278905216} - - {fileID: 7927863737550955148} - - {fileID: 7370826325351747278} - - {fileID: 2835265873350387129} - - {fileID: 6857027438714089387} rightHand: {fileID: 8342660944763911090} leftHand: {fileID: 8342660944763911089} centerOfMass: {fileID: 4185505338602700740} - grabRight: {fileID: 3016776706953809226} - grabLeft: {fileID: 308789990690968185} forwardIsCameraDirection: 1 moveSpeed: 10 turnSpeed: 5 @@ -3213,14 +3178,10 @@ MonoBehaviour: autoGetUpWhenPossible: 1 useStepPrediction: 1 balanceHeight: 2.5 - balanceStrength: 5000 - coreStrength: 1500 - limbStrength: 500 StepDuration: 0.2 StepHeight: 1.7 FeetMountForce: 25 reachSensitivity: 350 - armReachStiffness: 2000 canBeKnockoutByImpact: 1 requiredForceToBeKO: 20 canPunch: 1 @@ -3230,6 +3191,45 @@ MonoBehaviour: inAir: 0 punchingRight: 0 punchingLeft: 0 + cam: {fileID: 0} + jointHandler: + balanceStrength: 5000 + coreStrength: 1500 + limbStrength: 500 + armReachStiffness: 2000 + joints: + keys: + - Root + - Body + - Head + - UpperRightArm + - LowerRightArm + - RightHand + - UpperLeftArm + - LowerLeftArm + - LeftHand + - UpperRightLeg + - LowerRightLeg + - RightFoot + - UpperLeftLeg + - LowerLeftLeg + - LeftFoot + values: + - {fileID: 4985531305610238155} + - {fileID: 2342578877390874844} + - {fileID: 8180284542250461611} + - {fileID: 5939825930290575603} + - {fileID: 2424591407695190332} + - {fileID: 7622080051543942553} + - {fileID: 1139281219103369986} + - {fileID: 2646510523600694781} + - {fileID: 5152617412082605911} + - {fileID: 6109431878821211215} + - {fileID: 6701170567278905216} + - {fileID: 7927863737550955148} + - {fileID: 7370826325351747278} + - {fileID: 2835265873350387129} + - {fileID: 6857027438714089387} --- !u!1 &8342660944763911102 GameObject: m_ObjectHideFlags: 0 @@ -3471,7 +3471,6 @@ MonoBehaviour: m_EditorClassIdentifier: ragdollController: {fileID: 853821725901430288} Left: 1 - hasJoint: 0 --- !u!1 &8342660944763911103 GameObject: m_ObjectHideFlags: 0 @@ -3713,4 +3712,3 @@ MonoBehaviour: m_EditorClassIdentifier: ragdollController: {fileID: 853821725901430288} Left: 0 - hasJoint: 0 diff --git a/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs b/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs deleted file mode 100644 index 7954812..0000000 --- a/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEngine; - -internal class JointDriveHelper -{ - internal static JointDrive CreateJointDrive(float positionSpring) - { - JointDrive jointDrive = new JointDrive(); - jointDrive.positionSpring = positionSpring; - jointDrive.positionDamper = 0; - jointDrive.maximumForce = Mathf.Infinity; - return jointDrive; - } -} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs.meta b/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs.meta deleted file mode 100644 index c6df86c..0000000 --- a/Assets/Scripts/ActiveRagdoll/JointDriveHelper.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 328fd81864404eb59eafd2f159768096 -timeCreated: 1691903841 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollController.cs b/Assets/Scripts/ActiveRagdoll/RagdollController.cs index 02e51df..7b014e2 100644 --- a/Assets/Scripts/ActiveRagdoll/RagdollController.cs +++ b/Assets/Scripts/ActiveRagdoll/RagdollController.cs @@ -1,161 +1,72 @@ using System; using System.Collections; using System.Runtime.CompilerServices; +using ActiveRagdoll; using UnityEngine; using Utils; -public class RagdollController : MonoBehaviour, IInputListener +public class RagdollController : MonoBehaviour { - [SerializeField] private UDictionary RagdollDict = new UDictionary(); - - [SerializeField] private Rigidbody rightHand; - [SerializeField] private Rigidbody leftHand; - + [SerializeField] private RagdollJointHandler jointHandler; + [SerializeField] private RagdollImpactHandler impactHandler; + [SerializeField] private RagdollLocomotionController locomotionController; + [SerializeField] private bool forwardIsCameraDirection = true; [SerializeField] private Transform centerOfMass; - - [Header("Movement Properties")] public bool forwardIsCameraDirection = true; - public float moveSpeed = 10f; - public float turnSpeed = 6f; - public float jumpForce = 18f; - - public Vector2 MovementAxis { get; set; } = Vector2.zero; - public Vector2 AimAxis { get; set; } - public float JumpValue { get; set; } = 0; - public float GrabLeftValue { get; set; } = 0; - public float GrabRightValue { get; set; } = 0; - public bool PunchLeftValue { get; set; } - public bool PunchRightValue { get; set; } - - [Header("Balance Properties")] public bool autoGetUpWhenPossible = true; - public bool useStepPrediction = true; - public float balanceHeight = 2.5f; - public float balanceStrength = 5000f; - public float coreStrength = 1500f; - public float limbStrength = 500f; - - public float StepDuration = 0.2f; - public float StepHeight = 1.7f; - public float FeetMountForce = 25f; - + [SerializeField] private float turnSpeed = 6f; [Header("Reach Properties")] public float reachSensitivity = 25f; - public float armReachStiffness = 2000f; - - [Header("Actions")] public bool canBeKnockoutByImpact = true; - public float requiredForceToBeKO = 20f; - public bool canPunch = true; + [Header("Actions")] public bool canPunch = true; public float punchForce = 15f; - - private const string ROOT = "Root"; - private const string BODY = "Body"; - private const string HEAD = "Head"; - private const string UPPER_RIGHT_ARM = "UpperRightArm"; - private const string LOWER_RIGHT_ARM = "LowerRightArm"; - private const string UPPER_LEFT_ARM = "UpperLeftArm"; - private const string LOWER_LEFT_ARM = "LowerLeftArm"; - private const string UPPER_RIGHT_LEG = "UpperRightLeg"; - private const string LOWER_RIGHT_LEG = "LowerRightLeg"; - private const string UPPER_LEFT_LEG = "UpperLeftLeg"; - private const string LOWER_LEFT_LEG = "LowerLeftLeg"; - private const string RIGHT_FOOT = "RightFoot"; - private const string LEFT_FOOT = "LeftFoot"; - - //Hidden variables - private float timer; - private float Step_R_timer; - private float Step_L_timer; - private float MouseYAxisArms; - private float MouseXAxisArms; - private float MouseYAxisBody; - - private bool WalkForward; - private bool WalkBackward; - private bool StepRight; - private bool StepLeft; - private bool Alert_Leg_Right; - private bool Alert_Leg_Left; - private bool balanced = true; - private bool GettingUp; - private bool ResetPose; - private bool isRagdoll; - private bool isKeyDown; - private bool moveAxisUsed; - private bool jumpAxisUsed; - private bool reachLeftAxisUsed; - private bool reachRightAxisUsed; - - [HideInInspector] public bool jumping; - [HideInInspector] public bool isJumping; - [HideInInspector] public bool inAir; - [HideInInspector] public bool punchingRight; - [HideInInspector] public bool punchingLeft; - + private readonly RagdollInputHandler inputHandler = new(); + private readonly RagdollState ragdollState = new(); [SerializeField] private Camera cam; - private Vector3 Direction; - private Vector3 CenterOfMassPoint; - - private JointDrive BalanceOn; - private JointDrive PoseOn; - private JointDrive CoreStiffness; - private JointDrive ReachStiffness; - private JointDrive DriveOff; - - private Quaternion HeadTarget; - private Quaternion BodyTarget; - private Quaternion UpperRightArmTarget; - private Quaternion LowerRightArmTarget; - private Quaternion UpperLeftArmTarget; - private Quaternion LowerLeftArmTarget; - private Quaternion UpperRightLegTarget; - private Quaternion LowerRightLegTarget; - private Quaternion UpperLeftLegTarget; - private Quaternion LowerLeftLegTarget; - - private static int groundLayer; - private WaitForSeconds punchDelayWaitTime = new WaitForSeconds(0.3f); - - void Awake() + private Vector3 CenterOfMassPoint; //TODO: Check usage + private RagdollDefaultTargetState defaultTargetState; + private readonly WaitForSeconds punchDelayWaitTime = new(0.3f); + private Rigidbody RightHandRigidBody => jointHandler.GetRigidBodyFromJoint(RagdollParts.RIGHT_HAND); + private Rigidbody LeftHandRigidBody => jointHandler.GetRigidBodyFromJoint(RagdollParts.LEFT_HAND); + + private void Awake() { - //cam = Camera.main; - InputManager.Instance.RegisterListener(this); - groundLayer = LayerMask.NameToLayer("Ground"); - SetupJointDrives(); - SetupOriginalPose(); + inputHandler.Init(); + defaultTargetState = new RagdollDefaultTargetState(jointHandler); + locomotionController.Init(jointHandler, ragdollState, defaultTargetState); + SetupHandContacts(); + SetupFeetContacts(); + SetupRagdollImpactContacts(); } - private void SetupJointDrives() + private void SetupRagdollImpactContacts() { - BalanceOn = JointDriveHelper.CreateJointDrive(balanceStrength); - PoseOn = JointDriveHelper.CreateJointDrive(limbStrength); - CoreStiffness = JointDriveHelper.CreateJointDrive(coreStrength); - ReachStiffness = JointDriveHelper.CreateJointDrive(armReachStiffness); - DriveOff = JointDriveHelper.CreateJointDrive(25); + var impactContacts = GetComponentsInChildren(); + foreach (var impactContact in impactContacts) + { + impactContact.Init(impactHandler, locomotionController); + } } - private void SetupOriginalPose() + private void SetupHandContacts() { - BodyTarget = GetJointTargetRotation(ROOT); - HeadTarget = GetJointTargetRotation(HEAD); - UpperRightArmTarget = GetJointTargetRotation(UPPER_RIGHT_ARM); - LowerRightArmTarget = GetJointTargetRotation(LOWER_RIGHT_ARM); - UpperLeftArmTarget = GetJointTargetRotation(UPPER_LEFT_ARM); - LowerLeftArmTarget = GetJointTargetRotation(LOWER_LEFT_ARM); - UpperRightLegTarget = GetJointTargetRotation(UPPER_RIGHT_LEG); - LowerRightLegTarget = GetJointTargetRotation(LOWER_RIGHT_LEG); - UpperLeftLegTarget = GetJointTargetRotation(UPPER_LEFT_LEG); - LowerLeftLegTarget = GetJointTargetRotation(LOWER_LEFT_LEG); + var handContacts = GetComponentsInChildren(); + foreach (var handContact in handContacts) + { + handContact.Init(inputHandler, ragdollState); + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Quaternion GetJointTargetRotation(string jointName) + private void SetupFeetContacts() { - return RagdollDict[jointName].Joint.targetRotation; + var feetContacts = GetComponentsInChildren(); + foreach (var feetContact in feetContacts) + { + feetContact.Init(ragdollState); + } } private void Update() { - if (!inAir) + if (!ragdollState.inAir) { - PlayerMovement(); + locomotionController.PlayerMovement(forwardIsCameraDirection, inputHandler.MovementAxis); if (canPunch) { @@ -165,32 +76,28 @@ private void Update() PlayerReach(); - if (balanced && useStepPrediction) - { - PerformStepPrediction(); - UpdateCenterOfMass(); - } - - if (!useStepPrediction) - { - ResetWalkCycle(); - } + locomotionController.HandleStepPrediction(centerOfMass.transform.position.z); - GroundCheck(); + locomotionController.GroundCheck(); UpdateCenterOfMass(); } private void FixedUpdate() { - PerformWalking(); + locomotionController.PerformWalking(); PerformPlayerRotation(); ResetPlayerPose(); - PerformPlayerGetUpJumping(); + locomotionController.PerformPlayerGetUpJumping(inputHandler.JumpValue); } private void PerformPlayerRotation() { - ConfigurableJoint rootJoint = RagdollDict[ROOT].Joint; + if (!jointHandler.TryGetJointWithID(RagdollParts.ROOT, out var joint)) + { + return; + } + + ConfigurableJoint rootJoint = joint.Joint; if (forwardIsCameraDirection) { @@ -204,10 +111,10 @@ private void PerformPlayerRotation() //buffer all changes to quaternion before applying to memory location Quaternion rootJointTargetRotation = rootJoint.targetRotation; - if (MovementAxis.x != 0) + if (inputHandler.MovementAxis.x != 0) { rootJointTargetRotation = Quaternion.Lerp(rootJointTargetRotation, - rootJointTargetRotation.DisplaceY(-MovementAxis.x * turnSpeed), + rootJointTargetRotation.DisplaceY(-inputHandler.MovementAxis.x * turnSpeed), 6 * Time.fixedDeltaTime); } @@ -227,362 +134,98 @@ private void PerformPlayerRotation() private void ResetPlayerPose() { - if (ResetPose && !jumping) - { - RagdollDict[BODY].Joint.targetRotation = BodyTarget; - RagdollDict[UPPER_RIGHT_ARM].Joint.targetRotation = UpperRightArmTarget; - RagdollDict[LOWER_RIGHT_ARM].Joint.targetRotation = LowerRightArmTarget; - RagdollDict[UPPER_LEFT_ARM].Joint.targetRotation = UpperLeftArmTarget; - RagdollDict[LOWER_LEFT_ARM].Joint.targetRotation = LowerLeftArmTarget; - - MouseYAxisArms = 0; - ResetPose = false; - } + if (!locomotionController.resetPose || ragdollState.jumping) + return; + + jointHandler.GetConfigurableJointWithID(RagdollParts.BODY).targetRotation = defaultTargetState.BodyTarget; + jointHandler.GetConfigurableJointWithID(RagdollParts.UPPER_RIGHT_ARM).targetRotation = + defaultTargetState.UpperRightArmTarget; + jointHandler.GetConfigurableJointWithID(RagdollParts.LOWER_RIGHT_ARM).targetRotation = + defaultTargetState.LowerRightArmTarget; + jointHandler.GetConfigurableJointWithID(RagdollParts.UPPER_LEFT_ARM).targetRotation = + defaultTargetState.UpperLeftArmTarget; + jointHandler.GetConfigurableJointWithID(RagdollParts.LOWER_LEFT_ARM).targetRotation = + defaultTargetState.LowerLeftArmTarget; + + ragdollState.mouseYAxisArms = 0; + locomotionController.resetPose = false; } public void PlayerLanded() { if (CanResetPoseAfterLanding()) { - inAir = false; - ResetPose = true; + ragdollState.inAir = false; + locomotionController.resetPose = true; } } private bool CanResetPoseAfterLanding() { - return inAir && !isJumping && !jumping; + return ragdollState.inAir && !ragdollState.isJumping && !ragdollState.jumping; } - private void PerformPlayerGetUpJumping() + private void PlayerReach() { - if (JumpValue > 0) - { - if (!jumpAxisUsed) - { - if (balanced && !inAir) - { - jumping = true; - } - - else if (!balanced) - { - DeactivateRagdoll(); - } - } - - jumpAxisUsed = true; - } - - else - { - jumpAxisUsed = false; - } + ragdollState.mouseYAxisBody = + Mathf.Clamp(ragdollState.mouseYAxisBody += (inputHandler.AimAxis.y / reachSensitivity), -0.2f, 0.1f); + jointHandler.GetConfigurableJointWithID(RagdollParts.BODY).targetRotation = + new Quaternion(ragdollState.mouseYAxisBody, 0, 0, 1); - - if (jumping) - { - isJumping = true; - - Rigidbody rootRigidbody = RagdollDict[ROOT].Rigidbody; - rootRigidbody.velocity = rootRigidbody.velocity.ModifyY(rootRigidbody.transform.up.y * jumpForce); - } - - if (isJumping) - { - timer += Time.fixedDeltaTime; - - if (timer > 0.2f) - { - timer = 0.0f; - jumping = false; - isJumping = false; - inAir = true; - } - } + HandleLeftSideReach(); + HandleRightSideReach(); } - private void GroundCheck() + private void HandlePlayerReach(bool punchingSide, float grabValue, ref bool reachSideAxisUsed, string upperArmJoint, + string lowerArmJoint, bool isRightArm) { - Transform rootTransform = RagdollDict[ROOT].transform; - Ray ray = new Ray(rootTransform.position, -rootTransform.up); - bool isHittingGround = Physics.Raycast(ray, out _, balanceHeight, 1 << groundLayer); - - if (!isHittingGround) + if (punchingSide) + return; + if (grabValue != 0) { - if (balanced) + if (!reachSideAxisUsed) { - balanced = false; + jointHandler.SetJointAngularDrives(upperArmJoint, in jointHandler.ReachStiffness); + jointHandler.SetJointAngularDrives(lowerArmJoint, in jointHandler.ReachStiffness); + jointHandler.SetJointAngularDrives(RagdollParts.BODY, in jointHandler.CoreStiffness); + reachSideAxisUsed = true; } - } - else if (ShouldSetBalanced()) - { - balanced = true; - } - - bool needsStateChange = (balanced == isRagdoll); - - if (!needsStateChange) - return; - - if (balanced) - { - DeactivateRagdoll(); - } - else - { - ActivateRagdoll(); - } - } - - private bool ShouldSetBalanced() - { - return !inAir && - !isJumping && - !reachRightAxisUsed && - !reachLeftAxisUsed && - !balanced && - RagdollDict[ROOT].Rigidbody.velocity.magnitude < 1f && - autoGetUpWhenPossible; - } - - - private void SetRagdollState(bool shouldRagdoll, ref JointDrive rootJointDrive, ref JointDrive poseJointDrive, - bool shouldResetPose) - { - isRagdoll = shouldRagdoll; - balanced = !shouldRagdoll; - - SetJointAngularDrives(ROOT, in rootJointDrive); - SetJointAngularDrives(HEAD, in poseJointDrive); - - if (!reachRightAxisUsed) - { - SetJointAngularDrives(UPPER_RIGHT_ARM, in poseJointDrive); - SetJointAngularDrives(LOWER_RIGHT_ARM, in poseJointDrive); - } - - if (!reachLeftAxisUsed) - { - SetJointAngularDrives(UPPER_LEFT_ARM, in poseJointDrive); - SetJointAngularDrives(LOWER_LEFT_ARM, in poseJointDrive); - } - - SetJointAngularDrives(UPPER_RIGHT_LEG, in poseJointDrive); - SetJointAngularDrives(LOWER_RIGHT_LEG, in poseJointDrive); - SetJointAngularDrives(UPPER_LEFT_LEG, in poseJointDrive); - SetJointAngularDrives(LOWER_LEFT_LEG, in poseJointDrive); - SetJointAngularDrives(RIGHT_FOOT, in poseJointDrive); - SetJointAngularDrives(LEFT_FOOT, in poseJointDrive); - - if (shouldResetPose) - ResetPose = true; - } - - private void DeactivateRagdoll() => SetRagdollState(false, ref BalanceOn, ref PoseOn, true); - - public void ActivateRagdoll() => SetRagdollState(true, ref DriveOff, ref DriveOff, false); - - private void SetJointAngularDrives(string jointName, in JointDrive jointDrive) - { - RagdollDict[jointName].Joint.angularXDrive = jointDrive; - RagdollDict[jointName].Joint.angularYZDrive = jointDrive; - } - - private void PlayerMovement() - { - if (forwardIsCameraDirection) - { - MoveInCameraDirection(); - } - else - { - MoveInOwnDirection(); - } - } - - private void MoveInCameraDirection() - { - Direction = RagdollDict[ROOT].transform.rotation * new Vector3(MovementAxis.x, 0.0f, MovementAxis.y); - Direction.y = 0f; - Rigidbody rootRigidbody = RagdollDict[ROOT].Rigidbody; - var velocity = rootRigidbody.velocity; - rootRigidbody.velocity = Vector3.Lerp(velocity, - (Direction * moveSpeed) + new Vector3(0, velocity.y, 0), 0.8f); - - if (MovementAxis.x != 0 || MovementAxis.y != 0 && balanced) - { - StartWalkingForward(); - } - else if (MovementAxis is { x: 0, y: 0 }) - { - StopWalkingForward(); - } - } - private void StartWalkingForward() - { - if (!WalkForward && !moveAxisUsed) - { - WalkForward = true; - moveAxisUsed = true; - isKeyDown = true; - } - } - - private void StopWalkingForward() - { - if (WalkForward && moveAxisUsed) - { - WalkForward = false; - moveAxisUsed = false; - isKeyDown = false; - } - } - - private void MoveInOwnDirection() - { - if (MovementAxis.y != 0) - { - var rootRigidbody = RagdollDict[ROOT].Rigidbody; - var v3 = rootRigidbody.transform.forward * (MovementAxis.y * moveSpeed); - v3.y = rootRigidbody.velocity.y; - rootRigidbody.velocity = v3; - } - - if (MovementAxis.y > 0) - { - StartWalkingForwardInOwnDirection(); - } - else if (MovementAxis.y < 0) - { - StartWalkingBackward(); + int multiplier = isRightArm ? 1 : -1; + ragdollState.mouseYAxisArms = + Mathf.Clamp(ragdollState.mouseYAxisArms += (inputHandler.AimAxis.y / reachSensitivity), -1.2f, 1.2f); + jointHandler.GetConfigurableJointWithID(upperArmJoint).targetRotation = + new Quaternion((0.58f + (ragdollState.mouseYAxisArms)) * multiplier, + -0.88f - (ragdollState.mouseYAxisArms), 0.8f * multiplier, + 1); } else { - StopWalking(); - } - } - - private void StartWalkingForwardInOwnDirection() => - SetWalkMovingState(() => (!WalkForward && !moveAxisUsed), true, false, true, true, PoseOn); - - private void StartWalkingBackward() => - SetWalkMovingState(() => !WalkBackward && !moveAxisUsed, false, true, true, true, PoseOn); - - private void StopWalking() => SetWalkMovingState(() => WalkForward || WalkBackward && moveAxisUsed, false, false, - false, false, DriveOff); - - private void SetWalkMovingState(Func activationCondition, bool walkForwardSetState, bool walkBackwardSetState, - bool isMoveAxisUsed, bool isKeyCurrentlyDown, in JointDrive legsJointDrive) - { - if (activationCondition.Invoke()) - { - InternalChangeWalkState(walkForwardSetState, walkBackwardSetState, isMoveAxisUsed, isKeyCurrentlyDown, - in legsJointDrive); - } - } - - private void InternalChangeWalkState(bool walkForward, bool walkBackward, bool isMoveAxisUsed, - bool isKeyCurrentlyDown, - in JointDrive legsJointDrive) - { - WalkForward = walkForward; - WalkBackward = walkBackward; - moveAxisUsed = isMoveAxisUsed; - isKeyDown = isKeyCurrentlyDown; - if (isRagdoll) - SetJointAngularDrivesForLegs(in legsJointDrive); - } - - private void SetJointAngularDrivesForLegs(in JointDrive jointDrive) - { - SetJointAngularDrives(UPPER_RIGHT_LEG, in jointDrive); - SetJointAngularDrives(LOWER_RIGHT_LEG, in jointDrive); - SetJointAngularDrives(UPPER_LEFT_LEG, in jointDrive); - SetJointAngularDrives(LOWER_LEFT_LEG, in jointDrive); - SetJointAngularDrives(RIGHT_FOOT, in jointDrive); - SetJointAngularDrives(LEFT_FOOT, in jointDrive); - } - - private void PlayerReach() - { - MouseYAxisBody = Mathf.Clamp(MouseYAxisBody += (AimAxis.y / reachSensitivity), -0.2f, 0.1f); - RagdollDict[BODY].Joint.targetRotation = new Quaternion(MouseYAxisBody, 0, 0, 1); - - if (GrabLeftValue != 0 && !punchingLeft) - { - if (!reachLeftAxisUsed) + if (!reachSideAxisUsed) + return; + if (locomotionController.balanced) { - SetJointAngularDrives(UPPER_LEFT_ARM, in ReachStiffness); - SetJointAngularDrives(LOWER_LEFT_ARM, in ReachStiffness); - SetJointAngularDrives(BODY, in CoreStiffness); - reachLeftAxisUsed = true; - reachLeftAxisUsed = true; + jointHandler.SetJointAngularDrives(upperArmJoint, in jointHandler.PoseOn); + jointHandler.SetJointAngularDrives(lowerArmJoint, in jointHandler.PoseOn); + jointHandler.SetJointAngularDrives(RagdollParts.BODY, in jointHandler.PoseOn); } - - MouseYAxisArms = Mathf.Clamp(MouseYAxisArms += (AimAxis.y / reachSensitivity), -1.2f, 1.2f); - RagdollDict[UPPER_LEFT_ARM].Joint.targetRotation = - new Quaternion(-0.58f - (MouseYAxisArms), -0.88f - (MouseYAxisArms), -0.8f, 1); - } - - if (GrabLeftValue == 0 && !punchingLeft) - { - if (reachLeftAxisUsed) + else { - if (balanced) - { - SetJointAngularDrives(UPPER_LEFT_ARM, in PoseOn); - SetJointAngularDrives(LOWER_LEFT_ARM, in PoseOn); - SetJointAngularDrives(BODY, in PoseOn); - } - else if (!balanced) - { - SetJointAngularDrives(UPPER_LEFT_ARM, in DriveOff); - SetJointAngularDrives(LOWER_LEFT_ARM, in DriveOff); - } - - ResetPose = true; - reachLeftAxisUsed = false; + jointHandler.SetJointAngularDrives(upperArmJoint, in jointHandler.DriveOff); + jointHandler.SetJointAngularDrives(lowerArmJoint, in jointHandler.DriveOff); } + + locomotionController.resetPose = true; + reachSideAxisUsed = false; } + } - if (GrabRightValue != 0 && !punchingRight) - { - if (!reachRightAxisUsed) - { - SetJointAngularDrives(UPPER_RIGHT_ARM, in ReachStiffness); - SetJointAngularDrives(LOWER_RIGHT_ARM, in ReachStiffness); - SetJointAngularDrives(BODY, in CoreStiffness); - reachRightAxisUsed = true; - } - MouseYAxisArms = Mathf.Clamp(MouseYAxisArms += (AimAxis.y / reachSensitivity), -1.2f, 1.2f); - RagdollDict[UPPER_RIGHT_ARM].Joint.targetRotation = - new Quaternion(0.58f + (MouseYAxisArms), -0.88f - (MouseYAxisArms), 0.8f, 1); - } + private void HandleRightSideReach() => HandlePlayerReach(ragdollState.punchingRight, inputHandler.GrabRightValue, + ref ragdollState.reachRightAxisUsed, RagdollParts.UPPER_RIGHT_ARM, RagdollParts.LOWER_RIGHT_ARM, true); - if (GrabRightValue == 0 && !punchingRight) - { - if (reachRightAxisUsed) - { - if (balanced) - { - SetJointAngularDrives(UPPER_RIGHT_ARM, in PoseOn); - SetJointAngularDrives(LOWER_RIGHT_ARM, in PoseOn); - SetJointAngularDrives(BODY, in PoseOn); - } - else if (!balanced) - { - SetJointAngularDrives(UPPER_RIGHT_ARM, in DriveOff); - SetJointAngularDrives(LOWER_RIGHT_ARM, in DriveOff); - } - - ResetPose = true; - reachRightAxisUsed = false; - } - } - } + private void HandleLeftSideReach() => HandlePlayerReach(ragdollState.punchingLeft, inputHandler.GrabLeftValue, + ref ragdollState.reachLeftAxisUsed, RagdollParts.UPPER_LEFT_ARM, RagdollParts.LOWER_LEFT_ARM, false); private void PerformPlayerPunch() { @@ -603,16 +246,16 @@ private void HandlePunch( if (punchingArmState == punchingArmValue) return; - ConfigurableJoint bodyJoint = RagdollDict[BODY].Joint; - ConfigurableJoint upperArmJoint = RagdollDict[upperArmLabel].Joint; - ConfigurableJoint lowerArmJoint = RagdollDict[lowerArmLabel].Joint; + RagdollJoint bodyJoint = jointHandler.GetRagdollJointWithID(RagdollParts.BODY); + ConfigurableJoint upperArmJoint = jointHandler.GetConfigurableJointWithID(upperArmLabel); + ConfigurableJoint lowerArmJoint = jointHandler.GetConfigurableJointWithID(lowerArmLabel); punchingArmState = punchingArmValue; int punchRotationMultiplier = isRightPunch ? -1 : 1; if (punchingArmValue) { - bodyJoint.targetRotation = new Quaternion(-0.15f, 0.15f * punchRotationMultiplier, 0, 1); + bodyJoint.Joint.targetRotation = new Quaternion(-0.15f, 0.15f * punchRotationMultiplier, 0, 1); upperArmJoint.targetRotation = new Quaternion(0.62f * punchRotationMultiplier, -0.51f, 0.02f, 1); lowerArmJoint.targetRotation = new Quaternion(-1.31f * punchRotationMultiplier, 0.5f, 0.5f * punchRotationMultiplier, 1); @@ -620,12 +263,13 @@ private void HandlePunch( else { - bodyJoint.targetRotation = new Quaternion(-0.15f, -0.15f * punchRotationMultiplier, 0, 1); + bodyJoint.Joint.targetRotation = new Quaternion(-0.15f, -0.15f * punchRotationMultiplier, 0, 1); upperArmJoint.targetRotation = new Quaternion(-0.74f * punchRotationMultiplier, 0.04f, 0f, 1); lowerArmJoint.targetRotation = new Quaternion(-0.2f * punchRotationMultiplier, 0, 0, 1); - handRigidbody.AddForce(RagdollDict[ROOT].transform.forward * punchForce, ForceMode.Impulse); - RagdollDict[BODY].Rigidbody.AddForce(RagdollDict[BODY].transform.forward * punchForce, ForceMode.Impulse); + handRigidbody.AddForce(jointHandler.GetRagdollJointWithID(RagdollParts.ROOT).transform.forward * punchForce, + ForceMode.Impulse); + bodyJoint.Rigidbody.AddForce(bodyJoint.transform.forward * punchForce, ForceMode.Impulse); StartCoroutine(PunchDelayCoroutine(isRightPunch, upperArmJoint, lowerArmJoint, upperArmTargetMethod, lowerArmTargetMethod)); @@ -637,7 +281,7 @@ private IEnumerator PunchDelayCoroutine(bool isRightArm, ConfigurableJoint upper { yield return punchDelayWaitTime; //Mainly because we can't pass in ref of bool value to coroutine, if not using unsafe void* - bool punchValueToCheck = isRightArm ? PunchRightValue : PunchLeftValue; + bool punchValueToCheck = isRightArm ? inputHandler.PunchRightValue : inputHandler.PunchLeftValue; if (punchValueToCheck) yield break; upperArmJoint.targetRotation = upperArmTarget.Invoke(); @@ -645,238 +289,18 @@ private IEnumerator PunchDelayCoroutine(bool isRightArm, ConfigurableJoint upper } private void HandleLeftPunch() => - HandlePunch(ref punchingLeft, PunchLeftValue, false, UPPER_LEFT_ARM, LOWER_LEFT_ARM, leftHand, - () => UpperLeftArmTarget, () => LowerLeftArmTarget); - - private void HandleRightPunch() => HandlePunch(ref punchingRight, PunchRightValue, true, UPPER_RIGHT_ARM, - LOWER_RIGHT_ARM, rightHand, () => UpperRightArmTarget, () => LowerLeftArmTarget); - - private void PerformWalking() - { - if (inAir) - return; - - if (WalkForward) - { - WalkForwards(); - } - - if (WalkBackward) - { - WalkBackwards(); - } - - if (StepRight) - { - TakeStepRight(); - } - else - { - ResetStepRight(); - } - - if (StepLeft) - { - TakeStepLeft(); - } - else - { - ResetStepLeft(); - } - } - - private void ResetStepLeft() => - ResetStep(UPPER_LEFT_LEG, LOWER_LEFT_LEG, in UpperLeftLegTarget, in LowerLeftLegTarget, 7f, 18f); - - private void ResetStepRight() => ResetStep(UPPER_RIGHT_LEG, LOWER_RIGHT_LEG, in UpperRightLegTarget, - in LowerRightLegTarget, 8f, 17f); - - private void ResetStep(string upperLegLabel, - string lowerLegLabel, - in Quaternion upperLegTarget, - in Quaternion lowerLegTarget, - float upperLegLerpMultiplier, - float lowerLegLerpMultiplier) - { - RagdollDict[upperLegLabel].Joint.targetRotation = Quaternion.Lerp( - RagdollDict[upperLegLabel].Joint.targetRotation, upperLegTarget, - upperLegLerpMultiplier * Time.fixedDeltaTime); - RagdollDict[lowerLegLabel].Joint.targetRotation = Quaternion.Lerp( - RagdollDict[lowerLegLabel].Joint.targetRotation, lowerLegTarget, - lowerLegLerpMultiplier * Time.fixedDeltaTime); - - Vector3 feetForce = -Vector3.up * (FeetMountForce * Time.deltaTime); - RagdollDict[RIGHT_FOOT].Rigidbody.AddForce(feetForce, ForceMode.Impulse); - RagdollDict[LEFT_FOOT].Rigidbody.AddForce(feetForce, ForceMode.Impulse); - } - - private void TakeStepLeft() => TakeStep(ref Step_L_timer, LEFT_FOOT, ref StepLeft, ref StepRight, UPPER_LEFT_LEG, - LOWER_LEFT_LEG, UPPER_RIGHT_LEG); - - private void TakeStepRight() => TakeStep(ref Step_R_timer, RIGHT_FOOT, ref StepRight, ref StepLeft, UPPER_RIGHT_LEG, - LOWER_RIGHT_LEG, UPPER_LEFT_LEG); - - private void TakeStep(ref float stepTimer, - string footLabel, - ref bool stepFootState, - ref bool oppositeStepFootState, - string upperJointLabel, - string lowerJointLabel, - string upperOppositeJointLabel) - { - stepTimer += Time.fixedDeltaTime; - RagdollDict[footLabel].Rigidbody - .AddForce(-Vector3.up * (FeetMountForce * Time.deltaTime), ForceMode.Impulse); + HandlePunch(ref ragdollState.punchingLeft, inputHandler.PunchLeftValue, false, RagdollParts.UPPER_LEFT_ARM, + RagdollParts.LOWER_LEFT_ARM, LeftHandRigidBody, + () => defaultTargetState.UpperLeftArmTarget, () => defaultTargetState.LowerLeftArmTarget); - var upperLegJoint = RagdollDict[upperJointLabel].Joint; - var upperLegJointTargetRotation = upperLegJoint.targetRotation; - - var lowerLegJoint = RagdollDict[lowerJointLabel].Joint; - var lowerLegJointTargetRotation = lowerLegJoint.targetRotation; - - var upperOppositeLegJoint = RagdollDict[upperOppositeJointLabel].Joint; - var upperOppositeLegJointTargetRotation = upperOppositeLegJoint.targetRotation; - - bool isWalking = WalkForward || WalkBackward; - - if (WalkForward) - { - upperLegJointTargetRotation = upperLegJointTargetRotation.DisplaceX(0.09f * StepHeight); - lowerLegJointTargetRotation = lowerLegJointTargetRotation.DisplaceX(-0.09f * StepHeight * 2); - upperOppositeLegJointTargetRotation = - upperOppositeLegJointTargetRotation.DisplaceX(-0.12f * StepHeight / 2); - } - - if (WalkBackward) - { - //TODO: Is this necessary for something? It's multiplying by 0. - upperLegJointTargetRotation = upperLegJointTargetRotation.DisplaceX(-0.00f * StepHeight); - lowerLegJointTargetRotation = lowerLegJointTargetRotation.DisplaceX(-0.07f * StepHeight * 2); - upperOppositeLegJointTargetRotation = upperOppositeLegJointTargetRotation.DisplaceX(0.02f * StepHeight / 2); - } - - if (isWalking) - { - upperLegJoint.targetRotation = upperLegJointTargetRotation; - lowerLegJoint.targetRotation = lowerLegJointTargetRotation; - upperOppositeLegJoint.targetRotation = upperOppositeLegJointTargetRotation; - } - - - if (stepTimer <= StepDuration) - return; - - stepTimer = 0; - stepFootState = false; - - if (isWalking) - { - oppositeStepFootState = true; - } - } - - private void Walk( - string forwardFootLabel, - string backFootLabel, - ref bool forwardFootState, - ref bool backFootState, - ref bool forwardAlertLeg, - ref bool backAlertLeg) - { - bool forwardFootIsBehind = RagdollDict[forwardFootLabel].transform.position.z < - RagdollDict[backFootLabel].transform.position.z; - bool forwardFootIsAhead = RagdollDict[forwardFootLabel].transform.position.z > - RagdollDict[backFootLabel].transform.position.z; - - if (forwardFootIsBehind && !backFootState && !forwardAlertLeg) - { - forwardFootState = true; - forwardAlertLeg = true; - backAlertLeg = true; - } - - if (forwardFootIsAhead && !forwardFootState && !backAlertLeg) - { - backFootState = true; - backAlertLeg = true; - forwardAlertLeg = true; - } - } - - private void WalkBackwards() => Walk(LEFT_FOOT, RIGHT_FOOT, ref StepLeft, ref StepRight, ref Alert_Leg_Left, - ref Alert_Leg_Right); - - private void WalkForwards() => Walk(RIGHT_FOOT, LEFT_FOOT, ref StepRight, ref StepLeft, ref Alert_Leg_Right, - ref Alert_Leg_Left); - - private void PerformStepPrediction() - { - if (!WalkForward && !WalkBackward) - { - StepRight = false; - StepLeft = false; - Step_R_timer = 0; - Step_L_timer = 0; - Alert_Leg_Right = false; - Alert_Leg_Left = false; - } - - if (centerOfMass.position.z < RagdollDict[RIGHT_FOOT].transform.position.z && - centerOfMass.position.z < RagdollDict[LEFT_FOOT].transform.position.z) - { - WalkBackward = true; - } - else - { - if (!isKeyDown) - { - WalkBackward = false; - } - } - - if (centerOfMass.position.z > RagdollDict[RIGHT_FOOT].transform.position.z && - centerOfMass.position.z > RagdollDict[LEFT_FOOT].transform.position.z) - { - WalkForward = true; - } - else - { - if (!isKeyDown) - { - WalkForward = false; - } - } - } + private void HandleRightPunch() => HandlePunch(ref ragdollState.punchingRight, inputHandler.PunchRightValue, true, + RagdollParts.UPPER_RIGHT_ARM, + RagdollParts.LOWER_RIGHT_ARM, RightHandRigidBody, () => defaultTargetState.UpperRightArmTarget, + () => defaultTargetState.LowerLeftArmTarget); [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UpdateCenterOfMass() { - //Be wary of this, it's called up to 2 times per frame - Vector3 massPositionDisplacement = Vector3.zero; - float totalMass = 0; - - foreach (var element in RagdollDict) - { - var joint = element.Value; - var mass = joint.Rigidbody.mass; - massPositionDisplacement += mass * joint.transform.position; - totalMass += mass; - } - - CenterOfMassPoint = (massPositionDisplacement / totalMass); - centerOfMass.position = CenterOfMassPoint; - } - - private void ResetWalkCycle() - { - if (!WalkForward && !WalkBackward) - { - StepRight = false; - StepLeft = false; - Step_R_timer = 0; - Step_L_timer = 0; - Alert_Leg_Right = false; - Alert_Leg_Left = false; - } + jointHandler.GetCenterOfMass(out CenterOfMassPoint, centerOfMass); } } \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollFeetContact.cs b/Assets/Scripts/ActiveRagdoll/RagdollFeetContact.cs index d96688c..d870e41 100644 --- a/Assets/Scripts/ActiveRagdoll/RagdollFeetContact.cs +++ b/Assets/Scripts/ActiveRagdoll/RagdollFeetContact.cs @@ -1,18 +1,39 @@ +using ActiveRagdoll; using UnityEngine; public class RagdollFeetContact : MonoBehaviour { [SerializeField] private RagdollController RagdollPlayer; private const string GROUND = "Ground"; - - void OnCollisionEnter(Collision col) + private int groundLayer = -1; + private RagdollState ragdollState; + + private int GroundLayer { - if(!RagdollPlayer.isJumping && RagdollPlayer.inAir) + get { - if(col.gameObject.layer == LayerMask.NameToLayer(GROUND)) + if (groundLayer == -1) { - RagdollPlayer.PlayerLanded(); + groundLayer = LayerMask.NameToLayer(GROUND); } + + return groundLayer; + } + } + + public void Init(RagdollState state) + { + ragdollState = state; + } + + private void OnCollisionEnter(Collision col) + { + if (ragdollState.isJumping || !ragdollState.inAir) + return; + + if (col.gameObject.layer == GroundLayer) + { + RagdollPlayer.PlayerLanded(); } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollHandContact.cs b/Assets/Scripts/ActiveRagdoll/RagdollHandContact.cs index 80f63c8..af7be56 100644 --- a/Assets/Scripts/ActiveRagdoll/RagdollHandContact.cs +++ b/Assets/Scripts/ActiveRagdoll/RagdollHandContact.cs @@ -1,35 +1,43 @@ +using ActiveRagdoll; using UnityEngine; public class RagdollHandContact : MonoBehaviour { public RagdollController ragdollController; public bool Left; - public bool hasJoint; + private bool HasJoint => joint != null; private const string CAN_BE_GRABBED = "CanBeGrabbed"; + private IInputListener inputListener; + private FixedJoint joint; + private RagdollState ragdollState; + + public void Init(IInputListener newInputListener, RagdollState state) + { + inputListener = newInputListener; + ragdollState = state; + } private void Update() { - HandleJointRelease(Left ? ragdollController.GrabLeftValue : ragdollController.GrabRightValue); + //TODO: Add grabValue change event + HandleJointRelease(Left ? inputListener.GrabLeftValue : inputListener.GrabRightValue); } private void HandleJointRelease(float reachAxisValue) { - if (hasJoint && reachAxisValue == 0) - { - DestroyJoint(); - } + if (!HasJoint) + return; - if (hasJoint && gameObject.GetComponent() == null) + if (reachAxisValue == 0) { - hasJoint = false; + DestroyJoint(); } } private void DestroyJoint() { - gameObject.GetComponent().breakForce = 0; - hasJoint = false; + joint.breakForce = 0; } @@ -46,26 +54,26 @@ private void OnCollisionEnter(Collision col) private bool CanGrab(Collision col) { - return col.gameObject.CompareTag(CAN_BE_GRABBED) && !hasJoint; + return col.gameObject.CompareTag(CAN_BE_GRABBED) && !HasJoint; } private bool CanPerformGrabAction() { if (Left) { - return ragdollController.GrabLeftValue != 0 && !ragdollController.punchingLeft; + return inputListener.GrabLeftValue != 0 && !ragdollState.punchingLeft; } else { - return ragdollController.GrabRightValue != 0 && !ragdollController.punchingRight; + return inputListener.GrabRightValue != 0 && !ragdollState.punchingRight; } } private void PerformGrabAction(Rigidbody connectedBody) { - hasJoint = true; - gameObject.AddComponent(); - gameObject.GetComponent().breakForce = Mathf.Infinity; - gameObject.GetComponent().connectedBody = connectedBody; + // hasJoint = true; + joint = gameObject.AddComponent(); + joint.breakForce = Mathf.Infinity; + joint.connectedBody = connectedBody; } } \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollImpactContact.cs b/Assets/Scripts/ActiveRagdoll/RagdollImpactContact.cs index 0dab923..86d6a39 100644 --- a/Assets/Scripts/ActiveRagdoll/RagdollImpactContact.cs +++ b/Assets/Scripts/ActiveRagdoll/RagdollImpactContact.cs @@ -1,14 +1,23 @@ +using ActiveRagdoll; using UnityEngine; public class RagdollImpactContact : MonoBehaviour { - public RagdollController ragdollController; + private RagdollImpactHandler ragdollImpactHandler; + private RagdollLocomotionController locomotionController; - void OnCollisionEnter(Collision col) + public void Init(RagdollImpactHandler impactHandler, RagdollLocomotionController locomotionController) { - if (ragdollController.canBeKnockoutByImpact && col.relativeVelocity.magnitude > ragdollController.requiredForceToBeKO) - { - ragdollController.ActivateRagdoll(); - } + ragdollImpactHandler = impactHandler; + this.locomotionController = locomotionController; } -} + + private void OnCollisionEnter(Collision col) + { + if (!ragdollImpactHandler.canBeKnockoutByImpact || + col.relativeVelocity.magnitude < ragdollImpactHandler.requiredForceToBeKO) + return; + + locomotionController.ActivateRagdoll(); + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs b/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs new file mode 100644 index 0000000..a64d6a9 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +namespace ActiveRagdoll +{ + public class RagdollInputHandler : IInputListener + { + public Vector2 MovementAxis { get; set; } + public Vector2 AimAxis { get; set; } + public float JumpValue { get; set; } + public float GrabLeftValue { get; set; } + public float GrabRightValue { get; set; } + public bool PunchLeftValue { get; set; } + public bool PunchRightValue { get; set; } + + public void Init() + { + InputManager.Instance.RegisterListener(this); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs.meta b/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs.meta new file mode 100644 index 0000000..25f5c4c --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/RagdollInputHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0a4935dcad5f4b60897926ee70ebefd7 +timeCreated: 1692562239 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollJoint.cs b/Assets/Scripts/ActiveRagdoll/RagdollJoint.cs index cef52dc..0c32ad1 100644 --- a/Assets/Scripts/ActiveRagdoll/RagdollJoint.cs +++ b/Assets/Scripts/ActiveRagdoll/RagdollJoint.cs @@ -2,7 +2,7 @@ public class RagdollJoint : MonoBehaviour { - [SerializeField] private Rigidbody rigidbody; + [SerializeField] private new Rigidbody rigidbody; [SerializeField] private ConfigurableJoint joint; public Rigidbody Rigidbody => rigidbody; diff --git a/Assets/Scripts/ActiveRagdoll/RagdollParts.cs b/Assets/Scripts/ActiveRagdoll/RagdollParts.cs new file mode 100644 index 0000000..3676a06 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/RagdollParts.cs @@ -0,0 +1,21 @@ +namespace ActiveRagdoll +{ + public class RagdollParts + { + internal const string ROOT = "Root"; + internal const string BODY = "Body"; + internal const string HEAD = "Head"; + internal const string UPPER_RIGHT_ARM = "UpperRightArm"; + internal const string LOWER_RIGHT_ARM = "LowerRightArm"; + internal const string UPPER_LEFT_ARM = "UpperLeftArm"; + internal const string LOWER_LEFT_ARM = "LowerLeftArm"; + internal const string UPPER_RIGHT_LEG = "UpperRightLeg"; + internal const string LOWER_RIGHT_LEG = "LowerRightLeg"; + internal const string UPPER_LEFT_LEG = "UpperLeftLeg"; + internal const string LOWER_LEFT_LEG = "LowerLeftLeg"; + internal const string RIGHT_FOOT = "RightFoot"; + internal const string LEFT_FOOT = "LeftFoot"; + internal const string RIGHT_HAND = "RightHand"; + internal const string LEFT_HAND = "LeftHand"; + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/RagdollParts.cs.meta b/Assets/Scripts/ActiveRagdoll/RagdollParts.cs.meta new file mode 100644 index 0000000..bd0b0f2 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/RagdollParts.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f9be3084a1244dc3929f837801bb735f +timeCreated: 1692566079 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers.meta new file mode 100644 index 0000000..e0b368e --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1c6e60544abe4af98a30664cac3d963e +timeCreated: 1692669145 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs new file mode 100644 index 0000000..2154044 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs @@ -0,0 +1,40 @@ +using System.Runtime.CompilerServices; +using UnityEngine; +using UnityEngine.Assertions; + +namespace ActiveRagdoll +{ + public class RagdollDefaultTargetState + { + public Quaternion HeadTarget { get; private set; } + public Quaternion BodyTarget { get; private set; } + public Quaternion UpperRightArmTarget { get; private set; } + public Quaternion LowerRightArmTarget { get; private set; } + public Quaternion UpperLeftArmTarget { get; private set; } + public Quaternion LowerLeftArmTarget { get; private set; } + public Quaternion UpperRightLegTarget { get; private set; } + public Quaternion LowerRightLegTarget { get; private set; } + public Quaternion UpperLeftLegTarget { get; private set; } + public Quaternion LowerLeftLegTarget { get; private set; } + + public RagdollDefaultTargetState(RagdollJointHandler jointHandler) + { + SetupOriginalPose(jointHandler); + } + + private void SetupOriginalPose(RagdollJointHandler jointsHandler) + { + //TODO: Consider baking this data into the prefab instead of calculating on startup. + BodyTarget = jointsHandler.GetJointTargetRotation(RagdollParts.ROOT); + HeadTarget = jointsHandler.GetJointTargetRotation(RagdollParts.HEAD); + UpperRightArmTarget = jointsHandler.GetJointTargetRotation(RagdollParts.UPPER_RIGHT_ARM); + LowerRightArmTarget = jointsHandler.GetJointTargetRotation(RagdollParts.LOWER_RIGHT_ARM); + UpperLeftArmTarget = jointsHandler.GetJointTargetRotation(RagdollParts.UPPER_LEFT_ARM); + LowerLeftArmTarget = jointsHandler.GetJointTargetRotation(RagdollParts.LOWER_LEFT_ARM); + UpperRightLegTarget = jointsHandler.GetJointTargetRotation(RagdollParts.UPPER_RIGHT_LEG); + LowerRightLegTarget = jointsHandler.GetJointTargetRotation(RagdollParts.LOWER_RIGHT_LEG); + UpperLeftLegTarget = jointsHandler.GetJointTargetRotation(RagdollParts.UPPER_LEFT_LEG); + LowerLeftLegTarget = jointsHandler.GetJointTargetRotation(RagdollParts.LOWER_LEFT_LEG); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs.meta new file mode 100644 index 0000000..86ebbea --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollDefaultTargetState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 656b1f12a86245589df191a19997d407 +timeCreated: 1692575652 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs new file mode 100644 index 0000000..a529128 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace ActiveRagdoll +{ + [System.Serializable] + public class RagdollImpactHandler + { + [field: SerializeField] public bool canBeKnockoutByImpact { get; private set; } = true; + [field: SerializeField] public float requiredForceToBeKO { get; private set; } = 20f; + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs.meta new file mode 100644 index 0000000..e92f516 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollImpactHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fe3e1d157867417cbdf91e7dd90d2e56 +timeCreated: 1692667379 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs new file mode 100644 index 0000000..efee5e7 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs @@ -0,0 +1,140 @@ +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace ActiveRagdoll +{ + [System.Serializable] + public class RagdollJointHandler + { + [SerializeField, Tooltip("The balancing strength to be used by this ragdoll")] + private float balanceStrength = 5000f; + + [SerializeField, Tooltip("The force to be applied in order to stiffen the core of the ragdoll")] + private float coreStrength = 1500f; + + [SerializeField, Tooltip("Mati llena este dato porque no se que es xd")] + private float limbStrength = 500f; + + [SerializeField] private float armReachStiffness = 2000f; + + [SerializeField] private UDictionary joints = new(); + + internal JointDrive BalanceOn; + internal JointDrive PoseOn; + internal JointDrive CoreStiffness; + internal JointDrive ReachStiffness; + internal JointDrive DriveOff; + + + public RagdollJointHandler() + { + Init(); + } + + private void Init() + { + BalanceOn = CreateJointDrive(balanceStrength); + PoseOn = CreateJointDrive(limbStrength); + CoreStiffness = CreateJointDrive(coreStrength); + ReachStiffness = CreateJointDrive(armReachStiffness); + DriveOff = CreateJointDrive(25); + } + + internal void SetJointAngularDrives(string jointName, in JointDrive jointDrive) + { + joints[jointName].Joint.angularXDrive = jointDrive; + joints[jointName].Joint.angularYZDrive = jointDrive; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Quaternion GetJointTargetRotation(string jointName) + { + return joints[jointName].Joint.targetRotation; + } + + private static JointDrive CreateJointDrive(float positionSpring) + { + var jointDrive = new JointDrive + { + positionSpring = positionSpring, + positionDamper = 0, + maximumForce = Mathf.Infinity + }; + return jointDrive; + } + + internal Rigidbody GetRigidBodyFromJoint(string jointID) + { + RagdollJoint joint = GetRagdollJointWithID(jointID); + return joint.Rigidbody; + } + + internal bool TryGetJointWithID(string jointID, out RagdollJoint joint) + { + bool gotJoint = joints.TryGetValue(jointID, out joint); +#if UNITY_EDITOR || DEBUG + if (!gotJoint) + Debug.LogWarning($"Joint with id {jointID} not found"); +#endif + return gotJoint; + } + + /// + /// Obtains a ragdoll joint with a specific ID. Only use if absolutely sure the joint exists + /// + /// + /// The specified > + internal RagdollJoint GetRagdollJointWithID(string jointID) + { + if (!joints.TryGetValue(jointID, out var joint)) + { +#if UNITY_EDITOR || DEBUG + Debug.LogWarning($"Ragdoll joint with id {jointID} not found"); +#endif + } + + return joint; + } + + + internal ConfigurableJoint GetConfigurableJointWithID(string jointID) + { + if (joints.TryGetValue(jointID, out var joint)) + { + return joint.Joint; + } + +#if UNITY_EDITOR || DEBUG + Debug.LogWarning($"Configurable joint for Ragdolljoint with id {jointID} not found"); +#endif + return default; + } + + public void GetCenterOfMass(out Vector3 CenterOfMassPoint, Transform centerOfMass) + { + Vector3 massPositionDisplacement = Vector3.zero; + float totalMass = 0; + + foreach (var element in joints) + { + var joint = element.Value; + var mass = joint.Rigidbody.mass; + massPositionDisplacement += mass * joint.transform.position; + totalMass += mass; + } + + CenterOfMassPoint = (massPositionDisplacement / totalMass); + centerOfMass.position = CenterOfMassPoint; + } + + public void SetJointAngularDrivesForLegs(in JointDrive jointDrive) + { + SetJointAngularDrives(RagdollParts.UPPER_RIGHT_LEG, in jointDrive); + SetJointAngularDrives(RagdollParts.LOWER_RIGHT_LEG, in jointDrive); + SetJointAngularDrives(RagdollParts.UPPER_LEFT_LEG, in jointDrive); + SetJointAngularDrives(RagdollParts.LOWER_LEFT_LEG, in jointDrive); + SetJointAngularDrives(RagdollParts.RIGHT_FOOT, in jointDrive); + SetJointAngularDrives(RagdollParts.LEFT_FOOT, in jointDrive); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs.meta new file mode 100644 index 0000000..d715837 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollJointHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8aa314aa9198450b986abf25dadcfd3f +timeCreated: 1692566224 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs new file mode 100644 index 0000000..4df3650 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs @@ -0,0 +1,537 @@ +using System; +using UnityEngine; +using Utils; + +namespace ActiveRagdoll +{ + [Serializable] + public class RagdollLocomotionController + { + [Header("Movement Properties")] [SerializeField] + private float moveSpeed = 10f; + + [SerializeField] private float jumpForce = 18f; + [SerializeField] private float StepDuration = 0.2f; + [SerializeField] private float StepHeight = 1.7f; + [SerializeField] private float FeetMountForce = 25f; + + internal float stepRTimer; + internal float stepLTimer; + internal bool walkForward; + internal bool walkBackward; + internal bool stepRight; + internal bool stepLeft; + internal bool alertLegRight; + internal bool alertLegLeft; + internal bool balanced = true; + internal bool gettingUp; + internal bool resetPose; + internal bool isRagdoll; + + + [Header("Balance Properties")] public bool autoGetUpWhenPossible = true; + public bool useStepPrediction = true; + public float balanceHeight = 2.5f; + + private RagdollJointHandler jointHandler; + private static int groundLayer; + private const string GROUND_LAYER_NAME = "Ground"; + private RagdollState ragdollState; + private RagdollDefaultTargetState defaultTargetState; + + public void Init(RagdollJointHandler jointsHandler, RagdollState state, + RagdollDefaultTargetState defaultTargetState) + { + jointHandler = jointsHandler; + groundLayer = LayerMask.NameToLayer(GROUND_LAYER_NAME); + ragdollState = state; + this.defaultTargetState = defaultTargetState; + } + + private void SetRagdollState(bool shouldRagdoll, ref JointDrive rootJointDrive, + ref JointDrive poseJointDrive, + bool shouldResetPose) + { + isRagdoll = shouldRagdoll; + balanced = !shouldRagdoll; + + jointHandler.SetJointAngularDrives(RagdollParts.ROOT, in rootJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.HEAD, in poseJointDrive); + + if (!ragdollState.reachRightAxisUsed) + { + jointHandler.SetJointAngularDrives(RagdollParts.UPPER_RIGHT_ARM, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.LOWER_RIGHT_ARM, in poseJointDrive); + } + + if (!ragdollState.reachLeftAxisUsed) + { + jointHandler.SetJointAngularDrives(RagdollParts.UPPER_LEFT_ARM, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.LOWER_LEFT_ARM, in poseJointDrive); + } + + jointHandler.SetJointAngularDrives(RagdollParts.UPPER_RIGHT_LEG, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.LOWER_RIGHT_LEG, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.UPPER_LEFT_LEG, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.LOWER_LEFT_LEG, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.RIGHT_FOOT, in poseJointDrive); + jointHandler.SetJointAngularDrives(RagdollParts.LEFT_FOOT, in poseJointDrive); + + if (shouldResetPose) + resetPose = true; + } + + public void DeactivateRagdoll() => + SetRagdollState(false, ref jointHandler.BalanceOn, ref jointHandler.PoseOn, true); + + public void ActivateRagdoll() => + SetRagdollState(true, ref jointHandler.DriveOff, ref jointHandler.DriveOff, false); + + + internal void Walk(string forwardFootLabel, string backFootLabel, ref bool forwardFootState, + ref bool backFootState, ref bool forwardAlertLeg, ref bool backAlertLeg) + { + float forwardFootTransformZ = + jointHandler.GetConfigurableJointWithID(forwardFootLabel).transform.position.z; + float backFootTransformZ = jointHandler.GetConfigurableJointWithID(backFootLabel).transform.position.z; + + bool forwardFootIsBehind = forwardFootTransformZ < backFootTransformZ; + bool forwardFootIsAhead = forwardFootTransformZ > backFootTransformZ; + + //TODO: Displace logic to not use alternating conditions + if (forwardFootIsBehind && !backFootState && !forwardAlertLeg) + { + forwardFootState = true; + forwardAlertLeg = true; + backAlertLeg = true; + } + + if (forwardFootIsAhead && !forwardFootState && !backAlertLeg) + { + backFootState = true; + backAlertLeg = true; + forwardAlertLeg = true; + } + } + + internal void GroundCheck() + { + Transform rootTransform = jointHandler.GetRagdollJointWithID(RagdollParts.ROOT).transform; + Ray ray = new Ray(rootTransform.position, Vector3.down); + bool isHittingGround = Physics.Raycast(ray, out _, balanceHeight, 1 << groundLayer); + + if (!isHittingGround) + { + if (balanced) + { + balanced = false; + } + } + else if (ShouldSetBalanced()) + { + balanced = true; + } + + bool needsStateChange = (balanced == isRagdoll); + + if (!needsStateChange) + return; + + if (balanced) + { + DeactivateRagdoll(); + } + else + { + ActivateRagdoll(); + } + } + + private bool ShouldSetBalanced() + { + return !ragdollState.inAir && + !ragdollState.isJumping && + !ragdollState.reachRightAxisUsed && + !ragdollState.reachLeftAxisUsed && + !balanced && + jointHandler.GetRigidBodyFromJoint(RagdollParts.ROOT).velocity.magnitude < 1f && + autoGetUpWhenPossible; + } + + internal void HandleStepPrediction(float centerOfMassZPosition) + { + if (useStepPrediction) + { + PerformStepPrediction(centerOfMassZPosition); + } + else + { + ResetWalkCycle(); + } + } + + private void PerformStepPrediction(float centerOfMassZPosition) + { + if (!balanced) + return; + + if (!walkForward && !walkBackward) + { + stepRight = false; + stepLeft = false; + stepRTimer = 0; + stepLTimer = 0; + alertLegRight = false; + alertLegLeft = false; + } + + float rightFootZPosition = + jointHandler.GetConfigurableJointWithID(RagdollParts.RIGHT_FOOT).transform.position.z; + float leftFootZPosition = + jointHandler.GetConfigurableJointWithID(RagdollParts.LEFT_FOOT).transform.position.z; + + //TODO: Refactor to reduce amount of code here + if (centerOfMassZPosition < rightFootZPosition && centerOfMassZPosition < leftFootZPosition) + { + walkBackward = true; + } + else + { + if (!ragdollState.isKeyDown) + { + walkBackward = false; + } + } + + if (centerOfMassZPosition > rightFootZPosition && centerOfMassZPosition > leftFootZPosition) + { + walkForward = true; + } + else + { + if (!ragdollState.isKeyDown) + { + walkForward = false; + } + } + } + + private void ResetWalkCycle() + { + if (!walkForward && !walkBackward) + { + stepRight = false; + stepLeft = false; + stepRTimer = 0; + stepLTimer = 0; + alertLegRight = false; + alertLegLeft = false; + } + } + + internal void PerformPlayerGetUpJumping(float jumpValue) + { + if (jumpValue > 0) + { + if (!ragdollState.jumpAxisUsed) + { + if (balanced && !ragdollState.inAir) + { + ragdollState.jumping = true; + } + + else if (!balanced) + { + DeactivateRagdoll(); + } + } + + ragdollState.jumpAxisUsed = true; + } + + else + { + ragdollState.jumpAxisUsed = false; + } + + + if (ragdollState.jumping) + { + ragdollState.isJumping = true; + + Rigidbody rootRigidbody = jointHandler.GetRigidBodyFromJoint(RagdollParts.ROOT); + rootRigidbody.velocity = rootRigidbody.velocity.ModifyY(rootRigidbody.transform.up.y * jumpForce); + } + + if (ragdollState.isJumping) + { + ragdollState.jumpingResetTimer += Time.fixedDeltaTime; + + if (ragdollState.jumpingResetTimer > 0.2f) + { + ragdollState.jumpingResetTimer = 0.0f; + ragdollState.jumping = false; + ragdollState.isJumping = false; + ragdollState.inAir = true; + } + } + } + + internal void PerformWalking() + { + if (ragdollState.inAir) + return; + + if (walkForward) + { + WalkForwards(); + } + + if (walkBackward) + { + WalkBackwards(); + } + + if (stepRight) + { + TakeStepRight(); + } + else + { + ResetStepRight(); + } + + if (stepLeft) + { + TakeStepLeft(); + } + else + { + ResetStepLeft(); + } + } + + private void WalkBackwards() => Walk(RagdollParts.LEFT_FOOT, RagdollParts.RIGHT_FOOT, + ref stepLeft, ref stepRight, + ref alertLegLeft, + ref alertLegRight); + + private void WalkForwards() => Walk(RagdollParts.RIGHT_FOOT, RagdollParts.LEFT_FOOT, + ref stepRight, ref stepLeft, + ref alertLegRight, + ref alertLegLeft); + + private void TakeStepLeft() => TakeStep(ref stepLTimer, RagdollParts.LEFT_FOOT, + ref stepLeft, ref stepRight, + RagdollParts.UPPER_LEFT_LEG, + RagdollParts.LOWER_LEFT_LEG, RagdollParts.UPPER_RIGHT_LEG); + + private void TakeStepRight() => TakeStep(ref stepRTimer, RagdollParts.RIGHT_FOOT, + ref stepRight, ref stepLeft, + RagdollParts.UPPER_RIGHT_LEG, + RagdollParts.LOWER_RIGHT_LEG, RagdollParts.UPPER_LEFT_LEG); + + private void TakeStep(ref float stepTimer, + string footLabel, + ref bool stepFootState, + ref bool oppositeStepFootState, + string upperJointLabel, + string lowerJointLabel, + string upperOppositeJointLabel) + { + stepTimer += Time.fixedDeltaTime; + jointHandler.GetRigidBodyFromJoint(footLabel) + .AddForce(-Vector3.up * (FeetMountForce * Time.deltaTime), ForceMode.Impulse); + + var upperLegJoint = jointHandler.GetConfigurableJointWithID(upperJointLabel); + var upperLegJointTargetRotation = upperLegJoint.targetRotation; + + var lowerLegJoint = jointHandler.GetConfigurableJointWithID(lowerJointLabel); + var lowerLegJointTargetRotation = lowerLegJoint.targetRotation; + + var upperOppositeLegJoint = jointHandler.GetConfigurableJointWithID(upperOppositeJointLabel); + var upperOppositeLegJointTargetRotation = upperOppositeLegJoint.targetRotation; + + bool isWalking = walkForward || walkBackward; + + if (walkForward) + { + upperLegJointTargetRotation = upperLegJointTargetRotation.DisplaceX(0.09f * StepHeight); + lowerLegJointTargetRotation = lowerLegJointTargetRotation.DisplaceX(-0.09f * StepHeight * 2); + upperOppositeLegJointTargetRotation = + upperOppositeLegJointTargetRotation.DisplaceX(-0.12f * StepHeight / 2); + } + + if (walkBackward) + { + //TODO: Is this necessary for something? It's multiplying by 0. + upperLegJointTargetRotation = upperLegJointTargetRotation.DisplaceX(-0.00f * StepHeight); + lowerLegJointTargetRotation = lowerLegJointTargetRotation.DisplaceX(-0.07f * StepHeight * 2); + upperOppositeLegJointTargetRotation = + upperOppositeLegJointTargetRotation.DisplaceX(0.02f * StepHeight / 2); + } + + if (isWalking) + { + upperLegJoint.targetRotation = upperLegJointTargetRotation; + lowerLegJoint.targetRotation = lowerLegJointTargetRotation; + upperOppositeLegJoint.targetRotation = upperOppositeLegJointTargetRotation; + } + + + if (stepTimer <= StepDuration) + return; + + stepTimer = 0; + stepFootState = false; + + if (isWalking) + { + oppositeStepFootState = true; + } + } + + private void ResetStepLeft() => + ResetStep(RagdollParts.UPPER_LEFT_LEG, RagdollParts.LOWER_LEFT_LEG, + defaultTargetState.UpperLeftLegTarget, defaultTargetState.LowerLeftLegTarget, + 7f, 18f); + + private void ResetStepRight() => ResetStep( + RagdollParts.UPPER_RIGHT_LEG, RagdollParts.LOWER_RIGHT_LEG, + defaultTargetState.UpperRightLegTarget, defaultTargetState.LowerRightLegTarget, + 8f, 17f); + + private void ResetStep(string upperLegLabel, + string lowerLegLabel, + Quaternion upperLegTarget, + Quaternion lowerLegTarget, + float upperLegLerpMultiplier, + float lowerLegLerpMultiplier) + { + jointHandler.GetConfigurableJointWithID(upperLegLabel).targetRotation = Quaternion.Lerp( + jointHandler.GetJointTargetRotation(upperLegLabel), upperLegTarget, + upperLegLerpMultiplier * Time.fixedDeltaTime); + jointHandler.GetConfigurableJointWithID(lowerLegLabel).targetRotation = Quaternion.Lerp( + jointHandler.GetJointTargetRotation(lowerLegLabel), lowerLegTarget, + lowerLegLerpMultiplier * Time.fixedDeltaTime); + + Vector3 feetForce = -Vector3.up * (FeetMountForce * Time.deltaTime); + jointHandler.GetRigidBodyFromJoint(RagdollParts.RIGHT_FOOT).AddForce(feetForce, ForceMode.Impulse); + jointHandler.GetRigidBodyFromJoint(RagdollParts.LEFT_FOOT).AddForce(feetForce, ForceMode.Impulse); + } + + internal void PlayerMovement(bool forwardIsCameraDirection, Vector2 movementVector) + { + if (forwardIsCameraDirection) + { + MoveInCameraDirection(movementVector); + } + else + { + MoveInOwnDirection(movementVector); + } + } + + private void MoveInCameraDirection(Vector2 movementVector) + { + var direction = jointHandler.GetRagdollJointWithID(RagdollParts.ROOT).transform.rotation * + new Vector3(movementVector.x, 0.0f, movementVector.y); + direction.y = 0f; + Rigidbody rootRigidbody = jointHandler.GetRigidBodyFromJoint(RagdollParts.ROOT); + var velocity = rootRigidbody.velocity; + rootRigidbody.velocity = Vector3.Lerp(velocity, + (direction * moveSpeed) + new Vector3(0, velocity.y, 0), 0.8f); + + if (movementVector.x != 0 || movementVector.y != 0 && balanced) + { + StartWalkingForward(); + } + else if (movementVector is { x: 0, y: 0 }) + { + StopWalkingForward(); + } + } + + private void StartWalkingForward() + { + if (walkForward || ragdollState.moveAxisUsed) + return; + + walkForward = true; + ragdollState.moveAxisUsed = true; + ragdollState.isKeyDown = true; + } + + private void StopWalkingForward() + { + if (!walkForward || !ragdollState.moveAxisUsed) + return; + + walkForward = false; + ragdollState.moveAxisUsed = false; + ragdollState.isKeyDown = false; + } + + private void MoveInOwnDirection(Vector2 movementVector) + { + if (movementVector.y != 0) + { + var rootRigidbody = jointHandler.GetRigidBodyFromJoint(RagdollParts.ROOT); + var v3 = rootRigidbody.transform.forward * (movementVector.y * moveSpeed); + v3.y = rootRigidbody.velocity.y; + rootRigidbody.velocity = v3; + } + + if (movementVector.y > 0) + { + StartWalkingForwardInOwnDirection(); + } + else if (movementVector.y < 0) + { + StartWalkingBackward(); + } + else + { + StopWalking(); + } + } + + private void StartWalkingForwardInOwnDirection() => + SetWalkMovingState(() => (!walkForward && !ragdollState.moveAxisUsed), true, false, + true, true, + jointHandler.PoseOn); + + private void StartWalkingBackward() => + SetWalkMovingState(() => !walkBackward && !ragdollState.moveAxisUsed, false, true, + true, true, + jointHandler.PoseOn); + + private void StopWalking() => SetWalkMovingState( + () => walkForward || + walkBackward && ragdollState.moveAxisUsed, false, false, + false, false, jointHandler.DriveOff); + + private void SetWalkMovingState(Func activationCondition, bool walkForwardSetState, + bool walkBackwardSetState, + bool isMoveAxisUsed, bool isKeyCurrentlyDown, in JointDrive legsJointDrive) + { + if (activationCondition.Invoke()) + { + InternalChangeWalkState(walkForwardSetState, walkBackwardSetState, isMoveAxisUsed, isKeyCurrentlyDown, + in legsJointDrive); + } + } + + private void InternalChangeWalkState(bool walkForwardState, bool walkBackwardState, bool isMoveAxisUsed, + bool isKeyCurrentlyDown, + in JointDrive legsJointDrive) + { + this.walkForward = walkForwardState; + this.walkBackward = walkBackwardState; + ragdollState.moveAxisUsed = isMoveAxisUsed; + ragdollState.isKeyDown = isKeyCurrentlyDown; + if (isRagdoll) + jointHandler.SetJointAngularDrivesForLegs(in legsJointDrive); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs.meta new file mode 100644 index 0000000..8e69d75 --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollLocomotionController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a34f8140d980431d8da4e397f1d62d2e +timeCreated: 1692579269 \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs new file mode 100644 index 0000000..919978f --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs @@ -0,0 +1,20 @@ +namespace ActiveRagdoll +{ + public class RagdollState + { + public bool jumping; + public bool isJumping; + public bool inAir; + public bool punchingRight; + public bool punchingLeft; + internal float jumpingResetTimer; + internal float mouseYAxisArms; + internal float mouseXAxisArms; + internal float mouseYAxisBody; + internal bool isKeyDown; + internal bool moveAxisUsed; + internal bool jumpAxisUsed; + internal bool reachLeftAxisUsed; + internal bool reachRightAxisUsed; + } +} \ No newline at end of file diff --git a/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs.meta b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs.meta new file mode 100644 index 0000000..5f9d80d --- /dev/null +++ b/Assets/Scripts/ActiveRagdoll/SubSystemHandlers/RagdollState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 52e8a81a2259438ba2f8c5706468892e +timeCreated: 1692666604 \ No newline at end of file diff --git a/Assets/Scripts/Camera/CameraController.cs b/Assets/Scripts/Camera/CameraController.cs index f894298..b68cb39 100644 --- a/Assets/Scripts/Camera/CameraController.cs +++ b/Assets/Scripts/Camera/CameraController.cs @@ -16,7 +16,7 @@ public class CameraController : MonoBehaviour public float minAngle = -35.0f; public float maxAngle = -15.0f; - [SerializeField] private Camera camera; + [SerializeField] private new Camera camera; private float currentX = 0.0f; private float currentY = 0.0f; private Quaternion rotation; diff --git a/Assets/Scripts/Utils/QuaternionExtensions.cs.meta b/Assets/Scripts/Utils/QuaternionExtensions.cs.meta new file mode 100644 index 0000000..4819559 --- /dev/null +++ b/Assets/Scripts/Utils/QuaternionExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4de070c76d377a242a84c2a508bde949 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/SingletonObject.cs b/Assets/Scripts/Utils/SingletonObject.cs index 3e723c1..4f9f222 100644 --- a/Assets/Scripts/Utils/SingletonObject.cs +++ b/Assets/Scripts/Utils/SingletonObject.cs @@ -21,4 +21,10 @@ public static T Instance return instance; } } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + private static void ResetInstance() + { + instance = null; + } } \ No newline at end of file diff --git a/Assets/Scripts/Utils/Vector3Extensions.cs.meta b/Assets/Scripts/Utils/Vector3Extensions.cs.meta new file mode 100644 index 0000000..0a3ea6e --- /dev/null +++ b/Assets/Scripts/Utils/Vector3Extensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef57b5b2ba5d2364793179efccbfc14b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: