136 lines
3.8 KiB
C#
136 lines
3.8 KiB
C#
using UnityEngine;
|
|
|
|
[DefaultExecutionOrder(16001)]
|
|
public class SimplePoseTransfer : MonoBehaviour
|
|
{
|
|
[Header("Pose Transfer Settings")]
|
|
public Animator sourceBone;
|
|
public Animator[] targetBones;
|
|
|
|
// 캐싱된 Transform들
|
|
private Transform[] cachedSourceBones;
|
|
private Transform[,] cachedTargetBones;
|
|
|
|
// 각 targetBone의 초기 회전 차이를 저장
|
|
private Quaternion[,] boneRotationDifferences;
|
|
|
|
private void Start()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
if (targetBones == null || targetBones.Length == 0)
|
|
{
|
|
Debug.LogError("Target bones are null or empty");
|
|
return;
|
|
}
|
|
|
|
if (sourceBone == null)
|
|
{
|
|
Debug.LogError("Source bone is null");
|
|
return;
|
|
}
|
|
|
|
InitializeTargetBones();
|
|
CacheAllBoneTransforms();
|
|
|
|
Debug.Log($"SimplePoseTransfer initialized with {targetBones.Length} targets");
|
|
}
|
|
|
|
private void InitializeTargetBones()
|
|
{
|
|
boneRotationDifferences = new Quaternion[targetBones.Length, 55];
|
|
|
|
for (int i = 0; i < targetBones.Length; i++)
|
|
{
|
|
if (targetBones[i] == null)
|
|
{
|
|
Debug.LogError($"targetBones[{i}] is null");
|
|
continue;
|
|
}
|
|
|
|
// 55개의 휴머노이드 본에 대해 회전 차이 계산
|
|
for (int j = 0; j < 55; j++)
|
|
{
|
|
Transform sourceBoneTransform = sourceBone.GetBoneTransform((HumanBodyBones)j);
|
|
Transform targetBoneTransform = targetBones[i].GetBoneTransform((HumanBodyBones)j);
|
|
|
|
if (sourceBoneTransform != null && targetBoneTransform != null)
|
|
{
|
|
boneRotationDifferences[i, j] = Quaternion.Inverse(sourceBoneTransform.rotation) * targetBoneTransform.rotation;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CacheAllBoneTransforms()
|
|
{
|
|
// 소스 본 캐싱
|
|
cachedSourceBones = new Transform[55];
|
|
for (int i = 0; i < 55; i++)
|
|
{
|
|
cachedSourceBones[i] = sourceBone.GetBoneTransform((HumanBodyBones)i);
|
|
}
|
|
|
|
// 타겟 본 캐싱
|
|
cachedTargetBones = new Transform[targetBones.Length, 55];
|
|
for (int t = 0; t < targetBones.Length; t++)
|
|
{
|
|
for (int i = 0; i < 55; i++)
|
|
{
|
|
cachedTargetBones[t, i] = targetBones[t].GetBoneTransform((HumanBodyBones)i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
TransferPoses();
|
|
}
|
|
|
|
private void TransferPoses()
|
|
{
|
|
if (sourceBone == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < targetBones.Length; i++)
|
|
{
|
|
if (targetBones[i] != null && targetBones[i].gameObject.activeInHierarchy)
|
|
{
|
|
TransferPoseToTarget(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TransferPoseToTarget(int targetIndex)
|
|
{
|
|
Animator targetBone = targetBones[targetIndex];
|
|
|
|
// 루트 회전 동기화
|
|
targetBone.transform.rotation = sourceBone.transform.rotation;
|
|
|
|
// 모든 본에 대해 포즈 전송
|
|
for (int i = 0; i < 55; i++)
|
|
{
|
|
Transform targetBoneTransform = cachedTargetBones[targetIndex, i];
|
|
Transform sourceBoneTransform = cachedSourceBones[i];
|
|
|
|
if (targetBoneTransform != null && sourceBoneTransform != null)
|
|
{
|
|
// 회전 적용
|
|
targetBoneTransform.rotation = sourceBoneTransform.rotation * boneRotationDifferences[targetIndex, i];
|
|
|
|
// 펠비스 위치 동기화 (HumanBodyBones.Hips = 0)
|
|
if (i == 0)
|
|
{
|
|
targetBoneTransform.position = sourceBoneTransform.position;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |