From 52d9e9f54898e2e9c1f7bbbf184996f9891f0a0d Mon Sep 17 00:00:00 2001 From: KINDNICK <68893236+KINDNICK@users.noreply.github.com> Date: Sun, 14 Dec 2025 21:50:35 +0900 Subject: [PATCH] =?UTF-8?q?Fix=20:=20=EC=8B=A0=EC=B2=B4=EA=B0=80=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=A7=80=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomRetargetingScript.cs | 31 ++++----- .../KindRetargeting/FingerShapedController.cs | 63 ++++++++++++++++++- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs b/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs index 49520577..68ab3fc9 100644 --- a/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs +++ b/Assets/Scripts/KindRetargeting/CustomRetargetingScript.cs @@ -192,9 +192,10 @@ namespace KindRetargeting private Dictionary fingerFilterBuffers = new Dictionary(); private Dictionary fingerFilterIndices = new Dictionary(); - // CopyFingerPoseByMuscle에서 사용할 본 Transform 저장용 (메모리 재사용) - private Dictionary savedBoneTransforms = - new Dictionary(); + // CopyFingerPoseByMuscle에서 사용할 본 로컬 회전 저장용 (메모리 재사용) + // 위치는 SetHumanPose가 처리하므로 회전만 저장 + private Dictionary savedBoneLocalRotations = + new Dictionary(); // 손가락을 제외한 모든 휴먼본 목록 (캐싱) private static readonly HumanBodyBones[] nonFingerBones = new HumanBodyBones[] @@ -1364,14 +1365,14 @@ namespace KindRetargeting if (sourcePoseHandler == null || targetPoseHandler == null) return; - // 1. 손가락을 제외한 모든 본의 위치/회전 저장 - savedBoneTransforms.Clear(); + // 1. 손가락을 제외한 모든 본의 로컬 회전 저장 (위치는 복원 불필요) + savedBoneLocalRotations.Clear(); for (int i = 0; i < nonFingerBones.Length; i++) { Transform bone = targetAnimator.GetBoneTransform(nonFingerBones[i]); if (bone != null) { - savedBoneTransforms[nonFingerBones[i]] = (bone.position, bone.rotation); + savedBoneLocalRotations[nonFingerBones[i]] = bone.localRotation; } } @@ -1408,13 +1409,13 @@ namespace KindRetargeting // 3. 머슬 포즈 적용 (손가락 포함 전체 본에 영향) targetPoseHandler.SetHumanPose(ref targetPose); - // 4. 손가락을 제외한 모든 본의 위치/회전 복원 - foreach (var kvp in savedBoneTransforms) + // 4. 손가락을 제외한 모든 본의 로컬 회전 복원 (위치는 복원하지 않음 - 본 길이 변형 방지) + foreach (var kvp in savedBoneLocalRotations) { Transform bone = targetAnimator.GetBoneTransform(kvp.Key); if (bone != null) { - bone.SetPositionAndRotation(kvp.Value.position, kvp.Value.rotation); + bone.localRotation = kvp.Value; } } } @@ -1518,14 +1519,14 @@ namespace KindRetargeting if (sourcePoseHandler == null || targetPoseHandler == null) return; - // 1. 손가락을 제외한 모든 본의 위치/회전 저장 - savedBoneTransforms.Clear(); + // 1. 손가락을 제외한 모든 본의 로컬 회전 저장 (위치는 복원 불필요) + savedBoneLocalRotations.Clear(); for (int i = 0; i < nonFingerBones.Length; i++) { Transform bone = targetAnimator.GetBoneTransform(nonFingerBones[i]); if (bone != null) { - savedBoneTransforms[nonFingerBones[i]] = (bone.position, bone.rotation); + savedBoneLocalRotations[nonFingerBones[i]] = bone.localRotation; } } @@ -1586,13 +1587,13 @@ namespace KindRetargeting // 4. 머슬 포즈 적용 targetPoseHandler.SetHumanPose(ref targetPose); - // 5. 손가락을 제외한 모든 본의 위치/회전 복원 - foreach (var kvp in savedBoneTransforms) + // 5. 손가락을 제외한 모든 본의 로컬 회전 복원 (위치는 복원하지 않음 - 본 길이 변형 방지) + foreach (var kvp in savedBoneLocalRotations) { Transform bone = targetAnimator.GetBoneTransform(kvp.Key); if (bone != null) { - bone.SetPositionAndRotation(kvp.Value.position, kvp.Value.rotation); + bone.localRotation = kvp.Value; } } } diff --git a/Assets/Scripts/KindRetargeting/FingerShapedController.cs b/Assets/Scripts/KindRetargeting/FingerShapedController.cs index 1613d711..025e4562 100644 --- a/Assets/Scripts/KindRetargeting/FingerShapedController.cs +++ b/Assets/Scripts/KindRetargeting/FingerShapedController.cs @@ -1,11 +1,45 @@ using UnityEngine; +using System.Collections.Generic; [DefaultExecutionOrder(2)] public class FingerShapedController : MonoBehaviour { private Animator animator; private HumanPoseHandler humanPoseHandler; - + + // 손가락을 제외한 모든 본의 로컬 회전 저장용 (SetHumanPose 호출 시 몸 복원용) + private Dictionary savedBoneLocalRotations = new Dictionary(); + + // 손가락을 제외한 모든 휴먼본 목록 + private static readonly HumanBodyBones[] nonFingerBones = new HumanBodyBones[] + { + HumanBodyBones.Hips, + HumanBodyBones.Spine, + HumanBodyBones.Chest, + HumanBodyBones.UpperChest, + HumanBodyBones.Neck, + HumanBodyBones.Head, + HumanBodyBones.LeftShoulder, + HumanBodyBones.LeftUpperArm, + HumanBodyBones.LeftLowerArm, + HumanBodyBones.LeftHand, + HumanBodyBones.RightShoulder, + HumanBodyBones.RightUpperArm, + HumanBodyBones.RightLowerArm, + HumanBodyBones.RightHand, + HumanBodyBones.LeftUpperLeg, + HumanBodyBones.LeftLowerLeg, + HumanBodyBones.LeftFoot, + HumanBodyBones.LeftToes, + HumanBodyBones.RightUpperLeg, + HumanBodyBones.RightLowerLeg, + HumanBodyBones.RightFoot, + HumanBodyBones.RightToes, + HumanBodyBones.LeftEye, + HumanBodyBones.RightEye, + HumanBodyBones.Jaw + }; + [Header("왼손 제어 값")] [Range(-1, 1)] public float leftPinkyCurl; // 새끼손가락 구부리기 [Range(-1, 1)] public float leftRingCurl; // 약지 구부리기 @@ -54,18 +88,41 @@ public class FingerShapedController : MonoBehaviour private void UpdateMuscleValues() { + // 1. 손가락을 제외한 모든 본의 로컬 회전 저장 (SetHumanPose 호출 전) + savedBoneLocalRotations.Clear(); + for (int i = 0; i < nonFingerBones.Length; i++) + { + Transform bone = animator.GetBoneTransform(nonFingerBones[i]); + if (bone != null) + { + savedBoneLocalRotations[nonFingerBones[i]] = bone.localRotation; + } + } + + // 2. HumanPose 가져오기 및 손가락 머슬 설정 HumanPose humanPose = new HumanPose(); humanPoseHandler.GetHumanPose(ref humanPose); // 왼손 제어 - SetHandMuscles(true, leftThumbCurl, leftIndexCurl, leftMiddleCurl, leftRingCurl, + SetHandMuscles(true, leftThumbCurl, leftIndexCurl, leftMiddleCurl, leftRingCurl, leftPinkyCurl, leftSpreadFingers, ref humanPose); // 오른손 제어 - SetHandMuscles(false, rightThumbCurl, rightIndexCurl, rightMiddleCurl, rightRingCurl, + SetHandMuscles(false, rightThumbCurl, rightIndexCurl, rightMiddleCurl, rightRingCurl, rightPinkyCurl, rightSpreadFingers, ref humanPose); + // 3. 머슬 포즈 적용 (손가락 포함 전체 본에 영향) humanPoseHandler.SetHumanPose(ref humanPose); + + // 4. 손가락을 제외한 모든 본의 로컬 회전 복원 (본 길이 변형 방지) + foreach (var kvp in savedBoneLocalRotations) + { + Transform bone = animator.GetBoneTransform(kvp.Key); + if (bone != null) + { + bone.localRotation = kvp.Value; + } + } } private void SetHandMuscles(bool isLeft, float thumb, float index, float middle, float ring,