Fix : 신체가 길어지는 버그 해결

This commit is contained in:
KINDNICK 2025-12-14 21:50:35 +09:00
parent d2a28e133a
commit 52d9e9f548
2 changed files with 76 additions and 18 deletions

View File

@ -192,9 +192,10 @@ namespace KindRetargeting
private Dictionary<int, float[]> fingerFilterBuffers = new Dictionary<int, float[]>();
private Dictionary<int, int> fingerFilterIndices = new Dictionary<int, int>();
// CopyFingerPoseByMuscle에서 사용할 본 Transform 저장용 (메모리 재사용)
private Dictionary<HumanBodyBones, (Vector3 position, Quaternion rotation)> savedBoneTransforms =
new Dictionary<HumanBodyBones, (Vector3, Quaternion)>();
// CopyFingerPoseByMuscle에서 사용할 본 로컬 회전 저장용 (메모리 재사용)
// 위치는 SetHumanPose가 처리하므로 회전만 저장
private Dictionary<HumanBodyBones, Quaternion> savedBoneLocalRotations =
new Dictionary<HumanBodyBones, Quaternion>();
// 손가락을 제외한 모든 휴먼본 목록 (캐싱)
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;
}
}
}

View File

@ -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<HumanBodyBones, Quaternion> savedBoneLocalRotations = new Dictionary<HumanBodyBones, Quaternion>();
// 손가락을 제외한 모든 휴먼본 목록
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,