Merge remote-tracking branch 'origin/Chair-Response-System'

This commit is contained in:
DESKTOP-S4BOTN2\user 2025-12-01 12:03:50 +09:00
commit f686524ca8
5 changed files with 85 additions and 3 deletions

Binary file not shown.

View File

@ -38,6 +38,7 @@ namespace KindRetargeting
private float hipsOffsetZ = 0f; // 캐릭터 기준 앞뒤 (항상 Forward 방향)
[HideInInspector] public float HipsWeightOffset = 1f;
[HideInInspector] public float ChairSeatHeightOffset = 0f; // 의자 좌석 높이 오프셋 (월드 Y 기준)
// 축 매핑: 월드 방향(Right/Up/Forward)을 담당하는 로컬 축을 저장
// 예: localAxisForWorldRight = (0, 0, 1) 이면 로컬 Z축이 월드 Right 방향을 담당
@ -164,6 +165,8 @@ namespace KindRetargeting
public List<RotationOffsetData> fingerCloseRotationsCache;
// 소스 머슬 캘리브레이션 데이터
public List<MuscleCalibrationData> sourceMuscleCalibrationCache;
// 의자 앉기 높이 오프셋 (LimbWeightController)
public float chairSeatHeightOffset;
}
[System.Serializable]
@ -624,6 +627,10 @@ namespace KindRetargeting
muscleCalibrationCache.Add(new MuscleCalibrationData(kvp.Key, kvp.Value.open, kvp.Value.close));
}
// LimbWeightController에서 의자 높이 오프셋 가져오기
var limbController = GetComponent<LimbWeightController>();
float chairOffset = limbController != null ? limbController.chairSeatHeightOffset : 0.05f;
var settings = new RetargetingSettings
{
hipsOffsetX = hipsOffsetX,
@ -647,6 +654,7 @@ namespace KindRetargeting
fingerOpenRotationsCache = fingerOpenCache,
fingerCloseRotationsCache = fingerCloseCache,
sourceMuscleCalibrationCache = muscleCalibrationCache,
chairSeatHeightOffset = chairOffset,
};
string json = JsonUtility.ToJson(settings, true);
@ -740,6 +748,13 @@ namespace KindRetargeting
// Mingle 캘리브레이션 완료 여부 확인
isMingleCalibrated = fingerOpenRotations.Count > 0 && fingerCloseRotations.Count > 0;
// LimbWeightController에 의자 높이 오프셋 적용
var limbController = GetComponent<LimbWeightController>();
if (limbController != null)
{
limbController.chairSeatHeightOffset = settings.chairSeatHeightOffset;
}
//너무 자주 출력되어서 주석처리
//Debug.Log($"설정을 로드했습니다: {filePath}");
}
@ -1601,6 +1616,9 @@ namespace KindRetargeting
// 4. 바닥 높이 추가 (월드 Y축 - 바닥은 항상 월드 기준)
adjustedPosition.y += floorHeight;
// 5. 의자 좌석 높이 오프셋 추가 (월드 Y축 - 로컬 보정과 별개)
adjustedPosition.y += ChairSeatHeightOffset;
targetHips.position = adjustedPosition;
// 6. IK 타겟에도 동기화

View File

@ -20,6 +20,7 @@ namespace KindRetargeting
SerializedProperty footHeightMaxThreshold;
SerializedProperty enableLeftArmIK;
SerializedProperty enableRightArmIK;
SerializedProperty chairSeatHeightOffset;
private bool showDistanceSettings = true;
private bool showWeightSettings = true;
@ -28,6 +29,7 @@ namespace KindRetargeting
private bool showGroundHipsSettings = true;
private bool showFootHeightSettings = true;
private bool showIKActivationSettings = true;
private bool showChairSeatSettings = true;
protected override void OnEnable()
{
@ -50,6 +52,7 @@ namespace KindRetargeting
footHeightMaxThreshold = serializedObject.FindProperty("footHeightMaxThreshold");
enableLeftArmIK = serializedObject.FindProperty("enableLeftArmIK");
enableRightArmIK = serializedObject.FindProperty("enableRightArmIK");
chairSeatHeightOffset = serializedObject.FindProperty("chairSeatHeightOffset");
}
}
@ -170,6 +173,15 @@ namespace KindRetargeting
EditorGUI.indentLevel--;
}
EditorGUILayout.Space(5);
showChairSeatSettings = EditorGUILayout.Foldout(showChairSeatSettings, "의자 앉기 높이 설정", true);
if (showChairSeatSettings)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(chairSeatHeightOffset, new GUIContent("좌석 높이 오프셋", "의자에 앉을 때 엉덩이가 좌석면에서 떠있는 높이 (월드 Y 기준)"));
EditorGUI.indentLevel--;
}
EditorGUILayout.Space(5);
showReferences = EditorGUILayout.Foldout(showReferences, "참조 설정", true);
if (showReferences)

View File

@ -295,6 +295,24 @@ public class RetargetingControlWindow : EditorWindow
EditorGUILayout.Slider(hipsOffsetZProp, -1f, 1f,
new GUIContent("← 앞뒤 →", "캐릭터 기준 뒤(-) / 앞(+)"));
// 의자 앉기 높이 설정 (월드 Y 기준)
EditorGUILayout.Space(5);
var limb = script.GetComponent<LimbWeightController>();
if (limb != null)
{
var serializedLimb = new SerializedObject(limb);
serializedLimb.Update();
var chairSeatHeightOffset = serializedLimb.FindProperty("chairSeatHeightOffset");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Slider(chairSeatHeightOffset, -1f, 1f,
new GUIContent("의자 앉기 높이", "의자에 앉을 때 엉덩이 높이 조정 (월드 Y 기준)"));
if (EditorGUI.EndChangeCheck())
{
serializedLimb.ApplyModifiedProperties();
EditorUtility.SetDirty(limb);
}
}
EditorGUI.indentLevel--;
}

View File

@ -32,6 +32,11 @@ namespace KindRetargeting
[SerializeField] public bool enableLeftArmIK = true; // 왼팔 IK 활성화 여부
[SerializeField] public bool enableRightArmIK = true; // 오른팔 IK 활성화 여부
[Header("의자 앉기 높이 설정")]
[Tooltip("의자에 앉을 때 엉덩이 높이 조정 (월드 Y 기준, +: 위로, -: 아래로)")]
[SerializeField, Range(-1f, 1f)]
public float chairSeatHeightOffset = 0.05f;
private FullBodyInverseKinematics_RND fbik;
private CustomRetargetingScript crs;
@ -60,6 +65,10 @@ namespace KindRetargeting
List<float> hipsWeights = new List<float>();
private float MasterHipsWeight = 1f;
// 의자 좌석 높이 오프셋 (월드 Y 기준)
private float currentChairSeatOffset = 0f;
private float targetChairSeatOffset = 0f;
void Update()
{
//손의 거리를 기반으로한 가중치 적용
@ -297,18 +306,35 @@ namespace KindRetargeting
if (hipsTransform != null && props != null)
{
float minDistance = float.MaxValue;
bool foundChair = false;
foreach (Transform prop in props)
{
PropTypeController ptc = prop.GetComponent<PropTypeController>();
if (ptc != null && ptc.propType == EnumsList.PropType.Chair)
{
float distance = Vector3.Distance(hipsTransform.position, prop.childCount > 0 ? prop.GetChild(0).position : prop.position);
minDistance = Mathf.Min(minDistance, distance);
if (distance < minDistance)
{
minDistance = distance;
foundChair = true;
}
}
}
float t = Mathf.Clamp01((minDistance - hipsMinDistance) / (hipsMaxDistance - hipsMinDistance));
hipsWeights[0] = t; // 직접 HipsWeightOffset 수정 대신 배열에 저장
// 의자 좌석 높이 오프셋 계산 (가까울수록 더 적용) - 캐릭터별 설정 사용
if (foundChair)
{
// t가 0에 가까울수록 의자에 가까움 → 좌석 오프셋 더 적용
targetChairSeatOffset = chairSeatHeightOffset * (1f - t);
}
else
{
targetChairSeatOffset = 0f;
}
}
}
@ -362,10 +388,18 @@ namespace KindRetargeting
weightSmoothSpeed * deltaTime
);
// 의자 좌석 높이 오프셋 스무딩 (월드 Y 기준)
currentChairSeatOffset = Mathf.Lerp(
currentChairSeatOffset,
targetChairSeatOffset,
weightSmoothSpeed * deltaTime
);
// CustomRetargetingScript에 최종 가중치 전달
if (crs != null)
{
crs.HipsWeightOffset = MasterHipsWeight;
crs.ChairSeatHeightOffset = currentChairSeatOffset;
}
}