diff --git a/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs b/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs index c704d952d..198793b24 100644 --- a/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs +++ b/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs @@ -9,12 +9,6 @@ namespace KindRetargeting /// 이 스크립트는 원본 아바타(Source)의 포즈 손가락 움직임을 대상 아바타(Target)에 리타게팅(Retargeting)합니다. /// 또한 IK 타겟을 생성하여 대상 아바타의 관절 움직임을 자연스럽게 조정합니다. /// - [RequireComponent(typeof(LimbWeightController))] - [RequireComponent(typeof(ShoulderCorrectionFunction))] - [RequireComponent(typeof(TwoBoneIKSolver))] - [RequireComponent(typeof(FootGroundingController))] - [RequireComponent(typeof(PropLocationController))] - [RequireComponent(typeof(FingerShapedController))] [DefaultExecutionOrder(1)] public class CustomRetargetingScript : MonoBehaviour { @@ -101,6 +95,9 @@ namespace KindRetargeting [HideInInspector] public Vector3 tPoseHeadForward = Vector3.forward; [HideInInspector] public Vector3 tPoseHeadUp = Vector3.up; + [Header("어깨 보정")] + [SerializeField] public ShoulderCorrectionFunction shoulderCorrection = new ShoulderCorrectionFunction(); + [Header("아바타 크기 조정")] [SerializeField, Range(0.1f, 3f)] private float avatarScale = 1f; private float previousScale = 1f; @@ -324,6 +321,10 @@ namespace KindRetargeting Debug.LogWarning("[CustomRetargetingScript] 머리 본을 찾을 수 없습니다!"); } } + + // 어깨 보정 모듈 초기화 + if (targetAnimator != null) + shoulderCorrection.Initialize(targetAnimator); } /// @@ -821,6 +822,9 @@ namespace KindRetargeting break; } + // 어깨 보정 (기존 ExecutionOrder 3) + shoulderCorrection.OnUpdate(); + // 스케일 변경 확인 및 적용 if (!Mathf.Approximately(previousScale, avatarScale)) { diff --git a/Assets/Scripts/KindRetargeting/ShoulderCorrectionFunction.cs b/Assets/Scripts/KindRetargeting/ShoulderCorrectionFunction.cs index daa61e9e5..434a0f70a 100644 --- a/Assets/Scripts/KindRetargeting/ShoulderCorrectionFunction.cs +++ b/Assets/Scripts/KindRetargeting/ShoulderCorrectionFunction.cs @@ -2,22 +2,20 @@ using UnityEngine; namespace KindRetargeting { - [DefaultExecutionOrder(3)] - public class ShoulderCorrectionFunction : MonoBehaviour + [System.Serializable] + public class ShoulderCorrectionFunction { - private CustomRetargetingScript retargetingScript; // 소스 데이터를 가져올 리타게팅 스크립트 - [Header("설정")] [Range(0f, 5f)] - public float blendStrength = 2f; // 전체적인 보정 강도 + public float blendStrength = 2f; [Range(0f, 1f)] - public float maxShoulderBlend = 0.7f; // 어깨에 최대로 전달될 수 있는 회전 비율 - public bool reverseLeftRotation = false; // 왼쪽 어깨 회전 방향 반전 설정 - public bool reverseRightRotation = false; // 오른쪽 어깨 회전 방향 반전 설정 + public float maxShoulderBlend = 0.7f; + public bool reverseLeftRotation = false; + public bool reverseRightRotation = false; [Header("높이 제한 설정")] - public float maxHeightDifference = 0.8f; // 최대 높이 차이 - public float minHeightDifference = -0.1f; // 최소 높이 차이 (이 값 이하에서는 보정하지 않음) + public float maxHeightDifference = 0.8f; + public float minHeightDifference = -0.1f; [Header("보정 커브 설정")] public AnimationCurve shoulderCorrectionCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); @@ -29,26 +27,24 @@ namespace KindRetargeting private Transform rightShoulder; private Transform leftUpperArm; private Transform rightUpperArm; - // 최적화: 팔꿈치(LowerArm) Transform 캐싱 추가 private Transform leftLowerArm; private Transform rightLowerArm; - private void Start() + public void Initialize(Animator targetAnimator) { - retargetingScript = GetComponent(); - - leftShoulder = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.LeftShoulder); - rightShoulder = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.RightShoulder); - leftUpperArm = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.LeftUpperArm); - rightUpperArm = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.RightUpperArm); - // 최적화: 팔꿈치 Transform도 Start에서 캐싱 - leftLowerArm = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.LeftLowerArm); - rightLowerArm = retargetingScript.targetAnimator.GetBoneTransform(HumanBodyBones.RightLowerArm); + leftShoulder = targetAnimator.GetBoneTransform(HumanBodyBones.LeftShoulder); + rightShoulder = targetAnimator.GetBoneTransform(HumanBodyBones.RightShoulder); + leftUpperArm = targetAnimator.GetBoneTransform(HumanBodyBones.LeftUpperArm); + rightUpperArm = targetAnimator.GetBoneTransform(HumanBodyBones.RightUpperArm); + leftLowerArm = targetAnimator.GetBoneTransform(HumanBodyBones.LeftLowerArm); + rightLowerArm = targetAnimator.GetBoneTransform(HumanBodyBones.RightLowerArm); } - private void Update() + public void OnUpdate() { - // 왼쪽 어깨 보정 (최적화: 캐싱된 Transform 사용) + if (leftShoulder == null || rightShoulder == null) return; + + // 왼쪽 어깨 보정 Vector3 leftElbowPos = leftLowerArm.position; float leftHeightDiff = leftElbowPos.y - leftShoulder.position.y; float leftRawBlend = Mathf.Clamp01( @@ -56,7 +52,7 @@ namespace KindRetargeting ); leftBlendWeight = shoulderCorrectionCurve.Evaluate(leftRawBlend) * maxShoulderBlend; - // 오른쪽 어깨 보정 (최적화: 캐싱된 Transform 사용) + // 오른쪽 어깨 보정 Vector3 rightElbowPos = rightLowerArm.position; float rightHeightDiff = rightElbowPos.y - rightShoulder.position.y; float rightRawBlend = Mathf.Clamp01( @@ -69,12 +65,12 @@ namespace KindRetargeting { Quaternion currentWorldShoulderRot = leftShoulder.rotation; Quaternion currentWorldArmRot = leftUpperArm.rotation; - + Vector3 shoulderToArm = (leftUpperArm.position - leftShoulder.position).normalized; - Quaternion targetRotation = Quaternion.FromToRotation(leftShoulder.forward, + Quaternion targetRotation = Quaternion.FromToRotation(leftShoulder.forward, reverseLeftRotation ? shoulderToArm : -shoulderToArm); Quaternion targetWorldShoulderRot = targetRotation * currentWorldShoulderRot; - + leftShoulder.rotation = Quaternion.Lerp(currentWorldShoulderRot, targetWorldShoulderRot, leftBlendWeight); leftUpperArm.rotation = currentWorldArmRot; } @@ -83,12 +79,12 @@ namespace KindRetargeting { Quaternion currentWorldShoulderRot = rightShoulder.rotation; Quaternion currentWorldArmRot = rightUpperArm.rotation; - + Vector3 shoulderToArm = (rightUpperArm.position - rightShoulder.position).normalized; - Quaternion targetRotation = Quaternion.FromToRotation(rightShoulder.forward, + Quaternion targetRotation = Quaternion.FromToRotation(rightShoulder.forward, reverseRightRotation ? -shoulderToArm : shoulderToArm); Quaternion targetWorldShoulderRot = targetRotation * currentWorldShoulderRot; - + rightShoulder.rotation = Quaternion.Lerp(currentWorldShoulderRot, targetWorldShoulderRot, rightBlendWeight); rightUpperArm.rotation = currentWorldArmRot; }