Refactor : ShoulderCorrectionFunction을 Serializable 모듈로 전환

- RequireComponent 6개 제거 (모듈화 준비)
- ShoulderCorrectionFunction: MonoBehaviour → [Serializable] 클래스
- Start() → Initialize(Animator), Update() → OnUpdate()
- CustomRetargetingScript에서 shoulderCorrection 필드로 소유 및 호출

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user 2026-03-07 23:00:35 +09:00
parent b0c967e1fd
commit 52d6960710
2 changed files with 36 additions and 36 deletions

View File

@ -9,12 +9,6 @@ namespace KindRetargeting
/// 이 스크립트는 원본 아바타(Source)의 포즈 손가락 움직임을 대상 아바타(Target)에 리타게팅(Retargeting)합니다.
/// 또한 IK 타겟을 생성하여 대상 아바타의 관절 움직임을 자연스럽게 조정합니다.
/// </summary>
[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);
}
/// <summary>
@ -821,6 +822,9 @@ namespace KindRetargeting
break;
}
// 어깨 보정 (기존 ExecutionOrder 3)
shoulderCorrection.OnUpdate();
// 스케일 변경 확인 및 적용
if (!Mathf.Approximately(previousScale, avatarScale))
{

View File

@ -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<CustomRetargetingScript>();
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(