kinectManager


using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; using Kinect = Windows.Kinect; public class WarmUpGame : MonoBehaviour { public enum ExerciseAction { ArmRaise, // 举双手 HeadShake, // 摇头 LegLift, // 抬脚 Jump, // 跳跃 RightBend, // 向右弯腰 Bow, // 鞠躬 Run, // 原地跑步 Squat // 深蹲 } private KinectManager _kinectManager; private ExerciseAction _currentAction; private int _actionCount = 0; private int _score = 0; public float _timeRemaining = 30f; private bool _gameActive = true; public Animator _animator; [Header("UI Elements")] public Text actionText; public Text countText; public Text scoreText; public Text timerText; public Text debugText; // 新增调试信息显示 [Header("Animation Settings")] public float animationSpeed = 1.0f; [Header("Game Settings")] public int targetCount = 5; public float actionThreshold = 0.6f; public int validationFrames = 10; // 动作确认所需连续帧数 // 新增灵敏度参数 [Header("Sensitivity Settings")] public float headShakeSensitivity = 0.3f; public float legLiftSensitivity = 0.7f; public float jumpSensitivity = 0.5f; public float bendSensitivity = 0.5f; [Header("Sensitivity Settings")] public float armRaiseAngleThreshold = 150f; // 手臂伸直角度阈值 public float bowAngleThreshold = 30f; // 鞠躬角度阈值 public float armHeightThreshold = 0.2f; // 手臂高度阈值(相对于头部) public float headDropThreshold = 0.15f; // 头部下降阈值 public float spineBendThreshold = 25f; // 脊柱弯曲阈值 // 动作状态跟踪 private Dictionary<ExerciseAction, bool> _actionValidated = new Dictionary<ExerciseAction, bool>(); private Dictionary<ExerciseAction, int> _validationCounters = new Dictionary<ExerciseAction, int>(); private Queue<Vector3> _headPositionHistory = new Queue<Vector3>(); private Vector3 _lastSpineBasePosition; private float _lastHeadRotation; private bool _lastLegLiftState; private Vector3 _initialHipPosition; private Vector3 _lastFootPosition; private Vector3 _initialHeadPosition; private Vector3 _initialSpineShoulderPosition; private Vector3 _initialSpineBasePosition; public bool feetOffGround; private float _lastBowDetectionTime; public float jumpHeight; public float headDrop; public float shoulderHipHeightDiff; private float _initialSpineLength; public float spineAngle; public Vector3 spineBase; void Start() { _initialSpineLength = 0.5f; // 默认值 _kinectManager = KinectManager.Instance; if (_animator != null) _animator.speed = animationSpeed; InitializeActionSystems(); // 记录初始位置 if (_kinectManager.IsUserDetected()) { long userId = _kinectManager.GetUserIdByIndex(0); _initialHeadPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); _initialSpineShoulderPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); _initialSpineBasePosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); _initialHipPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); } if (_kinectManager.IsUserDetected()) { long userId = _kinectManager.GetUserIdByIndex(0); _lastSpineBasePosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); } _lastSpineBasePosition = Vector3.zero; _initialHipPosition = Vector3.zero; _initialHeadPosition = Vector3.zero; // 强制初始化计数器 foreach (var key in _validationCounters.Keys.ToList()) { _validationCounters[key] = 0; } if (_kinectManager.IsUserDetected()) { long userId = _kinectManager.GetUserIdByIndex(0); Vector3 spineShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); Vector3 spineBase = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); // ===== 添加位置有效性检查 ===== if (spineShoulder != Vector3.zero && spineBase != Vector3.zero) { // 记录初始脊柱长度 _initialSpineLength = Vector3.Distance(spineShoulder, spineBase); Debug.Log($"脊柱长度初始化: {_initialSpineLength:F3}m"); } else { // 使用默认值避免除零错误 _initialSpineLength = 0.5f; // 成年人平均脊柱长度 Debug.LogWarning("脊柱关节位置无效,使用默认长度"); } } else { // 无用户时的备选方案 _initialSpineLength = 0.5f; } StartNewAction(); StartCoroutine(GameTimer()); } void InitializeActionSystems() { foreach (ExerciseAction action in System.Enum.GetValues(typeof(ExerciseAction))) { _actionValidated[action] = false; _validationCounters[action] = 0; } } IEnumerator GameTimer() { while (_timeRemaining > 0 && _gameActive) { yield return new WaitForSeconds(1f); _timeRemaining--; timerText.text = $"时间: {_timeRemaining}s"; } if (_gameActive) { _gameActive = false; actionText.text = "游戏结束!"; if (_animator != null) _animator.enabled = false; } } void StartNewAction() { List<ExerciseAction> availableActions = new List<ExerciseAction>((ExerciseAction[])System.Enum.GetValues(typeof(ExerciseAction))); if (availableActions.Count > 1 && availableActions.Contains(_currentAction)) availableActions.Remove(_currentAction); _lastBowDetectionTime = Time.time - 2f; // 确保可以立即检测 _currentAction = availableActions[Random.Range(0, availableActions.Count)]; _actionCount = 0; countText.text = $"0/{targetCount}"; actionText.text = GetActionName(_currentAction); // 重置所有验证状态 foreach (var key in new List<ExerciseAction>(_validationCounters.Keys)) { _validationCounters[key] = 0; _actionValidated[key] = false; } // 重置初始位置记录 if (_kinectManager.IsUserDetected()) { long userId = _kinectManager.GetUserIdByIndex(0); _initialHipPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HipLeft); } if (_animator != null) PlayActionAnimation(_currentAction); if (_kinectManager.IsUserDetected()) { long userId = _kinectManager.GetUserIdByIndex(0); Vector3 spineShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); Vector3 spineBase = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); // 记录初始脊柱长度 _initialSpineLength = Vector3.Distance(spineShoulder, spineBase); } } void PlayActionAnimation(ExerciseAction action) { foreach (ExerciseAction a in System.Enum.GetValues(typeof(ExerciseAction))) { _animator.SetBool(a.ToString(), false); } _animator.SetBool(action.ToString(), true); } string GetActionName(ExerciseAction action) { switch (action) { case ExerciseAction.ArmRaise: return "举双手"; case ExerciseAction.HeadShake: return "摇头"; case ExerciseAction.LegLift: return "抬左脚"; case ExerciseAction.Jump: return "跳跃"; case ExerciseAction.RightBend: return "向右弯腰"; case ExerciseAction.Bow: return "鞠躬"; case ExerciseAction.Run: return "原地跑步"; case ExerciseAction.Squat: return "深蹲"; default: return "未知动作"; } } void Update() { if (!_gameActive || !_kinectManager.IsUserDetected()) { debugText.text = "等待用户..."; return; } long userId = _kinectManager.GetUserIdByIndex(0); UpdateActionDetection(userId); // 显示当前动作的调试信息 ShowDebugInfo(userId); } void UpdateActionDetection(long userId) { bool actionDetected = false; switch (_currentAction) { case ExerciseAction.ArmRaise: actionDetected = ValidateArmRaise(userId); break; case ExerciseAction.HeadShake: actionDetected = ValidateHeadShake(userId); break; case ExerciseAction.LegLift: actionDetected = ValidateLegLift(userId); break; case ExerciseAction.Jump: actionDetected = ValidateJump(userId); break; case ExerciseAction.RightBend: actionDetected = ValidateRightBend(userId); break; case ExerciseAction.Bow: actionDetected = ValidateBow(userId); break; case ExerciseAction.Run: actionDetected = ValidateRunning(userId); break; case ExerciseAction.Squat: actionDetected = ValidateSquat(userId); break; } if (actionDetected) { if (!_actionValidated[_currentAction]) { _actionCount++; countText.text = $"{_actionCount}/{targetCount}"; _actionValidated[_currentAction] = true; if (_actionCount >= targetCount) { _score += 50; scoreText.text = $"分数: {_score}"; StartNewAction(); } } } else { _actionValidated[_currentAction] = false; } } // 显示调试信息 void ShowDebugInfo(long userId) { string debugInfo = $"当前动作: {_currentAction}\n"; switch (_currentAction) { case ExerciseAction.HeadShake: Vector3 headPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); Vector3 neckPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Neck); float headRotation = Vector3.Angle(Vector3.up, headPosition - neckPosition); debugInfo += $"头部旋转: {headRotation:F1}°\n阈值: >20°"; break; case ExerciseAction.LegLift: Vector3 hipLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HipLeft); Vector3 ankleLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.AnkleLeft); float liftHeight = ankleLeft.y - hipLeft.y; debugInfo += $"抬腿高度: {liftHeight:F2}m\n阈值: >{legLiftSensitivity:F2}m"; break; case ExerciseAction.Jump: // 强制获取实时数据 Vector3 spineBaseNow = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); Vector3 initialHipNow = _initialHipPosition; debugInfo = $"当前脊柱Y: {spineBaseNow.y:F3}m | 初始Y: {initialHipNow.y:F3}m\n"; debugInfo += $"高度差: {jumpHeight:F3}m | 离地: {feetOffGround}\n"; // 添加速度显示 if (_lastSpineBasePosition != Vector3.zero) { Vector3 velocity = (spineBaseNow - _lastSpineBasePosition) / Time.deltaTime; debugInfo += $"速度Y: {velocity.y:F2}m/s\n"; } debugInfo += $"计数器: {_validationCounters[_currentAction]}/2"; break; case ExerciseAction.RightBend: Vector3 shoulderCenter = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); Vector3 hipCenter = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); Vector3 spineVector = hipCenter - shoulderCenter; float bendAngle = Vector3.Angle(spineVector, Vector3.up); debugInfo += $"弯曲角度: {bendAngle:F1}°\n阈值: >20°"; break; case ExerciseAction.Bow: Vector3 spineShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); spineBase = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); Vector3 headPos = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); Vector3 neck = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Neck); float spineLength = Vector3.Distance(spineShoulder, spineBase); string compressionInfo = "N/A"; if (_initialSpineLength > 0.01f) { float compression = 1 - (spineLength / _initialSpineLength); compressionInfo = $"{compression * 100:F1}%"; } debugInfo = $"脊柱弯曲: {spineAngle:F1}°\n"; debugInfo += $"头降量: {(neck.y - headPos.y):F2}m\n"; debugInfo += $"脊柱压缩: {compressionInfo}"; break; } debugText.text = debugInfo; } // ===== 改进的动作检测算法 ===== private bool ValidateArmRaise(long userId) { // 获取必要关节位置 Vector3 leftHand = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HandLeft); Vector3 rightHand = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HandRight); Vector3 leftShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.ShoulderLeft); Vector3 rightShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.ShoulderRight); Vector3 head = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); // 简化的举双手检测 - 只关注手部是否高于肩膀 bool leftHandRaised = leftHand.y > leftShoulder.y + 0.1f; // 手高于肩膀10cm bool rightHandRaised = rightHand.y > rightShoulder.y + 0.1f; // 备选方案:手部高于头部 // bool leftHandRaised = leftHand.y > head.y; // bool rightHandRaised = rightHand.y > head.y; // 双手举起即视为成功 return leftHandRaised && rightHandRaised; } private bool ValidateHeadShake(long userId) { Vector3 headPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); Vector3 neckPosition = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Neck); // 计算头部旋转角度 Vector3 headDirection = headPosition - neckPosition; float currentRotation = Vector3.Angle(Vector3.up, headDirection); // 记录历史旋转 _headPositionHistory.Enqueue(headPosition); if (_headPositionHistory.Count > 30) _headPositionHistory.Dequeue(); // 检查旋转变化 bool rotationDetected = false; if (_headPositionHistory.Count > 10) { Vector3[] positions = _headPositionHistory.ToArray(); float minAngle = float.MaxValue; float maxAngle = float.MinValue; for (int i = 0; i < positions.Length; i++) { Vector3 dir = positions[i] - neckPosition; float angle = Vector3.Angle(Vector3.up, dir); if (angle < minAngle) minAngle = angle; if (angle > maxAngle) maxAngle = angle; } rotationDetected = (maxAngle - minAngle) > 20f; // 20度变化阈值 } // 增加直接旋转检测 bool directRotation = currentRotation > 20f || Mathf.Abs(currentRotation - _lastHeadRotation) > 15f; _lastHeadRotation = currentRotation; return rotationDetected || directRotation; } // 改进的抬腿检测 private bool ValidateLegLift(long userId) { Vector3 hipLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HipLeft); Vector3 kneeLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.KneeLeft); Vector3 ankleLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.AnkleLeft); // 计算腿部角度(髋-膝-踝) float legAngle = Vector3.Angle(kneeLeft - hipLeft, ankleLeft - kneeLeft); // 计算抬腿高度 float liftHeight = ankleLeft.y - hipLeft.y; // 检测腿部运动状态变化 bool isLifted = liftHeight > legLiftSensitivity && legAngle < 140f; bool stateChanged = isLifted && !_lastLegLiftState; _lastLegLiftState = isLifted; return stateChanged; } // 改进的跳跃检测 private bool ValidateJump(long userId) { // 数据验证代码... // 初始化上一帧位置(首次执行时) if (_lastSpineBasePosition == Vector3.zero) { _lastSpineBasePosition = spineBase; _initialHipPosition = spineBase; // 同步初始化 return false; } // 计算速度(添加除零保护) float deltaTime = Mathf.Max(Time.deltaTime, 0.001f); // 防止除零 Vector3 velocity = (spineBase - _lastSpineBasePosition) / deltaTime; _lastSpineBasePosition = spineBase; // 动态更新初始位置 if (_validationCounters[_currentAction] == 0) { _initialHipPosition = spineBase; } // 高度计算(添加容错) jumpHeight = Mathf.Max(spineBase.y - _initialHipPosition.y, 0); // 离地检测(使用绝对高度差) Vector3 footLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.FootLeft); Vector3 footRight = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.FootRight); feetOffGround = (footLeft.y > _initialHipPosition.y + 0.1f) || (footRight.y > _initialHipPosition.y + 0.1f); // ==== 调试输出强制显示 ==== Debug.Log($"跳跃检测: 高度={jumpHeight} 速度Y={velocity.y} 离地={feetOffGround}"); Vector3 spineBaseNow = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); // 检测逻辑(简化版) if (spineBaseNow.y > 0.8f) { _validationCounters[_currentAction]++; if (_validationCounters[_currentAction] >= 2) // 降低帧数要求 { _validationCounters[_currentAction] = 0; return true; } } else { _validationCounters[_currentAction] = 0; } return false; } // 改进的右弯检测 private bool ValidateRightBend(long userId) { Vector3 shoulderCenter = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); Vector3 hipCenter = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); Vector3 shoulderLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.ShoulderLeft); Vector3 shoulderRight = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.ShoulderRight); // 计算躯干倾斜角度 Vector3 spineVector = hipCenter - shoulderCenter; float bendAngle = Vector3.Angle(spineVector, Vector3.up); // 计算肩膀高度差 float shoulderHeightDiff = shoulderLeft.y - shoulderRight.y; // 使用复合条件提高准确性 return (bendAngle < 148f ); } private bool ValidateBow(long userId) { // 获取当前关节位置 Vector3 headPos = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Head); Vector3 spineShoulder = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineShoulder); Vector3 spineMid = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineMid); Vector3 spineBase = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.SpineBase); Vector3 neck = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.Neck); // ===== 关键修复:验证关节位置有效性 ===== if (spineShoulder == Vector3.zero || spineBase == Vector3.zero) { Debug.LogWarning("脊柱关节位置无效,跳过鞠躬检测"); return false; } // 1. 计算脊柱弯曲角度 Vector3 upperSpine = spineShoulder - spineMid; Vector3 lowerSpine = spineBase - spineMid; spineAngle = Vector3.Angle(upperSpine, lowerSpine); // 2. 相对头部下降量 float headDrop = neck.y - headPos.y; // 3. 脊柱长度变化检测(添加安全校验) float spineLength = Vector3.Distance(spineShoulder, spineBase); float spineCompression = 0f; // ===== 修复除零错误 ===== if (_initialSpineLength > 0.01f) // 有效长度阈值 { spineCompression = 1 - (spineLength / _initialSpineLength); } else { Debug.LogWarning($"初始脊柱长度无效: {_initialSpineLength},使用备选方案"); // 备选方案:使用标准身高比例估算 spineCompression = Mathf.Clamp((0.5f - spineLength) / 0.5f, 0, 1); } // 检测条件 bool isBowing = spineAngle < 140f || headDrop > 0.15f || spineCompression <0f; Debug.Log(spineCompression); // 冷却时间检查 bool canDetectAgain = (Time.time - _lastBowDetectionTime) > 0.5f; if (isBowing && canDetectAgain) { _lastBowDetectionTime = Time.time; return true; } return false; } private bool ValidateRunning(long userId) { Vector3 ankleLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.AnkleLeft); Vector3 ankleRight = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.AnkleRight); // 检测腿部交替运动 float verticalMovement = Mathf.Abs(ankleLeft.y - ankleRight.y); bool legsMoving = verticalMovement > actionThreshold * 0.5f; // 位置变化检测 if (_lastFootPosition != Vector3.zero) { float positionChange = Vector3.Distance(ankleLeft, _lastFootPosition); legsMoving |= positionChange > actionThreshold * 0.2f; } _lastFootPosition = ankleLeft; return legsMoving; } private bool ValidateSquat(long userId) { Vector3 hipLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.HipLeft); Vector3 kneeLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.KneeLeft); Vector3 ankleLeft = _kinectManager.GetJointPosition(userId, (int)Kinect.JointType.AnkleLeft); // 计算大腿-小腿夹角 Vector3 thighVector = kneeLeft - hipLeft; Vector3 shinVector = ankleLeft - kneeLeft; float kneeAngle = Vector3.Angle(thighVector, shinVector); return kneeAngle < 100f; } } 使用以上代碼,重新編寫鞠躬和跳躍檢測,當然彎腰鞠躬后要起身才能做下一個鞠躬,跳躍要挑起落地后才能在跳起
最新发布
12-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值