Files
yangbear f0a6b96da5 feat: MCP Unity 场景优化 — 完整交互体系搭建
- 删除重复 Ground
- 创建 [Managers] 空物体,挂载 GameManager + StepManager + ExperimentFlowCoordinator + AudioManager
- Main Camera 挂载 InteractionSystem
- 伤者 InjectedPerson 下创建 5 个交互子物体 (InjuryVisual/Swelling/Pain/VitalSigns/Neuro)
- 创建绑带位置、踝关节、衬垫、夹板位置等空物体
- 道具摆放到位:伤者(2,0.05,5) 施救者(3,0,5) 鞋(2.7,0.15,5.5) 绷带/夹板/急救箱在旁
- InjuryLeg Tag 修正,Ground Tag 修正
- 全部新脚本同步导入 (ExperimentTypes/StepData/ExperimentConfig/StepManager/GameManager/ExperimentFlowCoordinator/InteractionSystem/DraggableObject/HighlightEffect/UIManager/ExamPopup/ScoreDisplay/VideoController/AudioManager/CharacterAnimController/StepAnimationHandler)
- 旧脚本 (ExperimentController/ConfigLoader/AnimationController/HUDController/VideoPlayerController/PopupSystem/ModeSelectionUI) 全部兼容修复或 stub
- 编译通过,0 错误
- Canvas 挂载 UIManager
2026-06-24 02:33:48 +08:00

182 lines
5.6 KiB
C#

using UnityEngine;
using System.Collections;
/// <summary>
/// 按步骤触发对应动画:开场动画、脱鞋、绑带、夹板放置等。
/// 挂在场景中有动画关联物体的 GameObject 上。
/// 由 ExperimentFlowCoordinator 绑定到 StepManager.OnStepChanged。
/// </summary>
public class StepAnimationHandler : MonoBehaviour
{
[Header("角色引用")]
[SerializeField] private CharacterAnimController _patient;
[SerializeField] private CharacterAnimController _rescuer;
[Header("道具引用")]
[SerializeField] private GameObject _shoeLeft; // 伤者左脚鞋
[SerializeField] private GameObject _shoeRight; // 伤者右脚鞋
[SerializeField] private GameObject[] _bandages; // 绑带物件列表
[SerializeField] private GameObject[] _splints; // 夹板物件列表
[SerializeField] private GameObject _padding; // 衬垫
[Header("夹板固定专用道具")]
[SerializeField] private GameObject _splintLeft;
[SerializeField] private GameObject _splintRight;
[Header("伤口高亮")]
[SerializeField] private GameObject _woundHighlight;
[Header("动画时长")]
[SerializeField] private float _shoeRemoveDuration = 1.5f;
[SerializeField] private float _bandageAppearDuration = 0.5f;
/// <summary>由 StepManager.OnStepChanged 调用</summary>
public void PlayStepAnimation(int stepIndex)
{
var sm = FindObjectOfType<StepManager>();
if (sm == null) return;
var step = sm.GetCurrentStep();
if (step == null) return;
StopAllCoroutines();
// 根据步骤名称匹配动画
switch (step.StepName)
{
case "OpeningScene":
StartCoroutine(PlayOpeningScene());
break;
case "RemoveShoes":
StartCoroutine(PlayRemoveShoes());
break;
case "PlaceBandage":
StartCoroutine(PlayPlaceBandage());
break;
case "LimbFixation":
StartCoroutine(PlayLimbFixation());
break;
case "SplintFixation":
StartCoroutine(PlaySplintFixation());
break;
case "AnkleFixation":
StartCoroutine(PlayAnkleFixation());
break;
case "FinalCheck":
break;
default:
Debug.Log($"StepAnimationHandler: 步骤 {step.StepName} 无专属动画");
break;
}
}
#region 动画协程
private IEnumerator PlayOpeningScene()
{
// 伤者跑步 → 跳高 → 摔倒
_patient?.PlayRun();
yield return new WaitForSeconds(4f);
_patient?.TriggerJump();
yield return new WaitForSeconds(1f);
_patient?.TriggerFall();
yield return new WaitForSeconds(1.5f);
_patient?.StopRun();
}
private IEnumerator PlayRemoveShoes()
{
// 鞋子弹开/移出
if (_shoeLeft != null)
{
Vector3 target = _shoeLeft.transform.position + Vector3.right * 0.5f + Vector3.up * 0.2f;
yield return StartCoroutine(MoveToPosition(_shoeLeft, target, _shoeRemoveDuration));
_shoeLeft.SetActive(false);
}
if (_shoeRight != null)
{
Vector3 target = _shoeRight.transform.position + Vector3.right * 0.5f + Vector3.up * 0.2f;
yield return StartCoroutine(MoveToPosition(_shoeRight, target, _shoeRemoveDuration));
_shoeRight.SetActive(false);
}
}
private IEnumerator PlayPlaceBandage()
{
// 显示绑带
foreach (var b in _bandages)
{
if (b != null) b.SetActive(true);
}
yield return null;
}
private IEnumerator PlayLimbFixation()
{
// 显示衬垫 + 激活绑带
if (_padding != null) _padding.SetActive(true);
yield return new WaitForSeconds(0.5f);
// 依次显示绑带
for (int i = 0; i < _bandages.Length; i++)
{
if (_bandages[i] != null)
{
_bandages[i].SetActive(true);
yield return new WaitForSeconds(_bandageAppearDuration);
}
}
}
private IEnumerator PlaySplintFixation()
{
// 显示夹板
if (_splintLeft != null) _splintLeft.SetActive(true);
if (_splintRight != null) _splintRight.SetActive(true);
yield return new WaitForSeconds(0.5f);
foreach (var s in _splints)
{
if (s != null) s.SetActive(true);
yield return new WaitForSeconds(_bandageAppearDuration);
}
}
private IEnumerator PlayAnkleFixation()
{
// 8 字绑带动画 - 激活脚踝处绑带
if (_bandages.Length > 0 && _bandages[_bandages.Length - 1] != null)
{
_bandages[_bandages.Length - 1].SetActive(true);
}
yield return null;
}
#endregion
#region 工具方法
private IEnumerator MoveToPosition(GameObject obj, Vector3 target, float duration)
{
if (obj == null) yield break;
Vector3 start = obj.transform.position;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
obj.transform.position = Vector3.Lerp(start, target, elapsed / duration);
yield return null;
}
obj.transform.position = target;
}
/// <summary>显示伤口高亮</summary>
public void ShowWoundHighlight(bool show)
{
if (_woundHighlight != null) _woundHighlight.SetActive(show);
}
#endregion
}