فهرست منبع

保存Replay,播放Replay完成

tanghai 2 سال پیش
والد
کامیت
ae2c5cb06e
42فایلهای تغییر یافته به همراه1598 افزوده شده و 49 حذف شده
  1. 3 0
      DotNet/Model/DotNet.Model.csproj
  2. BIN
      Unity/1.rep
  3. BIN
      Unity/2.rep
  4. 556 4
      Unity/Assets/Bundles/UI/LockStep/UILSLobby.prefab
  5. 765 0
      Unity/Assets/Bundles/UI/LockStep/UILSRoom.prefab
  6. 7 0
      Unity/Assets/Bundles/UI/LockStep/UILSRoom.prefab.meta
  7. 1 1
      Unity/Assets/Resources/GlobalConfig.asset
  8. 8 7
      Unity/Assets/Scenes/Init.unity
  9. 1 1
      Unity/Assets/Scripts/Core/Module/Network/MessageSerializeHelper.cs
  10. 6 6
      Unity/Assets/Scripts/Core/Serialize/SerializeHelper.cs
  11. 24 2
      Unity/Assets/Scripts/Hotfix/Client/LockStep/LSSceneChangeHelper.cs
  12. 4 0
      Unity/Assets/Scripts/Hotfix/Client/LockStep/OneFrameInputsHandler.cs
  13. 4 0
      Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayHelper.cs
  14. 1 1
      Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayHelper.cs.meta
  15. 8 11
      Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayUpdaterSystem.cs
  16. 12 0
      Unity/Assets/Scripts/Hotfix/Share/LockStep/LSHelper.cs
  17. 13 3
      Unity/Assets/Scripts/Hotfix/Share/LockStep/RoomSystem.cs
  18. 1 1
      Unity/Assets/Scripts/HotfixView/Client/Demo/UI/UIHelper.cs
  19. 8 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera.meta
  20. 10 2
      Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera/CameraComponentSystem.cs
  21. 1 1
      Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera/CameraComponentSystem.cs.meta
  22. 5 2
      Unity/Assets/Scripts/HotfixView/Client/LockStep/LockStepSceneChangeStart_AddComponent.cs
  23. 15 1
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSLobby/UILSLobbyComponentSystem.cs
  24. 8 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom.meta
  25. 29 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomComponentSystem.cs
  26. 11 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomComponentSystem.cs.meta
  27. 24 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomEvent.cs
  28. 11 0
      Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomEvent.cs.meta
  29. 1 0
      Unity/Assets/Scripts/Model/Client/LockStep/EventType.cs
  30. 2 2
      Unity/Assets/Scripts/Model/Client/LockStep/ReplayUpdater.cs
  31. 1 1
      Unity/Assets/Scripts/Model/Share/LockStep/LSConstValue.cs
  32. 1 1
      Unity/Assets/Scripts/Model/Share/LockStep/Replay.cs
  33. 11 0
      Unity/Assets/Scripts/Model/Share/LockStep/Replay.cs.meta
  34. 2 2
      Unity/Assets/Scripts/Model/Share/LockStep/Room.cs
  35. 8 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/Camera.meta
  36. 2 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/Camera/CameraComponent.cs
  37. 0 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/Camera/CameraComponent.cs.meta
  38. 2 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSLobby/UILSLobbyComponent.cs
  39. 8 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom.meta
  40. 12 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom/UILSRoomComponent.cs
  41. 11 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom/UILSRoomComponent.cs.meta
  42. 1 0
      Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UIType.cs

+ 3 - 0
DotNet/Model/DotNet.Model.csproj

@@ -47,5 +47,8 @@
         <ProjectReference Include="..\Core\DotNet.Core.csproj" />
         <ProjectReference Include="..\Loader\DotNet.Loader.csproj" />
         <ProjectReference Include="..\ThirdParty\DotNet.ThirdParty.csproj" />
+    </ItemGroup> 
+    <ItemGroup>
+      <Folder Include="Client\LockStep\" />
     </ItemGroup>
 </Project>

BIN
Unity/1.rep


BIN
Unity/2.rep


+ 556 - 4
Unity/Assets/Bundles/UI/LockStep/UILSLobby.prefab

@@ -93,6 +93,10 @@ MonoBehaviour:
   data:
   - key: EnterMap
     gameObject: {fileID: 899722670427233733}
+  - key: Replay
+    gameObject: {fileID: 8953588741749063052}
+  - key: ReplayPath
+    gameObject: {fileID: 4395569874077604387}
 --- !u!1 &899722670427233733
 GameObject:
   m_ObjectHideFlags: 0
@@ -106,7 +110,7 @@ GameObject:
   - component: {fileID: 1003519326168939849}
   - component: {fileID: 7768120852135991652}
   m_Layer: 5
-  m_Name: EnterMap
+  m_Name: Match
   m_TagString: Untagged
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
@@ -130,8 +134,8 @@ RectTransform:
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0.5, y: 0.5}
   m_AnchorMax: {x: 0.5, y: 0.5}
-  m_AnchoredPosition: {x: 0.000061035, y: -31.15}
-  m_SizeDelta: {x: 263.5, y: 62.3}
+  m_AnchoredPosition: {x: 0, y: 53}
+  m_SizeDelta: {x: 263.5, y: 62.299988}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &1111846559939914969
 CanvasRenderer:
@@ -247,6 +251,7 @@ RectTransform:
   m_Children:
   - {fileID: 8175113987340912499}
   - {fileID: 1109878335635189875}
+  - {fileID: 4874256544544303799}
   m_Father: {fileID: 224438795553994780}
   m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -293,6 +298,351 @@ MonoBehaviour:
   m_FillOrigin: 0
   m_UseSpriteMesh: 0
   m_PixelsPerUnitMultiplier: 1
+--- !u!1 &3479259119195873563
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2076769517444835984}
+  - component: {fileID: 138414179539499625}
+  - component: {fileID: 1071148689110842223}
+  m_Layer: 5
+  m_Name: Placeholder
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2076769517444835984
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3479259119195873563}
+  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: 2768584574692861273}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &138414179539499625
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3479259119195873563}
+  m_CullTransparentMesh: 1
+--- !u!114 &1071148689110842223
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3479259119195873563}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.23584908, g: 0.23584908, b: 0.23584908, a: 0.5}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 2
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 3
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Enter text...
+--- !u!1 &3693083160201062571
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 736899194757976890}
+  - component: {fileID: 7106128318160646470}
+  - component: {fileID: 8168496817488904769}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &736899194757976890
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3693083160201062571}
+  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: 7621972986425101864}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &7106128318160646470
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3693083160201062571}
+  m_CullTransparentMesh: 0
+--- !u!114 &8168496817488904769
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3693083160201062571}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Replay
+--- !u!1 &4395569874077604387
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2768584574692861273}
+  - component: {fileID: 3859870581258374020}
+  - component: {fileID: 2564991462387735650}
+  - component: {fileID: 1888676198012664535}
+  m_Layer: 5
+  m_Name: ReplayPath
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2768584574692861273
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4395569874077604387}
+  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: 2076769517444835984}
+  - {fileID: 2859361732101890305}
+  m_Father: {fileID: 4874256544544303799}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 120.31, y: -61.570007}
+  m_SizeDelta: {x: 240.62952, y: 57.15}
+  m_Pivot: {x: 1, y: 0.5}
+--- !u!222 &3859870581258374020
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4395569874077604387}
+  m_CullTransparentMesh: 1
+--- !u!114 &2564991462387735650
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4395569874077604387}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!114 &1888676198012664535
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4395569874077604387}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d199490a83bb2b844b9695cbf13b01ef, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 2564991462387735650}
+  m_TextComponent: {fileID: 6858719830969498837}
+  m_Placeholder: {fileID: 1071148689110842223}
+  m_ContentType: 0
+  m_InputType: 0
+  m_AsteriskChar: 42
+  m_KeyboardType: 0
+  m_LineType: 0
+  m_HideMobileInput: 0
+  m_CharacterValidation: 0
+  m_CharacterLimit: 0
+  m_OnSubmit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnDidEndEdit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnValueChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_CustomCaretColor: 0
+  m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412}
+  m_Text: 
+  m_CaretBlinkRate: 0.85
+  m_CaretWidth: 1
+  m_ReadOnly: 0
+  m_ShouldActivateOnSelect: 1
+--- !u!1 &4567620429296564010
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4874256544544303799}
+  m_Layer: 5
+  m_Name: GameObject
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &4874256544544303799
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4567620429296564010}
+  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: 2768584574692861273}
+  - {fileID: 7621972986425101864}
+  m_Father: {fileID: 4771239781044397799}
+  m_RootOrder: 2
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
 --- !u!1 &5394418754133166232
 GameObject:
   m_ObjectHideFlags: 0
@@ -448,4 +798,206 @@ MonoBehaviour:
     m_HorizontalOverflow: 0
     m_VerticalOverflow: 0
     m_LineSpacing: 1
-  m_Text: "\u5339\u914D"
+  m_Text: Match
+--- !u!1 &6941100451382580996
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2859361732101890305}
+  - component: {fileID: 8906366112307339978}
+  - component: {fileID: 6858719830969498837}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2859361732101890305
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6941100451382580996}
+  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: 2768584574692861273}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &8906366112307339978
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6941100451382580996}
+  m_CullTransparentMesh: 1
+--- !u!114 &6858719830969498837
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6941100451382580996}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 3
+    m_AlignByGeometry: 0
+    m_RichText: 0
+    m_HorizontalOverflow: 1
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!1 &8953588741749063052
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 7621972986425101864}
+  - component: {fileID: 2846390290717257282}
+  - component: {fileID: 2794544952984314283}
+  - component: {fileID: 4259866312124243016}
+  m_Layer: 5
+  m_Name: Replay
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &7621972986425101864
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8953588741749063052}
+  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: 736899194757976890}
+  m_Father: {fileID: 4874256544544303799}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -135}
+  m_SizeDelta: {x: 133.3943, y: 62.300003}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &2846390290717257282
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8953588741749063052}
+  m_CullTransparentMesh: 0
+--- !u!114 &2794544952984314283
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8953588741749063052}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!114 &4259866312124243016
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8953588741749063052}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 2794544952984314283}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls: []

+ 765 - 0
Unity/Assets/Bundles/UI/LockStep/UILSRoom.prefab

@@ -0,0 +1,765 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1386170326414932
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 224438795553994780}
+  - component: {fileID: 1431576037130298801}
+  - component: {fileID: 1431576037130298803}
+  - component: {fileID: 114905074804487618}
+  m_Layer: 5
+  m_Name: UILSRoom
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &224438795553994780
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1386170326414932}
+  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: 4771239781044397799}
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!223 &1431576037130298801
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1386170326414932}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 1
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!114 &1431576037130298803
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1386170326414932}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &114905074804487618
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1386170326414932}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 502d8cafd6a5a0447ab1db9a24cdcb10, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  data:
+  - key: SaveReplay
+    gameObject: {fileID: 2520555391245056746}
+  - key: SaveName
+    gameObject: {fileID: 5756238228320737012}
+--- !u!1 &443161762425607488
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1792105715031702230}
+  - component: {fileID: 1517835945500719159}
+  - component: {fileID: 5252949383912244642}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1792105715031702230
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 443161762425607488}
+  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: 3090481317299282819}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &1517835945500719159
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 443161762425607488}
+  m_CullTransparentMesh: 1
+--- !u!114 &5252949383912244642
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 443161762425607488}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 0
+    m_HorizontalOverflow: 1
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!1 &1329268365971367435
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 5584600435331946617}
+  - component: {fileID: 7967827839072717203}
+  - component: {fileID: 418782035814473946}
+  m_Layer: 5
+  m_Name: Placeholder
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &5584600435331946617
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1329268365971367435}
+  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: 3090481317299282819}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &7967827839072717203
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1329268365971367435}
+  m_CullTransparentMesh: 1
+--- !u!114 &418782035814473946
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1329268365971367435}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 2
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Enter text...
+--- !u!1 &2520555391245056746
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 895650316332628775}
+  - component: {fileID: 6307454425002981456}
+  - component: {fileID: 8368651048187234218}
+  - component: {fileID: 242686799324548184}
+  m_Layer: 5
+  m_Name: SaveReplay
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &895650316332628775
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2520555391245056746}
+  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: 592631028990097364}
+  m_Father: {fileID: 4771239781044397799}
+  m_RootOrder: 2
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 359, y: -43}
+  m_SizeDelta: {x: 95.2377, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &6307454425002981456
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2520555391245056746}
+  m_CullTransparentMesh: 1
+--- !u!114 &8368651048187234218
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2520555391245056746}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!114 &242686799324548184
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2520555391245056746}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 8368651048187234218}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls: []
+--- !u!1 &3318750498554037093
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4771239781044397799}
+  - component: {fileID: 7279718688677780413}
+  - component: {fileID: 1396409096631843897}
+  m_Layer: 5
+  m_Name: Panel
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &4771239781044397799
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3318750498554037093}
+  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: 280236444452826813}
+  - {fileID: 3090481317299282819}
+  - {fileID: 895650316332628775}
+  m_Father: {fileID: 224438795553994780}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &7279718688677780413
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3318750498554037093}
+  m_CullTransparentMesh: 1
+--- !u!114 &1396409096631843897
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3318750498554037093}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 0}
+  m_RaycastTarget: 0
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!1 &5756238228320737012
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3090481317299282819}
+  - component: {fileID: 1370278903330398853}
+  - component: {fileID: 4192512503159304661}
+  - component: {fileID: 1273401424810570531}
+  m_Layer: 5
+  m_Name: SaveName
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3090481317299282819
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5756238228320737012}
+  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: 5584600435331946617}
+  - {fileID: 1792105715031702230}
+  m_Father: {fileID: 4771239781044397799}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 223.68118, y: -43}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &1370278903330398853
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5756238228320737012}
+  m_CullTransparentMesh: 1
+--- !u!114 &4192512503159304661
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5756238228320737012}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!114 &1273401424810570531
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5756238228320737012}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d199490a83bb2b844b9695cbf13b01ef, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 4192512503159304661}
+  m_TextComponent: {fileID: 5252949383912244642}
+  m_Placeholder: {fileID: 418782035814473946}
+  m_ContentType: 0
+  m_InputType: 0
+  m_AsteriskChar: 42
+  m_KeyboardType: 0
+  m_LineType: 0
+  m_HideMobileInput: 0
+  m_CharacterValidation: 0
+  m_CharacterLimit: 0
+  m_OnSubmit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnDidEndEdit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnValueChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_CustomCaretColor: 0
+  m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412}
+  m_Text: 
+  m_CaretBlinkRate: 0.85
+  m_CaretWidth: 1
+  m_ReadOnly: 0
+  m_ShouldActivateOnSelect: 1
+--- !u!1 &6807433300459080502
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 592631028990097364}
+  - component: {fileID: 8453337959826911601}
+  - component: {fileID: 8548415133393940946}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &592631028990097364
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6807433300459080502}
+  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: 895650316332628775}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &8453337959826911601
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6807433300459080502}
+  m_CullTransparentMesh: 1
+--- !u!114 &8548415133393940946
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6807433300459080502}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Save Replay
+--- !u!1 &6878862313097994145
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 280236444452826813}
+  - component: {fileID: 6242254895195686563}
+  - component: {fileID: 479013233324409552}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &280236444452826813
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6878862313097994145}
+  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: 4771239781044397799}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 78.54535, y: -43}
+  m_SizeDelta: {x: 113.92828, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &6242254895195686563
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6878862313097994145}
+  m_CullTransparentMesh: 1
+--- !u!114 &479013233324409552
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6878862313097994145}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 3
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 'relay name:'

+ 7 - 0
Unity/Assets/Bundles/UI/LockStep/UILSRoom.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: fcad5af85f5a54eb3884cdfb6efc7d27
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: uilsroom.unity3d
+  assetBundleVariant: 

+ 1 - 1
Unity/Assets/Resources/GlobalConfig.asset

@@ -12,6 +12,6 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 36527db572638af47b03c805671cba75, type: 3}
   m_Name: GlobalConfig
   m_EditorClassIdentifier: 
-  CodeMode: 1
+  CodeMode: 3
   BuildType: 1
   SceneType: LockStep

+ 8 - 7
Unity/Assets/Scenes/Init.unity

@@ -283,12 +283,12 @@ Transform:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 429867060}
-  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_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children: []
-  m_Father: {fileID: 0}
+  m_Father: {fileID: 575235020}
   m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &493985069
@@ -421,12 +421,13 @@ Transform:
   m_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children:
+  - {fileID: 429867063}
   - {fileID: 1984349697}
   - {fileID: 1245951402}
   - {fileID: 1784017108}
   - {fileID: 630054496}
   m_Father: {fileID: 0}
-  m_RootOrder: 1
+  m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!114 &575235022
 MonoBehaviour:
@@ -485,7 +486,7 @@ Transform:
   m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 575235020}
-  m_RootOrder: 3
+  m_RootOrder: 4
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &872594939
 GameObject:
@@ -620,7 +621,7 @@ Transform:
   m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 575235020}
-  m_RootOrder: 1
+  m_RootOrder: 2
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!81 &1245951403
 AudioListener:
@@ -848,7 +849,7 @@ Transform:
   - {fileID: 493985070}
   - {fileID: 1439952249}
   m_Father: {fileID: 575235020}
-  m_RootOrder: 2
+  m_RootOrder: 3
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!114 &1784017109
 MonoBehaviour:
@@ -965,7 +966,7 @@ Transform:
   m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 575235020}
-  m_RootOrder: 0
+  m_RootOrder: 1
   m_LocalEulerAnglesHint: {x: 60, y: 0, z: 0}
 --- !u!114 &1984349698
 MonoBehaviour:

+ 1 - 1
Unity/Assets/Scripts/Core/Module/Network/MessageSerializeHelper.cs

@@ -5,7 +5,7 @@ namespace ET
 {
     public static class MessageSerializeHelper
     {
-        public static ushort MessageToStream(MemoryBuffer stream, object message)
+        public static ushort MessageToStream(MemoryBuffer stream, MessageObject message)
         {
             int headOffset = Packet.ActorIdLength;
 

+ 6 - 6
Unity/Assets/Scripts/Core/Serialize/SerializeHelper.cs

@@ -7,28 +7,28 @@ namespace ET
 {
     public static class SerializeHelper
 	{
-		public static byte[] Serialize(object message)
+		public static byte[] Serialize(MessageObject message)
 		{
 			return MemoryPackHelper.Serialize(message);
 		}
 
-        public static void Serialize(object message, MemoryBuffer stream)
+        public static void Serialize(MessageObject message, MemoryBuffer stream)
         {
 			MemoryPackHelper.Serialize(message, stream);
 		}
 		
-		public static object Deserialize(Type type, byte[] bytes, int index, int count)
+		public static MessageObject Deserialize(Type type, byte[] bytes, int index, int count)
 		{
 			object o = NetServices.Instance.FetchMessage(type);
 			MemoryPackHelper.Deserialize(type, bytes, index, count, ref o);
-			return o;
+			return o as MessageObject;
 		}
 
-		public static object Deserialize(Type type, MemoryBuffer stream)
+		public static MessageObject Deserialize(Type type, MemoryBuffer stream)
 		{
 			object o = NetServices.Instance.FetchMessage(type);
 			MemoryPackHelper.Deserialize(type, stream, ref o);
-			return o;
+			return o as MessageObject;
         }
     }
 }

+ 24 - 2
Unity/Assets/Scripts/Hotfix/Client/LockStep/LSSceneChangeHelper.cs

@@ -8,11 +8,11 @@ namespace ET.Client
         {
             clientScene.RemoveComponent<Room>();
 
-            Room room = clientScene.AddComponent<Room>();
+            Room room = clientScene.AddComponentWithId<Room>(sceneInstanceId);
             room.Name = sceneName;
 
             // 等待表现层订阅的事件完成
-            await EventSystem.Instance.PublishAsync(clientScene, new EventType.LockStepSceneChangeStart());
+            await EventSystem.Instance.PublishAsync(clientScene, new EventType.LockStepSceneChangeStart() {Room = room});
 
             clientScene.GetComponent<SessionComponent>().Session.Send(new C2Room_ChangeSceneFinish());
             
@@ -27,5 +27,27 @@ namespace ET.Client
             // 这个事件中可以订阅取消loading
             EventSystem.Instance.Publish(clientScene, new EventType.LockStepSceneInitFinish());
         }
+        
+        // 场景切换协程
+        public static async ETTask SceneChangeToReplay(Scene clientScene, Replay replay)
+        {
+            clientScene.RemoveComponent<Room>();
+
+            Room room = clientScene.AddComponent<Room>();
+            room.Name = "Map1";
+            room.IsReplay = true;
+            room.Replay = replay;
+
+            // 等待表现层订阅的事件完成
+            await EventSystem.Instance.PublishAsync(clientScene, new EventType.LockStepSceneChangeStart() {Room = room});
+            
+            room.LSWorld = new LSWorld(SceneType.LockStepClient);
+            room.Init(replay.UnitInfos, TimeHelper.ServerFrameTime());
+            
+            room.AddComponent<ReplayUpdater>();
+
+            // 这个事件中可以订阅取消loading
+            EventSystem.Instance.Publish(clientScene, new EventType.LockStepSceneInitFinish());
+        }
     }
 }

+ 4 - 0
Unity/Assets/Scripts/Hotfix/Client/LockStep/OneFrameInputsHandler.cs

@@ -33,6 +33,10 @@ namespace ET.Client
                 // 回滚到frameBuffer.AuthorityFrame
                 LSHelper.Rollback(room, room.AuthorityFrame);
             }
+            else
+            {
+                room.Record(frame);
+            }
 
             // 回收消息,减少GC
             NetServices.Instance.RecycleMessage(input);

+ 4 - 0
Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayHelper.cs

@@ -0,0 +1,4 @@
+namespace ET.Client
+{
+    public static class ReplayHelper {}
+}

+ 1 - 1
Unity/Assets/Scripts/Model/Share/LockStep/Record.cs.meta → Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayHelper.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 562210a21a5bc4e6a811e06763cec814
+guid: 5710f0881cff2419e9fceba5bab8ebcb
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 8 - 11
Unity/Assets/Scripts/Hotfix/Client/LockStep/ReplayUpdaterSystem.cs

@@ -5,16 +5,6 @@ namespace ET.Client
     [FriendOf(typeof(ReplayUpdater))]
     public static class ReplayComponentSystem
     {
-        [ObjectSystem]
-        public class AwakeSystem: AwakeSystem<ReplayUpdater, Record>
-        {
-            protected override void Awake(ReplayUpdater self, Record record)
-            {
-                self.Record = record;
-                self.GetParent<Room>().Init(self.Record.UnitInfos, TimeHelper.ServerFrameTime());
-            }
-        }
-
         [ObjectSystem]
         public class UpdateSystem: UpdateSystem<ReplayUpdater>
         {
@@ -35,7 +25,14 @@ namespace ET.Client
             }
 
             ++room.AuthorityFrame;
-            OneFrameInputs oneFrameInputs = self.Record.FrameInputs[room.AuthorityFrame];
+
+            if (room.AuthorityFrame >= room.Replay.FrameInputs.Count)
+            {
+                return;
+            }
+            
+            OneFrameInputs oneFrameInputs = room.Replay.FrameInputs[room.AuthorityFrame];
+            
             room.Update(oneFrameInputs, room.AuthorityFrame);
         }
     }

+ 12 - 0
Unity/Assets/Scripts/Hotfix/Share/LockStep/LSHelper.cs

@@ -1,3 +1,4 @@
+using System.IO;
 using ET.Client;
 
 namespace ET
@@ -70,5 +71,16 @@ namespace ET
                 to.Inputs[kv.Key] = kv.Value;
             }
         }
+
+        public static void SaveReplay(Room room, string path)
+        {
+            if (room.IsReplay)
+            {
+                return;
+            }
+            Log.Debug($"save replay: {path} frame: {room.Replay.FrameInputs.Count}");
+            byte[] bytes = MemoryPackHelper.Serialize(room.Replay);
+            File.WriteAllBytes(path, bytes);
+        }
     }
 }

+ 13 - 3
Unity/Assets/Scripts/Hotfix/Share/LockStep/RoomSystem.cs

@@ -7,10 +7,15 @@ namespace ET
     [FriendOf(typeof(Room))]
     public static class RoomSystem
     {
+        public static Room Room(this Entity entity)
+        {
+            return entity.Domain as Room;
+        }
+        
         public static void Init(this Room self, List<LockStepUnitInfo> unitInfos, long startTime)
         {
             self.StartTime = startTime;
-            
+            self.Replay.UnitInfos = unitInfos;
             self.FixedTimeCounter = new FixedTimeCounter(self.StartTime, 0, LSConstValue.UpdateInterval);
 
             LSWorld lsWorld = self.LSWorld;
@@ -67,16 +72,21 @@ namespace ET
             memoryBuffer.Seek(0, SeekOrigin.Begin);
         }
 
+        // 记录需要存档的数据
         public static void Record(this Room self, int frame)
         {
+            if (self.IsReplay)
+            {
+                return;
+            }
             OneFrameInputs oneFrameInputs = self.FrameBuffer.FrameInputs(frame);
             OneFrameInputs saveInput = new();
             oneFrameInputs.CopyTo(saveInput);
-            self.Record.FrameInputs.Add(saveInput);
+            self.Replay.FrameInputs.Add(saveInput);
             if (frame % LSConstValue.SaveLSWorldFrameCount == 0)
             {
                 MemoryBuffer memoryBuffer = self.FrameBuffer.Snapshot(frame);
-                self.Record.Snapshots.Add(memoryBuffer.ToArray());   
+                self.Replay.Snapshots.Add(memoryBuffer.ToArray());   
             }
         }
     }

+ 1 - 1
Unity/Assets/Scripts/HotfixView/Client/Demo/UI/UIHelper.cs

@@ -2,7 +2,7 @@
 {
     public static class UIHelper
     {
-        public static async ETTask<UI> Create(Scene scene, string uiType, UILayer uiLayer)
+        public static async ETTask<UI> Create(Entity scene, string uiType, UILayer uiLayer)
         {
             return await scene.GetComponent<UIComponent>().Create(uiType, uiLayer);
         }

+ 8 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera.meta

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

+ 10 - 2
Unity/Assets/Scripts/HotfixView/Client/Demo/Camera/CameraComponentSystem.cs → Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera/CameraComponentSystem.cs

@@ -32,12 +32,20 @@ namespace ET.Client
 		private static void LateUpdate(this CameraComponent self)
 		{
 			// 摄像机每帧更新位置
+			Room room = self.GetParent<Room>();
+			if (room.IsReplay)
+			{
+				if (Input.GetKeyDown(KeyCode.Tab))
+				{
+					++self.index;
+					self.MyUnitView = new LSUnitView();
+				}
+			}
 
 			LSUnitView lsUnit = self.MyUnitView;
 			if (lsUnit == null)
 			{
-				Room room = self.GetParent<Room>();
-				long id = room.GetParent<Scene>().GetComponent<PlayerComponent>().MyId;
+				long id = room.IsReplay? room.PlayerIds[self.index % room.PlayerIds.Count] : room.GetParent<Scene>().GetComponent<PlayerComponent>().MyId;
 				self.MyUnitView = room.GetComponent<LSUnitViewComponent>().GetChild<LSUnitView>(id);
 			}
 

+ 1 - 1
Unity/Assets/Scripts/HotfixView/Client/Demo/Camera/CameraComponentSystem.cs.meta → Unity/Assets/Scripts/HotfixView/Client/LockStep/Camera/CameraComponentSystem.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: ece5c63855bea1344a53ab46192dcb83
+guid: a2200b625f39c40f2a3a29a6f2399804
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 5 - 2
Unity/Assets/Scripts/HotfixView/Client/LockStep/LockStepSceneChangeStart_AddComponent.cs

@@ -8,11 +8,14 @@ namespace ET.Client
         protected override async ETTask Run(Scene clientScene, EventType.LockStepSceneChangeStart args)
         {
             Room room = clientScene.GetComponent<Room>();
+            room.AddComponent<ResourcesLoaderComponent>();
+            room.AddComponent<UIComponent>();
             
             // 创建loading界面
             
-            // 删除大厅UI
-            await UIHelper.Remove(clientScene, UIType.UILobby);
+            
+            // 创建房间UI
+            await UIHelper.Create(args.Room, UIType.UILSRoom, UILayer.Low);
             
             // 加载场景资源
             await ResourcesComponent.Instance.LoadBundleAsync($"{room.Name}.unity3d");

+ 15 - 1
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSLobby/UILSLobbyComponentSystem.cs

@@ -1,4 +1,5 @@
-using UnityEngine;
+using System.IO;
+using UnityEngine;
 using UnityEngine.UI;
 
 namespace ET.Client
@@ -18,6 +19,10 @@ namespace ET.Client
                 {
                     self.EnterMap().Coroutine();
                 });
+                
+                self.replay = rc.Get<GameObject>("Replay").GetComponent<Button>();
+                self.replayPath = rc.Get<GameObject>("ReplayPath").GetComponent<InputField>();
+                self.replay.onClick.AddListener(self.Replay);
             }
         }
 
@@ -25,5 +30,14 @@ namespace ET.Client
         {
             await EnterMapHelper.Match(self.ClientScene());
         }
+        
+        private static void Replay(this UILSLobbyComponent self)
+        {
+            byte[] bytes = File.ReadAllBytes(self.replayPath.text);
+            
+            Replay replay = MemoryPackHelper.Deserialize(typeof (Replay), bytes, 0, bytes.Length) as Replay;
+            
+            LSSceneChangeHelper.SceneChangeToReplay(self.ClientScene(), replay).Coroutine();
+        }
     }
 }

+ 8 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom.meta

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

+ 29 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomComponentSystem.cs

@@ -0,0 +1,29 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace ET.Client
+{
+    public static class UILSRoomComponentSystem
+    {
+        public class AwakeSystem : AwakeSystem<UILSRoomComponent>
+        {
+            protected override void Awake(UILSRoomComponent self)
+            {
+                ReferenceCollector rc = self.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>();
+                self.saveReplay = rc.Get<GameObject>("SaveReplay");
+                self.saveName = rc.Get<GameObject>("SaveName").GetComponent<InputField>();
+				
+                self.saveReplay.GetComponent<Button>().onClick.AddListener(()=> { self.OnSaveReplay().Coroutine(); });
+            }
+        }
+
+        private static async ETTask OnSaveReplay(this UILSRoomComponent self)
+        {
+            string name = self.saveName.text;
+            
+            LSHelper.SaveReplay(self.Room(), name);
+
+            await ETTask.CompletedTask;
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomComponentSystem.cs.meta

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

+ 24 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomEvent.cs

@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+
+namespace ET.Client
+{
+    [UIEvent(UIType.UILSRoom)]
+    public class UILSRoomEvent: AUIEvent
+    {
+        public override async ETTask<UI> OnCreate(UIComponent uiComponent, UILayer uiLayer)
+        {
+            await uiComponent.Room().GetComponent<ResourcesLoaderComponent>().LoadAsync(UIType.UILSRoom.StringToAB());
+            GameObject bundleGameObject = (GameObject) ResourcesComponent.Instance.GetAsset(UIType.UILSRoom.StringToAB(), UIType.UILSRoom);
+            GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject, UIEventComponent.Instance.GetLayer((int)uiLayer));
+            UI ui = uiComponent.AddChild<UI, string, GameObject>(UIType.UILSRoom, gameObject);
+            ui.AddComponent<UILSRoomComponent>();
+            return ui;
+        }
+
+        public override void OnRemove(UIComponent uiComponent)
+        {
+            ResourcesComponent.Instance.UnloadBundle(UIType.UILSRoom.StringToAB());
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/HotfixView/Client/LockStep/UI/UILSRoom/UILSRoomEvent.cs.meta

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

+ 1 - 0
Unity/Assets/Scripts/Model/Client/LockStep/EventType.cs

@@ -4,6 +4,7 @@
     {
         public struct LockStepSceneChangeStart
         {
+            public Room Room;
         }
         
         public struct LockStepSceneInitFinish

+ 2 - 2
Unity/Assets/Scripts/Model/Client/LockStep/ReplayUpdater.cs

@@ -1,7 +1,7 @@
 namespace ET.Client
 {
-    public class ReplayUpdater: Entity, IAwake<Record>, IUpdate
+    [ComponentOf(typeof(Room))]
+    public class ReplayUpdater: Entity, IAwake, IUpdate
     {
-        public Record Record;
     }
 }

+ 1 - 1
Unity/Assets/Scripts/Model/Share/LockStep/LSConstValue.cs

@@ -2,7 +2,7 @@ namespace ET
 {
     public static class LSConstValue
     {
-        public const int MatchCount = 2;
+        public const int MatchCount = 1;
         public const int UpdateInterval = 50;
         public const int FrameCountPerSecond = 1000 / UpdateInterval;
         public const int SaveLSWorldFrameCount = 60 * FrameCountPerSecond;

+ 1 - 1
Unity/Assets/Scripts/Model/Share/LockStep/Record.cs → Unity/Assets/Scripts/Model/Share/LockStep/Replay.cs

@@ -4,7 +4,7 @@ using MemoryPack;
 namespace ET
 {
     [MemoryPackable]
-    public partial class Record
+    public partial class Replay
     {
         [MemoryPackOrder(1)]
         public List<LockStepUnitInfo> UnitInfos;

+ 11 - 0
Unity/Assets/Scripts/Model/Share/LockStep/Replay.cs.meta

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

+ 2 - 2
Unity/Assets/Scripts/Model/Share/LockStep/Room.cs

@@ -27,7 +27,7 @@ namespace ET
         public int AuthorityFrame { get; set; } = -1;
 
         // 存档
-        public Record Record = new();
+        public Replay Replay { get; set; } = new();
 
         private EntityRef<LSWorld> lsWorld;
 
@@ -45,6 +45,6 @@ namespace ET
             }
         }
 
-        public bool IsReplay;
+        public bool IsReplay { get; set; }
     }
 }

+ 8 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/Camera.meta

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

+ 2 - 0
Unity/Assets/Scripts/ModelView/Client/Demo/Camera/CameraComponent.cs → Unity/Assets/Scripts/ModelView/Client/LockStep/Camera/CameraComponent.cs

@@ -36,5 +36,7 @@ namespace ET.Client
 				this.unitView = value;
 			}
 		}
+
+		public int index;
 	}
 }

+ 0 - 0
Unity/Assets/Scripts/ModelView/Client/Demo/Camera/CameraComponent.cs.meta → Unity/Assets/Scripts/ModelView/Client/LockStep/Camera/CameraComponent.cs.meta


+ 2 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSLobby/UILSLobbyComponent.cs

@@ -9,5 +9,7 @@ namespace ET.Client
 	{
 		public GameObject enterMap;
 		public Text text;
+		public Button replay;
+		public InputField replayPath;
 	}
 }

+ 8 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom.meta

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

+ 12 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom/UILSRoomComponent.cs

@@ -0,0 +1,12 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace ET.Client
+{
+    public class UILSRoomComponent: Entity, IAwake
+    {
+        public GameObject saveReplay;
+
+        public InputField saveName;
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UILSRoom/UILSRoomComponent.cs.meta

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

+ 1 - 0
Unity/Assets/Scripts/ModelView/Client/LockStep/UI/UIType.cs

@@ -7,5 +7,6 @@ namespace ET.Client
     {
 	    public const string UILSLogin = "UILSLogin";
 	    public const string UILSLobby = "UILSLobby";
+		public const string UILSRoom = "UILSRoom";
     }
 }