using System.Collections; using System.Collections.Generic; using UnityEngine; //Player Holding ¶¯×÷-ÄÃÎäÆ÷ public class Holding : MonoBehaviour { [HideInInspector] public HoldableObject heldObject; [HideInInspector] public HoldableObject heldObjectOffHand; [HideInInspector] public Transform baseTransform; private Rigidbody rightHand; private Rigidbody leftHand; [HideInInspector] public ConfigurableJoint leftHandJoint; [HideInInspector] public ConfigurableJoint rightHandJoint; public float grabForce; [HideInInspector] public bool isGrabbing; private Transform rotaionTarget; private bool hasMainHandWeapon; private PlayerDeath death; public LayerMask mask = default(LayerMask); private Strength str; private float strength = 1f; private PID leftHandPID; private PID rightHandPID; private StandingDataHandler standingData; private void Awake() { death = GetComponent(); standingData = GetComponent(); str = GetComponent(); if (!baseTransform) { baseTransform = GetComponentInChildren().transform; } rightHand = GetComponentInChildren().GetComponent(); leftHand = GetComponentInChildren().GetComponent(); rotaionTarget = base.transform.GetComponentInChildren().transform; mask = LayerMask.GetMask("Map"); leftHandPID = leftHand.GetComponent(); rightHandPID = rightHand.GetComponent(); } private void Update() { if (!death.dead && (bool)heldObject) { strength = str.strength; if (((bool)rightHandJoint || !heldObject.rightHandPos) && ((bool)leftHandJoint || !heldObject.leftHandPos) && (!heldObjectOffHand || (((bool)rightHandJoint || !heldObjectOffHand.rightHandPos) && ((bool)leftHandJoint || !heldObjectOffHand.leftHandPos)))) { isGrabbing = false; } } } private void FixedUpdate() { if (death.dead || isGrabbing) { return; } if ((bool)heldObject) { HoldObjectInPlace(heldObject.rig, heldObject, offHand: false, rightHand); if (!heldObjectOffHand && (bool)leftHandJoint) { HoldObjectInPlace(heldObject.rig, heldObject, offHand: false, leftHand, justHand: true); } } if ((bool)heldObjectOffHand) { HoldObjectInPlace(heldObjectOffHand.rig, heldObjectOffHand, offHand: true, leftHand); } } private void HoldObjectInPlace(Rigidbody rigi, HoldableObject held, bool offHand, Rigidbody hand, bool justHand = false) { Vector3 holdingPosition = held.holdingPosition; if (offHand) { holdingPosition.x *= -1f; } holdingPosition = baseTransform.TransformPoint(holdingPosition); Vector3 holdingRotation = held.holdingRotation; Vector3 targetRotation = baseTransform.TransformDirection(holdingRotation); Vector3 targetRotationUp = baseTransform.TransformDirection(held.holdingUpRotation); if (!justHand) { held.pid.DoPID(holdingPosition, targetRotation, targetRotationUp, strength); } PID pID = rightHandPID; Vector3 localPosition = held.rightHandPos.localPosition; if (hand == leftHand) { localPosition = held.leftHandPos.localPosition; pID = leftHandPID; } Vector3 position = held.holdingPosition + localPosition; if (offHand) { position.x *= -1f; } position = baseTransform.TransformPoint(position); Debug.DrawLine(position, position + Vector3.up); Debug.DrawLine(holdingPosition, holdingPosition + Vector3.up); pID.DoPID(position, Vector3.zero, Vector3.zero, strength); } public void StartHolding(HoldableObject holdableObject, bool hasOffHand) { holdableObject.isHeld = true; isGrabbing = true; bool offHand = false; if (!hasMainHandWeapon) { hasMainHandWeapon = true; heldObject = holdableObject; if ((bool)heldObject.rightHandPos) { StartCoroutine(Grab(mainHand: true, rightHand, heldObject, offHand: false)); } if ((bool)heldObject.leftHandPos && !hasOffHand) { StartCoroutine(Grab(mainHand: false, leftHand, heldObject, offHand: false)); } } else { offHand = true; heldObjectOffHand = holdableObject; heldObjectOffHand.leftHandPos = heldObjectOffHand.rightHandPos; if ((bool)heldObjectOffHand.rightHandPos) { StartCoroutine(Grab(mainHand: false, leftHand, heldObjectOffHand, offHand: true)); } } StartCoroutine(HoldweaponStill(holdableObject.rig, offHand, holdableObject)); } private IEnumerator Grab(bool mainHand, Rigidbody hand, HoldableObject held, bool offHand) { while (isGrabbing) { if (mainHand) { if (!rightHandJoint) { ReachForPoint(rightHand, rightHand.transform.GetChild(0).position, held.rightHandPos, isLeft: false, held.rig, held, offHand); rightHand.GetComponentInChildren().enabled = false; } } else if (!leftHandJoint) { ReachForPoint(leftHand, leftHand.transform.GetChild(0).position, held.leftHandPos, isLeft: true, held.rig, held, offHand); leftHand.GetComponentInChildren().enabled = false; } yield return null; } leftHand.GetComponentInChildren().enabled = true; rightHand.GetComponentInChildren().enabled = true; } private IEnumerator HoldweaponStill(Rigidbody rigToGrab, bool offHand, HoldableObject held) { while (isGrabbing) { Vector3 pos = held.holdingPosition; if (offHand) { pos.x *= -1f; } rigToGrab.transform.position = baseTransform.TransformPoint(pos); rigToGrab.transform.rotation = Quaternion.LookRotation(baseTransform.TransformDirection(heldObject.holdingRotation)); yield return null; } } public void Drop() { List list = new List(); if ((bool)heldObject) { list.Add(heldObject); } if ((bool)heldObjectOffHand) { list.Add(heldObjectOffHand); } for (int i = 0; i < list.Count; i++) { list[i].holder = null; list[i].isHeld = false; list[i].rig.useGravity = true; list[i].rig.drag = 0f; list[i].rig.angularDrag = 0f; Collider[] componentsInChildren = list[i].GetComponentsInChildren(); foreach (Collider collider in componentsInChildren) { collider.material = null; } } heldObject = null; heldObjectOffHand = null; if ((bool)rightHandJoint) { Object.Destroy(rightHandJoint); } if ((bool)leftHandJoint) { Object.Destroy(leftHandJoint); } hasMainHandWeapon = false; } private void ReachForPoint(Rigidbody rigToReach, Vector3 forcePosition, Transform targetPositionTransform, bool isLeft, Rigidbody rigToGrab, HoldableObject held, bool offHand) { Vector3 normalized = (targetPositionTransform.position - forcePosition).normalized; rigToReach.AddForceAtPosition(normalized * grabForce * Mathf.Clamp(Time.deltaTime, 0f, 0.1f), forcePosition, ForceMode.Acceleration); if (Vector3.Distance(targetPositionTransform.position, forcePosition) < 0.5f) { ConnectRig(rigToReach, rigToGrab, targetPositionTransform, isLeft, held, offHand); } } private void ConnectRig(Rigidbody startRig, Rigidbody targetRig, Transform targetPositionTransform, bool isLeft, HoldableObject held, bool offHand) { ConfigurableJoint configurableJoint = startRig.gameObject.AddComponent(); if (offHand) { targetPositionTransform.localRotation = Quaternion.Euler(targetPositionTransform.localEulerAngles.x, 0f - targetPositionTransform.localEulerAngles.y, targetPositionTransform.localEulerAngles.z); } startRig.transform.rotation = targetPositionTransform.rotation; startRig.transform.position += targetPositionTransform.position - startRig.transform.GetChild(0).position; configurableJoint.connectedBody = targetRig; configurableJoint.projectionMode = JointProjectionMode.PositionAndRotation; configurableJoint.xMotion = ConfigurableJointMotion.Locked; configurableJoint.yMotion = ConfigurableJointMotion.Locked; configurableJoint.zMotion = ConfigurableJointMotion.Locked; configurableJoint.angularXMotion = ConfigurableJointMotion.Limited; configurableJoint.angularYMotion = ConfigurableJointMotion.Limited; configurableJoint.angularZMotion = ConfigurableJointMotion.Limited; SoftJointLimit highAngularXLimit = configurableJoint.highAngularXLimit; highAngularXLimit.limit = held.swingAngles.y; configurableJoint.highAngularXLimit = highAngularXLimit; highAngularXLimit.limit = held.swingAngles.x; configurableJoint.lowAngularXLimit = highAngularXLimit; highAngularXLimit.limit = held.twistAngles.x; configurableJoint.angularYLimit = highAngularXLimit; highAngularXLimit.limit = held.twistAngles.y; configurableJoint.angularZLimit = highAngularXLimit; SoftJointLimitSpring angularXLimitSpring = configurableJoint.angularXLimitSpring; angularXLimitSpring.spring = held.swingSpring; configurableJoint.angularXLimitSpring = angularXLimitSpring; angularXLimitSpring.spring = held.twistSpring; configurableJoint.angularYZLimitSpring = angularXLimitSpring; configurableJoint.anchor = startRig.transform.InverseTransformPoint(startRig.transform.GetChild(0).position); if (isLeft) { leftHandJoint = configurableJoint; } else { rightHandJoint = configurableJoint; } } }