561 lines
22 KiB
C#
561 lines
22 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using RootMotion.FinalIK;
|
|
|
|
namespace KindRetargeting
|
|
{
|
|
[DefaultExecutionOrder(4)]
|
|
public class LimbWeightController : MonoBehaviour
|
|
{
|
|
[Header("거리 기반 가중치 설정")]
|
|
[SerializeField, Range(0.3f, 1f)] public float maxDistance = 0.5f; // 가중치가 0이 되는 최대 거리
|
|
[SerializeField, Range(0.05f, 0.3f)] public float minDistance = 0.1f; // 가중치가 1이 되는 최소 거리
|
|
|
|
[Header("마스터 가중치 변화 속도")]
|
|
[SerializeField, Range(0.1f, 20f)] public float weightSmoothSpeed = 10f; // 가중치 변화 속도
|
|
|
|
[Header("허리 가중치 설정")]
|
|
[SerializeField, Range(0.1f, 1f)] public float hipsMinDistance = 0.2f; // 최소 거리 (가중치 1)
|
|
[SerializeField, Range(0.1f, 1f)] public float hipsMaxDistance = 0.6f; // 최대 거리 (가중치 0)
|
|
|
|
[Header("바닥 기준 히프 보정")]
|
|
[SerializeField, Range(0.3f, 1f)] public float groundHipsMinHeight = 0f; // 최소 높이 (가중치 0)
|
|
[SerializeField, Range(0.5f, 1.5f)] public float groundHipsMaxHeight = 0.5f; // 최대 높이 (가중치 1)
|
|
|
|
[Header("발 높이 기반 가중치 설정")]
|
|
[SerializeField, Range(0.1f, 0.5f)] public float footHeightMinThreshold = 0.2f; // 최소 높이 (가중치 1)
|
|
[SerializeField, Range(0.5f, 1.0f)] public float footHeightMaxThreshold = 0.5f; // 최대 높이 (가중치 0)
|
|
|
|
[Header("IK 활성화 설정")]
|
|
[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;
|
|
private Dictionary<string, Dictionary<int, float>> weightLayers = new Dictionary<string, Dictionary<int, float>>();
|
|
|
|
List<float> leftArmEndWeights = new List<float>();
|
|
List<float> rightArmEndWeights = new List<float>();
|
|
List<float> leftLegEndWeights = new List<float>();
|
|
List<float> rightLegEndWeights = new List<float>();
|
|
|
|
List<float> leftLegBendWeights = new List<float>();
|
|
List<float> rightLegBendWeights = new List<float>();
|
|
|
|
private float MasterleftArmEndWeights = 0f;
|
|
private float MasterrightArmEndWeights = 0f;
|
|
private float MasterleftLegEndWeights = 0f;
|
|
private float MasterrightLegEndWeights = 0f;
|
|
private float MasterleftLegBendWeights = 0f;
|
|
private float MasterrightLegBendWeights = 0f;
|
|
|
|
public List<Transform> props = new List<Transform>();
|
|
|
|
public Transform characterRoot;
|
|
|
|
// 힙스 가중치 리스트 추가
|
|
List<float> hipsWeights = new List<float>();
|
|
private float MasterHipsWeight = 1f;
|
|
|
|
// 의자 좌석 높이 오프셋 (월드 Y 기준)
|
|
private float currentChairSeatOffset = 0f;
|
|
private float targetChairSeatOffset = 0f;
|
|
|
|
void Update()
|
|
{
|
|
//손의 거리를 기반으로한 가중치 적용
|
|
HandDistances();
|
|
|
|
//프랍과의 거리에 따른 가중치 적용
|
|
PropDistances();
|
|
|
|
// 마스터 변수에 가중치 적용
|
|
FinalizeWeights();
|
|
|
|
// 앉아있을 때 다리와의 거리에 따른 가중치 적용
|
|
SitLegDistances();
|
|
|
|
// 의자 타입 프랍과의 거리에 따른 가중치 적용
|
|
SitChairDistances();
|
|
|
|
// 바닥 기준 히프 보정 적용
|
|
UpdateGroundBasedHipsWeight();
|
|
|
|
// 발 높이에 따른 가중치 적용
|
|
UpdateFootHeightBasedWeight();
|
|
|
|
// FBIK에 최종 가중치 적용
|
|
ApplyWeightsToFBIK();
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
fbik = GetComponent<FullBodyInverseKinematics_RND>();
|
|
|
|
crs = GetComponent<CustomRetargetingScript>();
|
|
|
|
InitWeightLayers();
|
|
|
|
//프랍 오브젝트 찾기
|
|
props = FindObjectsByType<PropTypeController>(FindObjectsSortMode.None).Select(controller => controller.transform).ToList();
|
|
|
|
// 프랍 오브젝트 찾기
|
|
GetHand();
|
|
|
|
//HandDistances();에서 사용을 위한 리스트 추가
|
|
//손 거리에 따른 웨이트 업데이트 인덱스 0번
|
|
leftArmEndWeights.Add(0);
|
|
rightArmEndWeights.Add(0);
|
|
|
|
// 프랍과의 거리에 따른 웨이트 업데이트 인덱스 1번
|
|
leftArmEndWeights.Add(0);
|
|
rightArmEndWeights.Add(0);
|
|
|
|
// 앉아있을 때 다리와의 거리에 따른 가중치 적용 인덱스 0번
|
|
leftLegEndWeights.Add(0);
|
|
rightLegEndWeights.Add(0);
|
|
|
|
// 다리 골 가중치 초기화
|
|
leftLegBendWeights.Add(1f); // 기본 가중치
|
|
rightLegBendWeights.Add(1f); // 기본 가중치
|
|
|
|
// CharacterController가 있는 루트 오브젝트 찾기
|
|
|
|
|
|
if (characterRoot == null)
|
|
{
|
|
characterRoot = transform;
|
|
}
|
|
|
|
// 힙스 가중치 초기화 인덱스 0번
|
|
hipsWeights.Add(1f); // 의자 거리 기반 가중치
|
|
|
|
// 지면 높이 기반 가중치 초기화 인덱스 1번
|
|
hipsWeights.Add(1f); // 지면 높이 기반 가중치
|
|
|
|
// 발 높이 기반 가중치 초기화 인덱스 1번
|
|
leftLegEndWeights.Add(1f);
|
|
rightLegEndWeights.Add(1f);
|
|
}
|
|
|
|
private void GetHand()
|
|
{
|
|
// 모든 LimbWeightController 찾기
|
|
LimbWeightController[] allControllers = FindObjectsOfType<LimbWeightController>();
|
|
|
|
foreach (LimbWeightController controller in allControllers)
|
|
{
|
|
// 자기 자신은 제외
|
|
if (controller == this) continue;
|
|
|
|
// CustomRetargetingScript 가져오기
|
|
CustomRetargetingScript otherCrs = controller.GetComponent<CustomRetargetingScript>();
|
|
if (otherCrs == null) continue;
|
|
|
|
// 왼손과 오른손 Transform 가져오기
|
|
Transform leftHand = otherCrs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
|
|
Transform rightHand = otherCrs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
|
|
|
|
// 손이 존재하면 props 리스트에 추가
|
|
if (leftHand != null)
|
|
{
|
|
props.Add(leftHand);
|
|
}
|
|
if (rightHand != null)
|
|
{
|
|
props.Add(rightHand);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void InitWeightLayers()
|
|
{
|
|
fbik.solver.leftArm.positionWeight = 0f;
|
|
fbik.solver.leftArm.rotationWeight = 0f;
|
|
fbik.solver.leftArm.bendGoalWeight = 0f;
|
|
fbik.solver.rightArm.positionWeight = 0f;
|
|
fbik.solver.rightArm.rotationWeight = 0f;
|
|
fbik.solver.rightArm.bendGoalWeight = 0f;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 타겟과의 거리에 따라 가중치를 업데이트합니다.
|
|
/// </summary>
|
|
private void HandDistances()
|
|
{
|
|
if (fbik == null || crs == null) return;
|
|
|
|
// 왼쪽 팔 가중치 업데이트
|
|
if (fbik.solver.leftArm.target != null && fbik.solver.rightArm.target != null)
|
|
{
|
|
Transform leftHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
|
|
Transform rightHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
|
|
if (leftHandTransform != null && rightHandTransform != null &&
|
|
props != null && props.Count > 0)
|
|
{
|
|
float Distance = Vector3.Distance(leftHandTransform.position, rightHandTransform.position);
|
|
float Weight = 1f - Mathf.Clamp01((Distance - minDistance) / (maxDistance - minDistance));
|
|
leftArmEndWeights[0] = Weight;
|
|
rightArmEndWeights[0] = Weight;
|
|
}
|
|
else
|
|
{
|
|
// props가 없을 때 기본 가중치 설정
|
|
leftArmEndWeights[0] = 0f;
|
|
rightArmEndWeights[0] = 0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SitLegDistances()
|
|
{
|
|
if (fbik == null || crs == null || characterRoot == null) return;
|
|
|
|
Transform hips = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.Hips);
|
|
if (hips == null) return;
|
|
|
|
// 캐릭터 루트 기준으로 히프의 로컬 높이 계산
|
|
float hipHeight = characterRoot.InverseTransformPoint(hips.position).y;
|
|
|
|
// 기본적으로 다리 가중치를 1로 설정
|
|
leftLegEndWeights[0] = 1f;
|
|
rightLegEndWeights[0] = 1f;
|
|
|
|
// 바닥 기준 히프 보정 변수들을 활용한 앉아있는 판단
|
|
// groundHipsMaxHeight 이하일 때 앉아있다고 판단
|
|
if (hipHeight <= groundHipsMaxHeight)
|
|
{
|
|
// 왼쪽 다리 처리
|
|
ProcessSitLegWeight(hips, fbik.solver.leftLeg.target, leftLegEndWeights, 0);
|
|
|
|
// 오른쪽 다리 처리
|
|
ProcessSitLegWeight(hips, fbik.solver.rightLeg.target, rightLegEndWeights, 0);
|
|
}
|
|
}
|
|
|
|
private void ProcessSitLegWeight(Transform hips, Transform footTarget, List<float> weightList, int weightIndex)
|
|
{
|
|
if (footTarget == null) return;
|
|
|
|
// Y축을 제외한 실제 수평 거리 계산
|
|
Vector3 hipPos = hips.position;
|
|
Vector3 footPos = footTarget.position;
|
|
Vector3 hipPosFlat = new Vector3(hipPos.x, 0, hipPos.z);
|
|
Vector3 footPosFlat = new Vector3(footPos.x, 0, footPos.z);
|
|
float horizontalDistance = Vector3.Distance(hipPosFlat, footPosFlat);
|
|
|
|
// 다리 길이를 기준으로 최대/최소 허용 거리 설정
|
|
const float MAX_LEG_DISTANCE_RATIO = 0.8f; // 다리 길이의 80%
|
|
const float MIN_LEG_DISTANCE_RATIO = 0.3f; // 다리 길이의 30%
|
|
|
|
// 거리가 멀수록 가중치 감소
|
|
float weight = 1f - Mathf.Clamp01((horizontalDistance - MIN_LEG_DISTANCE_RATIO) /
|
|
(MAX_LEG_DISTANCE_RATIO - MIN_LEG_DISTANCE_RATIO));
|
|
|
|
weightList[weightIndex] = weight;
|
|
}
|
|
|
|
void PropDistances()
|
|
{
|
|
if (fbik == null || crs == null) return;
|
|
|
|
// 프랍과의 거리에 따른 웨이트 업데이트
|
|
Transform leftHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
|
|
Transform rightHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
|
|
|
|
if (leftHandTransform != null && rightHandTransform != null && props != null)
|
|
{
|
|
// 왼손과 프랍 사이의 최소 거리 계산
|
|
float minLeftDistance = float.MaxValue;
|
|
foreach (Transform prop in props)
|
|
{
|
|
float distance = Vector3.Distance(leftHandTransform.position, prop.position);
|
|
minLeftDistance = Mathf.Min(minLeftDistance, distance);
|
|
}
|
|
|
|
// 오른손과 프랍 사이의 최소 거리 계산
|
|
float minRightDistance = float.MaxValue;
|
|
foreach (Transform prop in props)
|
|
{
|
|
float distance = Vector3.Distance(rightHandTransform.position, prop.position);
|
|
minRightDistance = Mathf.Min(minRightDistance, distance);
|
|
}
|
|
|
|
// 거리에 따른 가중치 계산
|
|
float leftWeight = 1f - Mathf.Clamp01((minLeftDistance - minDistance) / (maxDistance - minDistance));
|
|
float rightWeight = 1f - Mathf.Clamp01((minRightDistance - minDistance) / (maxDistance - minDistance));
|
|
|
|
leftArmEndWeights[1] = leftWeight;
|
|
rightArmEndWeights[1] = rightWeight;
|
|
}
|
|
}
|
|
|
|
void SitChairDistances()
|
|
{
|
|
if (crs == null) return;
|
|
|
|
Transform hipsTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.Hips);
|
|
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);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 각 리스트의 최대 가중치 값을 마스터 변수에 부드럽게 설정합니다.
|
|
/// </summary>
|
|
public void FinalizeWeights()
|
|
{
|
|
float deltaTime = Time.deltaTime;
|
|
|
|
// 팔 가중치 계산 (최대값 사용)
|
|
MasterleftArmEndWeights = Mathf.Lerp(
|
|
MasterleftArmEndWeights,
|
|
GetMaxValue(leftArmEndWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
MasterrightArmEndWeights = Mathf.Lerp(
|
|
MasterrightArmEndWeights,
|
|
GetMaxValue(rightArmEndWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
|
|
// 다리 가중치 계산 (최소값 사용)
|
|
MasterleftLegEndWeights = Mathf.Lerp(
|
|
MasterleftLegEndWeights,
|
|
GetMinValue(leftLegEndWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
MasterrightLegEndWeights = Mathf.Lerp(
|
|
MasterrightLegEndWeights,
|
|
GetMinValue(rightLegEndWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
|
|
// 다리 골 가중치 계산
|
|
MasterleftLegBendWeights = Mathf.Lerp(
|
|
MasterleftLegBendWeights,
|
|
GetMinValue(leftLegBendWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
MasterrightLegBendWeights = Mathf.Lerp(
|
|
MasterrightLegBendWeights,
|
|
GetMinValue(rightLegBendWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
|
|
// 힙스 마스터 가중치 업데이트
|
|
MasterHipsWeight = Mathf.Lerp(
|
|
MasterHipsWeight,
|
|
GetMinValue(hipsWeights),
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
|
|
// 의자 좌석 높이 오프셋 스무딩 (월드 Y 기준)
|
|
currentChairSeatOffset = Mathf.Lerp(
|
|
currentChairSeatOffset,
|
|
targetChairSeatOffset,
|
|
weightSmoothSpeed * deltaTime
|
|
);
|
|
|
|
// CustomRetargetingScript에 최종 가중치 전달
|
|
if (crs != null)
|
|
{
|
|
crs.HipsWeightOffset = MasterHipsWeight;
|
|
crs.ChairSeatHeightOffset = currentChairSeatOffset;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 리스트에서 최대값을 찾습니다.
|
|
/// </summary>
|
|
private float GetMaxValue(List<float> list)
|
|
{
|
|
if (list.Count == 0) return 0f;
|
|
|
|
float max = list[0];
|
|
for (int i = 1; i < list.Count; i++)
|
|
{
|
|
if (list[i] > max)
|
|
{
|
|
max = list[i];
|
|
}
|
|
}
|
|
return max;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 리스트에서 최소값을 찾습니다.
|
|
/// </summary>
|
|
private float GetMinValue(List<float> list)
|
|
{
|
|
if (list.Count == 0) return 0f;
|
|
|
|
float min = list[0];
|
|
for (int i = 1; i < list.Count; i++)
|
|
{
|
|
if (list[i] < min)
|
|
{
|
|
min = list[i];
|
|
}
|
|
}
|
|
return min;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 마스터 가중치 값을 FBIK에 적용합니다.
|
|
/// </summary>
|
|
private void ApplyWeightsToFBIK()
|
|
{
|
|
if (fbik == null) return;
|
|
|
|
// 왼쪽 팔 가중치 적용
|
|
if (fbik.solver.leftArm != null)
|
|
{
|
|
if (fbik.solver.leftArm.target != null)
|
|
{
|
|
float finalLeftArmWeight = enableLeftArmIK ? MasterleftArmEndWeights : 0f;
|
|
fbik.solver.leftArm.positionWeight = finalLeftArmWeight;
|
|
fbik.solver.leftArm.rotationWeight = finalLeftArmWeight;
|
|
}
|
|
|
|
if (fbik.solver.leftArm.bendGoal != null)
|
|
fbik.solver.leftArm.bendGoalWeight = enableLeftArmIK ? MasterleftArmEndWeights : 0f;
|
|
}
|
|
|
|
// 오른쪽 팔 가중치 적용
|
|
if (fbik.solver.rightArm != null)
|
|
{
|
|
if (fbik.solver.rightArm.target != null)
|
|
{
|
|
float finalRightArmWeight = enableRightArmIK ? MasterrightArmEndWeights : 0f;
|
|
fbik.solver.rightArm.positionWeight = finalRightArmWeight;
|
|
fbik.solver.rightArm.rotationWeight = finalRightArmWeight;
|
|
}
|
|
|
|
if (fbik.solver.rightArm.bendGoal != null)
|
|
fbik.solver.rightArm.bendGoalWeight = enableRightArmIK ? MasterrightArmEndWeights : 0f;
|
|
}
|
|
|
|
// 왼쪽 다리 가중치 적용
|
|
if (fbik.solver.leftLeg != null)
|
|
{
|
|
if (fbik.solver.leftLeg.target != null)
|
|
{
|
|
fbik.solver.leftLeg.positionWeight = MasterleftLegEndWeights;
|
|
fbik.solver.leftLeg.rotationWeight = MasterleftLegEndWeights;
|
|
}
|
|
|
|
if (fbik.solver.leftLeg.bendGoal != null)
|
|
fbik.solver.leftLeg.bendGoalWeight = MasterleftLegBendWeights; // 골 가중치 적용
|
|
}
|
|
|
|
// 오른쪽 다리 가중치 적용
|
|
if (fbik.solver.rightLeg != null)
|
|
{
|
|
if (fbik.solver.rightLeg.target != null)
|
|
{
|
|
fbik.solver.rightLeg.positionWeight = MasterrightLegEndWeights;
|
|
fbik.solver.rightLeg.rotationWeight = MasterrightLegEndWeights;
|
|
}
|
|
|
|
if (fbik.solver.rightLeg.bendGoal != null)
|
|
fbik.solver.rightLeg.bendGoalWeight = MasterrightLegBendWeights; // 골 가중치 적용
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 바닥으로부터의 높이에 따라 히프 보정값을 조정합니다.
|
|
/// </summary>
|
|
private void UpdateGroundBasedHipsWeight()
|
|
{
|
|
if (crs == null || fbik == null || fbik == null) return;
|
|
|
|
Transform hipsTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.Hips);
|
|
if (hipsTransform != null)
|
|
{
|
|
float groundHeight = characterRoot.position.y;
|
|
float hipsHeight = hipsTransform.position.y - groundHeight;
|
|
|
|
float weight = Mathf.Clamp01((hipsHeight - groundHipsMinHeight) / (groundHipsMaxHeight - groundHipsMinHeight));
|
|
hipsWeights[1] = weight; // 직접 HipsWeightOffset 수정 대신 배열에 저장
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 발의 높이에 따라 IK 가중치를 조절합니다.
|
|
/// </summary>
|
|
private void UpdateFootHeightBasedWeight()
|
|
{
|
|
if (fbik == null || crs == null || characterRoot == null) return;
|
|
|
|
// 왼발 처리
|
|
ProcessFootHeightWeight(
|
|
fbik.solver.leftLeg.target,
|
|
leftLegEndWeights,
|
|
1 // 새로 추가된 레이어의 인덱스
|
|
);
|
|
|
|
// 오른발 처리
|
|
ProcessFootHeightWeight(
|
|
fbik.solver.rightLeg.target,
|
|
rightLegEndWeights,
|
|
1 // 새로 추가된 레이어의 인덱스
|
|
);
|
|
}
|
|
|
|
private void ProcessFootHeightWeight(Transform footTarget, List<float> weightList, int weightIndex)
|
|
{
|
|
if (footTarget == null) return;
|
|
|
|
// 캐릭터 루트 기준으로 발의 로컬 높이 계산
|
|
float footHeight = characterRoot.InverseTransformPoint(footTarget.position).y;
|
|
|
|
// 높이에 따른 가중치 계산 (높이가 높을수록 가중치 감소)
|
|
float weight = 1f - Mathf.Clamp01((footHeight - footHeightMinThreshold) /
|
|
(footHeightMaxThreshold - footHeightMinThreshold));
|
|
|
|
// 계산된 가중치 설정
|
|
weightList[weightIndex] = weight;
|
|
}
|
|
}
|
|
}
|