fix: WebGL关闭Brotli压缩解决服务器部署.br解析问题; 新增PageController编辑器页面预览下拉框; 创建FractureFixationConfig ScriptableObject; 修复ExperimentFlowCoordinator自动初始化问题

This commit is contained in:
yangbear
2026-06-24 06:05:55 +08:00
parent a6a7fd06d4
commit 3b4438731d
9 changed files with 494 additions and 47 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1d09ddba5730c41b3ac7bea8260a0289
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c4d6e876ac0714e9f8a49bb1113d519a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,358 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-8589662463764153072
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 15
SubStepCount: 1
StepIndex: 6
StepName: AnkleFixation
TipText: "Tip\uFF1A\u8E1D\u5173\u82828\u5B57\u56FA\u5B9A\uFF0C\u7ED3\u6253\u5728\u4E24\u8DB3\u80CC\u4E4B\u95F4\u3002"
DialogueText:
DetailedContent:
ExamQuestionText: "\u8BF7\u9009\u62E9\u8E1D\u5173\u8282\u6253\u7ED3\u4F4D\u7F6E"
ExamOptions:
- "\u8DB3\u5E95"
- "\u8DB3\u80CC"
CorrectOptionIndex: 1
ErrorFeedback: "\u5E94\u9009\u62E9\u8DB3\u80CC\u4F4D\u7F6E\u6253\u7ED3"
CompleteType: 1
TargetTag: Ankle
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &-8572732419025931964
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 5
SubStepCount: 1
StepIndex: 0
StepName: OpeningScene
TipText: "Tip\uFF1A\u89C2\u5BDF\u5468\u56F4\u73AF\u5883\u662F\u5426\u6709\u5371\u9669\uFF0C\u505A\u597D\u9632\u62A4\u63AA\u65BD\u3002"
DialogueText: "\u5468\u56F4\u73AF\u5883\u5B89\u5168\u3002\u6211\u662F\u6551\u62A4\u5FD7\u613F\u8005\uFF0C\u6211\u53EF\u4EE5\u5E2E\u52A9\u60A8\u5417\uFF1F"
DetailedContent:
ExamQuestionText: "\u70B9\u51FB\u786E\u8BA4\u540E\uFF0C\u8BF7\u6309\u6B63\u786E\u987A\u5E8F\u8FDB\u884C\u73AF\u5883\u8BC4\u4F30\u4E0E\u81EA\u6211\u4ECB\u7ECD"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u73AF\u5883\u8BC4\u4F30\u6D41\u7A0B\u4E0D\u6B63\u786E"
CompleteType: 3
TargetTag:
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &-7505961611728634602
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 10
SubStepCount: 1
StepIndex: 2
StepName: RemoveShoes
TipText: "Tip\uFF1A\u8BF7\u5C06\u4F24\u5458\u978B\u889C\u8131\u6389\u5E76\u4FDD\u5B58\u597D\uFF0C\u89C2\u5BDF\u672B\u7AEF\u8840\u6DB2\u5FAA\u73AF\u3001\u8FD0\u52A8\u53CA\u611F\u89C9"
DialogueText:
DetailedContent:
ExamQuestionText: "\u8BF7\u6B63\u786E\u64CD\u4F5C\u8131\u978B\u889C\u5E76\u89C2\u5BDF\u672B\u68A2\u5FAA\u73AF"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u8131\u978B\u889C\u64CD\u4F5C\u4E0D\u6B63\u786E"
CompleteType: 1
TargetTag: Shoe
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &-1716209357147542543
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 20
SubStepCount: 5
StepIndex: 1
StepName: CheckInjury
TipText: "Tip\uFF1A\u8BF7\u68C0\u67E5\u4F24\u5458\u53D7\u4F24\u4F4D\u7F6E"
DialogueText: "\u4F24\u5458\u5DE6\u5927\u817F\u7591\u4F3C\u9AA8\u6298\uFF0C\u65E0\u4F24\u53E3\u3002"
DetailedContent: "\u3010\u4F24\u60C5\u68C0\u67E5\u8BE6\u7EC6\u64CD\u4F5C\u987B\u77E5\u3011\n1)\u901A\u8FC7\u89C6\u89C9\u68C0\u67E5\u9AA8\u6298\u90E8\u4F4D\u662F\u5426\u5B58\u5728\u660E\u663E\u80BF\u80C0\u3001\u53D8\u5F62\u6216\u5F02\u5E38\u89D2\u5EA6\u3002\n2)\u89C2\u5BDF\u9AA8\u6298\u90E8\u4F4D\u80BF\u80C0\u4E0E\u7578\u5F62\uFF0C\u6D4B\u8BD5\u60A3\u80A2\u6D3B\u52A8\u80FD\u529B\u3002\n3)\u8BC4\u4F30\u75BC\u75DB\u4E0E\u529F\u80FD\u969C\u788D\uFF0C\u6392\u67E5\u4F24\u53E3\u6C61\u67D3\u60C5\u51B5\u3002\n4)\u76D1\u6D4B\u751F\u547D\u4F53\u5F81\uFF08\u8840\u538B\u3001\u8109\u640F\uFF09\uFF0C\u5173\u6CE8\u4F11\u514B\u524D\u5146\u3002\n5)\u795E\u7ECF\u7CFB\u7EDF\u72B6\u6001\u8BC4\u4F30\uFF0C\u6392\u9664\u9885\u8111/\u810A\u9AD3\u635F\u4F24\u3002"
ExamQuestionText: "\u70B9\u51FB\u786E\u8BA4\u540E\uFF0C\u8BF7\u6309\u6B63\u786E\u987A\u5E8F\u68C0\u67E5\u4F24\u60C5"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u4F24\u60C5\u68C0\u67E5\u6B65\u9AA4\u4E0D\u5B8C\u6574\u6216\u4E0D\u6B63\u786E"
CompleteType: 5
TargetTag: InjuryLeg
ClickSequenceTags:
- InjuryVisual
- InjurySwelling
- InjuryPain
- InjuryVitalSigns
- InjuryNeuro
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &-67247684073233390
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 20
SubStepCount: 3
StepIndex: 5
StepName: KneeFixation
TipText: "Tip\uFF1A\u8BF7\u5728\u672A\u53D7\u4F24\u817F\u5206\u522B\u56FA\u5B9A\u9AA8\u6298\u8FD1\u5FC3\u7AEF\uFF08\u4E0A\u7AEF\uFF09\u3001\u9AA8\u6298\u8FDC\u5FC3\u7AEF\uFF08\u4E0B\u7AEF\uFF09\uFF0C\u7136\u540E\u56FA\u5B9A\u819D\u5173\u8282\u4E0B\uFF0C\u7ED3\u6253\u5728\u53F3\u4FA7\u3002"
DialogueText:
DetailedContent:
ExamQuestionText: "\u8BF7\u9009\u62E9\u6B63\u786E\u7684\u7CFB\u5E26\u5B50\u987A\u5E8F"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u7CFB\u5E26\u5B50\u987A\u5E8F\u4E0D\u6B63\u786E\uFF0C\u5E94\u662F\u8FD1\u5FC3\u7AEF\u2192\u8FDC\u5FC3\u7AEF\u2192\u819D\u5173\u8282\u4E0B"
CompleteType: 5
TargetTag:
ClickSequenceTags:
- BandagePos1
- BandagePos2
- BandagePos3
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 24d3a8cba581943e1a2b2c167c7dd259, type: 3}
m_Name: FractureFixationConfig
m_EditorClassIdentifier:
Type: 1
DisplayName: "\u9AA8\u6298\u56FA\u5B9A\u865A\u62DF\u4EFF\u771F\u5B9E\u9A8C"
DefaultFixationMethod: 0
LearnStepsLimb:
- {fileID: -8572732419025931964}
- {fileID: -1716209357147542543}
- {fileID: -7505961611728634602}
- {fileID: 6606452316300291892}
- {fileID: 8462047121893510914}
- {fileID: -67247684073233390}
- {fileID: -8589662463764153072}
- {fileID: 7458162247652040644}
LearnStepsSplint:
- {fileID: -8572732419025931964}
- {fileID: -1716209357147542543}
- {fileID: -7505961611728634602}
- {fileID: 6606452316300291892}
- {fileID: 3701308421136855872}
- {fileID: 3600838309550434696}
- {fileID: -8589662463764153072}
- {fileID: 7458162247652040644}
ExamStepsLimb:
- {fileID: -8572732419025931964}
- {fileID: -1716209357147542543}
- {fileID: -7505961611728634602}
- {fileID: 6606452316300291892}
- {fileID: 8462047121893510914}
- {fileID: -67247684073233390}
- {fileID: -8589662463764153072}
- {fileID: 7458162247652040644}
ExamStepsSplint:
- {fileID: -8572732419025931964}
- {fileID: -1716209357147542543}
- {fileID: -7505961611728634602}
- {fileID: 6606452316300291892}
- {fileID: 3701308421136855872}
- {fileID: 3600838309550434696}
- {fileID: -8589662463764153072}
- {fileID: 7458162247652040644}
--- !u!114 &3600838309550434696
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 20
SubStepCount: 2
StepIndex: 5
StepName: SplintFixation
TipText: "Tip\uFF1A\u8BF7\u7528\u5E26\u5B50\u5C06\u5939\u677F\u56FA\u5B9A\u5728\u817F\u4E0A"
DialogueText:
DetailedContent: "\u3010\u56FA\u5B9A\u540E\u68C0\u67E5\u3011\n3)\u56FA\u5B9A\u5B8C\u6210\u540E\u68C0\u67E5\u60A3\u80A2\u672B\u68A2\u989C\u8272\u3001\u6E29\u5EA6\u53CA\u8109\u640F\u3002\n4)\u6BCF\u5C0F\u65F6\u8BC4\u4F30\u56FA\u5B9A\u6548\u679C\uFF0C\u8BB0\u5F55\u80A2\u4F53\u80BF\u80C0\u3001\u75BC\u75DB\u53D8\u5316\u3002"
ExamQuestionText: "\u8BF7\u6309\u987A\u5E8F\u56FA\u5B9A\u5939\u677F\uFF08\u5148\u5185\u4FA7\u540E\u5916\u4FA7\uFF09"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u5939\u677F\u56FA\u5B9A\u987A\u5E8F\u4E0D\u6B63\u786E"
CompleteType: 5
TargetTag:
ClickSequenceTags:
- SplintLeft
- SplintRight
IsSplintOnly: 1
ShowPipVideo: 0
VideoFileName:
--- !u!114 &3701308421136855872
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 10
SubStepCount: 2
StepIndex: 4
StepName: SplintPlacement
TipText: "Tip\uFF1A\u8BF7\u5728\u9AA8\u6298\u80A2\u4F53\u52A0\u886C\u57AB\uFF0C\u5E76\u7528\u5939\u677F\u56FA\u5B9A\u3002\u5DE6\u5927\u817F\u9AA8\u6298\uFF1A\u5185\u4FA7\u5939\u677F\u4E0A\u81F3\u5927\u817F\u6839\u90E8\u4E0B\u8FC7\u8DB3\u8DDF\uFF0C\u5916\u4FA7\u5939\u677F\u4E0A\u81F3\u814B\u7A9D\u4E0B\u8FC7\u8DB3\u8DDF\u3002"
DialogueText:
DetailedContent: "\u3010\u5939\u677F\u56FA\u5B9A\u64CD\u4F5C\u8981\u70B9\u3011\n1)\u6839\u636E\u9AA8\u6298\u90E8\u4F4D\u9009\u62E9\u957F\u5EA6\u3001\u786C\u5EA6\u9002\u5B9C\u7684\u5939\u677F\u3002\n2)\u5728\u9AA8\u7A81\u5904\u52A0\u539A\u886C\u57AB\uFF0C\u5206\u6563\u538B\u529B\u3002\u5173\u8282\u5904\u53CA\u7A7A\u9699\u90E8\u4F4D\u653E\u7F6E\u886C\u57AB\u3002"
ExamQuestionText: "\u8BF7\u6B63\u786E\u653E\u7F6E\u5939\u677F\uFF08\u5185\u4FA7+\u5916\u4FA7\uFF09"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u5939\u677F\u653E\u7F6E\u4F4D\u7F6E\u4E0D\u6B63\u786E"
CompleteType: 2
TargetTag: SplintLeft
ClickSequenceTags: []
IsSplintOnly: 1
ShowPipVideo: 0
VideoFileName:
--- !u!114 &6606452316300291892
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 10
SubStepCount: 1
StepIndex: 3
StepName: PlaceBandage
TipText: "Tip\uFF1A\u8BF7\u5728\u6B63\u786E\u7684\u4F4D\u7F6E\u7A7F\u5BBD\u5EA6\u7EA610cm\u7684\u5E26\u5B50"
DialogueText:
DetailedContent:
ExamQuestionText: "\u8BF7\u9009\u62E9\u5408\u9002\u7684\u5E26\u5B50\u5BBD\u5EA6"
ExamOptions:
- 5cm
- 10cm
- 20cm
CorrectOptionIndex: 1
ErrorFeedback: "\u5E94\u9009\u62E910cm\u5BBD\u5EA6\u7684\u5E26\u5B50"
CompleteType: 4
TargetTag: BandagePos1
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 1
VideoFileName: bandage_demo.mp4
--- !u!114 &7458162247652040644
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 10
SubStepCount: 1
StepIndex: 7
StepName: FinalCheck
TipText: "Tip\uFF1A\u5305\u624E\u5B8C\u6BD5\u8BF7\u68C0\u67E5\u4F24\u80A2\u8840\u6DB2\u5FAA\u73AF\uFF0C\u8FD0\u52A8\u53CA\u611F\u89C9\u3002"
DialogueText: "\u4F24\u5458\u4E00\u5207\u6B63\u5E38\uFF0C\u5305\u624E\u5B8C\u6BD5\u3002"
DetailedContent:
ExamQuestionText: "\u5305\u624E\u5B8C\u6BD5\uFF0C\u8BF7\u786E\u8BA4\u5E76\u7ED3\u675F\u5B9E\u9A8C"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback:
CompleteType: 3
TargetTag:
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
--- !u!114 &8462047121893510914
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dac314898f2b743efa29d166b0ed2980, type: 3}
m_Name:
m_EditorClassIdentifier:
ScoreWeight: 10
SubStepCount: 1
StepIndex: 4
StepName: LimbFixation
TipText: "Tip\uFF1A\u8BF7\u5728\u4E24\u4E0B\u80A2\u95F4\u52A0\u886C\u57AB\uFF0C\u79FB\u52A8\u5065\u80A2\uFF0C\u5C06\u53CC\u4E0B\u80A2\u8F7B\u8F7B\u5E76\u62E2"
DialogueText:
DetailedContent:
ExamQuestionText: "\u8BF7\u9009\u62E9\u6B63\u786E\u7684\u653E\u5E26\u5B50\u987A\u5E8F"
ExamOptions: []
CorrectOptionIndex: -1
ErrorFeedback: "\u653E\u5E26\u5B50\u987A\u5E8F\u4E0D\u6B63\u786E"
CompleteType: 2
TargetTag: PaddingPos
ClickSequenceTags: []
IsSplintOnly: 0
ShowPipVideo: 0
VideoFileName:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b8186bf740de49458c808d08f2ddd4c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
+3 -2
View File
@@ -1836,7 +1836,7 @@ MonoBehaviour:
_uiManager: {fileID: 1642393470} _uiManager: {fileID: 1642393470}
_animationHandler: {fileID: 0} _animationHandler: {fileID: 0}
_audioManager: {fileID: 441640510} _audioManager: {fileID: 441640510}
_defaultConfig: {fileID: 0} _defaultConfig: {fileID: 11400000, guid: 4b8186bf740de49458c808d08f2ddd4c, type: 2}
--- !u!114 &441640513 --- !u!114 &441640513
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1849,7 +1849,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: a2535da3ddf9046e686f9b0d2ce5f569, type: 3} m_Script: {fileID: 11500000, guid: a2535da3ddf9046e686f9b0d2ce5f569, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
Config: {fileID: 0} Config: {fileID: 11400000, guid: 4b8186bf740de49458c808d08f2ddd4c, type: 2}
OnStepChanged: OnStepChanged:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
@@ -5780,6 +5780,7 @@ MonoBehaviour:
_btnSplintFixation: {fileID: 327179436} _btnSplintFixation: {fileID: 327179436}
_practiceModeDesc: "\u25CF \u6A21\u62DF\u7EC3\u4E60\u6A21\u5F0F\uFF1A\u4E0D\u9650\u65F6\u957F\uFF0C\u53EF\u53CD\u590D\u7EC3\u4E60\u3002\u7CFB\u7EDF\u4E0D\u8BC4\u5206\uFF0C\u5E2E\u52A9\u60A8\u719F\u6089\u5B9E\u9A8C\u6D41\u7A0B\u548C\u64CD\u4F5C\u6B65\u9AA4\u3002" _practiceModeDesc: "\u25CF \u6A21\u62DF\u7EC3\u4E60\u6A21\u5F0F\uFF1A\u4E0D\u9650\u65F6\u957F\uFF0C\u53EF\u53CD\u590D\u7EC3\u4E60\u3002\u7CFB\u7EDF\u4E0D\u8BC4\u5206\uFF0C\u5E2E\u52A9\u60A8\u719F\u6089\u5B9E\u9A8C\u6D41\u7A0B\u548C\u64CD\u4F5C\u6B65\u9AA4\u3002"
_examModeDesc: "\u25CF \u8003\u6838\u8BC4\u4F30\u6A21\u5F0F\uFF1A\u9650\u5B9A\u65F6\u95F4\uFF0C\u5B8C\u6210\u540E\u7CFB\u7EDF\u81EA\u52A8\u8BC4\u5206\uFF0C\u5E76\u63D0\u4F9B\u8BE6\u7EC6\u53CD\u9988\u62A5\u544A\u3002" _examModeDesc: "\u25CF \u8003\u6838\u8BC4\u4F30\u6A21\u5F0F\uFF1A\u9650\u5B9A\u65F6\u95F4\uFF0C\u5B8C\u6210\u540E\u7CFB\u7EDF\u81EA\u52A8\u8BC4\u5206\uFF0C\u5E76\u63D0\u4F9B\u8BE6\u7EC6\u53CD\u9988\u62A5\u544A\u3002"
_editorPreview: 0
--- !u!1 &1654726178 --- !u!1 &1654726178
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -3,7 +3,9 @@ using UnityEngine;
/// <summary> /// <summary>
/// 实验场景的总协调器:挂载在 Experiment 场景的根 GameObject 上, /// 实验场景的总协调器:挂载在 Experiment 场景的根 GameObject 上,
/// 负责将 StepManager / InteractionSystem / UIManager 串联在一起。 /// 负责将 StepManager / InteractionSystem / UIManager 串联在一起。
/// 考核模式以 proportion0~1)计分。 ///
/// 不再在 Start() 中自动初始化 StepManager——由 PageController 在用户选择
/// 固定方式后触发 InitializeFromGameManager()。
/// </summary> /// </summary>
public class ExperimentFlowCoordinator : MonoBehaviour public class ExperimentFlowCoordinator : MonoBehaviour
{ {
@@ -14,11 +16,15 @@ public class ExperimentFlowCoordinator : MonoBehaviour
[SerializeField] private StepAnimationHandler _animationHandler; [SerializeField] private StepAnimationHandler _animationHandler;
[SerializeField] private AudioManager _audioManager; [SerializeField] private AudioManager _audioManager;
[Header("配置")] [Header("兜底配置(当 StepManager.Config 未在 Inspector 中赋值时使用)")]
[SerializeField] private ExperimentConfig _defaultConfig; [SerializeField] private ExperimentConfig _defaultConfig;
/// <summary>供 StepManager 读取兜底配置</summary>
public ExperimentConfig DefaultConfig => _defaultConfig;
private void Start() private void Start()
{ {
// 只绑定事件回调,不自动初始化实验流程
if (_interactionSystem != null && _stepManager != null) if (_interactionSystem != null && _stepManager != null)
{ {
_interactionSystem.OnObjectClicked.AddListener(OnObjectClicked); _interactionSystem.OnObjectClicked.AddListener(OnObjectClicked);
@@ -30,12 +36,14 @@ public class ExperimentFlowCoordinator : MonoBehaviour
_stepManager.OnStepChanged.AddListener(_animationHandler.PlayStepAnimation); _stepManager.OnStepChanged.AddListener(_animationHandler.PlayStepAnimation);
} }
if (_defaultConfig != null) // 将兜底配置传给 StepManager
if (_stepManager != null && _stepManager.Config == null && _defaultConfig != null)
{ {
_stepManager.Config = _defaultConfig; _stepManager.Config = _defaultConfig;
} }
_stepManager.InitializeFromGameManager(); // 实验流程由 PageController 在用户选择完模式和固定方式后启动
Debug.Log("ExperimentFlowCoordinator: 就绪,等待 PageController 触发实验启动。");
} }
#region #region
@@ -62,12 +70,10 @@ public class ExperimentFlowCoordinator : MonoBehaviour
break; break;
case StepCompleteType.SequenceClick: case StepCompleteType.SequenceClick:
// 按子项命中比例计分
bool isComplete; bool isComplete;
bool isCorrect = _interactionSystem.TrySequenceClick(tag, out isComplete); bool isCorrect = _interactionSystem.TrySequenceClick(tag, out isComplete);
if (isComplete) if (isComplete)
{ {
// 取当前序列已命中数 / 总子项数
int hit = _interactionSystem.GetSequenceHitCount(); int hit = _interactionSystem.GetSequenceHitCount();
int total = step.ClickSequenceTags?.Length ?? step.SubStepCount; int total = step.ClickSequenceTags?.Length ?? step.SubStepCount;
float proportion = total > 0 ? (float)hit / total : 1f; float proportion = total > 0 ? (float)hit / total : 1f;
+35 -26
View File
@@ -8,31 +8,33 @@ using UnityEngine.Events;
/// </summary> /// </summary>
public class StepManager : MonoBehaviour public class StepManager : MonoBehaviour
{ {
[Header("配置")] [Header("配置(优先级:Inspector直接赋值 > ExperimentFlowCoordinator兜底 > Resources加载)")]
public ExperimentConfig Config; public ExperimentConfig Config;
[Header("事件(拖入场景对象或通过代码绑定)")] [Header("事件(拖入场景对象或通过代码绑定)")]
public UnityEvent<int> OnStepChanged; // 步骤切换时触发,传新步骤索引 public UnityEvent<int> OnStepChanged;
public UnityEvent<string> OnTipChanged; // Tip 文案更新 public UnityEvent<string> OnTipChanged;
public UnityEvent<string> OnDialogueChanged; // 角色对话更新 public UnityEvent<string> OnDialogueChanged;
public UnityEvent<StepData> OnExamPopup; // 考核弹窗触发,传当前 StepData public UnityEvent<StepData> OnExamPopup;
public UnityEvent<string> OnDetailedContent; // 详细操作说明更新(甲方补充) public UnityEvent<string> OnDetailedContent;
public UnityEvent OnExperimentComplete; // 实验全部完成 public UnityEvent OnExperimentComplete;
public UnityEvent<string, bool> OnVideoToggle; // 画中画视频开关(文件名, 是否激活) public UnityEvent<string, bool> OnVideoToggle;
public UnityEvent<bool> OnModeUIUpdate; // 通知 UI 刷新模式按钮状态 public UnityEvent<bool> OnModeUIUpdate;
// 私有状态 // 私有状态
private StepData[] _activeSteps; private StepData[] _activeSteps;
private int _currentStepIndex = -1; private int _currentStepIndex = -1;
private ExperimentMode _mode; private ExperimentMode _mode;
private FixationMethod _fixation; private FixationMethod _fixation;
private bool _initialized = false;
public int CurrentStepIndex => _currentStepIndex; public int CurrentStepIndex => _currentStepIndex;
public int TotalSteps => _activeSteps != null ? _activeSteps.Length : 0; public int TotalSteps => _activeSteps != null ? _activeSteps.Length : 0;
public ExperimentMode Mode => _mode; public ExperimentMode Mode => _mode;
public FixationMethod Fixation => _fixation; public FixationMethod Fixation => _fixation;
public bool IsInitialized => _initialized;
/// <summary>用 GameManager 的当前设置初始化实验流程</summary> /// <summary>用 GameManager 的当前设置初始化</summary>
public void InitializeFromGameManager() public void InitializeFromGameManager()
{ {
var gm = GameManager.Instance; var gm = GameManager.Instance;
@@ -43,16 +45,33 @@ public class StepManager : MonoBehaviour
/// <summary>显式指定参数初始化</summary> /// <summary>显式指定参数初始化</summary>
public void Initialize(ExperimentType type, ExperimentMode mode, FixationMethod fixation) public void Initialize(ExperimentType type, ExperimentMode mode, FixationMethod fixation)
{ {
_mode = mode; // 如果 Inspector 里没有直接拖 Config,尝试从 ExperimentFlowCoordinator 获取兜底配置
_fixation = fixation;
Config = Resources.Load<ExperimentConfig>($"Configs/{type}Config");
if (Config == null) if (Config == null)
{ {
Debug.LogError($"StepManager: 找不到 ExperimentConfig for {type},请在 Resources/Configs/ 下创建"); var coordinator = FindObjectOfType<ExperimentFlowCoordinator>();
if (coordinator != null && coordinator.DefaultConfig != null)
{
Config = coordinator.DefaultConfig;
}
}
// 最后尝试从 Resources 加载
if (Config == null)
{
Config = Resources.Load<ExperimentConfig>($"Configs/{type}Config");
}
if (Config == null)
{
Debug.LogError($"StepManager: 找不到 ExperimentConfig for {type}。" +
"请在 Inspector 中直接拖入 Config,或在 ExperimentFlowCoordinator 上设置 Default Config" +
"或在 Resources/Configs/ 下创建 ScriptableObject。");
return; return;
} }
_mode = mode;
_fixation = fixation;
_activeSteps = Config.GetStepsFor(mode, fixation); _activeSteps = Config.GetStepsFor(mode, fixation);
if (_activeSteps == null || _activeSteps.Length == 0) if (_activeSteps == null || _activeSteps.Length == 0)
{ {
@@ -61,6 +80,7 @@ public class StepManager : MonoBehaviour
} }
_currentStepIndex = -1; _currentStepIndex = -1;
_initialized = true;
if (mode == ExperimentMode.Exam) if (mode == ExperimentMode.Exam)
GameManager.Instance.InitExamRecord(_activeSteps.Length); GameManager.Instance.InitExamRecord(_activeSteps.Length);
@@ -69,7 +89,6 @@ public class StepManager : MonoBehaviour
GoToStep(0); GoToStep(0);
} }
/// <summary>跳转到指定步骤(含边界检查)</summary>
public void GoToStep(int index) public void GoToStep(int index)
{ {
if (_activeSteps == null) return; if (_activeSteps == null) return;
@@ -103,7 +122,6 @@ public class StepManager : MonoBehaviour
OnStepChanged?.Invoke(_currentStepIndex); OnStepChanged?.Invoke(_currentStepIndex);
} }
/// <summary>下一步</summary>
public void NextStep() public void NextStep()
{ {
if (_activeSteps == null) return; if (_activeSteps == null) return;
@@ -115,14 +133,12 @@ public class StepManager : MonoBehaviour
GoToStep(_currentStepIndex + 1); GoToStep(_currentStepIndex + 1);
} }
/// <summary>上一步</summary>
public void PreviousStep() public void PreviousStep()
{ {
if (_activeSteps == null || _currentStepIndex <= 0) return; if (_activeSteps == null || _currentStepIndex <= 0) return;
GoToStep(_currentStepIndex - 1); GoToStep(_currentStepIndex - 1);
} }
/// <summary>获取当前步骤数据(只读)</summary>
public StepData GetCurrentStep() public StepData GetCurrentStep()
{ {
if (_activeSteps == null || _currentStepIndex < 0 || _currentStepIndex >= _activeSteps.Length) if (_activeSteps == null || _currentStepIndex < 0 || _currentStepIndex >= _activeSteps.Length)
@@ -130,10 +146,6 @@ public class StepManager : MonoBehaviour
return _activeSteps[_currentStepIndex]; return _activeSteps[_currentStepIndex];
} }
/// <summary>
/// 当前步骤互动完成后的回调。
/// proportion: 得分比例 0~1SequenceClick 按子项命中比例,其余全对=1,全错=0)。
/// </summary>
public void OnStepInteractionComplete(float proportion = 1f, string feedback = "") public void OnStepInteractionComplete(float proportion = 1f, string feedback = "")
{ {
var step = GetCurrentStep(); var step = GetCurrentStep();
@@ -149,21 +161,18 @@ public class StepManager : MonoBehaviour
NextStep(); NextStep();
} }
/// <summary>实验完成</summary>
private void CompleteExperiment() private void CompleteExperiment()
{ {
Debug.Log("StepManager: 实验流程结束"); Debug.Log("StepManager: 实验流程结束");
OnExperimentComplete?.Invoke(); OnExperimentComplete?.Invoke();
} }
/// <summary>切换模式(学习 ↔ 考核),从头开始</summary>
public void SwitchMode(ExperimentMode newMode) public void SwitchMode(ExperimentMode newMode)
{ {
GameManager.Instance.CurrentMode = newMode; GameManager.Instance.CurrentMode = newMode;
Initialize(GameManager.Instance.CurrentExperimentType, newMode, GameManager.Instance.CurrentFixationMethod); Initialize(GameManager.Instance.CurrentExperimentType, newMode, GameManager.Instance.CurrentFixationMethod);
} }
/// <summary>切换固定方式,从头开始</summary>
public void SwitchFixation(FixationMethod newFixation) public void SwitchFixation(FixationMethod newFixation)
{ {
GameManager.Instance.CurrentFixationMethod = newFixation; GameManager.Instance.CurrentFixationMethod = newFixation;
+59 -10
View File
@@ -36,7 +36,13 @@ public class PageController : MonoBehaviour
[SerializeField] [TextArea(2, 4)] private string _examModeDesc = [SerializeField] [TextArea(2, 4)] private string _examModeDesc =
"● 考核评估模式:限定时间,完成后系统自动评分,并提供详细反馈报告。"; "● 考核评估模式:限定时间,完成后系统自动评分,并提供详细反馈报告。";
private enum Page { Home, ModeSelect, Fixation, Experiment } [Header("=== 编辑器预览(仅 Editor 模式有效)===")]
[SerializeField] private EditorPreviewPage _editorPreview = EditorPreviewPage.None;
// Page 枚举改为 publicInspector 中可通过 _editorPreview 切换
public enum Page { Home, ModeSelect, Fixation, Experiment }
public enum EditorPreviewPage { None, Home, ModeSelect, Fixation, Experiment }
private Page _currentPage = Page.Home; private Page _currentPage = Page.Home;
private ExperimentMode _selectedMode = ExperimentMode.Learn; private ExperimentMode _selectedMode = ExperimentMode.Learn;
@@ -66,6 +72,58 @@ public class PageController : MonoBehaviour
ShowPage(Page.Home); ShowPage(Page.Home);
} }
#if UNITY_EDITOR
/// <summary>
/// 在 Inspector 中修改 _editorPreview 下拉框时,立即切换 Scene View 中显示的页面,
/// 方便编辑不同页面的 UI 布局。仅在非运行状态下生效。
/// </summary>
private void OnValidate()
{
if (Application.isPlaying) return;
// 延迟一帧执行,避免在序列化过程中修改场景导致警告
UnityEditor.EditorApplication.delayCall += () =>
{
if (this == null) return;
if (Application.isPlaying) return;
switch (_editorPreview)
{
case EditorPreviewPage.None:
// 不做任何切换,保留当前状态
break;
case EditorPreviewPage.Home:
ShowPageEditMode(Page.Home);
break;
case EditorPreviewPage.ModeSelect:
ShowPageEditMode(Page.ModeSelect);
break;
case EditorPreviewPage.Fixation:
ShowPageEditMode(Page.Fixation);
break;
case EditorPreviewPage.Experiment:
ShowPageEditMode(Page.Experiment);
break;
}
// 切换完成后重置为 None,避免与后续操作冲突
_editorPreview = EditorPreviewPage.None;
};
}
private void ShowPageEditMode(Page page)
{
if (_homePagePanel != null) _homePagePanel.SetActive(page == Page.Home);
if (_modeSelectPanel != null) _modeSelectPanel.SetActive(page == Page.ModeSelect);
if (_fixationPanel != null) _fixationPanel.SetActive(page == Page.Fixation);
if (_uiManager != null)
_uiManager.enabled = (page == Page.Experiment);
Debug.Log($"PageController(编辑器预览): 切换到 [{page}]");
}
#endif
#region #region
private void ShowPage(Page page) private void ShowPage(Page page)
@@ -76,7 +134,6 @@ public class PageController : MonoBehaviour
if (_modeSelectPanel != null) _modeSelectPanel.SetActive(page == Page.ModeSelect); if (_modeSelectPanel != null) _modeSelectPanel.SetActive(page == Page.ModeSelect);
if (_fixationPanel != null) _fixationPanel.SetActive(page == Page.Fixation); if (_fixationPanel != null) _fixationPanel.SetActive(page == Page.Fixation);
// 实验内界面:隐藏所有实验 UI,等模式确定后再由 UIManager 激活
if (_uiManager != null) if (_uiManager != null)
_uiManager.enabled = (page == Page.Experiment); _uiManager.enabled = (page == Page.Experiment);
} }
@@ -99,18 +156,15 @@ public class PageController : MonoBehaviour
#endif #endif
} }
// 模式选择页 -> 返回首页
private void OnModeBackClicked() private void OnModeBackClicked()
{ {
ShowPage(Page.Home); ShowPage(Page.Home);
} }
// 选择模式后 -> 进入固定方式选择页
private void OnModeSelected(ExperimentMode mode) private void OnModeSelected(ExperimentMode mode)
{ {
_selectedMode = mode; _selectedMode = mode;
// 更新说明文案显示当前选择
if (_modeDescText != null) if (_modeDescText != null)
{ {
_modeDescText.text = mode == ExperimentMode.Learn _modeDescText.text = mode == ExperimentMode.Learn
@@ -121,10 +175,8 @@ public class PageController : MonoBehaviour
ShowPage(Page.Fixation); ShowPage(Page.Fixation);
} }
// 固定方式选择页 -> 返回模式选择页
private void OnFixationBackClicked() private void OnFixationBackClicked()
{ {
// 恢复原始说明文案
if (_modeDescText != null) if (_modeDescText != null)
{ {
_modeDescText.text = _practiceModeDesc + "\n\n" + _examModeDesc; _modeDescText.text = _practiceModeDesc + "\n\n" + _examModeDesc;
@@ -133,7 +185,6 @@ public class PageController : MonoBehaviour
ShowPage(Page.ModeSelect); ShowPage(Page.ModeSelect);
} }
// 选择固定方式后 -> 进入实验
private void OnFixationSelected(FixationMethod method) private void OnFixationSelected(FixationMethod method)
{ {
var gm = GameManager.Instance; var gm = GameManager.Instance;
@@ -146,10 +197,8 @@ public class PageController : MonoBehaviour
gm.CurrentMode = _selectedMode; gm.CurrentMode = _selectedMode;
gm.CurrentFixationMethod = method; gm.CurrentFixationMethod = method;
// 切换到实验界面
ShowPage(Page.Experiment); ShowPage(Page.Experiment);
// 启动实验流程
var stepManager = FindObjectOfType<StepManager>(); var stepManager = FindObjectOfType<StepManager>();
if (stepManager != null) if (stepManager != null)
{ {
+3 -3
View File
@@ -792,18 +792,18 @@ PlayerSettings:
webGLExceptionSupport: 1 webGLExceptionSupport: 1
webGLNameFilesAsHashes: 0 webGLNameFilesAsHashes: 0
webGLShowDiagnostics: 0 webGLShowDiagnostics: 0
webGLDataCaching: 1 webGLDataCaching: 0
webGLDebugSymbols: 0 webGLDebugSymbols: 0
webGLEmscriptenArgs: webGLEmscriptenArgs:
webGLModulesDirectory: webGLModulesDirectory:
webGLTemplate: APPLICATION:Default webGLTemplate: APPLICATION:Default
webGLAnalyzeBuildSize: 0 webGLAnalyzeBuildSize: 0
webGLUseEmbeddedResources: 0 webGLUseEmbeddedResources: 0
webGLCompressionFormat: 0 webGLCompressionFormat: 2
webGLWasmArithmeticExceptions: 0 webGLWasmArithmeticExceptions: 0
webGLLinkerTarget: 1 webGLLinkerTarget: 1
webGLThreadsSupport: 0 webGLThreadsSupport: 0
webGLDecompressionFallback: 0 webGLDecompressionFallback: 1
webGLInitialMemorySize: 32 webGLInitialMemorySize: 32
webGLMaximumMemorySize: 2048 webGLMaximumMemorySize: 2048
webGLMemoryGrowthMode: 2 webGLMemoryGrowthMode: 2