Add : 페이셜 녹화 안되는 버그 해결

This commit is contained in:
KINDNICK 2025-07-29 01:26:39 +09:00
parent 57ff5e65a7
commit d05ec6738f
5 changed files with 5399 additions and 14 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,9 @@ namespace EasyMotionRecorder
[SerializeField] [SerializeField]
public List<float> BlendShapeValues = new List<float>(); public List<float> BlendShapeValues = new List<float>();
[SerializeField]
public List<string> SkinnedMeshRendererNames = new List<string>();
[SerializeField] [SerializeField]
public int FrameCount; public int FrameCount;

View File

@ -50,7 +50,11 @@ namespace Entum {
private int _frameCount = 0; private int _frameCount = 0;
CharacterFacialData.SerializeHumanoidFace _past = new CharacterFacialData.SerializeHumanoidFace(); CharacterFacialData.SerializeHumanoidFace _past = new CharacterFacialData.SerializeHumanoidFace() {
BlendShapeNames = new List<string>(),
BlendShapeValues = new List<float>(),
SkinnedMeshRendererNames = new List<string>()
};
private float _recordedTime = 0f; private float _recordedTime = 0f;
private float _startTime; private float _startTime;
@ -152,29 +156,90 @@ namespace Entum {
var clip = new AnimationClip(); var clip = new AnimationClip();
clip.frameRate = 30; clip.frameRate = 30;
var blendShapeNames = facial.Faces[0].BlendShapeNames; // 블렌드쉐이프와 렌더러별로 애니메이션 커브를 그룹화
var curves = new Dictionary<string, AnimationCurve>(); var rendererCurves = new Dictionary<string, Dictionary<string, AnimationCurve>>();
for(int i = 0; i < blendShapeNames.Count; i++) { // 첫 번째 프레임에서 모든 블렌드쉐이프와 렌더러 정보 수집
curves[blendShapeNames[i]] = new AnimationCurve(); if (facial.Faces.Count > 0)
{
var firstFace = facial.Faces[0];
// 기존 데이터 호환성 체크 (SkinnedMeshRendererNames가 없는 경우)
bool hasRendererNames = firstFace.SkinnedMeshRendererNames != null &&
firstFace.SkinnedMeshRendererNames.Count > 0;
for(int i = 0; i < firstFace.BlendShapeNames.Count; i++) {
var blendShapeName = firstFace.BlendShapeNames[i];
var rendererName = hasRendererNames && i < firstFace.SkinnedMeshRendererNames.Count
? firstFace.SkinnedMeshRendererNames[i]
: "DefaultRenderer"; // 기존 데이터 호환성을 위한 기본값
if (!rendererCurves.ContainsKey(rendererName)) {
rendererCurves[rendererName] = new Dictionary<string, AnimationCurve>();
}
if (!rendererCurves[rendererName].ContainsKey(blendShapeName)) {
rendererCurves[rendererName][blendShapeName] = new AnimationCurve();
}
}
if (!hasRendererNames) {
Debug.LogWarning("기존 데이터 형식 감지: SkinnedMeshRenderer 정보가 없습니다. 기본 경로를 사용합니다.");
}
} }
for(int i = 0; i < facial.Faces.Count; i++) { // 모든 프레임의 데이터를 커브에 추가
var face = facial.Faces[i]; for(int frameIdx = 0; frameIdx < facial.Faces.Count; frameIdx++) {
var face = facial.Faces[frameIdx];
var time = face.Time; var time = face.Time;
// 기존 데이터 호환성 체크
bool hasRendererNames = face.SkinnedMeshRendererNames != null &&
face.SkinnedMeshRendererNames.Count > 0;
for(int j = 0; j < face.BlendShapeNames.Count; j++) { for(int i = 0; i < face.BlendShapeNames.Count; i++) {
var blendShapeName = face.BlendShapeNames[j]; var blendShapeName = face.BlendShapeNames[i];
var value = face.BlendShapeValues[j]; var value = face.BlendShapeValues[i];
var rendererName = hasRendererNames && i < face.SkinnedMeshRendererNames.Count
? face.SkinnedMeshRendererNames[i]
: "DefaultRenderer"; // 기존 데이터 호환성을 위한 기본값
if(curves.ContainsKey(blendShapeName)) { if (rendererCurves.ContainsKey(rendererName) &&
curves[blendShapeName].AddKey(time, value); rendererCurves[rendererName].ContainsKey(blendShapeName)) {
rendererCurves[rendererName][blendShapeName].AddKey(time, value);
} }
} }
} }
foreach(var curve in curves) { // 렌더러별로 애니메이션 커브를 클립에 추가
clip.SetCurve("", typeof(SkinnedMeshRenderer), "blendShape." + curve.Key, curve.Value); foreach(var rendererPair in rendererCurves) {
var rendererName = rendererPair.Key;
var curves = rendererPair.Value;
string rendererPath;
// 기존 데이터 호환성: DefaultRenderer인 경우 빈 경로 사용
if (rendererName == "DefaultRenderer") {
rendererPath = "";
Debug.Log($"기존 데이터 호환성: 빈 경로로 {curves.Count}개 블렌드쉐이프 커브 추가");
} else {
// 해당 렌더러의 Transform 경로 찾기
rendererPath = FindRendererPath(root.transform, rendererName);
if (string.IsNullOrEmpty(rendererPath)) {
Debug.LogWarning($"렌더러 '{rendererName}'의 경로를 찾을 수 없습니다. 루트 경로를 사용합니다.");
rendererPath = rendererName;
}
Debug.Log($"렌더러 '{rendererName}' ({rendererPath})에 {curves.Count}개 블렌드쉐이프 커브 추가");
}
foreach(var curvePair in curves) {
var blendShapeName = curvePair.Key;
var curve = curvePair.Value;
clip.SetCurve(rendererPath, typeof(SkinnedMeshRenderer), "blendShape." + blendShapeName, curve);
}
} }
// 캐릭터 이름 가져오기 // 캐릭터 이름 가져오기
@ -198,6 +263,29 @@ namespace Entum {
#endif #endif
} }
/// <summary>
/// 지정된 렌더러 이름의 Transform 경로를 찾습니다.
/// </summary>
private string FindRendererPath(Transform root, string rendererName) {
if (root.name == rendererName) {
return "";
}
for (int i = 0; i < root.childCount; i++) {
var child = root.GetChild(i);
if (child.name == rendererName) {
return child.name;
}
string childPath = FindRendererPath(child, rendererName);
if (!string.IsNullOrEmpty(childPath)) {
return child.name + "/" + childPath;
}
}
return null;
}
private string GetCharacterName() private string GetCharacterName()
{ {
if (_animRecorder?.CharacterAnimator == null) return ""; if (_animRecorder?.CharacterAnimator == null) return "";
@ -272,10 +360,25 @@ namespace Entum {
return false; return false;
} }
if(a.SkinnedMeshRendererNames.Count != b.SkinnedMeshRendererNames.Count) {
return false;
}
for(int i = 0; i < a.BlendShapeNames.Count; i++) { for(int i = 0; i < a.BlendShapeNames.Count; i++) {
if(a.BlendShapeValues[i] != b.BlendShapeValues[i]) { if(a.BlendShapeValues[i] != b.BlendShapeValues[i]) {
return false; return false;
} }
if(a.BlendShapeNames[i] != b.BlendShapeNames[i]) {
return false;
}
// SkinnedMeshRenderer 이름도 비교
if(i < a.SkinnedMeshRendererNames.Count && i < b.SkinnedMeshRendererNames.Count) {
if(a.SkinnedMeshRendererNames[i] != b.SkinnedMeshRendererNames[i]) {
return false;
}
}
} }
return true; return true;
@ -300,6 +403,7 @@ namespace Entum {
var current = new CharacterFacialData.SerializeHumanoidFace(); var current = new CharacterFacialData.SerializeHumanoidFace();
current.BlendShapeNames = new List<string>(); current.BlendShapeNames = new List<string>();
current.BlendShapeValues = new List<float>(); current.BlendShapeValues = new List<float>();
current.SkinnedMeshRendererNames = new List<string>();
for(int i = 0; i < _smeshs.Length; i++) { for(int i = 0; i < _smeshs.Length; i++) {
var mesh = _smeshs[i]; var mesh = _smeshs[i];
@ -324,6 +428,7 @@ namespace Entum {
var weight = mesh.GetBlendShapeWeight(j); var weight = mesh.GetBlendShapeWeight(j);
current.BlendShapeNames.Add(blendShapeName); current.BlendShapeNames.Add(blendShapeName);
current.BlendShapeValues.Add(weight); current.BlendShapeValues.Add(weight);
current.SkinnedMeshRendererNames.Add(mesh.name);
} }
} }