Improve exam flow and WebGL build
This commit is contained in:
@@ -52,6 +52,10 @@ public class PageController : MonoBehaviour
|
||||
|
||||
// 一开始就隐藏鞋子,以免在主页或开场动画时穿帮
|
||||
HideShose();
|
||||
var splintFlow = EnsureSplintPracticeFlow();
|
||||
if (splintFlow != null) splintFlow.StopPractice();
|
||||
var initialExamFlow = EnsureExamFlow();
|
||||
if (initialExamFlow != null) initialExamFlow.StopExam();
|
||||
|
||||
// 关掉多余AudioListener(只留Main Camera的)
|
||||
var cam2 = GameObject.Find("camera2"); if (cam2 != null) { var al = cam2.GetComponent<AudioListener>(); if (al != null) al.enabled = false; }
|
||||
@@ -147,7 +151,7 @@ public class PageController : MonoBehaviour
|
||||
var audioManager = FindObjectOfType<AudioManager>();
|
||||
if (audioManager != null)
|
||||
{
|
||||
if (page == Page.Experiment) audioManager.PlayExperimentBg();
|
||||
if (page == Page.Experiment) audioManager.StopBgMusic();
|
||||
else audioManager.PlayHomeBg();
|
||||
}
|
||||
|
||||
@@ -211,6 +215,7 @@ public class PageController : MonoBehaviour
|
||||
if (_uiManager != null)
|
||||
{
|
||||
_uiManager.gameObject.SetActive(true);
|
||||
_uiManager.HideTip();
|
||||
}
|
||||
|
||||
var stepManager = FindObjectOfType<StepManager>();
|
||||
@@ -218,16 +223,22 @@ public class PageController : MonoBehaviour
|
||||
{
|
||||
stepManager.InitializeFromGameManager();
|
||||
}
|
||||
PrepareInitialInteractionObjects();
|
||||
StartCoroutine(StartInitialVoiceAndCameraRoutine());
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowPage(Page.Experiment);
|
||||
if (_uiManager != null) _uiManager.gameObject.SetActive(true);
|
||||
if (_uiManager != null)
|
||||
{
|
||||
_uiManager.gameObject.SetActive(true);
|
||||
_uiManager.HideTip();
|
||||
}
|
||||
|
||||
var stepManager = FindObjectOfType<StepManager>();
|
||||
if (stepManager != null) stepManager.InitializeFromGameManager();
|
||||
PrepareInitialInteractionObjects();
|
||||
StartCoroutine(StartInitialVoiceAndCameraRoutine());
|
||||
}
|
||||
}
|
||||
@@ -236,9 +247,8 @@ public class PageController : MonoBehaviour
|
||||
{
|
||||
if (GameManager.Instance == null) return;
|
||||
if (GameManager.Instance.CurrentMode != ExperimentMode.Exam) return;
|
||||
if (GameManager.Instance.CurrentFixationMethod != FixationMethod.LimbFixation) return;
|
||||
|
||||
var examFlow = FindObjectOfType<ExamFlowManager>();
|
||||
var examFlow = EnsureExamFlow();
|
||||
if (examFlow != null) examFlow.BeginExam();
|
||||
}
|
||||
|
||||
@@ -247,6 +257,31 @@ public class PageController : MonoBehaviour
|
||||
ReturnToHome();
|
||||
}
|
||||
|
||||
public void RestartExperimentWithMode(ExperimentMode mode)
|
||||
{
|
||||
FixationMethod fixation = GameManager.Instance != null
|
||||
? GameManager.Instance.CurrentFixationMethod
|
||||
: FixationMethod.LimbFixation;
|
||||
|
||||
Debug.Log($"PageController: 切换到 {mode},并从开场动画重新开始");
|
||||
ReturnToHome();
|
||||
StartCoroutine(RestartExperimentAfterReset(mode, fixation));
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator RestartExperimentAfterReset(ExperimentMode mode, FixationMethod fixation)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.CurrentMode = mode;
|
||||
GameManager.Instance.CurrentExperimentType = ExperimentType.FractureFixation;
|
||||
GameManager.Instance.CurrentFixationMethod = fixation;
|
||||
}
|
||||
|
||||
OnFixationSelected(fixation);
|
||||
}
|
||||
|
||||
public void ReturnToHome()
|
||||
{
|
||||
if (_lastReturnHomeFrame == Time.frameCount)
|
||||
@@ -261,6 +296,11 @@ public class PageController : MonoBehaviour
|
||||
StopAllCoroutines();
|
||||
ActionHistory.Clear();
|
||||
|
||||
var splintFlow = EnsureSplintPracticeFlow();
|
||||
if (splintFlow != null) splintFlow.StopPractice();
|
||||
var examFlow = EnsureExamFlow();
|
||||
if (examFlow != null) examFlow.StopExam();
|
||||
|
||||
if (_uiManager != null)
|
||||
{
|
||||
_uiManager.HideVideo();
|
||||
@@ -272,6 +312,7 @@ public class PageController : MonoBehaviour
|
||||
HideCanvasPanel("DialogueBubble");
|
||||
HideCanvasPanel("GradeResult");
|
||||
HideCanvasPanel("TipPanel");
|
||||
HideCanvasPanel("DetailPanel");
|
||||
|
||||
// --- 核心修复:退出时彻底清理并隐藏所有交互物体 ---
|
||||
foreach (var handler in GetSceneObjectsOfType<PingClickHandler>())
|
||||
@@ -399,20 +440,74 @@ public class PageController : MonoBehaviour
|
||||
{
|
||||
float waitTime = 1f; // 默认等1秒
|
||||
var am = FindObjectOfType<AudioManager>();
|
||||
|
||||
// 隐藏视频面板
|
||||
var allT = Resources.FindObjectsOfTypeAll<Transform>();
|
||||
foreach (var t in allT)
|
||||
if (am != null) am.PlayExperimentBg();
|
||||
|
||||
// 1. 强制播放第一句语音
|
||||
if (am != null)
|
||||
{
|
||||
if (t.name == "VideoPanel" && t.parent != null && t.parent.name == "Canvas")
|
||||
#if UNITY_EDITOR
|
||||
var autoClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/people/周围环境安全,我是救护志愿者,我可以帮助您吗.mp3");
|
||||
if (autoClip != null)
|
||||
{
|
||||
t.gameObject.SetActive(false);
|
||||
am.PlayVoice(autoClip);
|
||||
waitTime = autoClip.length + 1f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// 找鞋子
|
||||
Debug.Log($"PageController: 开始等待 {waitTime} 秒以切换摄像机并激活鞋子");
|
||||
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
|
||||
if (am != null) am.SwitchToCamera3();
|
||||
|
||||
var point2 = GameObject.Find("touchArray/point2");
|
||||
if (point2 == null)
|
||||
{
|
||||
var touchArray = GameObject.Find("touchArray");
|
||||
if (touchArray != null)
|
||||
{
|
||||
var p2 = touchArray.transform.Find("point2");
|
||||
if (p2 != null) point2 = p2.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (point2 != null)
|
||||
{
|
||||
point2.SetActive(true);
|
||||
Debug.Log("PageController: 镜头切换到camera3,point2 已显示");
|
||||
}
|
||||
|
||||
if (_uiManager != null)
|
||||
{
|
||||
_uiManager.ShowTip("请点击伤员大腿附近,评估伤情并确认是否疑似骨折。");
|
||||
}
|
||||
|
||||
StartExamFlowIfNeeded();
|
||||
}
|
||||
|
||||
private void PrepareInitialInteractionObjects()
|
||||
{
|
||||
bool isSplintPractice = GameManager.Instance != null &&
|
||||
GameManager.Instance.CurrentMode == ExperimentMode.Learn &&
|
||||
GameManager.Instance.CurrentFixationMethod == FixationMethod.SplintFixation;
|
||||
bool isSplintExam = GameManager.Instance != null &&
|
||||
GameManager.Instance.CurrentMode == ExperimentMode.Exam &&
|
||||
GameManager.Instance.CurrentFixationMethod == FixationMethod.SplintFixation;
|
||||
|
||||
var splintFlow = EnsureSplintPracticeFlow();
|
||||
if (isSplintPractice && splintFlow != null)
|
||||
{
|
||||
splintFlow.BeginPractice();
|
||||
}
|
||||
else if (splintFlow != null)
|
||||
{
|
||||
splintFlow.StopPractice();
|
||||
}
|
||||
|
||||
HideCanvasPanel("VideoPanel");
|
||||
|
||||
var shose = FindSceneObject("Shose");
|
||||
|
||||
var point2 = GameObject.Find("touchArray/point2");
|
||||
if (point2 == null)
|
||||
{
|
||||
@@ -429,61 +524,38 @@ public class PageController : MonoBehaviour
|
||||
var h = shose.GetComponent<ShoseClickHandler>();
|
||||
if (h == null) h = shose.AddComponent<ShoseClickHandler>();
|
||||
h.targetPoint = GameObject.Find("ShosePoint")?.transform;
|
||||
|
||||
|
||||
var ping004 = FindFirstPingStepObject();
|
||||
h.nextObject = ping004;
|
||||
|
||||
// 鞋子出现,但默认不开组件(不可点击)
|
||||
if (isSplintPractice && splintFlow != null && splintFlow.ConfigureShose(h))
|
||||
{
|
||||
Debug.Log("PageController: 夹板固定练习 Shose 已绑定到 manMuban/ping.001");
|
||||
}
|
||||
else if (isSplintExam)
|
||||
{
|
||||
h.nextObject = null;
|
||||
Debug.Log("PageController: 夹板固定考核 Shose 不直接激活肢体固定 ping");
|
||||
}
|
||||
else
|
||||
{
|
||||
h.nextObject = ping004;
|
||||
}
|
||||
|
||||
h.enabled = false;
|
||||
shose.SetActive(true);
|
||||
Debug.Log("PageController: Shose 已在开场完成后立即显示");
|
||||
}
|
||||
|
||||
|
||||
if (point2 != null)
|
||||
{
|
||||
var oldHandler = point2.GetComponent<TouchPositionHandler>();
|
||||
if (oldHandler != null) Destroy(oldHandler);
|
||||
|
||||
|
||||
var h2 = point2.GetComponent<Point2ClickHandler>();
|
||||
if (h2 == null) h2 = point2.AddComponent<Point2ClickHandler>();
|
||||
if (h2.nextObject == null) h2.nextObject = shose;
|
||||
|
||||
|
||||
point2.SetActive(false);
|
||||
}
|
||||
|
||||
// 1. 强制播放第一句语音
|
||||
if (am != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var autoClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/people/周围环境安全,我是救护志愿者,我可以帮助您吗.mp3");
|
||||
if (autoClip != null)
|
||||
{
|
||||
am.PlayVoice(autoClip);
|
||||
waitTime = autoClip.length + 1f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Debug.Log($"PageController: 开始等待 {waitTime} 秒以切换摄像机并激活鞋子");
|
||||
|
||||
var tipPanel = GameObject.Find("TipPanel");
|
||||
if (tipPanel == null)
|
||||
{
|
||||
foreach(var t in allT) { if (t.name == "TipPanel") { tipPanel = t.gameObject; break; } }
|
||||
}
|
||||
if (tipPanel != null) tipPanel.SetActive(true);
|
||||
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
|
||||
if (tipPanel != null) tipPanel.SetActive(false);
|
||||
if (am != null) am.SwitchToCamera3();
|
||||
|
||||
if (point2 != null)
|
||||
{
|
||||
point2.SetActive(true);
|
||||
Debug.Log("PageController: 镜头切换到camera3,point2 已显示");
|
||||
}
|
||||
|
||||
StartExamFlowIfNeeded();
|
||||
}
|
||||
|
||||
private void HideShose()
|
||||
@@ -495,6 +567,26 @@ public class PageController : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private SplintPracticeFlowManager EnsureSplintPracticeFlow()
|
||||
{
|
||||
var flow = FindObjectOfType<SplintPracticeFlowManager>(true);
|
||||
if (flow != null) return flow;
|
||||
|
||||
var managers = GameObject.Find("[Managers]");
|
||||
if (managers == null) managers = gameObject;
|
||||
return managers.AddComponent<SplintPracticeFlowManager>();
|
||||
}
|
||||
|
||||
private ExamFlowManager EnsureExamFlow()
|
||||
{
|
||||
var flow = FindObjectOfType<ExamFlowManager>(true);
|
||||
if (flow != null) return flow;
|
||||
|
||||
var managers = GameObject.Find("[Managers]");
|
||||
if (managers == null) managers = gameObject;
|
||||
return managers.AddComponent<ExamFlowManager>();
|
||||
}
|
||||
|
||||
private GameObject FindFirstPingStepObject()
|
||||
{
|
||||
foreach (var ping in GetSceneObjectsOfType<PingClickHandler>())
|
||||
|
||||
@@ -74,6 +74,17 @@ public class UIManager : MonoBehaviour
|
||||
var t = canvas.Find("EndPanel");
|
||||
if (t != null) _endPanel = t.gameObject;
|
||||
}
|
||||
|
||||
if (_tipPanel == null)
|
||||
{
|
||||
var t = canvas.Find("TipPanel");
|
||||
if (t != null) _tipPanel = t.gameObject;
|
||||
}
|
||||
|
||||
if (_tipPanel != null && _tipText == null)
|
||||
{
|
||||
_tipText = _tipPanel.GetComponentInChildren<Text>(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void BindNavbarButtons()
|
||||
@@ -94,6 +105,20 @@ public class UIManager : MonoBehaviour
|
||||
|
||||
var btnReturn = navbar.Find("BtnBack");
|
||||
if (btnReturn != null) { var btn = btnReturn.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnReturnClicked); btn.onClick.AddListener(OnReturnClicked); } }
|
||||
|
||||
var btnPracticeMode = navbar.Find("PracticeMode");
|
||||
if (btnPracticeMode != null)
|
||||
{
|
||||
var btn = btnPracticeMode.GetComponent<Button>();
|
||||
if (btn != null)
|
||||
{
|
||||
btn.onClick.RemoveListener(OnSwitchModeClicked);
|
||||
btn.onClick.AddListener(OnSwitchModeClicked);
|
||||
}
|
||||
}
|
||||
|
||||
bool isExamMode = GameManager.Instance != null && GameManager.Instance.CurrentMode == ExperimentMode.Exam;
|
||||
SetNavbarModeVisual(isExamMode);
|
||||
}
|
||||
|
||||
private void BindButtons()
|
||||
@@ -121,7 +146,26 @@ public class UIManager : MonoBehaviour
|
||||
private void UpdateModeUI(bool isExamMode)
|
||||
{
|
||||
if (_btnSwitchModeLabel != null)
|
||||
_btnSwitchModeLabel.text = isExamMode ? "切换到:练习模式" : "切换到:考核模式";
|
||||
_btnSwitchModeLabel.text = isExamMode ? "练习模式" : "考核模式";
|
||||
|
||||
SetNavbarModeVisual(isExamMode);
|
||||
UpdateFullScreenButtonVisual();
|
||||
}
|
||||
|
||||
private void SetNavbarModeVisual(bool isExamMode)
|
||||
{
|
||||
var experimentPanel = GameObject.Find("ExperimentPanel");
|
||||
if (experimentPanel == null) return;
|
||||
|
||||
var modeButton = experimentPanel.transform.Find("Navbar/PracticeMode");
|
||||
if (modeButton == null) return;
|
||||
|
||||
var practice = modeButton.Find("Practice");
|
||||
var examine = modeButton.Find("Examine");
|
||||
if (practice != null) practice.gameObject.SetActive(isExamMode);
|
||||
if (examine != null) examine.gameObject.SetActive(!isExamMode);
|
||||
SetChildTexts(practice, "练习模式");
|
||||
SetChildTexts(examine, "考核模式");
|
||||
}
|
||||
|
||||
private void OnStepChanged(int stepIndex)
|
||||
@@ -132,10 +176,21 @@ public class UIManager : MonoBehaviour
|
||||
|
||||
private void UpdateTipContent(string text)
|
||||
{
|
||||
AutoFindPanels();
|
||||
if (_tipPanel != null) _tipPanel.SetActive(!string.IsNullOrEmpty(text));
|
||||
if (_tipText != null) _tipText.text = text;
|
||||
}
|
||||
|
||||
public void ShowTip(string text)
|
||||
{
|
||||
UpdateTipContent(text);
|
||||
}
|
||||
|
||||
public void HideTip()
|
||||
{
|
||||
UpdateTipContent("");
|
||||
}
|
||||
|
||||
private void UpdateDialogueContent(string text)
|
||||
{
|
||||
if (_dialogueBubble == null)
|
||||
@@ -164,10 +219,24 @@ public class UIManager : MonoBehaviour
|
||||
|
||||
private void UpdateDetailContent(string text)
|
||||
{
|
||||
if (IsSplintPracticeMode())
|
||||
{
|
||||
if (_detailPanel != null) _detailPanel.SetActive(false);
|
||||
if (_detailText != null) _detailText.text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_detailPanel != null) _detailPanel.SetActive(!string.IsNullOrEmpty(text));
|
||||
if (_detailText != null) _detailText.text = text;
|
||||
}
|
||||
|
||||
private bool IsSplintPracticeMode()
|
||||
{
|
||||
return GameManager.Instance != null &&
|
||||
GameManager.Instance.CurrentMode == ExperimentMode.Learn &&
|
||||
GameManager.Instance.CurrentFixationMethod == FixationMethod.SplintFixation;
|
||||
}
|
||||
|
||||
private void ToggleVideo(string fileName, bool active)
|
||||
{
|
||||
if (active && !string.IsNullOrEmpty(fileName)) ShowVideo(fileName);
|
||||
@@ -314,10 +383,43 @@ public class UIManager : MonoBehaviour
|
||||
ShowEndPanel();
|
||||
}
|
||||
|
||||
private void ToggleFullScreen() { Screen.fullScreen = !Screen.fullScreen; }
|
||||
private void ToggleFullScreen()
|
||||
{
|
||||
bool targetFullScreen = !Screen.fullScreen;
|
||||
Screen.fullScreenMode = FullScreenMode.FullScreenWindow;
|
||||
Screen.SetResolution(1920, 1080, targetFullScreen);
|
||||
Screen.fullScreen = targetFullScreen;
|
||||
UpdateFullScreenButtonVisual();
|
||||
}
|
||||
|
||||
private void UpdateFullScreenButtonVisual()
|
||||
{
|
||||
var experimentPanel = GameObject.Find("ExperimentPanel");
|
||||
Transform fullScreenButton = experimentPanel != null ? experimentPanel.transform.Find("Navbar/FullScreen") : null;
|
||||
if (fullScreenButton == null) return;
|
||||
|
||||
Text label = fullScreenButton.GetComponentInChildren<Text>(true);
|
||||
if (label != null) label.text = Screen.fullScreen ? "退出全屏" : "全屏模式";
|
||||
}
|
||||
|
||||
private void SetChildTexts(Transform root, string value)
|
||||
{
|
||||
if (root == null) return;
|
||||
|
||||
Text[] texts = root.GetComponentsInChildren<Text>(true);
|
||||
for (int i = 0; i < texts.Length; i++)
|
||||
{
|
||||
if (texts[i] != null) texts[i].text = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNextClicked()
|
||||
{
|
||||
if (IsSplintPracticeMode())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
|
||||
|
||||
if (_stepManager != null && _stepManager.Mode == ExperimentMode.Exam)
|
||||
@@ -337,10 +439,22 @@ public class UIManager : MonoBehaviour
|
||||
|
||||
private void OnSwitchModeClicked()
|
||||
{
|
||||
if (_stepManager == null) return;
|
||||
var oldMode = _stepManager.Mode;
|
||||
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
|
||||
|
||||
ExperimentMode oldMode = GameManager.Instance != null ? GameManager.Instance.CurrentMode :
|
||||
(_stepManager != null ? _stepManager.Mode : ExperimentMode.Learn);
|
||||
var newMode = oldMode == ExperimentMode.Learn ? ExperimentMode.Exam : ExperimentMode.Learn;
|
||||
_stepManager.SwitchMode(newMode);
|
||||
|
||||
SetNavbarModeVisual(newMode == ExperimentMode.Exam);
|
||||
var pageCtrl = FindObjectOfType<PageController>();
|
||||
if (pageCtrl != null)
|
||||
{
|
||||
pageCtrl.RestartExperimentWithMode(newMode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameManager.Instance != null) GameManager.Instance.CurrentMode = newMode;
|
||||
if (_stepManager != null) _stepManager.SwitchMode(newMode);
|
||||
}
|
||||
|
||||
private void OnReturnClicked()
|
||||
|
||||
Reference in New Issue
Block a user