Streamingle_URP/Assets/Scripts/KindRetargeting/PropLocationController.cs

242 lines
8.7 KiB
C#

using UnityEngine;
using System.Collections.Generic;
using UniHumanoid;
namespace KindRetargeting
{
public class PropLocationController : MonoBehaviour
{
// 캐시된 타겟과 오프셋 Transform
[System.Serializable]
public class TargetOffset
{
public Transform target;
public Transform offset;
}
[SerializeField] private TargetOffset leftHandTargetOffset;
[SerializeField] private TargetOffset rightHandTargetOffset;
[SerializeField] private TargetOffset headTargetOffset;
private void Start()
{
CreateTargets();
}
public void SetTPose(Animator animator)
{
if (animator == null || animator.avatar == null)
return;
Avatar avatar = animator.avatar;
Transform transform = animator.transform;
// HumanPoseClip에 저장된 T-포즈 데이터를 로드하여 적용
var humanPoseClip = Resources.Load<HumanPoseClip>(HumanPoseClip.TPoseResourcePath);
if (humanPoseClip != null)
{
var pose = humanPoseClip.GetPose();
HumanPoseTransfer.SetPose(avatar, transform, pose);
}
else
{
Debug.LogWarning("T-Pose 데이터가 존재하지 않습니다.");
}
}
private void CreateTargets()
{
Animator animator = GetComponent<Animator>();
SetTPose(animator);
// 왼손 타겟 및 오프셋 설정
Transform leftHandBone = animator.GetBoneTransform(HumanBodyBones.LeftHand);
if (leftHandBone != null)
{
leftHandTargetOffset = new TargetOffset();
GameObject leftTarget = new GameObject("Left_Hand_Target");
leftTarget.transform.parent = leftHandBone; // 왼손 본에 직접 부모 설정
leftHandTargetOffset.target = leftTarget.transform;
leftTarget.transform.position = leftHandBone.position + new Vector3(-0.039f, -0.022f, 0f);
leftTarget.transform.rotation = Quaternion.Euler(90f, 0f, 0f);
GameObject leftOffset = new GameObject("Left_Hand_Offset");
leftOffset.transform.parent = leftTarget.transform;
leftHandTargetOffset.offset = leftOffset.transform;
// 로컬 포지션과 로테이션 설정
leftHandTargetOffset.offset.localPosition = Vector3.zero;
leftHandTargetOffset.offset.localRotation = Quaternion.identity;
}
// 오른손 타겟 및 오프셋 설정
Transform rightHandBone = animator.GetBoneTransform(HumanBodyBones.RightHand);
if (rightHandBone != null)
{
rightHandTargetOffset = new TargetOffset();
GameObject rightTarget = new GameObject("Right_Hand_Target");
rightTarget.transform.parent = rightHandBone; // 오른손 본에 직접 부모 설정
rightHandTargetOffset.target = rightTarget.transform;
rightTarget.transform.position = rightHandBone.position + new Vector3(0.039f, -0.022f, 0f);
rightTarget.transform.rotation = Quaternion.Euler(90f, 0f, 0f);
GameObject rightOffset = new GameObject("Right_Hand_Offset");
rightOffset.transform.parent = rightTarget.transform;
rightHandTargetOffset.offset = rightOffset.transform;
// 로컬 포지션과 로테이션 설정
rightHandTargetOffset.offset.localPosition = Vector3.zero;
rightHandTargetOffset.offset.localRotation = Quaternion.identity;
}
// 머리 타겟 및 오프셋 설정
Transform headBone = animator.GetBoneTransform(HumanBodyBones.Head);
if (headBone != null)
{
headTargetOffset = new TargetOffset();
GameObject headTarget = new GameObject("Head_Target");
headTarget.transform.parent = headBone; // 머리 본에 직접 부모 설정
headTargetOffset.target = headTarget.transform;
headTarget.transform.position = headBone.position + new Vector3(0f, 0.16f, 0f);
headTarget.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
GameObject headOffset = new GameObject("Head_Offset");
headOffset.transform.parent = headTarget.transform;
headTargetOffset.offset = headOffset.transform;
// 기본 오프셋 설정
headTargetOffset.offset.localPosition = Vector3.zero;
headTargetOffset.offset.localRotation = Quaternion.identity;
}
animator.enabled = true;
}
public void MoveToHead(GameObject targetObject)
{
if (headTargetOffset?.offset == null)
{
Debug.LogError("머리 타겟이 할당되지 않았습니다!");
return;
}
if (targetObject != null)
{
targetObject.transform.SetParent(headTargetOffset.offset);
targetObject.transform.localPosition = Vector3.zero;
targetObject.transform.localRotation = Quaternion.identity;
}
}
public void MoveToLeftHand(GameObject targetObject)
{
if (leftHandTargetOffset?.offset == null)
{
Debug.LogError("왼손 타겟이 할당되지 않았습니다!");
return;
}
if (targetObject != null)
{
targetObject.transform.SetParent(leftHandTargetOffset.offset);
targetObject.transform.localPosition = Vector3.zero;
targetObject.transform.localRotation = Quaternion.identity;
}
}
public void MoveToRightHand(GameObject targetObject)
{
if (rightHandTargetOffset?.offset == null)
{
Debug.LogError("오른손 타겟이 할당되지 않았습니다!");
return;
}
if (targetObject != null)
{
targetObject.transform.SetParent(rightHandTargetOffset.offset);
targetObject.transform.localPosition = Vector3.zero;
targetObject.transform.localRotation = Quaternion.identity;
}
}
public void DetachProp(GameObject targetObject)
{
if (targetObject != null)
{
targetObject.transform.SetParent(null);
targetObject.transform.localScale = Vector3.one;
}
else
{
Debug.LogWarning("해제할 오브젝트가 없습니다.");
}
}
// 에디터에서 사용할 메서드들
#if UNITY_EDITOR
public void MoveToHead()
{
MoveToHead(UnityEditor.Selection.activeGameObject);
}
public void MoveToLeftHand()
{
MoveToLeftHand(UnityEditor.Selection.activeGameObject);
}
public void MoveToRightHand()
{
MoveToRightHand(UnityEditor.Selection.activeGameObject);
}
public void DetachProp()
{
DetachProp(UnityEditor.Selection.activeGameObject);
}
#endif
// 오프셋 getter 메서드들 추가
public Transform GetLeftHandOffset()
{
return leftHandTargetOffset?.offset;
}
public Transform GetRightHandOffset()
{
return rightHandTargetOffset?.offset;
}
public Transform GetHeadOffset()
{
return headTargetOffset?.offset;
}
public GameObject[] GetHeadProps()
{
if (headTargetOffset?.offset == null) return new GameObject[0];
return GetChildObjects(headTargetOffset.offset);
}
public GameObject[] GetLeftHandProps()
{
if (leftHandTargetOffset?.offset == null) return new GameObject[0];
return GetChildObjects(leftHandTargetOffset.offset);
}
public GameObject[] GetRightHandProps()
{
if (rightHandTargetOffset?.offset == null) return new GameObject[0];
return GetChildObjects(rightHandTargetOffset.offset);
}
private GameObject[] GetChildObjects(Transform parent)
{
List<GameObject> children = new List<GameObject>();
for (int i = 0; i < parent.childCount; i++)
{
children.Add(parent.GetChild(i).gameObject);
}
return children.ToArray();
}
}
}