feat: Enhance scene transition management and HUD scaffolding

- Added RequestTransition method to ISceneService for direct scene transition requests without needing Inspector SO references.
- Updated DoorTransition and RoomTransition to utilize the new RequestTransition method via ServiceLocator.
- Introduced SceneFadeController to manage scene fade effects during transitions, with event channel integration for fade requests.
- Created HUDScaffoldWizard to automate HUD Canvas setup, including various UI elements and event channel bindings.
- Updated assembly definitions to include necessary dependencies for new UI components.
- Added Streaming assets for budget configuration to optimize scene loading and memory management.
This commit is contained in:
2026-06-03 08:08:27 +08:00
parent d27ae9407d
commit 613f2a4d13
15 changed files with 1285 additions and 64 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 712983ef837dc2745b7c72eb346da52f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !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: 65e349713a81a3846a654ea9f428ef99, type: 3}
m_Name: STR_BudgetConfig_Default
m_EditorClassIdentifier:
MaxDormantRooms: 6
MaxMemoryMB: 300
MaxConcurrentLoads: 2
PreloadLookaheadHops: 2
CoolingDuration: 6
LifecycleActivatePerFrame: 8
AtmosphericFadeOutDuration: 0.25
AtmosphericFadeInDuration: 0.3
RegionNameDisplayDuration: 1.2
SeamlessWaitTimeout: 10

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cd50a6ced54f54a43bda5a4d39b7865e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -281,6 +281,76 @@ AudioSource:
m_PreInfinity: 2 m_PreInfinity: 2
m_PostInfinity: 2 m_PostInfinity: 2
m_RotationOrder: 4 m_RotationOrder: 4
--- !u!1 &157732602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 157732603}
- component: {fileID: 157732605}
- component: {fileID: 157732604}
m_Layer: 0
m_Name: SYS_RoomStreamingManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &157732603
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157732602}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 162844601}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &157732604
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157732602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a6db86de2f8c90548ba7e185b9cd5df6, type: 3}
m_Name:
m_EditorClassIdentifier:
_streamingManagerRef: {fileID: 157732605}
_onFadeOutRequest: {fileID: 11400000, guid: a17901d6793dcf2409e2672ffb383208, type: 2}
_onFadeInRequest: {fileID: 11400000, guid: f8d520fe699782b4184ff72ce5200c25, type: 2}
_onRegionNameDisplay: {fileID: 0}
_onSceneWorldStateRestored: {fileID: 0}
_mapDatabase: {fileID: 0}
_budget: {fileID: 11400000, guid: cd50a6ced54f54a43bda5a4d39b7865e, type: 2}
--- !u!114 &157732605
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157732602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0c17eea5df8bd684599801eb7dd7c41f, type: 3}
m_Name:
m_EditorClassIdentifier:
_mapDatabase: {fileID: 0}
_budget: {fileID: 11400000, guid: cd50a6ced54f54a43bda5a4d39b7865e, type: 2}
_onRoomEntered: {fileID: 11400000, guid: 133c65f23b6631846ab619edb0e44708, type: 2}
_onRoomPreloaded: {fileID: 0}
_onRoomActivated: {fileID: 0}
_unitsPerGrid: 16
--- !u!1 &162844600 --- !u!1 &162844600
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -322,6 +392,8 @@ Transform:
- {fileID: 225262501} - {fileID: 225262501}
- {fileID: 737017261} - {fileID: 737017261}
- {fileID: 1208346588} - {fileID: 1208346588}
- {fileID: 1151871939}
- {fileID: 157732603}
m_Father: {fileID: 1218230064} m_Father: {fileID: 1218230064}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &225262500 --- !u!1 &225262500
@@ -432,8 +504,8 @@ MonoBehaviour:
_sceneService: {fileID: 1321234353} _sceneService: {fileID: 1321234353}
_eventChannelRegistry: {fileID: 750267177} _eventChannelRegistry: {fileID: 750267177}
_saveManager: {fileID: 737017262} _saveManager: {fileID: 737017262}
_checkpointService: {fileID: 1308486565} _checkpointService: {fileID: 1151871940}
_primaryListener: {fileID: 0} _primaryListener: {fileID: 464414703}
--- !u!1 &307714525 --- !u!1 &307714525
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -554,6 +626,176 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 307714525} m_GameObject: {fileID: 307714525}
m_CullTransparentMesh: 1 m_CullTransparentMesh: 1
--- !u!1 &315072829
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 315072830}
- component: {fileID: 315072836}
- component: {fileID: 315072835}
- component: {fileID: 315072834}
- component: {fileID: 315072833}
- component: {fileID: 315072832}
- component: {fileID: 315072831}
m_Layer: 0
m_Name: VCamA
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &315072830
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 537419888}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &315072831
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 886251e9a18ece04ea8e61686c173e1b, type: 3}
m_Name:
m_EditorClassIdentifier:
CameraDistance: 10
DeadZoneDepth: 0
Composition:
ScreenPosition: {x: 0, y: -0.15}
DeadZone:
Enabled: 1
Size: {x: 0.15, y: 0.05}
HardLimits:
Enabled: 0
Size: {x: 0.8, y: 0.8}
Offset: {x: 0, y: 0}
CenterOnActivate: 1
TargetOffset: {x: 0, y: 0, z: 0}
Damping: {x: 0.5, y: 0, z: 0}
Lookahead:
Enabled: 1
Time: 0.28
Smoothing: 5
IgnoreY: 1
--- !u!114 &315072832
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a12cbb2380ff137459b7ba80d492733f, type: 3}
m_Name:
m_EditorClassIdentifier:
_restScale: 0.25
_speedAtFullLookahead: 12
_speedSmoothing: 5
--- !u!114 &315072833
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cb5a7225ab133e74b81d1f0ae22ccc77, type: 3}
m_Name:
m_EditorClassIdentifier:
_dampingDown: 0.08
_dampingUp: 0.65
--- !u!114 &315072834
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7e2e7849ca8d76f438c4b2899c9fb421, type: 3}
m_Name:
m_EditorClassIdentifier:
LockX: 0
LockY: 0
LockedX: 0
LockedY: 0
--- !u!114 &315072835
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4d75924d76b05344aa410607bc57db98, type: 3}
m_Name:
m_EditorClassIdentifier:
BoundingVolume: {fileID: 0}
SlowingDistance: 0
--- !u!114 &315072836
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 315072829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
m_Name:
m_EditorClassIdentifier:
Priority:
Enabled: 0
m_Value: 0
OutputChannel: 1
StandbyUpdate: 2
m_StreamingVersion: 20241001
m_LegacyPriority: 0
Target:
TrackingTarget: {fileID: 0}
LookAtTarget: {fileID: 0}
CustomLookAtTarget: 0
Lens:
FieldOfView: 40
OrthographicSize: 10
NearClipPlane: 0.1
FarClipPlane: 5000
Dutch: 0
ModeOverride: 0
PhysicalProperties:
GateFit: 2
SensorSize: {x: 21.946, y: 16.002}
LensShift: {x: 0, y: 0}
FocusDistance: 10
Iso: 200
ShutterSpeed: 0.005
Aperture: 16
BladeCount: 5
Curvature: {x: 2, y: 11}
BarrelClipping: 0.25
Anamorphism: 0
BlendHint: 0
--- !u!1 &320356782 --- !u!1 &320356782
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -971,7 +1213,7 @@ Camera:
height: 1 height: 1
near clip plane: 0.1 near clip plane: 0.1
far clip plane: 5000 far clip plane: 5000
field of view: 10 field of view: 40
orthographic: 0 orthographic: 0
orthographic size: 10 orthographic size: 10
m_Depth: 0 m_Depth: 0
@@ -998,7 +1240,7 @@ Transform:
m_GameObject: {fileID: 464414701} m_GameObject: {fileID: 464414701}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -18.954266, y: 5.5, z: -64} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
@@ -1080,6 +1322,8 @@ Transform:
- {fileID: 464414705} - {fileID: 464414705}
- {fileID: 1838586610} - {fileID: 1838586610}
- {fileID: 1341315320} - {fileID: 1341315320}
- {fileID: 315072830}
- {fileID: 1852813069}
m_Father: {fileID: 1218230064} m_Father: {fileID: 1218230064}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &545025334 --- !u!1 &545025334
@@ -1255,6 +1499,54 @@ MonoBehaviour:
_onMapOpen: {fileID: 11400000, guid: b972e8c7aec9da34d80381e643d49cb2, type: 2} _onMapOpen: {fileID: 11400000, guid: b972e8c7aec9da34d80381e643d49cb2, type: 2}
_onCharmPanelOpen: {fileID: 0} _onCharmPanelOpen: {fileID: 0}
_onSpellSelectOpen: {fileID: 0} _onSpellSelectOpen: {fileID: 0}
--- !u!1 &712830947
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 712830948}
- component: {fileID: 712830949}
m_Layer: 0
m_Name: SYS_SceneFade
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &712830948
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 712830947}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1810445798}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &712830949
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 712830947}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5e4fa87eedbe2f24db81bdf66714343f, type: 3}
m_Name:
m_EditorClassIdentifier:
_fadeOut: {fileID: 0}
_fadeIn: {fileID: 0}
_onFadeOutRequest: {fileID: 11400000, guid: a17901d6793dcf2409e2672ffb383208, type: 2}
_onFadeInRequest: {fileID: 11400000, guid: f8d520fe699782b4184ff72ce5200c25, type: 2}
--- !u!1 &737017260 --- !u!1 &737017260
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1728,6 +2020,51 @@ MonoBehaviour:
_onLoadingStarted: {fileID: 11400000, guid: 78de6bbfc7741ad47ad568ba0b65fde0, type: 2} _onLoadingStarted: {fileID: 11400000, guid: 78de6bbfc7741ad47ad568ba0b65fde0, type: 2}
_onLoadingComplete: {fileID: 11400000, guid: 1e4580d266c4bd44c8b25a70d26608d3, type: 2} _onLoadingComplete: {fileID: 11400000, guid: 1e4580d266c4bd44c8b25a70d26608d3, type: 2}
_onLoadingProgressUpdated: {fileID: 11400000, guid: 2d366d52ee6a8214c8cd94d14e9ccd15, type: 2} _onLoadingProgressUpdated: {fileID: 11400000, guid: 2d366d52ee6a8214c8cd94d14e9ccd15, type: 2}
--- !u!1 &1151871938
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1151871939}
- component: {fileID: 1151871940}
m_Layer: 0
m_Name: CheckpointService
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1151871939
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1151871938}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 162844601}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1151871940
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1151871938}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 486e785d32d1c4c468a4eb0fd4cf1822, type: 3}
m_Name:
m_EditorClassIdentifier:
_onSceneLoaded: {fileID: 11400000, guid: ce0e5d2372599c74aabdac63c1620289, type: 2}
--- !u!1 &1189402268 --- !u!1 &1189402268
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -2958,6 +3295,7 @@ Transform:
- {fileID: 1758098875} - {fileID: 1758098875}
- {fileID: 1710356906} - {fileID: 1710356906}
- {fileID: 622211655} - {fileID: 622211655}
- {fileID: 712830948}
m_Father: {fileID: 1218230064} m_Father: {fileID: 1218230064}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1838586609 --- !u!1 &1838586609
@@ -3065,6 +3403,176 @@ MonoBehaviour:
_lensConfig: {fileID: 11400000, guid: 12fec951ce5cc3d499b00e38b5dfa14a, type: 2} _lensConfig: {fileID: 11400000, guid: 12fec951ce5cc3d499b00e38b5dfa14a, type: 2}
_onPlayerSpawned: {fileID: 11400000, guid: 7e2c7e614f6627b449a244ab44443adf, type: 2} _onPlayerSpawned: {fileID: 11400000, guid: 7e2c7e614f6627b449a244ab44443adf, type: 2}
_showDebugOverlay: 0 _showDebugOverlay: 0
--- !u!1 &1852813068
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1852813069}
- component: {fileID: 1852813075}
- component: {fileID: 1852813074}
- component: {fileID: 1852813073}
- component: {fileID: 1852813072}
- component: {fileID: 1852813071}
- component: {fileID: 1852813070}
m_Layer: 0
m_Name: VCamB
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1852813069
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 537419888}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1852813070
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 886251e9a18ece04ea8e61686c173e1b, type: 3}
m_Name:
m_EditorClassIdentifier:
CameraDistance: 10
DeadZoneDepth: 0
Composition:
ScreenPosition: {x: 0, y: -0.15}
DeadZone:
Enabled: 1
Size: {x: 0.15, y: 0.05}
HardLimits:
Enabled: 0
Size: {x: 0.8, y: 0.8}
Offset: {x: 0, y: 0}
CenterOnActivate: 1
TargetOffset: {x: 0, y: 0, z: 0}
Damping: {x: 0.5, y: 0, z: 0}
Lookahead:
Enabled: 1
Time: 0.28
Smoothing: 5
IgnoreY: 1
--- !u!114 &1852813071
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a12cbb2380ff137459b7ba80d492733f, type: 3}
m_Name:
m_EditorClassIdentifier:
_restScale: 0.25
_speedAtFullLookahead: 12
_speedSmoothing: 5
--- !u!114 &1852813072
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cb5a7225ab133e74b81d1f0ae22ccc77, type: 3}
m_Name:
m_EditorClassIdentifier:
_dampingDown: 0.08
_dampingUp: 0.65
--- !u!114 &1852813073
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7e2e7849ca8d76f438c4b2899c9fb421, type: 3}
m_Name:
m_EditorClassIdentifier:
LockX: 0
LockY: 0
LockedX: 0
LockedY: 0
--- !u!114 &1852813074
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4d75924d76b05344aa410607bc57db98, type: 3}
m_Name:
m_EditorClassIdentifier:
BoundingVolume: {fileID: 0}
SlowingDistance: 0
--- !u!114 &1852813075
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1852813068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
m_Name:
m_EditorClassIdentifier:
Priority:
Enabled: 0
m_Value: 0
OutputChannel: 1
StandbyUpdate: 2
m_StreamingVersion: 20241001
m_LegacyPriority: 0
Target:
TrackingTarget: {fileID: 0}
LookAtTarget: {fileID: 0}
CustomLookAtTarget: 0
Lens:
FieldOfView: 40
OrthographicSize: 10
NearClipPlane: 0.1
FarClipPlane: 5000
Dutch: 0
ModeOverride: 0
PhysicalProperties:
GateFit: 2
SensorSize: {x: 21.946, y: 16.002}
LensShift: {x: 0, y: 0}
FocusDistance: 10
Iso: 200
ShutterSpeed: 0.005
Aperture: 16
BladeCount: 5
Curvature: {x: 2, y: 11}
BarrelClipping: 0.25
Anamorphism: 0
BlendHint: 0
--- !u!1 &1859511082 --- !u!1 &1859511082
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -5627,6 +5627,102 @@ MonoBehaviour:
_noiseFrequency: 1 _noiseFrequency: 1
_dedicatedCamera: {fileID: 840207430} _dedicatedCamera: {fileID: 840207430}
_dedicatedPriority: 20 _dedicatedPriority: 20
--- !u!1 &318931261
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 318931262}
- component: {fileID: 318931264}
- component: {fileID: 318931263}
m_Layer: 25
m_Name: '[Shape_Polygon]'
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &318931262
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 318931261}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.291, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 831117707}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &318931263
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 318931261}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e11b931e351246344aec20aa35489592, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!60 &318931264
PolygonCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 318931261}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_ForceSendLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ForceReceiveLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ContactCaptureLayers:
serializedVersion: 2
m_Bits: 4294967295
m_CallbackLayers:
serializedVersion: 2
m_Bits: 4294967295
m_IsTrigger: 1
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
m_Points:
m_Paths:
- - {x: 0, y: 0.3}
- {x: 0.6047108, y: 0.3348503}
- {x: 0.7406552, y: 0.12676334}
- {x: 0.7771857, y: -0.2715292}
- {x: -0.79761577, y: -0.28302938}
- {x: -0.78284264, y: -0.07071018}
m_UseDelaunayMesh: 0
--- !u!1 &320063820 --- !u!1 &320063820
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -12912,7 +13008,7 @@ Transform:
m_GameObject: {fileID: 785719612} m_GameObject: {fileID: 785719612}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0.51, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
@@ -12992,10 +13088,10 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5 m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89 m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0} m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0 m_SortingLayerID: 652617267
m_SortingLayer: 0 m_SortingLayer: -6
m_SortingOrder: 0 m_SortingOrder: 0
m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Sprite: {fileID: 1805018772, guid: 97a250d50f6857443aa7d823bbe36304, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0 m_FlipX: 0
m_FlipY: 0 m_FlipY: 0
@@ -13798,9 +13894,9 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 831117707} - component: {fileID: 831117707}
- component: {fileID: 831117706}
- component: {fileID: 831117705} - component: {fileID: 831117705}
- component: {fileID: 831117704} - component: {fileID: 831117704}
- component: {fileID: 831117708}
m_Layer: 25 m_Layer: 25
m_Name: ContactDamageZone m_Name: ContactDamageZone
m_TagString: Untagged m_TagString: Untagged
@@ -13838,9 +13934,25 @@ MonoBehaviour:
_id: _id:
_rivalHitBoxMask: _rivalHitBoxMask:
serializedVersion: 2 serializedVersion: 2
m_Bits: 0 m_Bits: 512
--- !u!58 &831117706 --- !u!4 &831117707
CircleCollider2D: Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 831117703}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 318931262}
m_Father: {fileID: 1864792379}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!70 &831117708
CapsuleCollider2D:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
@@ -13871,24 +13983,9 @@ CircleCollider2D:
m_IsTrigger: 1 m_IsTrigger: 1
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: 0.40729484, y: 0.32778132}
serializedVersion: 2 m_Size: {x: 0.7284849, y: 0.65556294}
m_Radius: 0.4 m_Direction: 1
--- !u!4 &831117707
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 831117703}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1864792379}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &837279661 --- !u!1 &837279661
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -210626,8 +210723,8 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 1758953875} - component: {fileID: 1758953875}
- component: {fileID: 1758953874}
- component: {fileID: 1758953873} - component: {fileID: 1758953873}
- component: {fileID: 1758953876}
m_Layer: 27 m_Layer: 27
m_Name: HurtBox m_Name: HurtBox
m_TagString: Untagged m_TagString: Untagged
@@ -210649,8 +210746,23 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_onDamageDealt: {fileID: 0} _onDamageDealt: {fileID: 0}
_onHitConfirmed: {fileID: 11400000, guid: a67d56f5124e0db4f98f326c74be8091, type: 2} _onHitConfirmed: {fileID: 11400000, guid: a67d56f5124e0db4f98f326c74be8091, type: 2}
--- !u!70 &1758953874 --- !u!4 &1758953875
CapsuleCollider2D: Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1758953872}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1864792379}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!61 &1758953876
BoxCollider2D:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
@@ -210681,24 +210793,19 @@ CapsuleCollider2D:
m_IsTrigger: 1 m_IsTrigger: 1
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: -0.01498282, y: 0.4}
m_Size: {x: 0.55, y: 0.75} m_SpriteTilingProperty:
m_Direction: 0 border: {x: 0, y: 0, z: 0, w: 0}
--- !u!4 &1758953875 pivot: {x: 0, y: 0}
Transform: oldSize: {x: 0, y: 0}
m_ObjectHideFlags: 0 newSize: {x: 0, y: 0}
m_CorrespondingSourceObject: {fileID: 0} adaptiveTilingThreshold: 0
m_PrefabInstance: {fileID: 0} drawMode: 0
m_PrefabAsset: {fileID: 0} adaptiveTiling: 0
m_GameObject: {fileID: 1758953872} m_AutoTiling: 0
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_Size: {x: 1.5648925, y: 0.8}
m_LocalPosition: {x: 0, y: 0, z: 0} m_EdgeRadius: 0
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1864792379}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1766894770 --- !u!1 &1766894770
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -212034,6 +212141,7 @@ GameObject:
- component: {fileID: 1864792372} - component: {fileID: 1864792372}
- component: {fileID: 1864792371} - component: {fileID: 1864792371}
- component: {fileID: 1864792370} - component: {fileID: 1864792370}
- component: {fileID: 1864792380}
m_Layer: 13 m_Layer: 13
m_Name: ENM_CaoZhi m_Name: ENM_CaoZhi
m_TagString: Untagged m_TagString: Untagged
@@ -212282,7 +212390,7 @@ BoxCollider2D:
m_IsTrigger: 0 m_IsTrigger: 0
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: -0.01498282, y: 0.4}
m_SpriteTilingProperty: m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0} border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0} pivot: {x: 0, y: 0}
@@ -212293,7 +212401,7 @@ BoxCollider2D:
adaptiveTiling: 0 adaptiveTiling: 0
m_AutoTiling: 0 m_AutoTiling: 0
serializedVersion: 2 serializedVersion: 2
m_Size: {x: 0.6, y: 0.8} m_Size: {x: 1.5648925, y: 0.8}
m_EdgeRadius: 0 m_EdgeRadius: 0
--- !u!50 &1864792378 --- !u!50 &1864792378
Rigidbody2D: Rigidbody2D:
@@ -212341,6 +212449,67 @@ Transform:
- {fileID: 1650269713} - {fileID: 1650269713}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1864792380
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1864792369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cdaa3305fa954c45a80c9662aa6f425, type: 3}
m_Name:
m_EditorClassIdentifier:
m_GraphName: Behavior Tree
m_Index: 0
m_Data:
m_TaskData:
- m_ObjectType: Opsive.BehaviorDesigner.Runtime.Tasks.Actions.StackedAction
m_ValueHashes:
m_LongValueHashes: 30b77c28f48d1b2966cb3cf98c4bd96480f6501333363a66622a4da7e5588b5847627e5c3afba34af262c60c48f0bccad0ed2caea3f34ac163eb2caea3f34ac1a8724a1098fa102319cb31fdb78bb19fc8fad5b29007ef3a396f2e031315f24fe4a06bb554569d8946fff10c773614c9
m_ValuePositions: 000000000200000004000000060000000a0000003100000035000000390000003d0000004100000045000000460000004a0000004a000000
m_Values: 0000ffffffff010000004261736547616d65732e456e656d6965732e41492e42445f506174726f6c576179706f696e7473020000000000000001000000000000009a99993e000000000000000000
m_UnityObjects:
- {fileID: 5705765}
- {fileID: 1398696825}
m_Version: 3.4
m_EventTaskData:
- m_ObjectType: Opsive.BehaviorDesigner.Runtime.Tasks.Events.Start
m_ValueHashes:
m_LongValueHashes: 59405171878141b1
m_ValuePositions: 00000000
m_Values: 0000
m_UnityObjects: []
m_Version: 3.4
m_SharedVariableData: []
m_DisabledEventNodesData: []
m_DisabledLogicNodesData: []
m_UniqueID: 206339031
m_LogicNodePropertiesData:
- m_ObjectType: Opsive.GraphDesigner.Runtime.LogicNodeProperties
m_ValueHashes:
m_LongValueHashes: bc124df8ef5e104cf36ca30dee0de9958dd19827f48d1b29bd8814239a1bb7642f6406e2580d1e294f869cc9196b0c27aea3bc2e18d5b803a034c7c2b541f015557e981535906112a98ff48b9e8a66b37f542abda0a249c23a7f01b1f88d1a7b
m_ValuePositions: 00000000240000002c000000300000003000000030000000400000004100000045000000450000004700000049000000
m_Values: 35363062633134302d633833632d343334312d393338392d3063396165323031616638660000a54300008c4200000043000000000000000000000000000000000000000000ffffffff00
m_UnityObjects: []
m_Version: 3.4
m_EventNodePropertiesData:
- m_ObjectType: Opsive.GraphDesigner.Runtime.NodeProperties
m_ValueHashes:
m_LongValueHashes: bc124df8ef5e104cf36ca30dee0de9958dd19827f48d1b29bd8814239a1bb7642f6406e2580d1e294f869cc9196b0c27aea3bc2e18d5b803
m_ValuePositions: 00000000240000002c00000030000000300000003000000040000000
m_Values: 31383566623665622d343438392d346266612d616463652d3434353131393731373638310000a543000000000000dc420000000000000000000000000000000000
m_UnityObjects: []
m_Version: 3.4
m_GroupPropertiesData: []
m_SharedVariableGroupsData: []
m_StartWhenEnabled: 1
m_PauseWhenDisabled: 0
m_UpdateMode: 0
m_EvaluationType: 0
m_MaxEvaluationCount: 1
m_Subtree: {fileID: 0}
--- !u!1 &1865796628 --- !u!1 &1865796628
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -10,6 +10,12 @@ namespace BaseGames.Core
/// </summary> /// </summary>
public interface ISceneService public interface ISceneService
{ {
/// <summary>
/// 直接触发场景过渡请求(无需 Inspector SO 引用)。
/// 游戏场景物体RoomTransition、DoorTransition 等)通过 ServiceLocator 调用此方法,
/// 替代手动拖拽 SceneLoadRequestEventChannelSO。
/// </summary>
void RequestTransition(SceneLoadRequest request);
/// <summary>异步加载指定场景Additive。</summary> /// <summary>异步加载指定场景Additive。</summary>
IEnumerator LoadSceneCoroutine(SceneLoadRequest request); IEnumerator LoadSceneCoroutine(SceneLoadRequest request);
/// <summary>卸载当前房间场景(保留 Persistent。</summary> /// <summary>卸载当前房间场景(保留 Persistent。</summary>
@@ -69,6 +75,9 @@ namespace BaseGames.Core
private void OnDisable() => _subscriptions.Clear(); private void OnDisable() => _subscriptions.Clear();
/// <inheritdoc cref="ISceneService.RequestTransition"/>
public void RequestTransition(SceneLoadRequest request) => HandleSceneLoadRequest(request);
private void HandleSceneLoadRequest(SceneLoadRequest request) private void HandleSceneLoadRequest(SceneLoadRequest request)
{ {
// Seamless / AtmosphericFade 由 ITransitionDirector 处理(需要预加载支持) // Seamless / AtmosphericFade 由 ITransitionDirector 处理(需要预加载支持)

View File

@@ -35,7 +35,8 @@
"BaseGames.EventChain", "BaseGames.EventChain",
"BaseGames.VFX", "BaseGames.VFX",
"BaseGames.Localization", "BaseGames.Localization",
"Unity.InputSystem" "Unity.InputSystem",
"Unity.TextMeshPro"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"

View File

@@ -168,8 +168,19 @@ namespace BaseGames.Editor
AssignAsset(loadingMgr, "_onLoadingProgressUpdated", report, false, "EVT_LoadingProgressUpdated"); AssignAsset(loadingMgr, "_onLoadingProgressUpdated", report, false, "EVT_LoadingProgressUpdated");
loadingCanvasGo.SetActive(false); loadingCanvasGo.SetActive(false);
// ── SceneFadeController场景切换黑幕───────────────────────────
// 纯逻辑节点:监听淡出/淡入事件后调用 SceneFeedback.Play()。
// 实际 UI 效果完全由 SceneFeedback 内部的 MMF_Player 负责。
GameObject fadeCtrGo = GetOrCreateChild(ui.transform, "SYS_SceneFade").gameObject;
SceneFadeController fadeCtr = GetOrAddComponent<SceneFadeController>(fadeCtrGo);
AssignAsset(fadeCtr, "_onFadeOutRequest", report, false, "EVT_FadeOutRequest");
AssignAsset(fadeCtr, "_onFadeInRequest", report, false, "EVT_FadeInRequest");
report.Add("Canvas_Splash请将工作室 Logo CanvasGroup 赋给 _studioLogoGroup游戏标题 CanvasGroup 赋给 _gameTitleGroup。"); report.Add("Canvas_Splash请将工作室 Logo CanvasGroup 赋给 _studioLogoGroup游戏标题 CanvasGroup 赋给 _gameTitleGroup。");
report.Add("Canvas_Loading请为 LoadingScreenManager 绑定 _progressBarSlider和 _loadingPanelGameObject。"); report.Add("Canvas_Loading请为 LoadingScreenManager 绑定 _progressBarSlider和 _loadingPanelGameObject。");
report.Add("SYS_SceneFade请创建两个带 MMF_Player 的 SceneFeedback淡出/淡入)," +
"配置完毕后分别拖入 SceneFadeController._fadeOut / _fadeIn。" +
"MMF_Player 总时长应 ≤ SceneService._sceneFadeDuration默认 0.4 s。");
EnsureAudioSources(audioManagerGo, audioManager, report); EnsureAudioSources(audioManagerGo, audioManager, report);

View File

@@ -0,0 +1,402 @@
using System.Collections.Generic;
using BaseGames.UI;
using BaseGames.UI.HUD;
using TMPro;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace BaseGames.Editor.UI
{
/// <summary>
/// HUD 脚手架工具(架构 10_UIModule §HUD
/// 在当前活动场景中生成完整的 HUD Canvas 层级结构并自动绑定已存在的事件频道资产。
/// 执行路径BaseGames ▸ Scene ▸ Setup ▸ Scaffold HUD Canvas
/// </summary>
public static class HUDScaffoldWizard
{
[MenuItem("BaseGames/Scene/Setup/Scaffold HUD Canvas", priority = 203)]
public static void ScaffoldHUDCanvas()
{
var report = new List<string>();
Undo.SetCurrentGroupName("Scaffold HUD Canvas");
int undoGroup = Undo.GetCurrentGroup();
// ── Canvas ────────────────────────────────────────────────────────
GameObject canvasGo = GetOrCreateRootCanvas("HUD Canvas", 0);
// ── HUDRoot ───────────────────────────────────────────────────────
GameObject hudRootGo = GetOrCreateChild(canvasGo.transform, "HUDRoot").gameObject;
HUDController hudCtrl = GetOrAddComponent<HUDController>(hudRootGo);
// 若场景中已存在 UIManager自动将 _hudRoot 指向本 HUDRoot
UIManager uiManager = Object.FindFirstObjectByType<UIManager>();
if (uiManager != null)
AssignRef(uiManager, "_hudRoot", hudRootGo);
// ── HP 区域 ───────────────────────────────────────────────────────
GameObject hpContainerGo = GetOrCreateChild(hudRootGo.transform, "HP_Container").gameObject;
var hpLayout = GetOrAddComponent<HorizontalLayoutGroup>(hpContainerGo);
hpLayout.childForceExpandWidth = false;
hpLayout.childForceExpandHeight = false;
hpLayout.spacing = 4f;
// ── 魄元Soul量条 ──────────────────────────────────────────────
GameObject soulGaugeGo = GetOrCreateChild(hudRootGo.transform, "Gauge_Soul").gameObject;
Image soulFill = GetOrAddComponent<Image>(soulGaugeGo);
soulFill.type = Image.Type.Filled;
soulFill.fillMethod = Image.FillMethod.Horizontal;
soulFill.fillAmount = 1f;
// ── 灵力Spirit量条 ────────────────────────────────────────────
GameObject spiritGaugeGo = GetOrCreateChild(hudRootGo.transform, "Gauge_Spirit").gameObject;
Image spiritFill = GetOrAddComponent<Image>(spiritGaugeGo);
spiritFill.type = Image.Type.Filled;
spiritFill.fillMethod = Image.FillMethod.Horizontal;
spiritFill.fillAmount = 1f;
// ── 灵铢LingZhu文本 ───────────────────────────────────────────
GameObject lingZhuGo = GetOrCreateChild(hudRootGo.transform, "Text_LingZhu").gameObject;
TMP_Text lingZhuText = GetOrAddComponent<TextMeshProUGUI>(lingZhuGo);
lingZhuText.text = "0";
// ── 回春图标Spring Charges─────────────────────────────────────
GameObject springContainerGo = GetOrCreateChild(hudRootGo.transform, "Spring_Container").gameObject;
var springLayout = GetOrAddComponent<HorizontalLayoutGroup>(springContainerGo);
springLayout.childForceExpandWidth = false;
springLayout.childForceExpandHeight = false;
springLayout.spacing = 4f;
// ── 形态图标Form Icons × 4────────────────────────────────────
const int kFormIconCount = 4;
GameObject formIconsRoot = GetOrCreateChild(hudRootGo.transform, "FormIcons").gameObject;
Image[] formImages = new Image[kFormIconCount];
for (int i = 0; i < kFormIconCount; i++)
{
GameObject iconGo = GetOrCreateChild(formIconsRoot.transform, $"FormIcon_{i}").gameObject;
formImages[i] = GetOrAddComponent<Image>(iconGo);
}
// ── 交互提示InteractPrompt─────────────────────────────────────
GameObject interactPromptGo = GetOrCreateChild(hudRootGo.transform, "InteractPrompt").gameObject;
InteractPromptWidget interactWidget = GetOrAddComponent<InteractPromptWidget>(interactPromptGo);
GameObject promptRootGo = GetOrCreateChild(interactPromptGo.transform, "Root").gameObject;
GameObject promptKeyIconGo = GetOrCreateChild(promptRootGo.transform, "KeyIcon").gameObject;
Image keyIcon = GetOrAddComponent<Image>(promptKeyIconGo);
GameObject promptLabelGo = GetOrCreateChild(promptRootGo.transform, "LabelText").gameObject;
TMP_Text promptLabel = GetOrAddComponent<TextMeshProUGUI>(promptLabelGo);
promptLabel.text = "互动";
promptRootGo.SetActive(false);
AssignRef(interactWidget, "_keyIcon", keyIcon);
AssignRef(interactWidget, "_labelText", promptLabel);
AssignRef(interactWidget, "_root", promptRootGo);
// ── 法术槽SpellSlot───────────────────────────────────────────
GameObject spellSlotGo = GetOrCreateChild(hudRootGo.transform, "SpellSlot").gameObject;
SpellSlotWidget spellWidget = GetOrAddComponent<SpellSlotWidget>(spellSlotGo);
GameObject spellIconGo = GetOrCreateChild(spellSlotGo.transform, "IconImage").gameObject;
Image spellIcon = GetOrAddComponent<Image>(spellIconGo);
GameObject spellCdGo = GetOrCreateChild(spellSlotGo.transform, "CooldownFill").gameObject;
Image spellCd = GetOrAddComponent<Image>(spellCdGo);
spellCd.type = Image.Type.Filled;
spellCd.fillMethod = Image.FillMethod.Radial360;
spellCd.fillAmount = 0f;
GameObject spellEmptyGo = GetOrCreateChild(spellSlotGo.transform, "EmptySlot").gameObject;
AssignRef(spellWidget, "_iconImage", spellIcon);
AssignRef(spellWidget, "_cooldownFill", spellCd);
AssignRef(spellWidget, "_emptySlot", spellEmptyGo);
// ── 工具栏ToolHUD × 2 slots──────────────────────────────────
GameObject toolHUDGo = GetOrCreateChild(hudRootGo.transform, "ToolHUD").gameObject;
ToolHUD toolHUD = GetOrAddComponent<ToolHUD>(toolHUDGo);
const int kToolSlotCount = 2;
var toolSlots = new ToolSlotUI[kToolSlotCount];
for (int i = 0; i < kToolSlotCount; i++)
{
GameObject slotGo = GetOrCreateChild(toolHUDGo.transform, $"ToolSlot_{i}").gameObject;
ToolSlotUI slotUI = GetOrAddComponent<ToolSlotUI>(slotGo);
GameObject iconGo = GetOrCreateChild(slotGo.transform, "Icon").gameObject;
Image slotIcon = GetOrAddComponent<Image>(iconGo);
GameObject usesGo = GetOrCreateChild(slotGo.transform, "UsesText").gameObject;
TMP_Text usesText = GetOrAddComponent<TextMeshProUGUI>(usesGo);
usesText.text = "0";
GameObject cdGo = GetOrCreateChild(slotGo.transform, "CooldownMask").gameObject;
Image cdMask = GetOrAddComponent<Image>(cdGo);
cdMask.type = Image.Type.Filled;
cdMask.fillMethod = Image.FillMethod.Horizontal;
cdMask.fillAmount = 0f;
AssignRef(slotUI, "_icon", slotIcon);
AssignRef(slotUI, "_usesText", usesText);
AssignRef(slotUI, "_cooldownMask", cdMask);
toolSlots[i] = slotUI;
}
AssignArrayRefs(toolHUD, "_slots", toolSlots, report);
// ── Boss 血条BossHPBar────────────────────────────────────────
GameObject bossBarGo = GetOrCreateChild(hudRootGo.transform, "BossHPBar").gameObject;
bossBarGo.SetActive(false);
BossHPBar bossHPBar = GetOrAddComponent<BossHPBar>(bossBarGo);
GameObject bossNameGo = GetOrCreateChild(bossBarGo.transform, "BossName").gameObject;
TMP_Text bossName = GetOrAddComponent<TextMeshProUGUI>(bossNameGo);
bossName.text = "Boss 名称";
GameObject bossHPFillGo = GetOrCreateChild(bossBarGo.transform, "HPFill").gameObject;
Image bossHPFill = GetOrAddComponent<Image>(bossHPFillGo);
bossHPFill.type = Image.Type.Filled;
bossHPFill.fillMethod = Image.FillMethod.Horizontal;
bossHPFill.fillAmount = 1f;
GameObject phaseRootGo = GetOrCreateChild(bossBarGo.transform, "PhaseMarkersRoot").gameObject;
AssignRef(bossHPBar, "_bossNameText", bossName);
AssignRef(bossHPBar, "_hpFill", bossHPFill);
AssignRef(bossHPBar, "_phaseMarkersRoot", phaseRootGo.transform);
// ── 状态效果 HUDStatusEffectHUD──────────────────────────────
GameObject statusHUDGo = GetOrCreateChild(hudRootGo.transform, "StatusEffectHUD").gameObject;
StatusEffectHUD statusHUD = GetOrAddComponent<StatusEffectHUD>(statusHUDGo);
GameObject statusTemplateGo = GetOrCreateChild(statusHUDGo.transform, "SlotTemplate").gameObject;
statusTemplateGo.SetActive(false);
GetOrAddComponent<Image>(statusTemplateGo);
GameObject statusContainerGo = GetOrCreateChild(statusHUDGo.transform, "Container").gameObject;
var statusLayout = GetOrAddComponent<HorizontalLayoutGroup>(statusContainerGo);
statusLayout.childForceExpandWidth = false;
statusLayout.spacing = 4f;
AssignRef(statusHUD, "_slotTemplate", statusTemplateGo);
AssignRef(statusHUD, "_container", statusContainerGo.transform);
// ── 任务追踪QuestTracker──────────────────────────────────────
GameObject questTrackerGo = GetOrCreateChild(hudRootGo.transform, "QuestTracker").gameObject;
QuestTrackerWidget questWidget = GetOrAddComponent<QuestTrackerWidget>(questTrackerGo);
GameObject questTitleGo = GetOrCreateChild(questTrackerGo.transform, "QuestTitle").gameObject;
TMP_Text questTitle = GetOrAddComponent<TextMeshProUGUI>(questTitleGo);
questTitle.text = "任务名称";
GameObject objTemplateGo = GetOrCreateChild(questTrackerGo.transform, "ObjectiveRowTemplate").gameObject;
objTemplateGo.SetActive(false);
GetOrAddComponent<TextMeshProUGUI>(objTemplateGo);
GameObject objContainerGo = GetOrCreateChild(questTrackerGo.transform, "ObjectiveContainer").gameObject;
var objLayout = GetOrAddComponent<VerticalLayoutGroup>(objContainerGo);
objLayout.childForceExpandWidth = false;
objLayout.spacing = 2f;
AssignRef(questWidget, "_questTitleText", questTitle);
AssignRef(questWidget, "_objectiveRowTemplate", objTemplateGo);
AssignRef(questWidget, "_objectiveContainer", objContainerGo.transform);
// ── HUDController 子组件引用 ──────────────────────────────────────
AssignRef(hudCtrl, "_hpContainer", hpContainerGo.transform);
AssignRef(hudCtrl, "_soulGaugeFill", soulFill);
AssignRef(hudCtrl, "_spiritGaugeFill", spiritFill);
AssignRef(hudCtrl, "_lingZhuText", lingZhuText);
AssignRef(hudCtrl, "_springContainer", springContainerGo.transform);
AssignRef(hudCtrl, "_interactPromptWidget", interactWidget);
AssignArrayRefs(hudCtrl, "_formIcons", formImages, report);
// ── 事件频道 ──────────────────────────────────────────────────────
AssignAsset(hudCtrl, "_onHPChanged", report, true, "EVT_HPChanged", "EVT_PlayerHPChanged");
AssignAsset(hudCtrl, "_onMaxHPChanged", report, false, "EVT_MaxHPChanged", "EVT_PlayerMaxHPChanged");
AssignAsset(hudCtrl, "_onSoulPowerChanged", report, false, "EVT_SoulPowerChanged", "EVT_MagicPowerChanged");
AssignAsset(hudCtrl, "_onSpiritPowerChanged", report, false, "EVT_SpiritPowerChanged");
AssignAsset(hudCtrl, "_onLingZhuChanged", report, false, "EVT_LingZhuChanged", "EVT_CurrencyChanged");
AssignAsset(hudCtrl, "_onSpringChargesChanged", report, false, "EVT_SpringChargesChanged", "EVT_SpringCharges");
AssignAsset(hudCtrl, "_onFormChanged", report, false, "EVT_FormChanged");
AssignAsset(interactWidget, "_onShowPrompt", report, false, "EVT_ShowInteractPrompt", "EVT_InteractPromptShow");
AssignAsset(interactWidget, "_onHidePrompt", report, false, "EVT_HideInteractPrompt", "EVT_InteractPromptHide");
AssignAsset(bossHPBar, "_onBossFightToggled", report, false, "EVT_BossFightToggled", "EVT_BossFightStarted");
AssignAsset(bossHPBar, "_onBossHPChanged", report, false, "EVT_BossHPChanged");
AssignAsset(bossHPBar, "_onBossHPMaxSet", report, false, "EVT_BossHPMaxSet");
AssignAsset(bossHPBar, "_onBossNameSet", report, false, "EVT_BossNameSet");
AssignAsset(bossHPBar, "_onBossPhaseThreshold", report, false, "EVT_BossPhaseThreshold");
AssignAsset(statusHUD, "_onStatusEffectApplied", report, false, "EVT_StatusEffectApplied");
AssignAsset(statusHUD, "_onStatusEffectExpired", report, false, "EVT_StatusEffectExpired");
AssignAsset(questWidget, "_onQuestStarted", report, false, "EVT_QuestStarted");
AssignAsset(questWidget, "_onQuestCompleted", report, false, "EVT_QuestCompleted");
AssignAsset(questWidget, "_onQuestFailed", report, false, "EVT_QuestFailed");
AssignAsset(questWidget, "_onQuestAbandoned", report, false, "EVT_QuestAbandoned");
AssignAsset(questWidget, "_onQuestReadyToComplete", report, false, "EVT_QuestReadyToComplete");
AssignAsset(questWidget, "_onObjectiveBatchUpdated", report, false, "EVT_QuestObjectiveBatchUpdated");
AssignAsset(toolHUD, "_onToolUsed", report, false, "EVT_ToolUsed");
// ── 手工步骤说明 ──────────────────────────────────────────────────
report.Add("HUDController._hpCellPrefab请将 HP 格子 Prefab 赋给该字段。");
report.Add("HUDController._springIconPrefab请将回春图标 Prefab 赋给该字段。");
report.Add("BossHPBar._phaseMarkerPrefab请将阶段标记点 Prefab 赋给该字段。");
report.Add("StatusEffectHUD._slotConfigs请在 Inspector 中配置各状态效果的图标映射。");
Undo.CollapseUndoOperations(undoGroup);
MarkDirtyAndLog("HUD Canvas 脚手架", canvasGo, report);
}
// ─────────────────────────────────────────────────────────────────────
// Private helpers
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// 在活动场景中查找或创建 HUD Canvas。
/// 查找顺序:
/// 1. 遍历场景根节点中的直接同名节点
/// 2. 遍历各根节点下的 [UI]/UIRoot/{name} 或 UIRoot/{name} 子路径
/// 若均不存在则新建 Canvas并优先挂载至 UIRoot兼容 ScaffoldPersistentScene 层级);
/// 若场景中不存在 UIRoot则回退到场景根层并发出警告。
/// </summary>
private static GameObject GetOrCreateRootCanvas(string name, int sortOrder)
{
Scene scene = SceneManager.GetActiveScene();
// ── Phase 1: 搜索已存在的 Canvas ─────────────────────────────────
foreach (GameObject root in scene.GetRootGameObjects())
{
if (root.name == name)
return root;
// 兼容 ScaffoldPersistentScene 层级:[Persistent] ▸ [UI] ▸ UIRoot ▸ HUD Canvas
foreach (string path in new[] { $"[UI]/UIRoot/{name}", $"UIRoot/{name}", name })
{
Transform found = root.transform.Find(path);
if (found != null) return found.gameObject;
}
}
// ── Phase 2: 定位 UIRootCanvas 的正确父节点)───────────────────
Transform uiRoot = null;
foreach (GameObject root in scene.GetRootGameObjects())
{
uiRoot = root.transform.Find("[UI]/UIRoot")
?? root.transform.Find("UIRoot");
if (uiRoot != null) break;
}
if (uiRoot == null)
Debug.LogWarning(
"[HUDScaffold] 未找到 UIRoot期望路径[Persistent]/[UI]/UIRoot。" +
"将在场景根层创建 HUD Canvas。建议先执行 BaseGames/Scene/Setup/Scaffold Persistent Scene。");
// ── Phase 3: 创建 Canvas 并挂载至正确父节点 ──────────────────────
GameObject canvasGo = new GameObject(name);
Undo.RegisterCreatedObjectUndo(canvasGo, $"Create {name}");
if (uiRoot != null)
canvasGo.transform.SetParent(uiRoot, false);
Canvas canvas = canvasGo.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = sortOrder;
CanvasScaler scaler = canvasGo.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
canvasGo.AddComponent<GraphicRaycaster>();
return canvasGo;
}
private static Transform GetOrCreateChild(Transform parent, string name)
{
Transform child = parent.Find(name);
if (child != null) return child;
GameObject go = new GameObject(name);
Undo.RegisterCreatedObjectUndo(go, $"Create {name}");
go.transform.SetParent(parent, false);
return go.transform;
}
private static T GetOrAddComponent<T>(GameObject go) where T : Component
{
T c = go.GetComponent<T>();
return c != null ? c : Undo.AddComponent<T>(go);
}
private static void AssignRef(Object target, string propertyName, Object value)
{
var so = new SerializedObject(target);
var prop = so.FindProperty(propertyName);
if (prop == null)
{
Debug.LogWarning($"[HUDScaffold] 未找到属性 {target.GetType().Name}.{propertyName}", target);
return;
}
prop.objectReferenceValue = value;
so.ApplyModifiedPropertiesWithoutUndo();
}
private static void AssignArrayRefs<T>(Object target, string propertyName, T[] values, List<string> report)
where T : Object
{
var so = new SerializedObject(target);
var prop = so.FindProperty(propertyName);
if (prop == null || !prop.isArray)
{
report.Add($"{target.GetType().Name}.{propertyName} 不是可写数组字段。");
return;
}
prop.arraySize = values.Length;
for (int i = 0; i < values.Length; i++)
prop.GetArrayElementAtIndex(i).objectReferenceValue = values[i];
so.ApplyModifiedPropertiesWithoutUndo();
}
private static void AssignAsset(Object target, string propertyName, List<string> report,
bool required, params string[] candidates)
{
Object asset = FindFirstAsset(candidates);
if (asset == null)
{
if (required)
report.Add($"未找到 {target.GetType().Name}.{propertyName} 所需资产: {string.Join(" / ", candidates)}");
return;
}
AssignRef(target, propertyName, asset);
}
private static Object FindFirstAsset(params string[] candidates)
{
foreach (string candidate in candidates)
{
if (string.IsNullOrWhiteSpace(candidate)) continue;
string[] guids = AssetDatabase.FindAssets(candidate);
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
Object asset = AssetDatabase.LoadMainAssetAtPath(path);
if (asset != null && asset.name == candidate)
return asset;
}
}
return null;
}
private static void MarkDirtyAndLog(string scaffoldName, GameObject root, List<string> report)
{
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
Selection.activeGameObject = root;
if (report.Count == 0)
{
Debug.Log($"[HUDScaffold] {scaffoldName} 完成。", root);
return;
}
Debug.LogWarning(
$"[HUDScaffold] {scaffoldName} 完成,以下 {report.Count} 项需手动确认:\n- {string.Join("\n- ", report)}",
root);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74e18b6a781df434c86d28bb3bf54101
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -22,7 +22,8 @@
"BaseGames.Quest", "BaseGames.Quest",
"BaseGames.Skills", "BaseGames.Skills",
"Unity.Addressables", "Unity.Addressables",
"Unity.ResourceManager" "Unity.ResourceManager",
"BaseGames.Feedback"
], ],
"autoReferenced": true, "autoReferenced": true,
"overrideReferences": false, "overrideReferences": false,

View File

@@ -0,0 +1,44 @@
using UnityEngine;
using BaseGames.Core.Events;
using BaseGames.Feedback;
namespace BaseGames.UI
{
/// <summary>
/// 场景切换黑屏控制器Persistent 场景)。
/// 监听 EVT_FadeOutRequest / EVT_FadeInRequest调用对应 SceneFeedback.Play()。
/// 实际视觉效果(黑幕、淡入淡出动画等)完全由 SceneFeedback 内部的 MMF_Player 配置决定。
///
/// 挂载位置Persistent 场景 → [UI] → SYS_SceneFade
///
/// 配置步骤:
/// 1. 创建两个带 MMF_Player 的 SceneFeedback淡出 / 淡入),在 MMF_Player 中配置所需效果
/// 2. 将淡出 SceneFeedback 拖入 _fadeOut淡入 SceneFeedback 拖入 _fadeIn
/// 3. 将 EVT_FadeOutRequest / EVT_FadeInRequest 拖入对应频道槽
/// 4. MMF_Player 总时长应 ≤ SceneService._sceneFadeDuration默认 0.4 s
/// </summary>
[AddComponentMenu("BaseGames/UI/Scene Fade Controller")]
public class SceneFadeController : MonoBehaviour
{
[Header("Feedback")]
[SerializeField] private SceneFeedback _fadeOut;
[SerializeField] private SceneFeedback _fadeIn;
[Header("事件频道")]
[SerializeField] private VoidEventChannelSO _onFadeOutRequest;
[SerializeField] private VoidEventChannelSO _onFadeInRequest;
private readonly CompositeDisposable _subs = new();
private void OnEnable()
{
_onFadeOutRequest?.Subscribe(OnFadeOut).AddTo(_subs);
_onFadeInRequest?.Subscribe(OnFadeIn).AddTo(_subs);
}
private void OnDisable() => _subs.Clear();
private void OnFadeOut() => _fadeOut?.Play();
private void OnFadeIn() => _fadeIn?.Play();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e4fa87eedbe2f24db81bdf66714343f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,6 @@
using System.Collections; using System.Collections;
using Animancer; using Animancer;
using BaseGames.Core;
using BaseGames.Core.Events; using BaseGames.Core.Events;
using UnityEngine; using UnityEngine;
@@ -48,9 +49,6 @@ namespace BaseGames.World
[SerializeField] private bool _requiresKeyItem; [SerializeField] private bool _requiresKeyItem;
[SerializeField] private string _requiredItemId; [SerializeField] private string _requiredItemId;
[Header("事件频道")]
[SerializeField] private SceneLoadRequestEventChannelSO _onSceneLoadRequest;
[Header("世界状态")] [Header("世界状态")]
[SerializeField] private WorldStateRegistry _worldState; [SerializeField] private WorldStateRegistry _worldState;
@@ -95,14 +93,23 @@ namespace BaseGames.World
yield return state; // 等待动画完成 yield return state; // 等待动画完成
} }
_onSceneLoadRequest?.Raise(new SceneLoadRequest var request = new SceneLoadRequest
{ {
SceneName = _targetSceneAddress, SceneName = _targetSceneAddress,
EntryTransitionId = _targetTransitionId, EntryTransitionId = _targetTransitionId,
TransitionType = _transitionType, TransitionType = _transitionType,
ShowLoadingScreen = _transitionType == TransitionType.Scene, ShowLoadingScreen = _transitionType == TransitionType.Scene,
IsRespawn = false, IsRespawn = false,
}); };
var sceneService = ServiceLocator.GetOrDefault<ISceneService>();
if (sceneService != null)
{
sceneService.RequestTransition(request);
yield break;
}
Debug.LogWarning("[DoorTransition] 无法发送过渡请求ISceneService 未在 ServiceLocator 中注册。", this);
} }
/// <summary> /// <summary>

View File

@@ -1,3 +1,4 @@
using BaseGames.Core;
using BaseGames.Core.Events; using BaseGames.Core.Events;
using UnityEngine; using UnityEngine;
@@ -38,9 +39,6 @@ namespace BaseGames.World
[SerializeField] private bool _requiresKeyItem; // 是否需要持有指定钥匙物品 [SerializeField] private bool _requiresKeyItem; // 是否需要持有指定钥匙物品
[SerializeField] private string _requiredItemId; // 钥匙物品 ID_requiresKeyItem = true 时生效) [SerializeField] private string _requiredItemId; // 钥匙物品 ID_requiresKeyItem = true 时生效)
[Header("事件频道")]
[SerializeField] private SceneLoadRequestEventChannelSO _onSceneLoadRequest;
[Header("世界状态")] [Header("世界状态")]
[SerializeField] private WorldStateRegistry _worldState; [SerializeField] private WorldStateRegistry _worldState;
@@ -66,14 +64,23 @@ namespace BaseGames.World
{ {
if (_requiresKeyItem && !HasItem(_requiredItemId)) return; if (_requiresKeyItem && !HasItem(_requiredItemId)) return;
_onSceneLoadRequest?.Raise(new SceneLoadRequest var request = new SceneLoadRequest
{ {
SceneName = _targetSceneAddress, SceneName = _targetSceneAddress,
EntryTransitionId = _targetTransitionId, EntryTransitionId = _targetTransitionId,
TransitionType = _transitionType, TransitionType = _transitionType,
ShowLoadingScreen = _transitionType == TransitionType.Scene, ShowLoadingScreen = _transitionType == TransitionType.Scene,
IsRespawn = false, IsRespawn = false,
}); };
var sceneService = ServiceLocator.GetOrDefault<ISceneService>();
if (sceneService != null)
{
sceneService.RequestTransition(request);
return;
}
Debug.LogWarning("[RoomTransition] 无法发送过渡请求ISceneService 未在 ServiceLocator 中注册。", this);
} }
/// <summary>检查玩家是否持有指定物品(通过 WorldStateRegistry.IsCollected 检查)。</summary> /// <summary>检查玩家是否持有指定物品(通过 WorldStateRegistry.IsCollected 检查)。</summary>