From f4c97339a01fdd75d8b862be572eefe66bd51d5a Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期五, 16 五月 2025 19:18:21 +0800
Subject: [PATCH] update

---
 Main/Core/GameEngine/Player/PlayerBaseData.cs                        |  297 
 Main/Component/UI/Common/TimerBehaviour.cs                           |   96 
 Main/ResModule/BuiltInLoader.cs.meta                                 |   12 
 Main/ResModule/ScriptableObjectLoader.cs                             |  490 
 Main/ResModule/GameObjectPoolManager.cs.meta                         |   12 
 Main/Component/UI/Common/RandomImage.cs                              |   25 
 Main/Component/UI/Common/UIFuncOpen.cs                               |   99 
 Main/Component/UI/Common/UITextMark.cs.meta                          |   11 
 Main/Component/UI/HUD/StoryDialogueBubble.cs                         |   68 
 Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs.meta               |   12 
 Main/ResModule/AssetBundle/AssetInfo.cs                              |   18 
 Main/Component/UI/Common/UI3DModelFactory.cs.meta                    |   12 
 Main/Component/UI/HUD/HeadUpQuestSignPool.cs                         |   76 
 Main/System/Debug/DebugSwitch.cs                                     |   67 
 Main/Component/UI/Common/MultipleSmoothSlider.cs.meta                |   12 
 Main/Component/UI/Common/MaterialsContainer.cs                       |   37 
 Main/Component/UI/Common/PostEffectBase.cs.meta                      |   11 
 Main/Component/UI/Common/UIPrefabLoader.cs.meta                      |   12 
 Main/Core/GameEngine.meta                                            |    8 
 Main/Component/UI/Core/ToggleButtonGroup.cs                          |   50 
 Main/Component/UI/Common/UITextMark.cs                               |   16 
 Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs            |  122 
 Main/Component/UI/Common/FontColorSizeConfig.cs.meta                 |   12 
 Main/Component/UI/Core/ButtonEx.cs                                   |   73 
 Main/Component/UI/Core/DelayButton.cs                                |   59 
 Main/Component/UI/HUD/HeadUpQuestSign.cs.meta                        |   12 
 Main/Core/GameEngine/Player/PlayerExtersionData.cs                   |   71 
 Main/ResModule/MaterialLoader.cs.meta                                |   12 
 Main/Component/UI/Common/CanvasRaycastFilter.cs                      |   28 
 Main/Component/UI/Effect/TimeMgr.cs.meta                             |   12 
 Main/Utility/RunTimeABLoadLog.cs                                     |   28 
 Main/Component/UI/Core/DebugCanvasAddition.cs.meta                   |   12 
 Main/ResModule/AssetBundle/AssetBundleUtility.cs.meta                |   12 
 Main/Component/UI/Common/SmoothMask.cs                               |  124 
 Main/Component/UI/Common/AdaptiveLayout.cs                           |  241 
 Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs                  |   50 
 Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs          |   52 
 Main/System/GeneralConfig/ConstDefine.cs                             |   16 
 Main/Component/UI/HUD/HeadUpSkillName.cs                             |   68 
 Main/Component/UI/Common/RandomTip.cs                                |   78 
 Main/Core/GameEngine/Player/PlayerBaseData.cs.meta                   |   11 
 Main/Component/UI/Core/ToggleButtonGroup.cs.meta                     |   12 
 Main/Component/UI/Common/FakeButton.cs.meta                          |   12 
 Main/Component/UI/Common/AdaptiveRectOffset.cs.meta                  |   12 
 Main/Component/UI/Decorate/Graph/SectionImage.cs.meta                |   12 
 Main/Component/UI/Common/AdaptiveLayout.cs.meta                      |   12 
 Main/Component/UI/Decorate/Smooth/SmoothMove.cs                      |   91 
 Main/System/AssetVersion/DownloadMgr.cs.meta                         |   11 
 Main/Core/GameEngine/Player/PlayerDatas.cs                           | 1064 +
 Main/Component/UI/Effect/SpringDecorate.cs                           |   49 
 Main/Component/UI/Core.meta                                          |    9 
 Main/Component/UI/Common/NumKeyBoard.cs                              |  260 
 Main/Component/UI/Decorate/PingPong/PingPongRotation.cs.meta         |   12 
 Main/ResModule/AssetBundle.meta                                      |    9 
 Main/Component/UI/Common/UI3DModelExhibition.cs.meta                 |   12 
 Main/Component/UI/Decorate/Graph/FlipImage.cs                        |   70 
 Main/Component/UI/HUD/DialogueBubble.cs                              |   72 
 Main/ResModule/AssetBundle/AssetBundleInfo.cs                        |   16 
 Main/Login/ServerData.cs.meta                                        |   11 
 Main/Component/UI/Common/WindowConfig.cs                             |  168 
 Main/Component/UI/HUD/HeadUpSkillName.cs.meta                        |   12 
 Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs          |   79 
 Main/Component/UI/Common/BossLifeBar.cs.meta                         |   12 
 Main/ResModule.meta                                                  |    8 
 Main/Component/UI/Decorate/Graph/CustomImage.cs                      |   81 
 Main/Component/UI/Manager/UIEventTrigger.cs.meta                     |   12 
 Main/System/AssetVersion/AssetVersionUtility.cs.meta                 |   11 
 Main/ResModule/SceneLoader.cs                                        |   57 
 Main/Component/UI/HUD/HeadUpNamePool.cs                              |   81 
 Main/Component/UI/Common/PrepareWin.cs.meta                          |   12 
 Main/ResModule/AnimatorControllerLoader.cs                           |  126 
 Main/Component/UI/Common/UITextReplace.cs                            |   23 
 Main/Component/UI/Common/TimerToChsBehaviour.cs.meta                 |   12 
 Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs.meta     |   12 
 Main/Component/UI/Common/TimeDownMgr.cs                              |  122 
 Main/Component/UI/Decorate/Graph/OffsetImage2.cs                     |   79 
 Main/Component/UI/HUD/MonsterNameColor.cs                            |   86 
 Main/Utility/Constants.cs.meta                                       |   11 
 Main/Component/UI/Core/PointerDownUp.cs                              |  110 
 Main/Component/UI/HUD/MonsterNameColor.cs.meta                       |   12 
 Main/Component/UI/Decorate/Move/UISmoothMove.cs.meta                 |   12 
 Main/Component/UI/Common/LongPressButton.cs                          |  102 
 Main/Login/ServerListParser.cs.meta                                  |   11 
 Main/Component/UI/Common/DragItem.cs                                 |   62 
 Main/Component/UI/Common/FunctionButtonConfig.cs                     |   84 
 Main/Component/UI/Core/ImageEx.cs                                    |   66 
 Main/System/CrossServer/CrossServerUtility.cs                        |   67 
 Main/System/Debug/DebugController.cs                                 |   99 
 Main/Component/UI/Common/FrameEffect.cs                              |   98 
 Main/Component/UI/Common/WaterWaveSlider.cs.meta                     |   12 
 Main/Component/UI/Decorate.meta                                      |    9 
 Main/ResModule/MaterialLoader.cs                                     |  126 
 Main/Component/UI/Common/GestureCatcher.cs.meta                      |   12 
 Main/Login/ClientVersion/VersionConfig.cs.meta                       |   11 
 Main/Component/UI/Common/OnOffToggle.cs.meta                         |   12 
 Main/Component/UI/Common/MultipleSmoothSlider.cs                     |   95 
 Main/Component/UI/Effect/ActorEffectEvent.cs                         |   14 
 Main/Component/UI/Common/FunctionButtonConfig.cs.meta                |   12 
 Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs.meta       |   12 
 Main/System/Language.meta                                            |    8 
 Main/Component/UI/Common/RollNumber.cs                               |   60 
 Main/Component/UI/Core/RepeatedButton.cs                             |  112 
 Main/Component/UI/Decorate/Move/UISmoothMove.cs                      |   60 
 Main/Component/UI/Common/CircleMoveTo.cs                             |   96 
 Main/Component/UI/Common/SortTable.cs                                |  125 
 Main/Component/UI/Decorate/Effect.meta                               |    9 
 Main/ResModule/DebugItem.cs                                          |    6 
 Main/Component/UI/Core/PointerDownUp.cs.meta                         |   12 
 Main/Component/UI/Decorate/Graph/PolylineImage.cs                    |   71 
 Main/Component/UI/Decorate/Graph/CircleImage.cs                      |  164 
 Main/ResModule/UILoader.cs                                           |  374 
 Main/Utility/ComponentExtersion.cs                                   |   80 
 Main/Component/UI/HUD/PopUpNum.cs.meta                               |   12 
 Main/Component/UI/Common/EnableButtonConfig.cs.meta                  |   12 
 Main/Component/UI/Decorate/Graph/RayAccepter.cs                      |   21 
 Main/Component/UI/HUD/HUDBehaviour.cs.meta                           |   12 
 Main/Component/UI/Common/PopupMessage.cs                             |   58 
 Main/ResModule/AnimatorBuildConfig.cs                                |   62 
 Main/Component/UI/HUD/LifeBarPool.cs.meta                            |   12 
 Main/Component/UI/Common/FunctionButtonGroup.cs                      |  269 
 Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs.meta       |   12 
 Main/Component/UI/Effect/EffectMgr.cs.meta                           |   12 
 Main/Component/UI/Common/ScrollItem.cs                               |   61 
 Main/System/Debug/DebugRoot.cs                                       |   69 
 Main/Component/UI/Common/BoundedDrag.cs                              |  260 
 Main/Component/UI/Decorate/Graph/OffsetImage.cs                      |   97 
 Main/Component/UI/Core/GrayGroup.cs                                  |   48 
 Main/ResModule/AnimatorBuildConfig.cs.meta                           |   12 
 Main/Component/UI/Common/InputSpecialWordLimit.cs.meta               |   12 
 Main/Login/ServerListCenter.cs.meta                                  |   11 
 Main/Component/UI/Decorate/Graph/CircleImage.cs.meta                 |   12 
 Main/Component/UI/Common/SecondFrameLoader2.cs.meta                  |   11 
 Main/Component/UI/Common/ScrollItem.cs.meta                          |   12 
 Main/Component/UI/Decorate/Graph/SquareHollowImage.cs                |  136 
 Main/Component/UI/Common/SecondFrameLoader.cs.meta                   |   12 
 Main/Component/UI/HUD/FollowTargetIgnoreY.cs.meta                    |   12 
 Main/Utility/TimeUtility.cs                                          |  442 
 Main/Login/ClientVersion/VersionUtility.cs.meta                      |   11 
 Main/System/Debug/DebugAsset.cs                                      |  106 
 Main/Component/UI/Common/SmoothMask.cs.meta                          |   12 
 Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs.meta  |   25 
 Main/SDK.meta                                                        |    8 
 Main/Component/UI/Decorate/Graph/Rhombus.cs.meta                     |   12 
 Main/System/AssetVersion.meta                                        |    8 
 Main/Component/UI/Common/ItemBaseEffect.cs                           |  157 
 Main/System/AssetVersion/InGameDownLoad.cs.meta                      |   11 
 Main/Component/UI/Common/ScreenDiffuseMove.cs                        |  161 
 Main/Component/UI/Decorate/Tweens.meta                               |    9 
 Main/Manager/LoginManager.cs                                         |   29 
 Main/Component/UI/Common/TimerBehaviour.cs.meta                      |   12 
 Main/Component/UI/Common/SortCell.cs                                 |   20 
 Main/Component/UI/Effect/UIEffectTransmitController.cs.meta          |   11 
 Main/Component/UI/HUD/HUDCenter.cs                                   |   30 
 Main/Component/UI/Common/FunctionButton.cs.meta                      |   12 
 Main/Component/UI/Common/FakeButton2.cs                              |   62 
 Main/Utility/UIHelper.cs                                             | 1320 ++
 Main/System/Debug/DebugController.cs.meta                            |   12 
 Main/Component/UI/Common/UIPrefabLoader.cs                           |   51 
 Main/Component/UI/HUD/HeadUpQuestSign.cs                             |   50 
 Main/System/Language/Language.cs.meta                                |   11 
 Main/Component/UI/HUD/HeadUpSkillNamePool.cs.meta                    |   12 
 Main/System/AssetVersion/DownLoadAndDiscompressTask.cs               |  204 
 Main/Component/UI/Core/TextImage.cs                                  |   80 
 Main/Component/UI/Effect/UIEffect.cs                                 |  298 
 Main/Component/UI/Common/AdaptiveRectOffset.cs                       |   14 
 Main/Component/UI/Decorate/Graph/MirrorImage.cs                      |  103 
 Main/Utility/TimeUtility.cs.meta                                     |   11 
 Main/Component/UI/Core/ToggleEx.cs                                   |   27 
 Main/ResModule/UILoader.cs.meta                                      |   12 
 Main/Component/UI/Common/PopupMessage.cs.meta                        |   12 
 Main/System/Debug/DebugSwitch.cs.meta                                |   12 
 Main/UI/UIBase.cs                                                    |    4 
 Main/Component/UI/Common/ClickScreenOtherSpace.cs.meta               |   12 
 Main/Component/UI/HUD/LifeBarPool.cs                                 |   64 
 Main/Component/UI/Decorate/Graph/CircleHollowImage.cs.meta           |   12 
 Main/Component/UI/Common/FrameEffect.cs.meta                         |   12 
 Main/System/Debug/DebugAsset.cs.meta                                 |   12 
 Main/Component/UI/Core/ButtonEx.cs.meta                              |   12 
 Main/Login/ServerListCenter.cs                                       |  564 
 Main/Component/UI/Common/PressTip.cs.meta                            |   12 
 Main/Component/UI/Common/AutoSelectCyclicScroll.cs                   |   58 
 Main/Component/UI/Common/TimeDownMgr.cs.meta                         |   12 
 Main/Component/UI/Decorate/Graph/Hexagon.cs                          |   69 
 Main/Component/UI/Common/CyclicScroll.cs.meta                        |   12 
 Main/System/CrossServer/CrossServerUtility.cs.meta                   |   11 
 Main/Component/UI/Common/FakeButton.cs                               |   75 
 Main/Component/UI/Common/TreasureMeridianConfig.cs                   |  152 
 Main/Component/UI/Common/PriorityWindowConfig.cs                     |   21 
 Main/System/Redpoint/Redpoint.cs.meta                                |   11 
 Main/Component/UI/HUD/HeadUpName.cs.meta                             |   12 
 Main/Component/UI/Decorate/Graph/MirrorImage.cs.meta                 |   12 
 Main/Component/UI/HUD/HeadUpName.cs                                  |  522 
 Main/Component/UI/Common/SecondFrameLoader2.cs                       |  111 
 Main/System/Debug/DebugLogin.cs                                      |  126 
 Main/Component/UI/Common/PlayerLifeBar.cs.meta                       |   12 
 Main/System/Redpoint/RedpointCenter.cs                               |  130 
 Main/Component/UI/HUD/PopUpNumPool.cs.meta                           |   12 
 Main/Component/UI/Common/UI3DModelInteractProcessor.cs.meta          |   12 
 Main/ResModule/AnimatorControllerLoader.cs.meta                      |   12 
 Main/Component/UI/Decorate/Graph/OffsetImage.cs.meta                 |   12 
 Main/Component/UI/Common/LayoutElementSizeClamp.cs                   |   42 
 Main/Component/UI/Decorate/Tweens/PositionTween.cs.meta              |   12 
 Main/Component/UI/Decorate/Graph/OffsetImage2.cs.meta                |   12 
 Main/Component/UI/EnhancedScroller/SmallList.cs.meta                 |   25 
 Main/Component/UI/Common/UI3DTreasureExhibition.cs.meta              |   12 
 Main/System/Redpoint/RedpointCenter.cs.meta                          |   11 
 Main/Component/UI/Common/DynamicCyclicScroll.cs.meta                 |   12 
 Main/UI/UIManager.cs                                                 |    2 
 Main/System/GeneralConfig/GeneralDefine.cs                           | 1168 +
 Main/Component/UI/Effect/TimeItem.cs.meta                            |   12 
 Main/Component/UI/Common/ScrollRectGroup.cs.meta                     |   12 
 Main/Component/UI/Common/OnOffToggle.cs                              |   63 
 Main/Component/UI/Decorate/Effect/Reflection.cs                      |   83 
 Main/Component/UI/Decorate/Tweens/TweenCurve.cs.meta                 |   12 
 Main/Component/UI/Common/EnableButtonConfig.cs                       |   51 
 Main/Component/UI/Decorate/Tweens/PositionTween.cs                   |   48 
 Main/Component/UI/Common/UIPlaySound.cs                              |   50 
 Main/Component/UI/Decorate/Move/UILinerMove.cs.meta                  |   12 
 Main/Component/UI/Common/WaterWaveOnCamera.cs.meta                   |   11 
 Main/ResModule/DebugItem.cs.meta                                     |   12 
 Main/Component/UI/Common/CoolDownBehaviour.cs.meta                   |   12 
 Main/Component/UI/Common/GameObjectDefaultActive.cs.meta             |   12 
 Main/Component/UI/HUD/HeadUpStorySign.cs.meta                        |   12 
 Main/ResModule/InstanceResourcesLoader.cs.meta                       |   12 
 Main/Core/GameEngine/Player/PlayerExtersionData.cs.meta              |   11 
 Main/System/Debug/DebugRoot.cs.meta                                  |   12 
 Main/Component/UI/Decorate/Tweens/ScaleTween.cs                      |   40 
 Main/Component/UI/Common/SmoothSlider.cs.meta                        |   12 
 Main/Component/UI/Common/AutoSelectScrollItem.cs.meta                |   12 
 Main/Component/UI/Core/ToggleButton.cs                               |  129 
 Main/Component/UI/HUD.meta                                           |    9 
 Main/Component/UI/Core/TextEx.cs                                     |  102 
 Main/Component/UI/Decorate/Graph/RayAccepter.cs.meta                 |   12 
 Main/Component/UI/Common/WindowConfig.cs.meta                        |   12 
 Main/Component/UI/HUD/HUDRoot.cs.meta                                |   12 
 Main/Component/UI/Core/ToggleButton.cs.meta                          |   12 
 Main/Login/ClientVersion.meta                                        |    8 
 Main/Component/UI/Common/PressTip.cs                                 |  102 
 Main/Component/UI/HUD/HeadUpQuestSignPool.cs.meta                    |   12 
 Main/Component/UI/HUD/DialogueBubblePool.cs.meta                     |   12 
 Main/Component/UI/Common/UI3DModelFactory.cs                         |  372 
 Main/Component/UI/Common/AutoSelectCyclicScroll.cs.meta              |   12 
 Main/System/AssetVersion/InGameDownTestUtility.cs                    |   85 
 Main/Component/UI/Common/GestureCatcher.cs                           |   42 
 Main/Component/UI/Common/DragContainer.cs                            |   19 
 Main/Component/UI/Common/UI3DShowHero.cs.meta                        |   12 
 Main/Component/UI/Core/DelayButton.cs.meta                           |   12 
 Main/Component/UI/HUD/LifeBar.cs                                     |  198 
 Main/Component/UI/HUD/NPCDialogueBubble.cs                           |  197 
 Main/Component/UI/Effect.meta                                        |    9 
 Main/System/Debug/DebugUtility.cs                                    |  208 
 Main/Core/GameEngine/Player/PlayerDatas.cs.meta                      |   11 
 Main/Component/UI/Effect/PostEffectsBase.cs.meta                     |    9 
 Main/Component/UI/HUD/PopUpNumPool.cs                                |   82 
 Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs.meta           |   12 
 Main/Component/UI/Effect/SpringDecorate.cs.meta                      |   12 
 Main/Utility/RunTimeABLoadLog.cs.meta                                |   11 
 Main/Component/UI/Common/LongPressButton.cs.meta                     |   12 
 Main/Component/UI/Common/PopupMessageContainer.cs.meta               |   12 
 Main/Component/UI/Common/SortCell.cs.meta                            |   12 
 Main/ResModule/AssetBundle/AssetInfo.cs.meta                         |   12 
 Main/Component/UI/Decorate/Tweens/RotationTween.cs.meta              |   12 
 Main/Component/UI/Common/UI3DHeroSkillShow.cs                        |  358 
 Main/Component/UI/Common/UIRoot.cs                                   |  121 
 Main/Component/UI/Common/ScrollRectGroup.cs                          |  157 
 Main/ResModule/SceneLoader.cs.meta                                   |   12 
 Main/Component/UI/Common/Treasure3DConfig.cs.meta                    |   12 
 Main/System/Debug/DebugLogSetting.cs                                 |   72 
 Main/Component/UI/HUD/NPCDialogueBubble.cs.meta                      |   12 
 Main/System/Debug/DebugLogRecorder.cs                                |  173 
 Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs.meta     |   12 
 Main/ResModule/ObjectPool.cs                                         |   93 
 Main/Component/UI/Common/ItemBehaviour.cs.meta                       |   12 
 Main/Component/UI/Decorate/PingPong/PingPongScale.cs                 |   48 
 Main/Component/UI/Common/RandomTip.cs.meta                           |   12 
 Main/Component/UI/HUD/StoryDialogueBubble.cs.meta                    |   12 
 Main/SDK/SDKUtils.cs                                                 | 1463 ++
 Main/Component/UI/Common/CoolDownBehaviour.cs                        |   89 
 Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs       |   53 
 Main/System/GeneralConfig/ConstDefine.cs.meta                        |   11 
 Main/Component/UI/Decorate/PingPong.meta                             |    9 
 Main/Component/UI/Common/UIPlaySound.cs.meta                         |   12 
 Main/Component/UI/Effect/ActorEffectEvent.cs.meta                    |   12 
 Main/Component/UI/Effect/EffectMgr.cs                                |  121 
 Main/SDK/SDKUtils.cs.meta                                            |   11 
 Main/Component/UI/Common/AutoSelectScrollItem.cs                     |   16 
 Main/System/AssetVersion/DownloadMgr.cs                              |  483 
 Main/Component/UI/Common/FuncOpen.cs.meta                            |   12 
 Main/Login/ServerListParser.cs                                       |   81 
 Main/Component/UI/Common/GameObjectDefaultActive.cs                  |   27 
 Main/Component/UI/EnhancedScroller/SmallList.cs                      |  219 
 Main/ResModule/AudioLoader.cs                                        |   60 
 Main/Login/ClientVersion/VersionConfig.cs                            |  352 
 Main/Component/UI/Common/CircleMoveTo.cs.meta                        |   12 
 Main/Component/UI/Common/WaterWaveSlider.cs                          |   41 
 Main/Component/UI/HUD/DialogueBubble.cs.meta                         |   12 
 Main/ResModule/ScriptableObjectLoader.cs.meta                        |   12 
 Main/System/Debug.meta                                               |    8 
 Main/Component/UI.meta                                               |    8 
 Main/Component/UI/Decorate/Smooth.meta                               |    9 
 Main/Login/ClientVersion/VersionUtility.cs                           |  352 
 Main/Component/UI/Common/SmoothSlider.cs                             |   72 
 Main/Component/UI/Common/FuncEnable.cs                               |   43 
 Main/Component/UI/Manager/UIEventTrigger.cs                          |  191 
 Main/System/Language/Language.cs                                     |  161 
 Main/Component/UI/Common/DragContainer.cs.meta                       |   12 
 Main/Component/UI/Decorate/Graph/SectionImage.cs                     |   51 
 Main/Component/UI/Common/UIDragDropBehaviour.cs                      |   84 
 Main/Component/UI/Common/NumKeyBoard.cs.meta                         |   12 
 Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs                |   61 
 Main/Component/UI/HUD/HUDRoot.cs                                     |   54 
 Main/Component/UI/Decorate/PingPong/PingPongScale.cs.meta            |   12 
 Main/Component/UI/Decorate/Tweens/TweenCurve.cs                      |   43 
 Main/Component/UI/Common/RollNumber.cs.meta                          |   12 
 Main/System/AssetVersion/DownLoadAndDiscompressTask.cs.meta          |   11 
 Main/System/GeneralConfig/GeneralDefine.cs.meta                      |   11 
 Main/Component/UI/Decorate/Graph/Hexagon.cs.meta                     |   12 
 Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs                    |  233 
 Main/Component/UI/EnhancedScroller/EnhancedScroller.cs.meta          |   25 
 Main/Component/UI/HUD/HeadUpTreasure.cs                              |   45 
 Main/Component/UI/Common/ErrorProcessor.cs.meta                      |   12 
 Main/Component/UI/Common/FuncEnable.cs.meta                          |   12 
 Main/Component/UI/Decorate/Effect/Reflection.cs.meta                 |   12 
 Main/Component/UI/HUD/HeadUpTreasurePool.cs.meta                     |   12 
 Main/Component/UI/Common/UIDragDropBehaviour.cs.meta                 |   12 
 Main/ResModule/InstanceResourcesLoader.cs                            |  547 
 Main/Component/UI/Common/LanguageReplace.cs                          |   23 
 Main/Component/UI/HUD/HUDCenter.cs.meta                              |   12 
 Main/Component/UI/Common/EnableAccordingToMap.cs.meta                |   12 
 Main/Core/GameEngine/Player.meta                                     |    8 
 Main/System/CrossServer.meta                                         |    8 
 Main/Component/UI/Common/RandomImage.cs.meta                         |   12 
 Main/Component/UI/Common/UI3DHeroSkillShow.cs.meta                   |   12 
 Main/Component/UI/Effect/TimeMgr.cs                                  |  265 
 Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs.meta             |   12 
 Main/ResModule/AudioLoader.cs.meta                                   |   12 
 Main/Component/UI/Core/TextEx.cs.meta                                |   12 
 Main/Component/UI/EnhancedScroller/EnhancedScroller.cs               | 2260 +++
 Main/Component/UI/Common/TimerToChsBehaviour.cs                      |   19 
 Main/Component/UI/Common/UI3DShowHero.cs                             |  828 +
 Main/Component/UI/HUD/DialogueBubblePool.cs                          |   75 
 Main/System/Debug/DebugLogin.cs.meta                                 |   12 
 Main/System/Redpoint/Redpoint.cs                                     |   64 
 Main/Component/UI/Effect/UIEffectBehaviour.cs.meta                   |   12 
 Main/Component/UI/Core/ToggleEx.cs.meta                              |   12 
 Main/Component/UI/Decorate/Graph/Rhombus.cs                          |   73 
 Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs      |   53 
 Main/Utility/Constants.cs                                            |   52 
 Main/ResModule/AssetBundle/AssetBundleUtility.cs                     |  754 +
 Main/Component/UI/Manager.meta                                       |    9 
 Main/System/Debug/DebugLogSetting.cs.meta                            |   12 
 Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs.meta |   25 
 Main/Component/UI/Common/ClickScreenOtherSpace.cs                    |   67 
 Main/Component/UI/Common/DragItem.cs.meta                            |   12 
 Main/Component/UI/Effect/TimeItem.cs                                 |   52 
 Main/System/AssetVersion/InGameDownLoad.cs                           |  722 +
 Main/Core.meta                                                       |    8 
 Main/Component/UI/Common/UITextReplace.cs.meta                       |   11 
 Main/Component/UI/Decorate/Graph/DivideImage.cs.meta                 |   12 
 Main/Component/UI/Common/ItemBehaviour.cs                            |  199 
 Main/Component/UI/Decorate/Effect/SpriteEffect.cs.meta               |   12 
 Main/Component/UI/Common/NestingScrollRect.cs.meta                   |   12 
 Main/Component.meta                                                  |    8 
 Main/Component/UI/Decorate/Graph/FlipImage.cs.meta                   |   12 
 Main/Component/UI/Common/FuncOpen.cs                                 |  255 
 Main/Component/UI/HUD/FollowTargetIgnoreY.cs                         |   44 
 Main/Component/UI/Common/CyclicScroll.cs                             |  762 +
 Main/Utility/RunTimeExceptionUtility.cs                              |   76 
 Main/Component/UI/Core/GrayGroup.cs.meta                             |   12 
 Main/System.meta                                                     |    8 
 Main/Component/UI/Common/UIRoot.cs.meta                              |   12 
 Main/Component/UI/HUD/HeadUpTreasure.cs.meta                         |   12 
 Main/Component/UI/Common/CanvasRaycastFilter.cs.meta                 |   12 
 Main/Component/UI/Common/LanguageReplace.cs.meta                     |   11 
 Main/System/GeneralConfig.meta                                       |    8 
 Main/Config/ConfigBase.cs                                            |    3 
 Main/Component/UI/Decorate/Move.meta                                 |    9 
 Main/Component/UI/Common/InputSpecialWordLimit.cs                    |   44 
 Main/Manager/ConfigManager.cs                                        |   34 
 Main/Component/UI/Common/DynamicCyclicScroll.cs                      |   44 
 Main/Component/UI/Decorate/Tweens/ScaleTween.cs.meta                 |   12 
 Main/Component/UI/Common/FakeButton2.cs.meta                         |   12 
 Main/Component/UI/Decorate/Tweens/RotationTween.cs                   |   41 
 Main/Component/UI/Common/FontColorSizeConfig.cs                      |   32 
 Main/Component/UI/Common/ScreenMoveTo.cs.meta                        |   12 
 Main/Component/UI/Effect/ColorCorrectionCurves.cs                    |  181 
 Main/ResModule/ObjectPool.cs.meta                                    |   12 
 Main/Component/UI/Core/ImageEx.cs.meta                               |   12 
 Main/Component/UI/Common/ErrorProcessor.cs                           |   56 
 Main/ResModule/AssetBundle/AssetBundleInfo.cs.meta                   |   12 
 Main/System/AssetVersion/AssetVersion.cs                             |  222 
 Main/ResModule/VideoLoader.cs.meta                                   |   12 
 Main/Component/UI/Common/EnableAccordingToMap.cs                     |   88 
 Main/Component/UI/Common/FunctionButton.cs                           |  262 
 Main/Component/UI/Common/FontSwitch.cs                               |   36 
 Main/Component/UI/Core/TextImage.cs.meta                             |   12 
 Main/Component/UI/Effect/UIEffectTransmitController.cs               |   48 
 Main/Component/UI/Common/PlayerLifeBar.cs                            |  131 
 Main/Component/UI/Decorate/Graph/CustomImage.cs.meta                 |   12 
 Main/Component/UI/Core/ImageUV1.cs                                   |   45 
 Main/Component/UI/HUD/FacingCamera.cs                                |   33 
 Main/Component/UI/Common/UI3DModelExhibition.cs                      |  977 +
 Main/Component/UI/HUD/HeadUpStorySign.cs                             |   99 
 Main/Manager/StageManager.cs                                         |    2 
 Main/ResModule/BuiltInLoader.cs                                      |  209 
 Main/Component/UI/HUD/LifeBar.cs.meta                                |   12 
 Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs            |   79 
 Main/Component/UI/Core/CanvasAddition.cs.meta                        |   12 
 Main/Component/UI/Decorate/Graph/SquareHollowImage.cs.meta           |   12 
 Main/Component/UI/Common/UIFuncOpen.cs.meta                          |   12 
 Main/Component/UI/Effect/UIEffectBehaviour.cs                        |  158 
 Main/Component/UI/Core/CanvasAddition.cs                             |  113 
 Main/Component/UI/Decorate/PingPong/PingPongMove.cs.meta             |   12 
 Main/Component/UI/Effect/UIEffect.cs.meta                            |   12 
 Main/Component/UI/Common/WaterWaveOnCamera.cs                        |   22 
 Main/System/Debug/DebugUtility.cs.meta                               |   12 
 Main/Login/ServerData.cs                                             |  148 
 Main/Component/UI/Decorate/Tweens/Tween.cs                           |  236 
 Main/Component/UI/Decorate/PingPong/PingPongMove.cs                  |   47 
 Main/Component/UI/Common/UI3DTreasureExhibition.cs                   |  203 
 Main/Login.meta                                                      |    8 
 Main/UI/Login/LoginWin.cs                                            |    1 
 Main/Component/UI/Common.meta                                        |    9 
 Main/Component/UI/Common/SortTable.cs.meta                           |   12 
 Main/Component/UI/Common/PriorityWindowConfig.cs.meta                |   12 
 Main/ResModule/GameObjectPoolManager.cs                              |  637 
 Main/Component/UI/Decorate/Graph/PolylineImage.cs.meta               |   12 
 Main/Component/UI/Common/BossLifeBar.cs                              |  174 
 Main/Component/UI/Effect/PostEffectsBase.cs                          |  261 
 Main/Component/UI/Common/ScreenMoveTo.cs                             |  170 
 Main/Component/UI/Common/NestingScrollRect.cs                        |   58 
 Main/Component/UI/EnhancedScroller.meta                              |    9 
 Main/System/AssetVersion/InGameDownTestUtility.cs.meta               |   11 
 Main/Component/UI/Common/ItemBaseEffect.cs.meta                      |   12 
 Main/Component/UI/Decorate/Smooth/SmoothMove.cs.meta                 |   12 
 Main/Component/UI/Core/DebugCanvasAddition.cs                        |   39 
 Main/Component/UI/Common/ButtonClickInterval.cs.meta                 |   12 
 Main/Component/UI/Common/WaterWaveOnUI.cs.meta                       |   11 
 Main/Component/UI/Decorate/PingPong/PingPongRotation.cs              |   47 
 Main/Component/UI/Common/BoundedDrag.cs.meta                         |   12 
 Main/Component/UI/HUD/HeadUpTreasurePool.cs                          |   40 
 Main/Component/UI/Common/FunctionButtonGroup.cs.meta                 |   12 
 Main/Component/UI/HUD/HeadUpNamePool.cs.meta                         |   12 
 Main/System/AssetVersion/AssetVersion.cs.meta                        |   11 
 Main/Component/UI/HUD/FacingCamera.cs.meta                           |   12 
 Main/Component/UI/Core/RepeatedButton.cs.meta                        |   12 
 Main/Component/UI/Decorate/Move/UILinerMove.cs                       |   82 
 Main/System/Redpoint.meta                                            |    8 
 Main/Component/UI/Common/Treasure3DConfig.cs                         |   49 
 Main/Component/UI/HUD/HeadUpSkillNamePool.cs                         |   61 
 Main/Component/UI/Common/ButtonClickInterval.cs                      |   31 
 Main/Main.cs                                                         |    8 
 Main/Component/UI/Decorate/Tweens/Tween.cs.meta                      |   12 
 Main/Component/UI/HUD/PopUpNum.cs                                    |  416 
 Main/Utility/RunTimeExceptionUtility.cs.meta                         |   11 
 Main/Utility/UIHelper.cs.meta                                        |   11 
 Main/System/AssetVersion/AssetVersionUtility.cs                      |  412 
 Main/Component/UI/Common/SecondFrameLoader.cs                        |   39 
 Main/Component/UI/Common/PrepareWin.cs                               |  102 
 Main/Component/UI/Common/UI3DModelInteractProcessor.cs               |  110 
 Main/System/Debug/DebugLogRecorder.cs.meta                           |   12 
 Main/Component/UI/Decorate/Effect/SpriteEffect.cs                    |   69 
 Main/Component/UI/Common/FontSwitch.cs.meta                          |   12 
 Main/Component/UI/Common/ScreenDiffuseMove.cs.meta                   |   12 
 Main/Component/UI/Common/PostEffectBase.cs                           |   36 
 Main/Component/UI/Common/WaterWaveOnUI.cs                            |   47 
 Main/Component/UI/Decorate/Graph/DivideImage.cs                      |  107 
 Main/Component/UI/Core/ImageUV1.cs.meta                              |   12 
 Main/Component/UI/Common/TreasureMeridianConfig.cs.meta              |   12 
 /dev/null                                                            |   12 
 Main/Component/UI/Common/PopupMessageContainer.cs                    |   82 
 Main/Component/UI/Common/LayoutElementSizeClamp.cs.meta              |   12 
 Main/Component/UI/HUD/HUDBehaviour.cs                                |   94 
 Main/Component/UI/Decorate/Graph/CircleHollowImage.cs                |  128 
 Main/ResModule/VideoLoader.cs                                        |   61 
 Main/Component/UI/Decorate/Graph.meta                                |    9 
 Main/Component/UI/Common/MaterialsContainer.cs.meta                  |   12 
 Main/Component/UI/Effect/ColorCorrectionCurves.cs.meta               |   15 
 478 files changed, 38,601 insertions(+), 30 deletions(-)

diff --git a/Main/Common/LitJson/IJsonWrapper.cs b/Main/Common/LitJson/IJsonWrapper.cs
deleted file mode 100644
index 9b7e2d1..0000000
--- a/Main/Common/LitJson/IJsonWrapper.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-#region Header
-/**
- * IJsonWrapper.cs
- *   Interface that represents a type capable of handling all kinds of JSON
- *   data. This is mainly used when mapping objects through JsonMapper, and
- *   it's implemented by JsonData.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System.Collections;
-using System.Collections.Specialized;
-
-
-namespace LitJson
-{
-    public enum JsonType
-    {
-        None,
-
-        Object,
-        Array,
-        String,
-        Int,
-        Long,
-        Double,
-        Boolean
-    }
-
-    public interface IJsonWrapper : IList, IOrderedDictionary
-    {
-        bool IsArray   { get; }
-        bool IsBoolean { get; }
-        bool IsDouble  { get; }
-        bool IsInt     { get; }
-        bool IsLong    { get; }
-        bool IsObject  { get; }
-        bool IsString  { get; }
-
-        bool     GetBoolean ();
-        double   GetDouble ();
-        int      GetInt ();
-        JsonType GetJsonType ();
-        long     GetLong ();
-        string   GetString ();
-
-        void SetBoolean  (bool val);
-        void SetDouble   (double val);
-        void SetInt      (int val);
-        void SetJsonType (JsonType type);
-        void SetLong     (long val);
-        void SetString   (string val);
-
-        string ToJson ();
-        void   ToJson (JsonWriter writer);
-    }
-}
diff --git a/Main/Common/LitJson/IJsonWrapper.cs.meta b/Main/Common/LitJson/IJsonWrapper.cs.meta
deleted file mode 100644
index 6d04e58..0000000
--- a/Main/Common/LitJson/IJsonWrapper.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 271dce3dff1f78a4bab7ed5e77053b46
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonData.cs b/Main/Common/LitJson/JsonData.cs
deleted file mode 100644
index e89e4b1..0000000
--- a/Main/Common/LitJson/JsonData.cs
+++ /dev/null
@@ -1,1059 +0,0 @@
-#region Header
-/**
- * JsonData.cs
- *   Generic type to hold JSON data (objects, arrays, and so on). This is
- *   the default type returned by JsonMapper.ToObject().
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.IO;
-
-
-namespace LitJson
-{
-    public class JsonData : IJsonWrapper, IEquatable<JsonData>
-    {
-        #region Fields
-        private IList<JsonData>               inst_array;
-        private bool                          inst_boolean;
-        private double                        inst_double;
-        private int                           inst_int;
-        private long                          inst_long;
-        private IDictionary<string, JsonData> inst_object;
-        private string                        inst_string;
-        private string                        json;
-        private JsonType                      type;
-
-        // Used to implement the IOrderedDictionary interface
-        private IList<KeyValuePair<string, JsonData>> object_list;
-        #endregion
-
-
-        #region Properties
-        public int Count {
-            get { return EnsureCollection ().Count; }
-        }
-
-        public bool IsArray {
-            get { return type == JsonType.Array; }
-        }
-
-        public bool IsBoolean {
-            get { return type == JsonType.Boolean; }
-        }
-
-        public bool IsDouble {
-            get { return type == JsonType.Double; }
-        }
-
-        public bool IsInt {
-            get { return type == JsonType.Int; }
-        }
-
-        public bool IsLong {
-            get { return type == JsonType.Long; }
-        }
-
-        public bool IsObject {
-            get { return type == JsonType.Object; }
-        }
-
-        public bool IsString {
-            get { return type == JsonType.String; }
-        }
-
-        public ICollection<string> Keys {
-            get { EnsureDictionary (); return inst_object.Keys; }
-        }
-        
-        /// <summary>
-        /// Determines whether the json contains an element that has the specified key.
-        /// </summary>
-        /// <param name="key">The key to locate in the json.</param>
-        /// <returns>true if the json contains an element that has the specified key; otherwise, false.</returns>
-        public Boolean ContainsKey(String key) {
-            EnsureDictionary();
-            return this.inst_object.Keys.Contains(key);
-        }
-        #endregion
-
-
-        #region ICollection Properties
-        int ICollection.Count {
-            get {
-                return Count;
-            }
-        }
-
-        bool ICollection.IsSynchronized {
-            get {
-                return EnsureCollection ().IsSynchronized;
-            }
-        }
-
-        object ICollection.SyncRoot {
-            get {
-                return EnsureCollection ().SyncRoot;
-            }
-        }
-        #endregion
-
-
-        #region IDictionary Properties
-        bool IDictionary.IsFixedSize {
-            get {
-                return EnsureDictionary ().IsFixedSize;
-            }
-        }
-
-        bool IDictionary.IsReadOnly {
-            get {
-                return EnsureDictionary ().IsReadOnly;
-            }
-        }
-
-        ICollection IDictionary.Keys {
-            get {
-                EnsureDictionary ();
-                IList<string> keys = new List<string> ();
-
-                foreach (KeyValuePair<string, JsonData> entry in
-                         object_list) {
-                    keys.Add (entry.Key);
-                }
-
-                return (ICollection) keys;
-            }
-        }
-
-        ICollection IDictionary.Values {
-            get {
-                EnsureDictionary ();
-                IList<JsonData> values = new List<JsonData> ();
-
-                foreach (KeyValuePair<string, JsonData> entry in
-                         object_list) {
-                    values.Add (entry.Value);
-                }
-
-                return (ICollection) values;
-            }
-        }
-        #endregion
-
-
-
-        #region IJsonWrapper Properties
-        bool IJsonWrapper.IsArray {
-            get { return IsArray; }
-        }
-
-        bool IJsonWrapper.IsBoolean {
-            get { return IsBoolean; }
-        }
-
-        bool IJsonWrapper.IsDouble {
-            get { return IsDouble; }
-        }
-
-        bool IJsonWrapper.IsInt {
-            get { return IsInt; }
-        }
-
-        bool IJsonWrapper.IsLong {
-            get { return IsLong; }
-        }
-
-        bool IJsonWrapper.IsObject {
-            get { return IsObject; }
-        }
-
-        bool IJsonWrapper.IsString {
-            get { return IsString; }
-        }
-        #endregion
-
-
-        #region IList Properties
-        bool IList.IsFixedSize {
-            get {
-                return EnsureList ().IsFixedSize;
-            }
-        }
-
-        bool IList.IsReadOnly {
-            get {
-                return EnsureList ().IsReadOnly;
-            }
-        }
-        #endregion
-
-
-        #region IDictionary Indexer
-        object IDictionary.this[object key] {
-            get {
-                return EnsureDictionary ()[key];
-            }
-
-            set {
-                if (! (key is String))
-                    throw new ArgumentException (
-                        "The key has to be a string");
-
-                JsonData data = ToJsonData (value);
-
-                this[(string) key] = data;
-            }
-        }
-        #endregion
-
-
-        #region IOrderedDictionary Indexer
-        object IOrderedDictionary.this[int idx] {
-            get {
-                EnsureDictionary ();
-                return object_list[idx].Value;
-            }
-
-            set {
-                EnsureDictionary ();
-                JsonData data = ToJsonData (value);
-
-                KeyValuePair<string, JsonData> old_entry = object_list[idx];
-
-                inst_object[old_entry.Key] = data;
-
-                KeyValuePair<string, JsonData> entry =
-                    new KeyValuePair<string, JsonData> (old_entry.Key, data);
-
-                object_list[idx] = entry;
-            }
-        }
-        #endregion
-
-
-        #region IList Indexer
-        object IList.this[int index] {
-            get {
-                return EnsureList ()[index];
-            }
-
-            set {
-                EnsureList ();
-                JsonData data = ToJsonData (value);
-
-                this[index] = data;
-            }
-        }
-        #endregion
-
-
-        #region Public Indexers
-        public JsonData this[string prop_name] {
-            get {
-                EnsureDictionary ();
-                return inst_object[prop_name];
-            }
-
-            set {
-                EnsureDictionary ();
-
-                KeyValuePair<string, JsonData> entry =
-                    new KeyValuePair<string, JsonData> (prop_name, value);
-
-                if (inst_object.ContainsKey (prop_name)) {
-                    for (int i = 0; i < object_list.Count; i++) {
-                        if (object_list[i].Key == prop_name) {
-                            object_list[i] = entry;
-                            break;
-                        }
-                    }
-                } else
-                    object_list.Add (entry);
-
-                inst_object[prop_name] = value;
-
-                json = null;
-            }
-        }
-
-        public JsonData this[int index] {
-            get {
-                EnsureCollection ();
-
-                if (type == JsonType.Array)
-                    return inst_array[index];
-
-                return object_list[index].Value;
-            }
-
-            set {
-                EnsureCollection ();
-
-                if (type == JsonType.Array)
-                    inst_array[index] = value;
-                else {
-                    KeyValuePair<string, JsonData> entry = object_list[index];
-                    KeyValuePair<string, JsonData> new_entry =
-                        new KeyValuePair<string, JsonData> (entry.Key, value);
-
-                    object_list[index] = new_entry;
-                    inst_object[entry.Key] = value;
-                }
-
-                json = null;
-            }
-        }
-        #endregion
-
-
-        #region Constructors
-        public JsonData ()
-        {
-        }
-
-        public JsonData (bool boolean)
-        {
-            type = JsonType.Boolean;
-            inst_boolean = boolean;
-        }
-
-        public JsonData (double number)
-        {
-            type = JsonType.Double;
-            inst_double = number;
-        }
-
-        public JsonData (int number)
-        {
-            type = JsonType.Int;
-            inst_int = number;
-        }
-
-        public JsonData (long number)
-        {
-            type = JsonType.Long;
-            inst_long = number;
-        }
-
-        public JsonData (object obj)
-        {
-            if (obj is Boolean) {
-                type = JsonType.Boolean;
-                inst_boolean = (bool) obj;
-                return;
-            }
-
-            if (obj is Double) {
-                type = JsonType.Double;
-                inst_double = (double) obj;
-                return;
-            }
-
-            if (obj is Int32) {
-                type = JsonType.Int;
-                inst_int = (int) obj;
-                return;
-            }
-
-            if (obj is Int64) {
-                type = JsonType.Long;
-                inst_long = (long) obj;
-                return;
-            }
-
-            if (obj is String) {
-                type = JsonType.String;
-                inst_string = (string) obj;
-                return;
-            }
-
-            throw new ArgumentException (
-                "Unable to wrap the given object with JsonData");
-        }
-
-        public JsonData (string str)
-        {
-            type = JsonType.String;
-            inst_string = str;
-        }
-        #endregion
-
-
-        #region Implicit Conversions
-        public static implicit operator JsonData (Boolean data)
-        {
-            return new JsonData (data);
-        }
-
-        public static implicit operator JsonData (Double data)
-        {
-            return new JsonData (data);
-        }
-
-        public static implicit operator JsonData (Int32 data)
-        {
-            return new JsonData (data);
-        }
-
-        public static implicit operator JsonData (Int64 data)
-        {
-            return new JsonData (data);
-        }
-
-        public static implicit operator JsonData (String data)
-        {
-            return new JsonData (data);
-        }
-        #endregion
-
-
-        #region Explicit Conversions
-        public static explicit operator Boolean (JsonData data)
-        {
-            if (data.type != JsonType.Boolean)
-                throw new InvalidCastException (
-                    "Instance of JsonData doesn't hold a double");
-
-            return data.inst_boolean;
-        }
-
-        public static explicit operator Double (JsonData data)
-        {
-            if (data.type != JsonType.Double)
-                throw new InvalidCastException (
-                    "Instance of JsonData doesn't hold a double");
-
-            return data.inst_double;
-        }
-
-       public static explicit operator Int32(JsonData data)
-        {
-            if (data.type != JsonType.Int && data.type != JsonType.Long)
-            {
-                throw new InvalidCastException(
-                    "Instance of JsonData doesn't hold an int");
-            }
-
-            // cast may truncate data... but that's up to the user to consider
-            return data.type == JsonType.Int ? data.inst_int : (int)data.inst_long;
-        }
-
-        public static explicit operator Int64(JsonData data)
-        {
-            if (data.type != JsonType.Long && data.type != JsonType.Int)
-            {
-                throw new InvalidCastException(
-                    "Instance of JsonData doesn't hold a long");
-            }
-
-            return data.type == JsonType.Long ? data.inst_long : data.inst_int;
-        }
-
-        public static explicit operator String (JsonData data)
-        {
-            if (data.type != JsonType.String)
-                throw new InvalidCastException (
-                    "Instance of JsonData doesn't hold a string");
-
-            return data.inst_string;
-        }
-        #endregion
-
-
-        #region ICollection Methods
-        void ICollection.CopyTo (Array array, int index)
-        {
-            EnsureCollection ().CopyTo (array, index);
-        }
-        #endregion
-
-
-        #region IDictionary Methods
-        void IDictionary.Add (object key, object value)
-        {
-            JsonData data = ToJsonData (value);
-
-            EnsureDictionary ().Add (key, data);
-
-            KeyValuePair<string, JsonData> entry =
-                new KeyValuePair<string, JsonData> ((string) key, data);
-            object_list.Add (entry);
-
-            json = null;
-        }
-
-        void IDictionary.Clear ()
-        {
-            EnsureDictionary ().Clear ();
-            object_list.Clear ();
-            json = null;
-        }
-
-        bool IDictionary.Contains (object key)
-        {
-            return EnsureDictionary ().Contains (key);
-        }
-
-        IDictionaryEnumerator IDictionary.GetEnumerator ()
-        {
-            return ((IOrderedDictionary) this).GetEnumerator ();
-        }
-
-        void IDictionary.Remove (object key)
-        {
-            EnsureDictionary ().Remove (key);
-
-            for (int i = 0; i < object_list.Count; i++) {
-                if (object_list[i].Key == (string) key) {
-                    object_list.RemoveAt (i);
-                    break;
-                }
-            }
-
-            json = null;
-        }
-        #endregion
-
-
-        #region IEnumerable Methods
-        IEnumerator IEnumerable.GetEnumerator ()
-        {
-            return EnsureCollection ().GetEnumerator ();
-        }
-        #endregion
-
-
-        #region IJsonWrapper Methods
-        bool IJsonWrapper.GetBoolean ()
-        {
-            if (type != JsonType.Boolean)
-                throw new InvalidOperationException (
-                    "JsonData instance doesn't hold a boolean");
-
-            return inst_boolean;
-        }
-
-        double IJsonWrapper.GetDouble ()
-        {
-            if (type != JsonType.Double)
-                throw new InvalidOperationException (
-                    "JsonData instance doesn't hold a double");
-
-            return inst_double;
-        }
-
-        int IJsonWrapper.GetInt ()
-        {
-            if (type != JsonType.Int)
-                throw new InvalidOperationException (
-                    "JsonData instance doesn't hold an int");
-
-            return inst_int;
-        }
-
-        long IJsonWrapper.GetLong ()
-        {
-            if (type != JsonType.Long)
-                throw new InvalidOperationException (
-                    "JsonData instance doesn't hold a long");
-
-            return inst_long;
-        }
-
-        string IJsonWrapper.GetString ()
-        {
-            if (type != JsonType.String)
-                throw new InvalidOperationException (
-                    "JsonData instance doesn't hold a string");
-
-            return inst_string;
-        }
-
-        void IJsonWrapper.SetBoolean (bool val)
-        {
-            type = JsonType.Boolean;
-            inst_boolean = val;
-            json = null;
-        }
-
-        void IJsonWrapper.SetDouble (double val)
-        {
-            type = JsonType.Double;
-            inst_double = val;
-            json = null;
-        }
-
-        void IJsonWrapper.SetInt (int val)
-        {
-            type = JsonType.Int;
-            inst_int = val;
-            json = null;
-        }
-
-        void IJsonWrapper.SetLong (long val)
-        {
-            type = JsonType.Long;
-            inst_long = val;
-            json = null;
-        }
-
-        void IJsonWrapper.SetString (string val)
-        {
-            type = JsonType.String;
-            inst_string = val;
-            json = null;
-        }
-
-        string IJsonWrapper.ToJson ()
-        {
-            return ToJson ();
-        }
-
-        void IJsonWrapper.ToJson (JsonWriter writer)
-        {
-            ToJson (writer);
-        }
-        #endregion
-
-
-        #region IList Methods
-        int IList.Add (object value)
-        {
-            return Add (value);
-        }
-
-        void IList.Clear ()
-        {
-            EnsureList ().Clear ();
-            json = null;
-        }
-
-        bool IList.Contains (object value)
-        {
-            return EnsureList ().Contains (value);
-        }
-
-        int IList.IndexOf (object value)
-        {
-            return EnsureList ().IndexOf (value);
-        }
-
-        void IList.Insert (int index, object value)
-        {
-            EnsureList ().Insert (index, value);
-            json = null;
-        }
-
-        void IList.Remove (object value)
-        {
-            EnsureList ().Remove (value);
-            json = null;
-        }
-
-        void IList.RemoveAt (int index)
-        {
-            EnsureList ().RemoveAt (index);
-            json = null;
-        }
-        #endregion
-
-
-        #region IOrderedDictionary Methods
-        IDictionaryEnumerator IOrderedDictionary.GetEnumerator ()
-        {
-            EnsureDictionary ();
-
-            return new OrderedDictionaryEnumerator (
-                object_list.GetEnumerator ());
-        }
-
-        void IOrderedDictionary.Insert (int idx, object key, object value)
-        {
-            string property = (string) key;
-            JsonData data  = ToJsonData (value);
-
-            this[property] = data;
-
-            KeyValuePair<string, JsonData> entry =
-                new KeyValuePair<string, JsonData> (property, data);
-
-            object_list.Insert (idx, entry);
-        }
-
-        void IOrderedDictionary.RemoveAt (int idx)
-        {
-            EnsureDictionary ();
-
-            inst_object.Remove (object_list[idx].Key);
-            object_list.RemoveAt (idx);
-        }
-        #endregion
-
-
-        #region Private Methods
-        private ICollection EnsureCollection ()
-        {
-            if (type == JsonType.Array)
-                return (ICollection) inst_array;
-
-            if (type == JsonType.Object)
-                return (ICollection) inst_object;
-
-            throw new InvalidOperationException (
-                "The JsonData instance has to be initialized first");
-        }
-
-        private IDictionary EnsureDictionary ()
-        {
-            if (type == JsonType.Object)
-                return (IDictionary) inst_object;
-
-            if (type != JsonType.None)
-                throw new InvalidOperationException (
-                    "Instance of JsonData is not a dictionary");
-
-            type = JsonType.Object;
-            inst_object = new Dictionary<string, JsonData> ();
-            object_list = new List<KeyValuePair<string, JsonData>> ();
-
-            return (IDictionary) inst_object;
-        }
-
-        private IList EnsureList ()
-        {
-            if (type == JsonType.Array)
-                return (IList) inst_array;
-
-            if (type != JsonType.None)
-                throw new InvalidOperationException (
-                    "Instance of JsonData is not a list");
-
-            type = JsonType.Array;
-            inst_array = new List<JsonData> ();
-
-            return (IList) inst_array;
-        }
-
-        private JsonData ToJsonData (object obj)
-        {
-            if (obj == null)
-                return null;
-
-            if (obj is JsonData)
-                return (JsonData) obj;
-
-            return new JsonData (obj);
-        }
-
-        private static void WriteJson (IJsonWrapper obj, JsonWriter writer)
-        {
-            if (obj == null) {
-                writer.Write (null);
-                return;
-            }
-
-            if (obj.IsString) {
-                writer.Write (obj.GetString ());
-                return;
-            }
-
-            if (obj.IsBoolean) {
-                writer.Write (obj.GetBoolean ());
-                return;
-            }
-
-            if (obj.IsDouble) {
-                writer.Write (obj.GetDouble ());
-                return;
-            }
-
-            if (obj.IsInt) {
-                writer.Write (obj.GetInt ());
-                return;
-            }
-
-            if (obj.IsLong) {
-                writer.Write (obj.GetLong ());
-                return;
-            }
-
-            if (obj.IsArray) {
-                writer.WriteArrayStart ();
-                foreach (object elem in (IList) obj)
-                    WriteJson ((JsonData) elem, writer);
-                writer.WriteArrayEnd ();
-
-                return;
-            }
-
-            if (obj.IsObject) {
-                writer.WriteObjectStart ();
-
-                foreach (DictionaryEntry entry in ((IDictionary) obj)) {
-                    writer.WritePropertyName ((string) entry.Key);
-                    WriteJson ((JsonData) entry.Value, writer);
-                }
-                writer.WriteObjectEnd ();
-
-                return;
-            }
-        }
-        #endregion
-
-
-        public int Add (object value)
-        {
-            JsonData data = ToJsonData (value);
-
-            json = null;
-
-            return EnsureList ().Add (data);
-        }
-
-        public bool Remove(object obj)
-        {
-            json = null;
-            if(IsObject)
-            {
-                JsonData value = null;
-                if (inst_object.TryGetValue((string)obj, out value))
-                    return inst_object.Remove((string)obj) && object_list.Remove(new KeyValuePair<string, JsonData>((string)obj, value));
-                else
-                    throw new KeyNotFoundException("The specified key was not found in the JsonData object.");
-            }
-            if(IsArray)
-            {
-                return inst_array.Remove(ToJsonData(obj));
-            }
-            throw new InvalidOperationException (
-                    "Instance of JsonData is not an object or a list.");
-        }
-
-        public void Clear ()
-        {
-            if (IsObject) {
-                ((IDictionary) this).Clear ();
-                return;
-            }
-
-            if (IsArray) {
-                ((IList) this).Clear ();
-                return;
-            }
-        }
-
-        public bool Equals (JsonData x)
-        {
-            if (x == null)
-                return false;
-
-            if (x.type != this.type)
-            {
-                // further check to see if this is a long to int comparison
-                if ((x.type != JsonType.Int && x.type != JsonType.Long)
-                    || (this.type != JsonType.Int && this.type != JsonType.Long))
-                {
-                    return false;
-                }
-            }
-
-            switch (this.type) {
-            case JsonType.None:
-                return true;
-
-            case JsonType.Object:
-                return this.inst_object.Equals (x.inst_object);
-
-            case JsonType.Array:
-                return this.inst_array.Equals (x.inst_array);
-
-            case JsonType.String:
-                return this.inst_string.Equals (x.inst_string);
-
-            case JsonType.Int:
-            {
-                if (x.IsLong)
-                {
-                    if (x.inst_long < Int32.MinValue || x.inst_long > Int32.MaxValue)
-                        return false;
-                    return this.inst_int.Equals((int)x.inst_long);
-                }
-                return this.inst_int.Equals(x.inst_int);
-            }
-
-            case JsonType.Long:
-            {
-                if (x.IsInt)
-                {
-                    if (this.inst_long < Int32.MinValue || this.inst_long > Int32.MaxValue)
-                        return false;
-                    return x.inst_int.Equals((int)this.inst_long);
-                }
-                return this.inst_long.Equals(x.inst_long);
-            }
-
-            case JsonType.Double:
-                return this.inst_double.Equals (x.inst_double);
-
-            case JsonType.Boolean:
-                return this.inst_boolean.Equals (x.inst_boolean);
-            }
-
-            return false;
-        }
-
-        public JsonType GetJsonType ()
-        {
-            return type;
-        }
-
-        public void SetJsonType (JsonType type)
-        {
-            if (this.type == type)
-                return;
-
-            switch (type) {
-            case JsonType.None:
-                break;
-
-            case JsonType.Object:
-                inst_object = new Dictionary<string, JsonData> ();
-                object_list = new List<KeyValuePair<string, JsonData>> ();
-                break;
-
-            case JsonType.Array:
-                inst_array = new List<JsonData> ();
-                break;
-
-            case JsonType.String:
-                inst_string = default (String);
-                break;
-
-            case JsonType.Int:
-                inst_int = default (Int32);
-                break;
-
-            case JsonType.Long:
-                inst_long = default (Int64);
-                break;
-
-            case JsonType.Double:
-                inst_double = default (Double);
-                break;
-
-            case JsonType.Boolean:
-                inst_boolean = default (Boolean);
-                break;
-            }
-
-            this.type = type;
-        }
-
-        public string ToJson ()
-        {
-            if (json != null)
-                return json;
-
-            StringWriter sw = new StringWriter ();
-            JsonWriter writer = new JsonWriter (sw);
-            writer.Validate = false;
-
-            WriteJson (this, writer);
-            json = sw.ToString ();
-
-            return json;
-        }
-
-        public void ToJson (JsonWriter writer)
-        {
-            bool old_validate = writer.Validate;
-
-            writer.Validate = false;
-
-            WriteJson (this, writer);
-
-            writer.Validate = old_validate;
-        }
-
-        public override string ToString ()
-        {
-            switch (type) {
-            case JsonType.Array:
-                return "JsonData array";
-
-            case JsonType.Boolean:
-                return inst_boolean.ToString ();
-
-            case JsonType.Double:
-                return inst_double.ToString ();
-
-            case JsonType.Int:
-                return inst_int.ToString ();
-
-            case JsonType.Long:
-                return inst_long.ToString ();
-
-            case JsonType.Object:
-                return "JsonData object";
-
-            case JsonType.String:
-                return inst_string;
-            }
-
-            return "Uninitialized JsonData";
-        }
-    }
-
-
-    internal class OrderedDictionaryEnumerator : IDictionaryEnumerator
-    {
-        IEnumerator<KeyValuePair<string, JsonData>> list_enumerator;
-
-
-        public object Current {
-            get { return Entry; }
-        }
-
-        public DictionaryEntry Entry {
-            get {
-                KeyValuePair<string, JsonData> curr = list_enumerator.Current;
-                return new DictionaryEntry (curr.Key, curr.Value);
-            }
-        }
-
-        public object Key {
-            get { return list_enumerator.Current.Key; }
-        }
-
-        public object Value {
-            get { return list_enumerator.Current.Value; }
-        }
-
-
-        public OrderedDictionaryEnumerator (
-            IEnumerator<KeyValuePair<string, JsonData>> enumerator)
-        {
-            list_enumerator = enumerator;
-        }
-
-
-        public bool MoveNext ()
-        {
-            return list_enumerator.MoveNext ();
-        }
-
-        public void Reset ()
-        {
-            list_enumerator.Reset ();
-        }
-    }
-}
diff --git a/Main/Common/LitJson/JsonData.cs.meta b/Main/Common/LitJson/JsonData.cs.meta
deleted file mode 100644
index b38cf07..0000000
--- a/Main/Common/LitJson/JsonData.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: f08013cb4e26ac44f8537d847609a788
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonException.cs b/Main/Common/LitJson/JsonException.cs
deleted file mode 100644
index 4efd890..0000000
--- a/Main/Common/LitJson/JsonException.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-#region Header
-/**
- * JsonException.cs
- *   Base class throwed by LitJSON when a parsing error occurs.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-
-
-namespace LitJson
-{
-    public class JsonException :
-#if NETSTANDARD1_5
-        Exception
-#else
-        ApplicationException
-#endif
-    {
-        public JsonException () : base ()
-        {
-        }
-
-        internal JsonException (ParserToken token) :
-            base (String.Format (
-                    "Invalid token '{0}' in input string", token))
-        {
-        }
-
-        internal JsonException (ParserToken token,
-                                Exception inner_exception) :
-            base (String.Format (
-                    "Invalid token '{0}' in input string", token),
-                inner_exception)
-        {
-        }
-
-        internal JsonException (int c) :
-            base (String.Format (
-                    "Invalid character '{0}' in input string", (char) c))
-        {
-        }
-
-        internal JsonException (int c, Exception inner_exception) :
-            base (String.Format (
-                    "Invalid character '{0}' in input string", (char) c),
-                inner_exception)
-        {
-        }
-
-
-        public JsonException (string message) : base (message)
-        {
-        }
-
-        public JsonException (string message, Exception inner_exception) :
-            base (message, inner_exception)
-        {
-        }
-    }
-}
diff --git a/Main/Common/LitJson/JsonException.cs.meta b/Main/Common/LitJson/JsonException.cs.meta
deleted file mode 100644
index c3b9535..0000000
--- a/Main/Common/LitJson/JsonException.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 98f4dafaa0fce514bb6878d7a0fa26e7
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonMapper.cs b/Main/Common/LitJson/JsonMapper.cs
deleted file mode 100644
index fc10b28..0000000
--- a/Main/Common/LitJson/JsonMapper.cs
+++ /dev/null
@@ -1,995 +0,0 @@
-#region Header
-/**
- * JsonMapper.cs
- *   JSON to .Net object and object to JSON conversions.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-
-
-namespace LitJson
-{
-    internal struct PropertyMetadata
-    {
-        public MemberInfo Info;
-        public bool       IsField;
-        public Type       Type;
-    }
-
-
-    internal struct ArrayMetadata
-    {
-        private Type element_type;
-        private bool is_array;
-        private bool is_list;
-
-
-        public Type ElementType {
-            get {
-                if (element_type == null)
-                    return typeof (JsonData);
-
-                return element_type;
-            }
-
-            set { element_type = value; }
-        }
-
-        public bool IsArray {
-            get { return is_array; }
-            set { is_array = value; }
-        }
-
-        public bool IsList {
-            get { return is_list; }
-            set { is_list = value; }
-        }
-    }
-
-
-    internal struct ObjectMetadata
-    {
-        private Type element_type;
-        private bool is_dictionary;
-
-        private IDictionary<string, PropertyMetadata> properties;
-
-
-        public Type ElementType {
-            get {
-                if (element_type == null)
-                    return typeof (JsonData);
-
-                return element_type;
-            }
-
-            set { element_type = value; }
-        }
-
-        public bool IsDictionary {
-            get { return is_dictionary; }
-            set { is_dictionary = value; }
-        }
-
-        public IDictionary<string, PropertyMetadata> Properties {
-            get { return properties; }
-            set { properties = value; }
-        }
-    }
-
-
-    internal delegate void ExporterFunc    (object obj, JsonWriter writer);
-    public   delegate void ExporterFunc<T> (T obj, JsonWriter writer);
-
-    internal delegate object ImporterFunc                (object input);
-    public   delegate TValue ImporterFunc<TJson, TValue> (TJson input);
-
-    public delegate IJsonWrapper WrapperFactory ();
-
-
-    public class JsonMapper
-    {
-        #region Fields
-        private static readonly int max_nesting_depth;
-
-        private static readonly IFormatProvider datetime_format;
-
-        private static readonly IDictionary<Type, ExporterFunc> base_exporters_table;
-        private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table;
-        private static readonly object custom_exporters_table_lock = new Object();
-
-        private static readonly IDictionary<Type,
-                IDictionary<Type, ImporterFunc>> base_importers_table;
-        private static readonly IDictionary<Type,
-                IDictionary<Type, ImporterFunc>> custom_importers_table;
-        private static readonly object custom_importers_table_lock = new Object();
-
-        private static readonly IDictionary<Type, ArrayMetadata> array_metadata;
-        private static readonly object array_metadata_lock = new Object ();
-
-        private static readonly IDictionary<Type,
-                IDictionary<Type, MethodInfo>> conv_ops;
-        private static readonly object conv_ops_lock = new Object ();
-
-        private static readonly IDictionary<Type, ObjectMetadata> object_metadata;
-        private static readonly object object_metadata_lock = new Object ();
-
-        private static readonly IDictionary<Type,
-                IList<PropertyMetadata>> type_properties;
-        private static readonly object type_properties_lock = new Object ();
-
-        private static readonly JsonWriter      static_writer;
-        private static readonly object static_writer_lock = new Object ();
-        #endregion
-
-
-        #region Constructors
-        static JsonMapper ()
-        {
-            max_nesting_depth = 100;
-
-            array_metadata = new Dictionary<Type, ArrayMetadata> ();
-            conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>> ();
-            object_metadata = new Dictionary<Type, ObjectMetadata> ();
-            type_properties = new Dictionary<Type,
-                            IList<PropertyMetadata>> ();
-
-            static_writer = new JsonWriter ();
-
-            datetime_format = DateTimeFormatInfo.InvariantInfo;
-
-            base_exporters_table   = new Dictionary<Type, ExporterFunc> ();
-            custom_exporters_table = new Dictionary<Type, ExporterFunc> ();
-
-            base_importers_table = new Dictionary<Type,
-                                 IDictionary<Type, ImporterFunc>> ();
-            custom_importers_table = new Dictionary<Type,
-                                   IDictionary<Type, ImporterFunc>> ();
-
-            RegisterBaseExporters ();
-            RegisterBaseImporters ();
-        }
-        #endregion
-
-
-        #region Private Methods
-        private static void AddArrayMetadata (Type type)
-        {
-            if (array_metadata.ContainsKey (type))
-                return;
-
-            ArrayMetadata data = new ArrayMetadata ();
-
-            data.IsArray = type.IsArray;
-
-            if (type.GetInterface ("System.Collections.IList") != null)
-                data.IsList = true;
-
-            foreach (PropertyInfo p_info in type.GetProperties ()) {
-                if (p_info.Name != "Item")
-                    continue;
-
-                ParameterInfo[] parameters = p_info.GetIndexParameters ();
-
-                if (parameters.Length != 1)
-                    continue;
-
-                if (parameters[0].ParameterType == typeof (int))
-                    data.ElementType = p_info.PropertyType;
-            }
-
-            lock (array_metadata_lock) {
-                try {
-                    array_metadata.Add (type, data);
-                } catch (ArgumentException) {
-                    return;
-                }
-            }
-        }
-
-        private static void AddObjectMetadata (Type type)
-        {
-            if (object_metadata.ContainsKey (type))
-                return;
-
-            ObjectMetadata data = new ObjectMetadata ();
-
-            if (type.GetInterface ("System.Collections.IDictionary") != null)
-                data.IsDictionary = true;
-
-            data.Properties = new Dictionary<string, PropertyMetadata> ();
-
-            foreach (PropertyInfo p_info in type.GetProperties ()) {
-                if (p_info.Name == "Item") {
-                    ParameterInfo[] parameters = p_info.GetIndexParameters ();
-
-                    if (parameters.Length != 1)
-                        continue;
-
-                    if (parameters[0].ParameterType == typeof (string))
-                        data.ElementType = p_info.PropertyType;
-
-                    continue;
-                }
-
-                PropertyMetadata p_data = new PropertyMetadata ();
-                p_data.Info = p_info;
-                p_data.Type = p_info.PropertyType;
-
-                data.Properties.Add (p_info.Name, p_data);
-            }
-
-            foreach (FieldInfo f_info in type.GetFields ()) {
-                PropertyMetadata p_data = new PropertyMetadata ();
-                p_data.Info = f_info;
-                p_data.IsField = true;
-                p_data.Type = f_info.FieldType;
-
-                data.Properties.Add (f_info.Name, p_data);
-            }
-
-            lock (object_metadata_lock) {
-                try {
-                    object_metadata.Add (type, data);
-                } catch (ArgumentException) {
-                    return;
-                }
-            }
-        }
-
-        private static void AddTypeProperties (Type type)
-        {
-            if (type_properties.ContainsKey (type))
-                return;
-
-            IList<PropertyMetadata> props = new List<PropertyMetadata> ();
-
-            foreach (PropertyInfo p_info in type.GetProperties ()) {
-                if (p_info.Name == "Item")
-                    continue;
-
-                PropertyMetadata p_data = new PropertyMetadata ();
-                p_data.Info = p_info;
-                p_data.IsField = false;
-                props.Add (p_data);
-            }
-
-            foreach (FieldInfo f_info in type.GetFields ()) {
-                PropertyMetadata p_data = new PropertyMetadata ();
-                p_data.Info = f_info;
-                p_data.IsField = true;
-
-                props.Add (p_data);
-            }
-
-            lock (type_properties_lock) {
-                try {
-                    type_properties.Add (type, props);
-                } catch (ArgumentException) {
-                    return;
-                }
-            }
-        }
-
-        private static MethodInfo GetConvOp (Type t1, Type t2)
-        {
-            lock (conv_ops_lock) {
-                if (! conv_ops.ContainsKey (t1))
-                    conv_ops.Add (t1, new Dictionary<Type, MethodInfo> ());
-            }
-
-            if (conv_ops[t1].ContainsKey (t2))
-                return conv_ops[t1][t2];
-
-            MethodInfo op = t1.GetMethod (
-                "op_Implicit", new Type[] { t2 });
-
-            lock (conv_ops_lock) {
-                try {
-                    conv_ops[t1].Add (t2, op);
-                } catch (ArgumentException) {
-                    return conv_ops[t1][t2];
-                }
-            }
-
-            return op;
-        }
-
-        private static object ReadValue (Type inst_type, JsonReader reader)
-        {
-            reader.Read ();
-
-            if (reader.Token == JsonToken.ArrayEnd)
-                return null;
-
-            Type underlying_type = Nullable.GetUnderlyingType(inst_type);
-            Type value_type = underlying_type ?? inst_type;
-
-            if (reader.Token == JsonToken.Null) {
-                #if NETSTANDARD1_5
-                if (inst_type.IsClass() || underlying_type != null) {
-                    return null;
-                }
-                #else
-                if (inst_type.IsClass || underlying_type != null) {
-                    return null;
-                }
-                #endif
-
-                throw new JsonException (String.Format (
-                            "Can't assign null to an instance of type {0}",
-                            inst_type));
-            }
-
-            if (reader.Token == JsonToken.Double ||
-                reader.Token == JsonToken.Int ||
-                reader.Token == JsonToken.Long ||
-                reader.Token == JsonToken.String ||
-                reader.Token == JsonToken.Boolean) {
-
-                Type json_type = reader.Value.GetType ();
-
-                if (value_type.IsAssignableFrom (json_type))
-                    return reader.Value;
-
-                // If there's a custom importer that fits, use it
-                lock (custom_importers_table_lock) {
-                    if (custom_importers_table.TryGetValue(json_type, out IDictionary<Type, ImporterFunc> customImporterTablesValue) &&
-                        customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) {
-
-                        return customImporter(reader.Value);
-                    }
-                }
-
-                // Maybe there's a base importer that works
-                if (base_importers_table.TryGetValue(json_type, out IDictionary<Type, ImporterFunc> baseImporterTablesValue) &&
-                    baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) {
-
-                    return baseImporter(reader.Value);
-                }
-
-                // Maybe it's an enum
-                #if NETSTANDARD1_5
-                if (value_type.IsEnum())
-                    return Enum.ToObject (value_type, reader.Value);
-                #else
-                if (value_type.IsEnum)
-                    return Enum.ToObject (value_type, reader.Value);
-                #endif
-                // Try using an implicit conversion operator
-                MethodInfo conv_op = GetConvOp (value_type, json_type);
-
-                if (conv_op != null)
-                    return conv_op.Invoke (null,
-                                           new object[] { reader.Value });
-
-                // No luck
-                throw new JsonException (String.Format (
-                        "Can't assign value '{0}' (type {1}) to type {2}",
-                        reader.Value, json_type, inst_type));
-            }
-
-            object instance = null;
-
-            if (reader.Token == JsonToken.ArrayStart) {
-
-                AddArrayMetadata (inst_type);
-                ArrayMetadata t_data = array_metadata[inst_type];
-
-                if (! t_data.IsArray && ! t_data.IsList)
-                    throw new JsonException (String.Format (
-                            "Type {0} can't act as an array",
-                            inst_type));
-
-                IList list;
-                Type elem_type;
-
-                if (! t_data.IsArray) {
-                    list = (IList) Activator.CreateInstance (inst_type);
-                    elem_type = t_data.ElementType;
-                } else {
-                    list = new ArrayList ();
-                    elem_type = inst_type.GetElementType ();
-                }
-
-                list.Clear();
-
-                while (true) {
-                    object item = ReadValue (elem_type, reader);
-                    if (item == null && reader.Token == JsonToken.ArrayEnd)
-                        break;
-
-                    list.Add (item);
-                }
-
-                if (t_data.IsArray) {
-                    int n = list.Count;
-                    instance = Array.CreateInstance (elem_type, n);
-
-                    for (int i = 0; i < n; i++)
-                        ((Array) instance).SetValue (list[i], i);
-                } else
-                    instance = list;
-
-            } else if (reader.Token == JsonToken.ObjectStart) {
-                AddObjectMetadata (value_type);
-                ObjectMetadata t_data = object_metadata[value_type];
-
-                instance = Activator.CreateInstance (value_type);
-
-                while (true) {
-                    reader.Read ();
-
-                    if (reader.Token == JsonToken.ObjectEnd)
-                        break;
-
-                    string property = (string) reader.Value;
-
-                    if (t_data.Properties.ContainsKey (property)) {
-                        PropertyMetadata prop_data =
-                            t_data.Properties[property];
-
-                        if (prop_data.IsField) {
-                            ((FieldInfo) prop_data.Info).SetValue (
-                                instance, ReadValue (prop_data.Type, reader));
-                        } else {
-                            PropertyInfo p_info =
-                                (PropertyInfo) prop_data.Info;
-
-                            if (p_info.CanWrite)
-                                p_info.SetValue (
-                                    instance,
-                                    ReadValue (prop_data.Type, reader),
-                                    null);
-                            else
-                                ReadValue (prop_data.Type, reader);
-                        }
-
-                    } else {
-                        if (! t_data.IsDictionary) {
-
-                            if (! reader.SkipNonMembers) {
-                                throw new JsonException (String.Format (
-                                        "The type {0} doesn't have the " +
-                                        "property '{1}'",
-                                        inst_type, property));
-                            } else {
-                                ReadSkip (reader);
-                                continue;
-                            }
-                        }
-
-                        ((IDictionary) instance).Add (
-                            property, ReadValue (
-                                t_data.ElementType, reader));
-                    }
-
-                }
-
-            }
-
-            return instance;
-        }
-
-        private static IJsonWrapper ReadValue (WrapperFactory factory,
-                                               JsonReader reader)
-        {
-            reader.Read ();
-
-            if (reader.Token == JsonToken.ArrayEnd ||
-                reader.Token == JsonToken.Null)
-                return null;
-
-            IJsonWrapper instance = factory ();
-
-            if (reader.Token == JsonToken.String) {
-                instance.SetString ((string) reader.Value);
-                return instance;
-            }
-
-            if (reader.Token == JsonToken.Double) {
-                instance.SetDouble ((double) reader.Value);
-                return instance;
-            }
-
-            if (reader.Token == JsonToken.Int) {
-                instance.SetInt ((int) reader.Value);
-                return instance;
-            }
-
-            if (reader.Token == JsonToken.Long) {
-                instance.SetLong ((long) reader.Value);
-                return instance;
-            }
-
-            if (reader.Token == JsonToken.Boolean) {
-                instance.SetBoolean ((bool) reader.Value);
-                return instance;
-            }
-
-            if (reader.Token == JsonToken.ArrayStart) {
-                instance.SetJsonType (JsonType.Array);
-
-                while (true) {
-                    IJsonWrapper item = ReadValue (factory, reader);
-                    if (item == null && reader.Token == JsonToken.ArrayEnd)
-                        break;
-
-                    ((IList) instance).Add (item);
-                }
-            }
-            else if (reader.Token == JsonToken.ObjectStart) {
-                instance.SetJsonType (JsonType.Object);
-
-                while (true) {
-                    reader.Read ();
-
-                    if (reader.Token == JsonToken.ObjectEnd)
-                        break;
-
-                    string property = (string) reader.Value;
-
-                    ((IDictionary) instance)[property] = ReadValue (
-                        factory, reader);
-                }
-
-            }
-
-            return instance;
-        }
-
-        private static void ReadSkip (JsonReader reader)
-        {
-            ToWrapper (
-                delegate { return new JsonMockWrapper (); }, reader);
-        }
-
-        private static void RegisterBaseExporters ()
-        {
-            // This method is only called from the static initializer,
-            // so there is no need to explicitly lock any static members here
-            base_exporters_table[typeof (byte)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToInt32 ((byte) obj));
-                };
-
-            base_exporters_table[typeof (char)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToString ((char) obj));
-                };
-
-            base_exporters_table[typeof (DateTime)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToString ((DateTime) obj,
-                                                    datetime_format));
-                };
-
-            base_exporters_table[typeof (decimal)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write ((decimal) obj);
-                };
-
-            base_exporters_table[typeof (sbyte)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToInt32 ((sbyte) obj));
-                };
-
-            base_exporters_table[typeof (short)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToInt32 ((short) obj));
-                };
-
-            base_exporters_table[typeof (ushort)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToInt32 ((ushort) obj));
-                };
-
-            base_exporters_table[typeof (uint)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write (Convert.ToUInt64 ((uint) obj));
-                };
-
-            base_exporters_table[typeof (ulong)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write ((ulong) obj);
-                };
-
-            base_exporters_table[typeof(DateTimeOffset)] =
-                delegate (object obj, JsonWriter writer) {
-                    writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format));
-                };
-        }
-
-        private static void RegisterBaseImporters ()
-        {
-            // This method is only called from the static initializer,
-            // so there is no need to explicitly lock any static members here
-            ImporterFunc importer;
-
-            importer = delegate (object input) {
-                return Convert.ToByte ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (byte), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToUInt64 ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (ulong), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToInt64((int)input);
-            };
-            RegisterImporter(base_importers_table, typeof(int),
-                              typeof(long), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToSByte ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (sbyte), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToInt16 ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (short), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToUInt16 ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (ushort), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToUInt32 ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (uint), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToSingle ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (float), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToDouble ((int) input);
-            };
-            RegisterImporter (base_importers_table, typeof (int),
-                              typeof (double), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToDecimal ((double) input);
-            };
-            RegisterImporter (base_importers_table, typeof (double),
-                              typeof (decimal), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToSingle((double)input);
-            };
-            RegisterImporter(base_importers_table, typeof(double),
-                typeof(float), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToUInt32 ((long) input);
-            };
-            RegisterImporter (base_importers_table, typeof (long),
-                              typeof (uint), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToChar ((string) input);
-            };
-            RegisterImporter (base_importers_table, typeof (string),
-                              typeof (char), importer);
-
-            importer = delegate (object input) {
-                return Convert.ToDateTime ((string) input, datetime_format);
-            };
-            RegisterImporter (base_importers_table, typeof (string),
-                              typeof (DateTime), importer);
-
-            importer = delegate (object input) {
-                return DateTimeOffset.Parse((string)input, datetime_format);
-            };
-            RegisterImporter(base_importers_table, typeof(string),
-                typeof(DateTimeOffset), importer);
-        }
-
-        private static void RegisterImporter (
-            IDictionary<Type, IDictionary<Type, ImporterFunc>> table,
-            Type json_type, Type value_type, ImporterFunc importer)
-        {
-            if (! table.ContainsKey (json_type))
-                table.Add (json_type, new Dictionary<Type, ImporterFunc> ());
-
-            table[json_type][value_type] = importer;
-        }
-
-        private static void WriteValue (object obj, JsonWriter writer,
-                                        bool writer_is_private,
-                                        int depth)
-        {
-            if (depth > max_nesting_depth)
-                throw new JsonException (
-                    String.Format ("Max allowed object depth reached while " +
-                                   "trying to export from type {0}",
-                                   obj.GetType ()));
-
-            if (obj == null) {
-                writer.Write (null);
-                return;
-            }
-
-            if (obj is IJsonWrapper) {
-                if (writer_is_private)
-                    writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ());
-                else
-                    ((IJsonWrapper) obj).ToJson (writer);
-
-                return;
-            }
-
-            if (obj is String) {
-                writer.Write ((string) obj);
-                return;
-            }
-
-            if (obj is Double) {
-                writer.Write ((double) obj);
-                return;
-            }
-
-            if (obj is Single)
-            {
-                writer.Write((float)obj);
-                return;
-            }
-
-            if (obj is Int32) {
-                writer.Write ((int) obj);
-                return;
-            }
-
-            if (obj is Boolean) {
-                writer.Write ((bool) obj);
-                return;
-            }
-
-            if (obj is Int64) {
-                writer.Write ((long) obj);
-                return;
-            }
-
-            if (obj is Array) {
-                writer.WriteArrayStart ();
-
-                foreach (object elem in (Array) obj)
-                    WriteValue (elem, writer, writer_is_private, depth + 1);
-
-                writer.WriteArrayEnd ();
-
-                return;
-            }
-
-            if (obj is IList) {
-                writer.WriteArrayStart ();
-                foreach (object elem in (IList) obj)
-                    WriteValue (elem, writer, writer_is_private, depth + 1);
-                writer.WriteArrayEnd ();
-
-                return;
-            }
-
-            if (obj is IDictionary dictionary) {
-                writer.WriteObjectStart ();
-                foreach (DictionaryEntry entry in dictionary) {
-                    var propertyName = entry.Key is string key ?
-                        key
-                        : Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
-                    writer.WritePropertyName (propertyName);
-                    WriteValue (entry.Value, writer, writer_is_private,
-                                depth + 1);
-                }
-                writer.WriteObjectEnd ();
-
-                return;
-            }
-
-            Type obj_type = obj.GetType ();
-
-            // See if there's a custom exporter for the object
-            lock (custom_exporters_table_lock) {
-                if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) {
-                    customExporter(obj, writer);
-
-                    return;
-                }
-            }
-
-            // If not, maybe there's a base exporter
-            if (base_exporters_table.TryGetValue(obj_type, out ExporterFunc baseExporter)) {
-                baseExporter(obj, writer);
-
-                return;
-            }
-
-            // Last option, let's see if it's an enum
-            if (obj is Enum) {
-                Type e_type = Enum.GetUnderlyingType (obj_type);
-
-                if (e_type == typeof (long))
-                    writer.Write ((long) obj);
-                else if (e_type == typeof (uint))
-                    writer.Write ((uint) obj);
-                else if (e_type == typeof (ulong))
-                    writer.Write ((ulong) obj);
-                else if (e_type == typeof(ushort))
-                    writer.Write ((ushort)obj);
-                else if (e_type == typeof(short))
-                    writer.Write ((short)obj);
-                else if (e_type == typeof(byte))
-                    writer.Write ((byte)obj);
-                else if (e_type == typeof(sbyte))
-                    writer.Write ((sbyte)obj);
-                else
-                    writer.Write ((int) obj);
-
-                return;
-            }
-
-            // Okay, so it looks like the input should be exported as an
-            // object
-            AddTypeProperties (obj_type);
-            IList<PropertyMetadata> props = type_properties[obj_type];
-
-            writer.WriteObjectStart ();
-            foreach (PropertyMetadata p_data in props) {
-                if (p_data.IsField) {
-                    writer.WritePropertyName (p_data.Info.Name);
-                    WriteValue (((FieldInfo) p_data.Info).GetValue (obj),
-                                writer, writer_is_private, depth + 1);
-                }
-                else {
-                    PropertyInfo p_info = (PropertyInfo) p_data.Info;
-
-                    if (p_info.CanRead) {
-                        writer.WritePropertyName (p_data.Info.Name);
-                        WriteValue (p_info.GetValue (obj, null),
-                                    writer, writer_is_private, depth + 1);
-                    }
-                }
-            }
-            writer.WriteObjectEnd ();
-        }
-        #endregion
-
-
-        public static string ToJson (object obj)
-        {
-            lock (static_writer_lock) {
-                static_writer.Reset ();
-
-                WriteValue (obj, static_writer, true, 0);
-
-                return static_writer.ToString ();
-            }
-        }
-
-        public static void ToJson (object obj, JsonWriter writer)
-        {
-            WriteValue (obj, writer, false, 0);
-        }
-
-        public static JsonData ToObject (JsonReader reader)
-        {
-            return (JsonData) ToWrapper (
-                delegate { return new JsonData (); }, reader);
-        }
-
-        public static JsonData ToObject (TextReader reader)
-        {
-            JsonReader json_reader = new JsonReader (reader);
-
-            return (JsonData) ToWrapper (
-                delegate { return new JsonData (); }, json_reader);
-        }
-
-        public static JsonData ToObject (string json)
-        {
-            return (JsonData) ToWrapper (
-                delegate { return new JsonData (); }, json);
-        }
-
-        public static T ToObject<T> (JsonReader reader)
-        {
-            return (T) ReadValue (typeof (T), reader);
-        }
-
-        public static T ToObject<T> (TextReader reader)
-        {
-            JsonReader json_reader = new JsonReader (reader);
-
-            return (T) ReadValue (typeof (T), json_reader);
-        }
-
-        public static T ToObject<T> (string json)
-        {
-            JsonReader reader = new JsonReader (json);
-
-            return (T) ReadValue (typeof (T), reader);
-        }
-
-        public static object ToObject(string json, Type ConvertType )
-        {
-            JsonReader reader = new JsonReader(json);
-
-            return ReadValue(ConvertType, reader);
-        }
-
-        public static IJsonWrapper ToWrapper (WrapperFactory factory,
-                                              JsonReader reader)
-        {
-            return ReadValue (factory, reader);
-        }
-
-        public static IJsonWrapper ToWrapper (WrapperFactory factory,
-                                              string json)
-        {
-            JsonReader reader = new JsonReader (json);
-
-            return ReadValue (factory, reader);
-        }
-
-        public static void RegisterExporter<T> (ExporterFunc<T> exporter)
-        {
-            ExporterFunc exporter_wrapper =
-                delegate (object obj, JsonWriter writer) {
-                    exporter ((T) obj, writer);
-                };
-
-            lock (custom_exporters_table_lock) { 
-                custom_exporters_table[typeof (T)] = exporter_wrapper;
-            }
-        }
-
-        public static void RegisterImporter<TJson, TValue> (
-            ImporterFunc<TJson, TValue> importer)
-        {
-            ImporterFunc importer_wrapper =
-                delegate (object input) {
-                    return importer ((TJson) input);
-                };
-
-            lock (custom_importers_table_lock) {
-                RegisterImporter (custom_importers_table, typeof (TJson),
-                                 typeof (TValue), importer_wrapper);
-            }
-        }
-
-        public static void UnregisterExporters ()
-        {
-            lock (custom_exporters_table_lock) {
-                custom_exporters_table.Clear();
-            }
-        }
-
-        public static void UnregisterImporters ()
-        {
-            lock (custom_importers_table_lock) {
-                custom_importers_table.Clear();
-            }
-        }
-    }
-}
diff --git a/Main/Common/LitJson/JsonMapper.cs.meta b/Main/Common/LitJson/JsonMapper.cs.meta
deleted file mode 100644
index 345341a..0000000
--- a/Main/Common/LitJson/JsonMapper.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: c2a82b623add47f4b861ffdf072e7e73
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonMockWrapper.cs b/Main/Common/LitJson/JsonMockWrapper.cs
deleted file mode 100644
index dfe7adb..0000000
--- a/Main/Common/LitJson/JsonMockWrapper.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-#region Header
-/**
- * JsonMockWrapper.cs
- *   Mock object implementing IJsonWrapper, to facilitate actions like
- *   skipping data more efficiently.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-
-
-namespace LitJson
-{
-    public class JsonMockWrapper : IJsonWrapper
-    {
-        public bool IsArray   { get { return false; } }
-        public bool IsBoolean { get { return false; } }
-        public bool IsDouble  { get { return false; } }
-        public bool IsInt     { get { return false; } }
-        public bool IsLong    { get { return false; } }
-        public bool IsObject  { get { return false; } }
-        public bool IsString  { get { return false; } }
-
-        public bool     GetBoolean ()  { return false; }
-        public double   GetDouble ()   { return 0.0; }
-        public int      GetInt ()      { return 0; }
-        public JsonType GetJsonType () { return JsonType.None; }
-        public long     GetLong ()     { return 0L; }
-        public string   GetString ()   { return ""; }
-
-        public void SetBoolean  (bool val)      {}
-        public void SetDouble   (double val)    {}
-        public void SetInt      (int val)       {}
-        public void SetJsonType (JsonType type) {}
-        public void SetLong     (long val)      {}
-        public void SetString   (string val)    {}
-
-        public string ToJson ()                  { return ""; }
-        public void   ToJson (JsonWriter writer) {}
-
-
-        bool IList.IsFixedSize { get { return true; } }
-        bool IList.IsReadOnly  { get { return true; } }
-
-        object IList.this[int index] {
-            get { return null; }
-            set {}
-        }
-
-        int  IList.Add (object value)       { return 0; }
-        void IList.Clear ()                 {}
-        bool IList.Contains (object value)  { return false; }
-        int  IList.IndexOf (object value)   { return -1; }
-        void IList.Insert (int i, object v) {}
-        void IList.Remove (object value)    {}
-        void IList.RemoveAt (int index)     {}
-
-
-        int    ICollection.Count          { get { return 0; } }
-        bool   ICollection.IsSynchronized { get { return false; } }
-        object ICollection.SyncRoot       { get { return null; } }
-
-        void ICollection.CopyTo (Array array, int index) {}
-
-
-        IEnumerator IEnumerable.GetEnumerator () { return null; }
-
-
-        bool IDictionary.IsFixedSize { get { return true; } }
-        bool IDictionary.IsReadOnly  { get { return true; } }
-
-        ICollection IDictionary.Keys   { get { return null; } }
-        ICollection IDictionary.Values { get { return null; } }
-
-        object IDictionary.this[object key] {
-            get { return null; }
-            set {}
-        }
-
-        void IDictionary.Add (object k, object v) {}
-        void IDictionary.Clear ()                 {}
-        bool IDictionary.Contains (object key)    { return false; }
-        void IDictionary.Remove (object key)      {}
-
-        IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
-
-
-        object IOrderedDictionary.this[int idx] {
-            get { return null; }
-            set {}
-        }
-
-        IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
-            return null;
-        }
-        void IOrderedDictionary.Insert   (int i, object k, object v) {}
-        void IOrderedDictionary.RemoveAt (int i) {}
-    }
-}
diff --git a/Main/Common/LitJson/JsonMockWrapper.cs.meta b/Main/Common/LitJson/JsonMockWrapper.cs.meta
deleted file mode 100644
index 4aeb212..0000000
--- a/Main/Common/LitJson/JsonMockWrapper.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: fcd0c88788b3d3548aaaadda98570f82
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonReader.cs b/Main/Common/LitJson/JsonReader.cs
deleted file mode 100644
index e47eabc..0000000
--- a/Main/Common/LitJson/JsonReader.cs
+++ /dev/null
@@ -1,478 +0,0 @@
-#region Header
-/**
- * JsonReader.cs
- *   Stream-like access to JSON text.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Text;
-
-
-namespace LitJson
-{
-    public enum JsonToken
-    {
-        None,
-
-        ObjectStart,
-        PropertyName,
-        ObjectEnd,
-
-        ArrayStart,
-        ArrayEnd,
-
-        Int,
-        Long,
-        Double,
-
-        String,
-
-        Boolean,
-        Null
-    }
-
-
-    public class JsonReader
-    {
-        #region Fields
-        private static readonly IDictionary<int, IDictionary<int, int[]>> parse_table;
-
-        private Stack<int>    automaton_stack;
-        private int           current_input;
-        private int           current_symbol;
-        private bool          end_of_json;
-        private bool          end_of_input;
-        private Lexer         lexer;
-        private bool          parser_in_string;
-        private bool          parser_return;
-        private bool          read_started;
-        private TextReader    reader;
-        private bool          reader_is_owned;
-        private bool          skip_non_members;
-        private object        token_value;
-        private JsonToken     token;
-        #endregion
-
-
-        #region Public Properties
-        public bool AllowComments {
-            get { return lexer.AllowComments; }
-            set { lexer.AllowComments = value; }
-        }
-
-        public bool AllowSingleQuotedStrings {
-            get { return lexer.AllowSingleQuotedStrings; }
-            set { lexer.AllowSingleQuotedStrings = value; }
-        }
-
-        public bool SkipNonMembers {
-            get { return skip_non_members; }
-            set { skip_non_members = value; }
-        }
-
-        public bool EndOfInput {
-            get { return end_of_input; }
-        }
-
-        public bool EndOfJson {
-            get { return end_of_json; }
-        }
-
-        public JsonToken Token {
-            get { return token; }
-        }
-
-        public object Value {
-            get { return token_value; }
-        }
-        #endregion
-
-
-        #region Constructors
-        static JsonReader ()
-        {
-            parse_table = PopulateParseTable ();
-        }
-
-        public JsonReader (string json_text) :
-            this (new StringReader (json_text), true)
-        {
-        }
-
-        public JsonReader (TextReader reader) :
-            this (reader, false)
-        {
-        }
-
-        private JsonReader (TextReader reader, bool owned)
-        {
-            if (reader == null)
-                throw new ArgumentNullException ("reader");
-
-            parser_in_string = false;
-            parser_return    = false;
-
-            read_started = false;
-            automaton_stack = new Stack<int> ();
-            automaton_stack.Push ((int) ParserToken.End);
-            automaton_stack.Push ((int) ParserToken.Text);
-
-            lexer = new Lexer (reader);
-
-            end_of_input = false;
-            end_of_json  = false;
-
-            skip_non_members = true;
-
-            this.reader = reader;
-            reader_is_owned = owned;
-        }
-        #endregion
-
-
-        #region Static Methods
-        private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable ()
-        {
-            // See section A.2. of the manual for details
-            IDictionary<int, IDictionary<int, int[]>> parse_table = new Dictionary<int, IDictionary<int, int[]>> ();
-
-            TableAddRow (parse_table, ParserToken.Array);
-            TableAddCol (parse_table, ParserToken.Array, '[',
-                            '[',
-                            (int) ParserToken.ArrayPrime);
-
-            TableAddRow (parse_table, ParserToken.ArrayPrime);
-            TableAddCol (parse_table, ParserToken.ArrayPrime, '"',
-                            (int) ParserToken.Value,
-
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, '[',
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, ']',
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, '{',
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number,
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True,
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False,
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null,
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest,
-                            ']');
-
-            TableAddRow (parse_table, ParserToken.Object);
-            TableAddCol (parse_table, ParserToken.Object, '{',
-                            '{',
-                            (int) ParserToken.ObjectPrime);
-
-            TableAddRow (parse_table, ParserToken.ObjectPrime);
-            TableAddCol (parse_table, ParserToken.ObjectPrime, '"',
-                            (int) ParserToken.Pair,
-                            (int) ParserToken.PairRest,
-                            '}');
-            TableAddCol (parse_table, ParserToken.ObjectPrime, '}',
-                            '}');
-
-            TableAddRow (parse_table, ParserToken.Pair);
-            TableAddCol (parse_table, ParserToken.Pair, '"',
-                            (int) ParserToken.String,
-                            ':',
-                            (int) ParserToken.Value);
-
-            TableAddRow (parse_table, ParserToken.PairRest);
-            TableAddCol (parse_table, ParserToken.PairRest, ',',
-                            ',',
-                            (int) ParserToken.Pair,
-                            (int) ParserToken.PairRest);
-            TableAddCol (parse_table, ParserToken.PairRest, '}',
-                            (int) ParserToken.Epsilon);
-
-            TableAddRow (parse_table, ParserToken.String);
-            TableAddCol (parse_table, ParserToken.String, '"',
-                            '"',
-                            (int) ParserToken.CharSeq,
-                            '"');
-
-            TableAddRow (parse_table, ParserToken.Text);
-            TableAddCol (parse_table, ParserToken.Text, '[',
-                            (int) ParserToken.Array);
-            TableAddCol (parse_table, ParserToken.Text, '{',
-                            (int) ParserToken.Object);
-
-            TableAddRow (parse_table, ParserToken.Value);
-            TableAddCol (parse_table, ParserToken.Value, '"',
-                            (int) ParserToken.String);
-            TableAddCol (parse_table, ParserToken.Value, '[',
-                            (int) ParserToken.Array);
-            TableAddCol (parse_table, ParserToken.Value, '{',
-                            (int) ParserToken.Object);
-            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number,
-                            (int) ParserToken.Number);
-            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True,
-                            (int) ParserToken.True);
-            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False,
-                            (int) ParserToken.False);
-            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null,
-                            (int) ParserToken.Null);
-
-            TableAddRow (parse_table, ParserToken.ValueRest);
-            TableAddCol (parse_table, ParserToken.ValueRest, ',',
-                            ',',
-                            (int) ParserToken.Value,
-                            (int) ParserToken.ValueRest);
-            TableAddCol (parse_table, ParserToken.ValueRest, ']',
-                            (int) ParserToken.Epsilon);
-
-            return parse_table;
-        }
-
-        private static void TableAddCol (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken row, int col,
-                                         params int[] symbols)
-        {
-            parse_table[(int) row].Add (col, symbols);
-        }
-
-        private static void TableAddRow (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken rule)
-        {
-            parse_table.Add ((int) rule, new Dictionary<int, int[]> ());
-        }
-        #endregion
-
-
-        #region Private Methods
-        private void ProcessNumber (string number)
-        {
-            if (number.IndexOf ('.') != -1 ||
-                number.IndexOf ('e') != -1 ||
-                number.IndexOf ('E') != -1) {
-
-                double n_double;
-                if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) {
-                    token = JsonToken.Double;
-                    token_value = n_double;
-
-                    return;
-                }
-            }
-
-            int n_int32;
-            if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) {
-                token = JsonToken.Int;
-                token_value = n_int32;
-
-                return;
-            }
-
-            long n_int64;
-            if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) {
-                token = JsonToken.Long;
-                token_value = n_int64;
-
-                return;
-            }
-
-            ulong n_uint64;
-            if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64))
-            {
-                token = JsonToken.Long;
-                token_value = n_uint64;
-
-                return;
-            }
-
-            // Shouldn't happen, but just in case, return something
-            token = JsonToken.Int;
-            token_value = 0;
-        }
-
-        private void ProcessSymbol ()
-        {
-            if (current_symbol == '[')  {
-                token = JsonToken.ArrayStart;
-                parser_return = true;
-
-            } else if (current_symbol == ']')  {
-                token = JsonToken.ArrayEnd;
-                parser_return = true;
-
-            } else if (current_symbol == '{')  {
-                token = JsonToken.ObjectStart;
-                parser_return = true;
-
-            } else if (current_symbol == '}')  {
-                token = JsonToken.ObjectEnd;
-                parser_return = true;
-
-            } else if (current_symbol == '"')  {
-                if (parser_in_string) {
-                    parser_in_string = false;
-
-                    parser_return = true;
-
-                } else {
-                    if (token == JsonToken.None)
-                        token = JsonToken.String;
-
-                    parser_in_string = true;
-                }
-
-            } else if (current_symbol == (int) ParserToken.CharSeq) {
-                token_value = lexer.StringValue;
-
-            } else if (current_symbol == (int) ParserToken.False)  {
-                token = JsonToken.Boolean;
-                token_value = false;
-                parser_return = true;
-
-            } else if (current_symbol == (int) ParserToken.Null)  {
-                token = JsonToken.Null;
-                parser_return = true;
-
-            } else if (current_symbol == (int) ParserToken.Number)  {
-                ProcessNumber (lexer.StringValue);
-
-                parser_return = true;
-
-            } else if (current_symbol == (int) ParserToken.Pair)  {
-                token = JsonToken.PropertyName;
-
-            } else if (current_symbol == (int) ParserToken.True)  {
-                token = JsonToken.Boolean;
-                token_value = true;
-                parser_return = true;
-
-            }
-        }
-
-        private bool ReadToken ()
-        {
-            if (end_of_input)
-                return false;
-
-            lexer.NextToken ();
-
-            if (lexer.EndOfInput) {
-                Close ();
-
-                return false;
-            }
-
-            current_input = lexer.Token;
-
-            return true;
-        }
-        #endregion
-
-
-        public void Close ()
-        {
-            if (end_of_input)
-                return;
-
-            end_of_input = true;
-            end_of_json  = true;
-
-            if (reader_is_owned)
-            {
-                using(reader){}
-            }
-
-            reader = null;
-        }
-
-        public bool Read ()
-        {
-            if (end_of_input)
-                return false;
-
-            if (end_of_json) {
-                end_of_json = false;
-                automaton_stack.Clear ();
-                automaton_stack.Push ((int) ParserToken.End);
-                automaton_stack.Push ((int) ParserToken.Text);
-            }
-
-            parser_in_string = false;
-            parser_return    = false;
-
-            token       = JsonToken.None;
-            token_value = null;
-
-            if (! read_started) {
-                read_started = true;
-
-                if (! ReadToken ())
-                    return false;
-            }
-
-
-            int[] entry_symbols;
-
-            while (true) {
-                if (parser_return) {
-                    if (automaton_stack.Peek () == (int) ParserToken.End)
-                        end_of_json = true;
-
-                    return true;
-                }
-
-                current_symbol = automaton_stack.Pop ();
-
-                ProcessSymbol ();
-
-                if (current_symbol == current_input) {
-                    if (! ReadToken ()) {
-                        if (automaton_stack.Peek () != (int) ParserToken.End)
-                            throw new JsonException (
-                                "Input doesn't evaluate to proper JSON text");
-
-                        if (parser_return)
-                            return true;
-
-                        return false;
-                    }
-
-                    continue;
-                }
-
-                try {
-
-                    entry_symbols =
-                        parse_table[current_symbol][current_input];
-
-                } catch (KeyNotFoundException e) {
-                    throw new JsonException ((ParserToken) current_input, e);
-                }
-
-                if (entry_symbols[0] == (int) ParserToken.Epsilon)
-                    continue;
-
-                for (int i = entry_symbols.Length - 1; i >= 0; i--)
-                    automaton_stack.Push (entry_symbols[i]);
-            }
-        }
-
-    }
-}
diff --git a/Main/Common/LitJson/JsonReader.cs.meta b/Main/Common/LitJson/JsonReader.cs.meta
deleted file mode 100644
index d231136..0000000
--- a/Main/Common/LitJson/JsonReader.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: ab4ffde22b1fefb41900344a190ab56e
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/JsonWriter.cs b/Main/Common/LitJson/JsonWriter.cs
deleted file mode 100644
index 4bfaaac..0000000
--- a/Main/Common/LitJson/JsonWriter.cs
+++ /dev/null
@@ -1,484 +0,0 @@
-#region Header
-/**
- * JsonWriter.cs
- *   Stream-like facility to output JSON text.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Text;
-
-
-namespace LitJson
-{
-    internal enum Condition
-    {
-        InArray,
-        InObject,
-        NotAProperty,
-        Property,
-        Value
-    }
-
-    internal class WriterContext
-    {
-        public int  Count;
-        public bool InArray;
-        public bool InObject;
-        public bool ExpectingValue;
-        public int  Padding;
-    }
-
-    public class JsonWriter
-    {
-        #region Fields
-        private static readonly NumberFormatInfo number_format;
-
-        private WriterContext        context;
-        private Stack<WriterContext> ctx_stack;
-        private bool                 has_reached_end;
-        private char[]               hex_seq;
-        private int                  indentation;
-        private int                  indent_value;
-        private StringBuilder        inst_string_builder;
-        private bool                 pretty_print;
-        private bool                 validate;
-        private bool                 lower_case_properties;
-        private TextWriter           writer;
-        #endregion
-
-
-        #region Properties
-        public int IndentValue {
-            get { return indent_value; }
-            set {
-                indentation = (indentation / indent_value) * value;
-                indent_value = value;
-            }
-        }
-
-        public bool PrettyPrint {
-            get { return pretty_print; }
-            set { pretty_print = value; }
-        }
-
-        public TextWriter TextWriter {
-            get { return writer; }
-        }
-
-        public bool Validate {
-            get { return validate; }
-            set { validate = value; }
-        }
-
-        public bool LowerCaseProperties {
-            get { return lower_case_properties; }
-            set { lower_case_properties = value; }
-        }
-        #endregion
-
-
-        #region Constructors
-        static JsonWriter ()
-        {
-            number_format = NumberFormatInfo.InvariantInfo;
-        }
-
-        public JsonWriter ()
-        {
-            inst_string_builder = new StringBuilder ();
-            writer = new StringWriter (inst_string_builder);
-
-            Init ();
-        }
-
-        public JsonWriter (StringBuilder sb) :
-            this (new StringWriter (sb))
-        {
-        }
-
-        public JsonWriter (TextWriter writer)
-        {
-            if (writer == null)
-                throw new ArgumentNullException ("writer");
-
-            this.writer = writer;
-
-            Init ();
-        }
-        #endregion
-
-
-        #region Private Methods
-        private void DoValidation (Condition cond)
-        {
-            if (! context.ExpectingValue)
-                context.Count++;
-
-            if (! validate)
-                return;
-
-            if (has_reached_end)
-                throw new JsonException (
-                    "A complete JSON symbol has already been written");
-
-            switch (cond) {
-            case Condition.InArray:
-                if (! context.InArray)
-                    throw new JsonException (
-                        "Can't close an array here");
-                break;
-
-            case Condition.InObject:
-                if (! context.InObject || context.ExpectingValue)
-                    throw new JsonException (
-                        "Can't close an object here");
-                break;
-
-            case Condition.NotAProperty:
-                if (context.InObject && ! context.ExpectingValue)
-                    throw new JsonException (
-                        "Expected a property");
-                break;
-
-            case Condition.Property:
-                if (! context.InObject || context.ExpectingValue)
-                    throw new JsonException (
-                        "Can't add a property here");
-                break;
-
-            case Condition.Value:
-                if (! context.InArray &&
-                    (! context.InObject || ! context.ExpectingValue))
-                    throw new JsonException (
-                        "Can't add a value here");
-
-                break;
-            }
-        }
-
-        private void Init ()
-        {
-            has_reached_end = false;
-            hex_seq = new char[4];
-            indentation = 0;
-            indent_value = 4;
-            pretty_print = false;
-            validate = true;
-            lower_case_properties = false;
-
-            ctx_stack = new Stack<WriterContext> ();
-            context = new WriterContext ();
-            ctx_stack.Push (context);
-        }
-
-        private static void IntToHex (int n, char[] hex)
-        {
-            int num;
-
-            for (int i = 0; i < 4; i++) {
-                num = n % 16;
-
-                if (num < 10)
-                    hex[3 - i] = (char) ('0' + num);
-                else
-                    hex[3 - i] = (char) ('A' + (num - 10));
-
-                n >>= 4;
-            }
-        }
-
-        private void Indent ()
-        {
-            if (pretty_print)
-                indentation += indent_value;
-        }
-
-
-        private void Put (string str)
-        {
-            if (pretty_print && ! context.ExpectingValue)
-                for (int i = 0; i < indentation; i++)
-                    writer.Write (' ');
-
-            writer.Write (str);
-        }
-
-        private void PutNewline ()
-        {
-            PutNewline (true);
-        }
-
-        private void PutNewline (bool add_comma)
-        {
-            if (add_comma && ! context.ExpectingValue &&
-                context.Count > 1)
-                writer.Write (',');
-
-            if (pretty_print && ! context.ExpectingValue)
-                writer.Write (Environment.NewLine);
-        }
-
-        private void PutString (string str)
-        {
-            Put (String.Empty);
-
-            writer.Write ('"');
-
-            int n = str.Length;
-            for (int i = 0; i < n; i++) {
-                switch (str[i]) {
-                case '\n':
-                    writer.Write ("\\n");
-                    continue;
-
-                case '\r':
-                    writer.Write ("\\r");
-                    continue;
-
-                case '\t':
-                    writer.Write ("\\t");
-                    continue;
-
-                case '"':
-                case '\\':
-                    writer.Write ('\\');
-                    writer.Write (str[i]);
-                    continue;
-
-                case '\f':
-                    writer.Write ("\\f");
-                    continue;
-
-                case '\b':
-                    writer.Write ("\\b");
-                    continue;
-                }
-
-                if ((int) str[i] >= 32 && (int) str[i] <= 126) {
-                    writer.Write (str[i]);
-                    continue;
-                }
-
-                // Default, turn into a \uXXXX sequence
-                IntToHex ((int) str[i], hex_seq);
-                writer.Write ("\\u");
-                writer.Write (hex_seq);
-            }
-
-            writer.Write ('"');
-        }
-
-        private void Unindent ()
-        {
-            if (pretty_print)
-                indentation -= indent_value;
-        }
-        #endregion
-
-
-        public override string ToString ()
-        {
-            if (inst_string_builder == null)
-                return String.Empty;
-
-            return inst_string_builder.ToString ();
-        }
-
-        public void Reset ()
-        {
-            has_reached_end = false;
-
-            ctx_stack.Clear ();
-            context = new WriterContext ();
-            ctx_stack.Push (context);
-
-            if (inst_string_builder != null)
-                inst_string_builder.Remove (0, inst_string_builder.Length);
-        }
-
-        public void Write (bool boolean)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            Put (boolean ? "true" : "false");
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write (decimal number)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            Put (Convert.ToString (number, number_format));
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write (double number)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            string str = Convert.ToString (number, number_format);
-            Put (str);
-
-            if (str.IndexOf ('.') == -1 &&
-                str.IndexOf ('E') == -1)
-                writer.Write (".0");
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write(float number)
-        {
-            DoValidation(Condition.Value);
-            PutNewline();
-
-            string str = Convert.ToString(number, number_format);
-            Put(str);
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write (int number)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            Put (Convert.ToString (number, number_format));
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write (long number)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            Put (Convert.ToString (number, number_format));
-
-            context.ExpectingValue = false;
-        }
-
-        public void Write (string str)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            if (str == null)
-                Put ("null");
-            else
-                PutString (str);
-
-            context.ExpectingValue = false;
-        }
-
-        [CLSCompliant(false)]
-        public void Write (ulong number)
-        {
-            DoValidation (Condition.Value);
-            PutNewline ();
-
-            Put (Convert.ToString (number, number_format));
-
-            context.ExpectingValue = false;
-        }
-
-        public void WriteArrayEnd ()
-        {
-            DoValidation (Condition.InArray);
-            PutNewline (false);
-
-            ctx_stack.Pop ();
-            if (ctx_stack.Count == 1)
-                has_reached_end = true;
-            else {
-                context = ctx_stack.Peek ();
-                context.ExpectingValue = false;
-            }
-
-            Unindent ();
-            Put ("]");
-        }
-
-        public void WriteArrayStart ()
-        {
-            DoValidation (Condition.NotAProperty);
-            PutNewline ();
-
-            Put ("[");
-
-            context = new WriterContext ();
-            context.InArray = true;
-            ctx_stack.Push (context);
-
-            Indent ();
-        }
-
-        public void WriteObjectEnd ()
-        {
-            DoValidation (Condition.InObject);
-            PutNewline (false);
-
-            ctx_stack.Pop ();
-            if (ctx_stack.Count == 1)
-                has_reached_end = true;
-            else {
-                context = ctx_stack.Peek ();
-                context.ExpectingValue = false;
-            }
-
-            Unindent ();
-            Put ("}");
-        }
-
-        public void WriteObjectStart ()
-        {
-            DoValidation (Condition.NotAProperty);
-            PutNewline ();
-
-            Put ("{");
-
-            context = new WriterContext ();
-            context.InObject = true;
-            ctx_stack.Push (context);
-
-            Indent ();
-        }
-
-        public void WritePropertyName (string property_name)
-        {
-            DoValidation (Condition.Property);
-            PutNewline ();
-            string propertyName = (property_name == null || !lower_case_properties)
-                ? property_name
-                : property_name.ToLowerInvariant();
-
-            PutString (propertyName);
-
-            if (pretty_print) {
-                if (propertyName.Length > context.Padding)
-                    context.Padding = propertyName.Length;
-
-                for (int i = context.Padding - propertyName.Length;
-                     i >= 0; i--)
-                    writer.Write (' ');
-
-                writer.Write (": ");
-            } else
-                writer.Write (':');
-
-            context.ExpectingValue = true;
-        }
-    }
-}
diff --git a/Main/Common/LitJson/JsonWriter.cs.meta b/Main/Common/LitJson/JsonWriter.cs.meta
deleted file mode 100644
index feb35a1..0000000
--- a/Main/Common/LitJson/JsonWriter.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7ef909f080345c44a8305ebd799ba7ce
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/Lexer.cs b/Main/Common/LitJson/Lexer.cs
deleted file mode 100644
index cb62d55..0000000
--- a/Main/Common/LitJson/Lexer.cs
+++ /dev/null
@@ -1,912 +0,0 @@
-#region Header
-/**
- * Lexer.cs
- *   JSON lexer implementation based on a finite state machine.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-
-namespace LitJson
-{
-    internal class FsmContext
-    {
-        public bool  Return;
-        public int   NextState;
-        public Lexer L;
-        public int   StateStack;
-    }
-
-
-    internal class Lexer
-    {
-        #region Fields
-        private delegate bool StateHandler (FsmContext ctx);
-
-        private static readonly int[]          fsm_return_table;
-        private static readonly StateHandler[] fsm_handler_table;
-
-        private bool          allow_comments;
-        private bool          allow_single_quoted_strings;
-        private bool          end_of_input;
-        private FsmContext    fsm_context;
-        private int           input_buffer;
-        private int           input_char;
-        private TextReader    reader;
-        private int           state;
-        private StringBuilder string_buffer;
-        private string        string_value;
-        private int           token;
-        private int           unichar;
-        #endregion
-
-
-        #region Properties
-        public bool AllowComments {
-            get { return allow_comments; }
-            set { allow_comments = value; }
-        }
-
-        public bool AllowSingleQuotedStrings {
-            get { return allow_single_quoted_strings; }
-            set { allow_single_quoted_strings = value; }
-        }
-
-        public bool EndOfInput {
-            get { return end_of_input; }
-        }
-
-        public int Token {
-            get { return token; }
-        }
-
-        public string StringValue {
-            get { return string_value; }
-        }
-        #endregion
-
-
-        #region Constructors
-        static Lexer ()
-        {
-            PopulateFsmTables (out fsm_handler_table, out fsm_return_table);
-        }
-
-        public Lexer (TextReader reader)
-        {
-            allow_comments = true;
-            allow_single_quoted_strings = true;
-
-            input_buffer = 0;
-            string_buffer = new StringBuilder (128);
-            state = 1;
-            end_of_input = false;
-            this.reader = reader;
-
-            fsm_context = new FsmContext ();
-            fsm_context.L = this;
-        }
-        #endregion
-
-
-        #region Static Methods
-        private static int HexValue (int digit)
-        {
-            switch (digit) {
-            case 'a':
-            case 'A':
-                return 10;
-
-            case 'b':
-            case 'B':
-                return 11;
-
-            case 'c':
-            case 'C':
-                return 12;
-
-            case 'd':
-            case 'D':
-                return 13;
-
-            case 'e':
-            case 'E':
-                return 14;
-
-            case 'f':
-            case 'F':
-                return 15;
-
-            default:
-                return digit - '0';
-            }
-        }
-
-        private static void PopulateFsmTables (out StateHandler[] fsm_handler_table, out int[] fsm_return_table)
-        {
-            // See section A.1. of the manual for details of the finite
-            // state machine.
-            fsm_handler_table = new StateHandler[28] {
-                State1,
-                State2,
-                State3,
-                State4,
-                State5,
-                State6,
-                State7,
-                State8,
-                State9,
-                State10,
-                State11,
-                State12,
-                State13,
-                State14,
-                State15,
-                State16,
-                State17,
-                State18,
-                State19,
-                State20,
-                State21,
-                State22,
-                State23,
-                State24,
-                State25,
-                State26,
-                State27,
-                State28
-            };
-
-            fsm_return_table = new int[28] {
-                (int) ParserToken.Char,
-                0,
-                (int) ParserToken.Number,
-                (int) ParserToken.Number,
-                0,
-                (int) ParserToken.Number,
-                0,
-                (int) ParserToken.Number,
-                0,
-                0,
-                (int) ParserToken.True,
-                0,
-                0,
-                0,
-                (int) ParserToken.False,
-                0,
-                0,
-                (int) ParserToken.Null,
-                (int) ParserToken.CharSeq,
-                (int) ParserToken.Char,
-                0,
-                0,
-                (int) ParserToken.CharSeq,
-                (int) ParserToken.Char,
-                0,
-                0,
-                0,
-                0
-            };
-        }
-
-        private static char ProcessEscChar (int esc_char)
-        {
-            switch (esc_char) {
-            case '"':
-            case '\'':
-            case '\\':
-            case '/':
-                return Convert.ToChar (esc_char);
-
-            case 'n':
-                return '\n';
-
-            case 't':
-                return '\t';
-
-            case 'r':
-                return '\r';
-
-            case 'b':
-                return '\b';
-
-            case 'f':
-                return '\f';
-
-            default:
-                // Unreachable
-                return '?';
-            }
-        }
-
-        private static bool State1 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char == ' ' ||
-                    ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
-                    continue;
-
-                if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') {
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 3;
-                    return true;
-                }
-
-                switch (ctx.L.input_char) {
-                case '"':
-                    ctx.NextState = 19;
-                    ctx.Return = true;
-                    return true;
-
-                case ',':
-                case ':':
-                case '[':
-                case ']':
-                case '{':
-                case '}':
-                    ctx.NextState = 1;
-                    ctx.Return = true;
-                    return true;
-
-                case '-':
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 2;
-                    return true;
-
-                case '0':
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 4;
-                    return true;
-
-                case 'f':
-                    ctx.NextState = 12;
-                    return true;
-
-                case 'n':
-                    ctx.NextState = 16;
-                    return true;
-
-                case 't':
-                    ctx.NextState = 9;
-                    return true;
-
-                case '\'':
-                    if (! ctx.L.allow_single_quoted_strings)
-                        return false;
-
-                    ctx.L.input_char = '"';
-                    ctx.NextState = 23;
-                    ctx.Return = true;
-                    return true;
-
-                case '/':
-                    if (! ctx.L.allow_comments)
-                        return false;
-
-                    ctx.NextState = 25;
-                    return true;
-
-                default:
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State2 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') {
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 3;
-                return true;
-            }
-
-            switch (ctx.L.input_char) {
-            case '0':
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 4;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State3 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    continue;
-                }
-
-                if (ctx.L.input_char == ' ' ||
-                    ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-                }
-
-                switch (ctx.L.input_char) {
-                case ',':
-                case ']':
-                case '}':
-                    ctx.L.UngetChar ();
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-
-                case '.':
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 5;
-                    return true;
-
-                case 'e':
-                case 'E':
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 7;
-                    return true;
-
-                default:
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        private static bool State4 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            if (ctx.L.input_char == ' ' ||
-                ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-            }
-
-            switch (ctx.L.input_char) {
-            case ',':
-            case ']':
-            case '}':
-                ctx.L.UngetChar ();
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            case '.':
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 5;
-                return true;
-
-            case 'e':
-            case 'E':
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 7;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State5 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 6;
-                return true;
-            }
-
-            return false;
-        }
-
-        private static bool State6 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    continue;
-                }
-
-                if (ctx.L.input_char == ' ' ||
-                    ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-                }
-
-                switch (ctx.L.input_char) {
-                case ',':
-                case ']':
-                case '}':
-                    ctx.L.UngetChar ();
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-
-                case 'e':
-                case 'E':
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    ctx.NextState = 7;
-                    return true;
-
-                default:
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State7 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 8;
-                return true;
-            }
-
-            switch (ctx.L.input_char) {
-            case '+':
-            case '-':
-                ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                ctx.NextState = 8;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State8 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    continue;
-                }
-
-                if (ctx.L.input_char == ' ' ||
-                    ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') {
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-                }
-
-                switch (ctx.L.input_char) {
-                case ',':
-                case ']':
-                case '}':
-                    ctx.L.UngetChar ();
-                    ctx.Return = true;
-                    ctx.NextState = 1;
-                    return true;
-
-                default:
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State9 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'r':
-                ctx.NextState = 10;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State10 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'u':
-                ctx.NextState = 11;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State11 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'e':
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State12 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'a':
-                ctx.NextState = 13;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State13 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'l':
-                ctx.NextState = 14;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State14 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 's':
-                ctx.NextState = 15;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State15 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'e':
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State16 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'u':
-                ctx.NextState = 17;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State17 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'l':
-                ctx.NextState = 18;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State18 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'l':
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State19 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                switch (ctx.L.input_char) {
-                case '"':
-                    ctx.L.UngetChar ();
-                    ctx.Return = true;
-                    ctx.NextState = 20;
-                    return true;
-
-                case '\\':
-                    ctx.StateStack = 19;
-                    ctx.NextState = 21;
-                    return true;
-
-                default:
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    continue;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State20 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case '"':
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State21 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case 'u':
-                ctx.NextState = 22;
-                return true;
-
-            case '"':
-            case '\'':
-            case '/':
-            case '\\':
-            case 'b':
-            case 'f':
-            case 'n':
-            case 'r':
-            case 't':
-                ctx.L.string_buffer.Append (
-                    ProcessEscChar (ctx.L.input_char));
-                ctx.NextState = ctx.StateStack;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State22 (FsmContext ctx)
-        {
-            int counter = 0;
-            int mult    = 4096;
-
-            ctx.L.unichar = 0;
-
-            while (ctx.L.GetChar ()) {
-
-                if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' ||
-                    ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' ||
-                    ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') {
-
-                    ctx.L.unichar += HexValue (ctx.L.input_char) * mult;
-
-                    counter++;
-                    mult /= 16;
-
-                    if (counter == 4) {
-                        ctx.L.string_buffer.Append (
-                            Convert.ToChar (ctx.L.unichar));
-                        ctx.NextState = ctx.StateStack;
-                        return true;
-                    }
-
-                    continue;
-                }
-
-                return false;
-            }
-
-            return true;
-        }
-
-        private static bool State23 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                switch (ctx.L.input_char) {
-                case '\'':
-                    ctx.L.UngetChar ();
-                    ctx.Return = true;
-                    ctx.NextState = 24;
-                    return true;
-
-                case '\\':
-                    ctx.StateStack = 23;
-                    ctx.NextState = 21;
-                    return true;
-
-                default:
-                    ctx.L.string_buffer.Append ((char) ctx.L.input_char);
-                    continue;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State24 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case '\'':
-                ctx.L.input_char = '"';
-                ctx.Return = true;
-                ctx.NextState = 1;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State25 (FsmContext ctx)
-        {
-            ctx.L.GetChar ();
-
-            switch (ctx.L.input_char) {
-            case '*':
-                ctx.NextState = 27;
-                return true;
-
-            case '/':
-                ctx.NextState = 26;
-                return true;
-
-            default:
-                return false;
-            }
-        }
-
-        private static bool State26 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char == '\n') {
-                    ctx.NextState = 1;
-                    return true;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State27 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char == '*') {
-                    ctx.NextState = 28;
-                    return true;
-                }
-            }
-
-            return true;
-        }
-
-        private static bool State28 (FsmContext ctx)
-        {
-            while (ctx.L.GetChar ()) {
-                if (ctx.L.input_char == '*')
-                    continue;
-
-                if (ctx.L.input_char == '/') {
-                    ctx.NextState = 1;
-                    return true;
-                }
-
-                ctx.NextState = 27;
-                return true;
-            }
-
-            return true;
-        }
-        #endregion
-
-
-        private bool GetChar ()
-        {
-            if ((input_char = NextChar ()) != -1)
-                return true;
-
-            end_of_input = true;
-            return false;
-        }
-
-        private int NextChar ()
-        {
-            if (input_buffer != 0) {
-                int tmp = input_buffer;
-                input_buffer = 0;
-
-                return tmp;
-            }
-
-            return reader.Read ();
-        }
-
-        public bool NextToken ()
-        {
-            StateHandler handler;
-            fsm_context.Return = false;
-
-            while (true) {
-                handler = fsm_handler_table[state - 1];
-
-                if (! handler (fsm_context))
-                    throw new JsonException (input_char);
-
-                if (end_of_input)
-                    return false;
-
-                if (fsm_context.Return) {
-                    string_value = string_buffer.ToString ();
-                    string_buffer.Remove (0, string_buffer.Length);
-                    token = fsm_return_table[state - 1];
-
-                    if (token == (int) ParserToken.Char)
-                        token = input_char;
-
-                    state = fsm_context.NextState;
-
-                    return true;
-                }
-
-                state = fsm_context.NextState;
-            }
-        }
-
-        private void UngetChar ()
-        {
-            input_buffer = input_char;
-        }
-    }
-}
diff --git a/Main/Common/LitJson/Lexer.cs.meta b/Main/Common/LitJson/Lexer.cs.meta
deleted file mode 100644
index 357faad..0000000
--- a/Main/Common/LitJson/Lexer.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: cc76231e1fd6e994b9c978577dd26c0b
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/Netstandard15Polyfill.cs b/Main/Common/LitJson/Netstandard15Polyfill.cs
deleted file mode 100644
index 55b02a2..0000000
--- a/Main/Common/LitJson/Netstandard15Polyfill.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-#if NETSTANDARD1_5
-using System;
-using System.Reflection;
-namespace LitJson
-{
-    internal static class Netstandard15Polyfill
-    {
-        internal static Type GetInterface(this Type type, string name)
-        {
-            return type.GetTypeInfo().GetInterface(name); 
-        }
-
-        internal static bool IsClass(this Type type)
-        {
-            return type.GetTypeInfo().IsClass;
-        }
-
-        internal static bool IsEnum(this Type type)
-        {
-            return type.GetTypeInfo().IsEnum;
-        }
-    }
-}
-#endif
\ No newline at end of file
diff --git a/Main/Common/LitJson/Netstandard15Polyfill.cs.meta b/Main/Common/LitJson/Netstandard15Polyfill.cs.meta
deleted file mode 100644
index a03a2ca..0000000
--- a/Main/Common/LitJson/Netstandard15Polyfill.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7b5650e72413e15478074fd1672dbbfc
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Common/LitJson/ParserToken.cs b/Main/Common/LitJson/ParserToken.cs
deleted file mode 100644
index e23d477..0000000
--- a/Main/Common/LitJson/ParserToken.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-#region Header
-/**
- * ParserToken.cs
- *   Internal representation of the tokens used by the lexer and the parser.
- *
- * The authors disclaim copyright to this source code. For more details, see
- * the COPYING file included with this distribution.
- **/
-#endregion
-
-
-namespace LitJson
-{
-    internal enum ParserToken
-    {
-        // Lexer tokens (see section A.1.1. of the manual)
-        None = System.Char.MaxValue + 1,
-        Number,
-        True,
-        False,
-        Null,
-        CharSeq,
-        // Single char
-        Char,
-
-        // Parser Rules (see section A.2.1 of the manual)
-        Text,
-        Object,
-        ObjectPrime,
-        Pair,
-        PairRest,
-        Array,
-        ArrayPrime,
-        Value,
-        ValueRest,
-        String,
-
-        // End of input
-        End,
-
-        // The empty rule
-        Epsilon
-    }
-}
diff --git a/Main/Common/LitJson/ParserToken.cs.meta b/Main/Common/LitJson/ParserToken.cs.meta
deleted file mode 100644
index ba77ef9..0000000
--- a/Main/Common/LitJson/ParserToken.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: f20c9771c3db31240b02dcb1de323d48
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Component.meta b/Main/Component.meta
new file mode 100644
index 0000000..8d7a1e3
--- /dev/null
+++ b/Main/Component.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 87631a248c9a36447b6239b0a48a925b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI.meta b/Main/Component/UI.meta
new file mode 100644
index 0000000..73ca1e2
--- /dev/null
+++ b/Main/Component/UI.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 913f6c76396f01040a1fb42eb6d0a0b1
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common.meta b/Main/Component/UI/Common.meta
new file mode 100644
index 0000000..7c6eac1
--- /dev/null
+++ b/Main/Component/UI/Common.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: daf6385a87df9c94f8091f42368942aa
+folderAsset: yes
+timeCreated: 1497860618
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/AdaptiveLayout.cs b/Main/Component/UI/Common/AdaptiveLayout.cs
new file mode 100644
index 0000000..3053803
--- /dev/null
+++ b/Main/Component/UI/Common/AdaptiveLayout.cs
@@ -0,0 +1,241 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+namespace vnxbqy.UI
+{
+    [ExecuteAlways]
+    public class AdaptiveLayout : MonoBehaviour
+    {
+        [SerializeField] HorizonOrVertical m_HorizonOrVerticle;
+        [SerializeField] CanvasGroup m_CanvasGroup;
+        [SerializeField] List<AdaptiveElement> m_AdapElements;
+        [SerializeField] bool m_AutoIncludeChild=false;
+        [SerializeField] float m_LeastHeight = 0f;
+        [SerializeField] float m_LeastWidth = 0f;
+        [SerializeField] float m_MaxHeight = 0f;
+        [SerializeField] float m_MaxWidth = 0f;
+        [NonSerialized] RectTransform m_Rect;
+        public RectTransform rectTransform
+        {
+            get
+            {
+                if (m_Rect == null)
+                {
+                    m_Rect = GetComponent<RectTransform>();
+                }
+                return m_Rect;
+            }
+        }
+        public float Size
+        {
+            get
+            {
+                return m_HorizonOrVerticle == HorizonOrVertical.Horizon ? rectTransform.sizeDelta.x : rectTransform.sizeDelta.y;
+            }
+        }
+
+        public event Action adaptiveUpdateEvent;
+
+        private void OnEnable()
+        {
+            if (m_AdapElements == null)
+            {
+                enabled = false;
+                return;
+            }
+            if (m_CanvasGroup != null)
+            {
+                m_CanvasGroup.alpha = 0;
+                m_CanvasGroup.interactable = true;
+                StartCoroutine(Co_DelayShow());
+            }
+        }
+
+        private void TrackerRect(RectTransform _rect)
+        {
+            var _pivot = _rect.pivot;
+            var _anchorMax = _rect.anchorMax;
+            var _anchorMin = _rect.anchorMin;
+            if (m_HorizonOrVerticle == HorizonOrVertical.Horizon)
+            {
+                _pivot.x = 0; _pivot.y = 0.5f;
+                _anchorMax.x = 0; _anchorMax.y = 0.5f;
+                _anchorMin.x = 0; _anchorMin.y = 0.5f;
+            }
+            else
+            {
+                _pivot.x = 0.5f; _pivot.y = 1f;
+                _anchorMax.x = 0.5f; _anchorMax.y = 1;
+                _anchorMin.x = 0.5f; _anchorMin.y = 1;
+            }
+            if (_rect.pivot != _pivot || _rect.anchorMax != _anchorMax || _rect.anchorMin != _anchorMin)
+            {
+                _rect.pivot = _pivot;
+                _rect.anchorMax = _anchorMax;
+                _rect.anchorMin = _anchorMin;
+            }
+        }
+
+        private void CalculateLayout()
+        {
+            var _offset = 0.0f;
+            var _horizon = m_HorizonOrVerticle == HorizonOrVertical.Horizon;
+            for (int i = 0; i < m_AdapElements.Count; i++)
+            {
+                if (m_AdapElements[i].rect == null || !m_AdapElements[i].rect.gameObject.activeInHierarchy)
+                {
+                    continue;
+                }
+                _offset += _horizon ? m_AdapElements[i].padding.left : m_AdapElements[i].padding.top;
+                var _pos = m_AdapElements[i].rect.localPosition;
+                if (_horizon)
+                {
+                    _pos.x = _offset;
+                }
+                else
+                {
+                    _pos.y = -_offset;
+                }
+                if (m_AdapElements[i].rect.localPosition != _pos)
+                {
+                    m_AdapElements[i].rect.localPosition = _pos;
+                }
+                _offset += _horizon ? m_AdapElements[i].rect.sizeDelta.x : m_AdapElements[i].rect.sizeDelta.y;
+                _offset += _horizon ? m_AdapElements[i].padding.right : m_AdapElements[i].padding.bottom;
+            }
+            var _sizeDelta = rectTransform.sizeDelta;
+            if (_horizon)
+            {
+                if (m_LeastWidth > 1f)
+                {
+                    _offset = Mathf.Max(_offset, m_LeastWidth);
+                }
+                if (m_MaxWidth > 1f)
+                {
+                    _offset = Mathf.Min(_offset, m_MaxWidth);
+                }
+                _sizeDelta.x = _offset;
+            }
+            else
+            {
+                if (m_LeastHeight > 1f)
+                {
+                    _offset = Mathf.Max(_offset, m_LeastHeight);
+                }
+                if (m_MaxHeight > 1f)
+                {
+                    _offset = Mathf.Min(_offset, m_MaxHeight);
+                }
+                _sizeDelta.y = _offset;
+            }
+            if (rectTransform.sizeDelta != _sizeDelta)
+            {
+                rectTransform.sizeDelta = _sizeDelta;
+                if (adaptiveUpdateEvent != null)
+                {
+                    adaptiveUpdateEvent();
+                }
+            }
+        }
+
+        private void LateUpdate()
+        {
+            if (m_AdapElements == null)
+            {
+                return;
+            }
+            TrackerRect(rectTransform);
+            for (int i = 0; i < m_AdapElements.Count; i++)
+            {
+                if (m_AdapElements[i].rect == null)
+                {
+                    continue;
+                }
+                TrackerRect(m_AdapElements[i].rect);
+            }
+            CalculateLayout();
+        }
+
+        private void OnTransformChildrenChanged()
+        {
+            if (m_AutoIncludeChild)
+            {
+                AutoIncludeChild();
+            }
+        }
+
+        private void AutoIncludeChild()
+        {
+            var _index = 0;
+            foreach (Transform _child in transform)
+            {
+                if (m_AdapElements == null)
+                {
+                    m_AdapElements = new List<AdaptiveElement>();
+                }
+                var _rect = m_AdapElements.Find((x) =>
+                 {
+                     return x.rect == _child;
+                 });
+                var _rectOffset= _child.GetComponent<AdaptiveRectOffset>();
+                if (_rect == null)
+                {
+                    m_AdapElements.Insert(_index, new AdaptiveElement(_child as RectTransform, _rectOffset));
+                }
+                _index++;
+            }
+            if (m_AdapElements != null)
+            {
+                m_AdapElements.RemoveAll((x) =>
+                {
+                    return x.rect == null;
+                });
+            }
+            LateUpdate();
+        }
+
+        IEnumerator Co_DelayShow()
+        {
+            yield return WaitingForSecondConst.WaitMS100;
+            if (m_CanvasGroup != null)
+            {
+                m_CanvasGroup.alpha = 1;
+            }
+        }
+
+        public enum HorizonOrVertical
+        {
+            Horizon,
+            Vertical,
+        }
+        [Serializable]
+        public class AdaptiveElement
+        {
+            [SerializeField] RectTransform m_Rect;
+            public RectTransform rect
+            {
+                get
+                {
+                    return m_Rect;
+                }
+            }
+            [SerializeField] RectOffset m_Padding;
+            public RectOffset padding
+            {
+                get
+                {
+                    return m_Padding;
+                }
+            }
+
+            public AdaptiveElement(RectTransform _rect, AdaptiveRectOffset _offset)
+            {
+                m_Rect = _rect;
+                m_Padding = _offset == null ? new RectOffset() : _offset.rectOffset;
+            }
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Common/AdaptiveLayout.cs.meta b/Main/Component/UI/Common/AdaptiveLayout.cs.meta
new file mode 100644
index 0000000..1fb899c
--- /dev/null
+++ b/Main/Component/UI/Common/AdaptiveLayout.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ed6ba2ce9cad8924bb3ce0fbbfa7c1a4
+timeCreated: 1516935682
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/AdaptiveRectOffset.cs b/Main/Component/UI/Common/AdaptiveRectOffset.cs
new file mode 100644
index 0000000..c5c346a
--- /dev/null
+++ b/Main/Component/UI/Common/AdaptiveRectOffset.cs
@@ -0,0 +1,14 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+public class AdaptiveRectOffset : MonoBehaviour
+{
+    [SerializeField] RectOffset m_RectOffset;
+    public RectOffset rectOffset
+    {
+        get
+        {
+            return m_RectOffset;
+        }
+    }
+}
diff --git a/Main/Component/UI/Common/AdaptiveRectOffset.cs.meta b/Main/Component/UI/Common/AdaptiveRectOffset.cs.meta
new file mode 100644
index 0000000..a910bcb
--- /dev/null
+++ b/Main/Component/UI/Common/AdaptiveRectOffset.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 174c594c9d4d9a541be817920d14d236
+timeCreated: 1520582796
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/AutoSelectCyclicScroll.cs b/Main/Component/UI/Common/AutoSelectCyclicScroll.cs
new file mode 100644
index 0000000..d985f3e
--- /dev/null
+++ b/Main/Component/UI/Common/AutoSelectCyclicScroll.cs
@@ -0,0 +1,58 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, November 01, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+namespace vnxbqy.UI
+{
+
+    public class AutoSelectCyclicScroll : CyclicScroll
+    {
+
+        [SerializeField] RectTransform m_CenterSign;
+
+        public bool autoSelectable {
+            get { return Time.time > allowSelectTime; }
+        }
+
+        float allowSelectTime = 0f;
+        float forbidTime = 0f;
+
+        public void TrySelectData<T>(T _data)
+        {
+            var index = datas.IndexOf(_data);
+            if (index != -1)
+            {
+                MoveToCenter(index);
+                allowSelectTime = Time.time + forbidTime;
+            }
+        }
+
+        [ContextMenu("Arrange")]
+        public override void ReArrange()
+        {
+            base.ReArrange();
+
+            foreach (var item in infiniteItems)
+            {
+                var autoSelectItem = item as AutoSelectScrollItem;
+                if (autoSelectItem != null)
+                {
+                    autoSelectItem.autoSelectScroll = this;
+                    autoSelectItem.centerSign = m_CenterSign;
+                }
+            }
+        }
+
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/AutoSelectCyclicScroll.cs.meta b/Main/Component/UI/Common/AutoSelectCyclicScroll.cs.meta
new file mode 100644
index 0000000..56d47de
--- /dev/null
+++ b/Main/Component/UI/Common/AutoSelectCyclicScroll.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5a8abbe082ae3234db41b35b9132c350
+timeCreated: 1509526962
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/AutoSelectScrollItem.cs b/Main/Component/UI/Common/AutoSelectScrollItem.cs
new file mode 100644
index 0000000..9ff0ae1
--- /dev/null
+++ b/Main/Component/UI/Common/AutoSelectScrollItem.cs
@@ -0,0 +1,16 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+    public class AutoSelectScrollItem : ScrollItem
+    {
+        public AutoSelectCyclicScroll autoSelectScroll { get; set; }
+        public RectTransform centerSign { get; set; }
+
+    }
+}
+
diff --git a/Main/Component/UI/Common/AutoSelectScrollItem.cs.meta b/Main/Component/UI/Common/AutoSelectScrollItem.cs.meta
new file mode 100644
index 0000000..bfed56f
--- /dev/null
+++ b/Main/Component/UI/Common/AutoSelectScrollItem.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6ae9f97e721931f4585e010e53f47a5b
+timeCreated: 1497924839
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/BossLifeBar.cs b/Main/Component/UI/Common/BossLifeBar.cs
new file mode 100644
index 0000000..55d98b0
--- /dev/null
+++ b/Main/Component/UI/Common/BossLifeBar.cs
@@ -0,0 +1,174 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, September 11, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+using System.Text;
+
+namespace vnxbqy.UI
+{
+
+    public class BossLifeBar : MonoBehaviour
+    {
+        [SerializeField] Sprite[] m_LifeBarSprites;
+
+        [SerializeField] Image m_BossIcon;
+        [SerializeField] Image m_BackGround;
+        [SerializeField] Image m_MiddleGround;
+        [SerializeField] Image m_PrefaceGround;
+
+        [SerializeField] Slider m_SliderMiddleground;
+        [SerializeField] Slider m_SliderForeground;
+
+        [SerializeField] Text m_Surplus;
+        [SerializeField] Image m_Realm;
+        [SerializeField] Text m_BossName;
+        [SerializeField] Text m_BossLevel;
+
+        [SerializeField] float m_SmoothTime = 0.3f;
+        public float smoothTime {
+            get { return m_SmoothTime; }
+        }
+
+        Pattern pattern = Pattern.Reduce;
+        float targetValue = 0f;
+        int totalSegments = 1;
+        int surplusSegments = -1;
+
+        float refValue = 0f;
+        float timer = 0f;
+        float behaviourStartValue = 0f;
+
+        float m_CurrentBehaviourValue = 0f;
+        float currentBehaviourValue {
+            get { return m_CurrentBehaviourValue; }
+            set {
+                m_CurrentBehaviourValue = value;
+                UpdateSurplusSegments(currentBehaviourValue);
+                var behaviourDecimalValue = m_CurrentBehaviourValue - (int)m_CurrentBehaviourValue;
+                var trueDecimalValue = targetValue - (int)targetValue;
+                switch (pattern)
+                {
+                    case Pattern.Add:
+                        m_SliderForeground.value = behaviourDecimalValue;
+                        m_SliderMiddleground.value = behaviourDecimalValue > trueDecimalValue ? 1f : trueDecimalValue;
+                        break;
+                    case Pattern.Reduce:
+                        m_SliderMiddleground.value = behaviourDecimalValue;
+                        m_SliderForeground.value = behaviourDecimalValue < trueDecimalValue ? 0 : trueDecimalValue;
+                        break;
+                    case Pattern.None:
+                        m_SliderMiddleground.value = behaviourDecimalValue;
+                        m_SliderForeground.value = behaviourDecimalValue;
+                        break;
+                }
+            }
+        }
+
+        public void SetBaseInfo(int _npcId, ulong _hp, ulong _maxHp, int _level)
+        {
+            var npcConfig = NPCConfig.Get(_npcId);
+            m_BossName.text = npcConfig.charName;
+            m_BossLevel.text = _level.ToString();
+            m_BossIcon.SetSprite(npcConfig.HeadPortrait);
+
+            if (m_Realm != null)
+            {
+                if (npcConfig.Realm > 0 && RealmConfig.Has(npcConfig.Realm))
+                {
+                    m_Realm.SetActive(true);
+                    var realmConfig = RealmConfig.Get(npcConfig.Realm);
+                    m_Realm.SetSprite(realmConfig.Img);
+                }
+                else
+                {
+                    m_Realm.SetActive(false);
+                }
+            }
+
+            surplusSegments = -1;
+            totalSegments = npcConfig.LifeBarCount;
+            targetValue = currentBehaviourValue = ((float)_hp / _maxHp) * totalSegments - 0.0001f;
+            var behaviourDecimalValue = currentBehaviourValue - (int)currentBehaviourValue;
+            m_SliderForeground.value = m_SliderMiddleground.value = behaviourDecimalValue;
+
+            refValue = 0f;
+        }
+
+        public void Show(ulong _hp, ulong _maxHp)
+        {
+            var percentage = Mathf.Clamp(_hp, 0, _maxHp) / (float)_maxHp;
+            var tempValue = totalSegments * percentage - 0.00001f;
+            pattern = tempValue > targetValue ? Pattern.Add : tempValue < targetValue ? Pattern.Reduce : Pattern.None;
+
+            behaviourStartValue = currentBehaviourValue;
+            targetValue = tempValue;
+
+            timer = 0f;
+            refValue = 0f;
+        }
+
+        private void LateUpdate()
+        {
+            if (Mathf.Abs(currentBehaviourValue - targetValue) > 0.00001f)
+            {
+                var newValue = Mathf.SmoothDamp(currentBehaviourValue, targetValue, ref refValue, smoothTime);
+                currentBehaviourValue = newValue;
+            }
+        }
+
+        static StringBuilder stringBuild = new StringBuilder();
+        private void UpdateSurplusSegments(float _targetValue)
+        {
+            var currentSurplus = Mathf.CeilToInt(_targetValue);
+            if (currentSurplus != surplusSegments)
+            {
+                surplusSegments = currentSurplus;
+                var colorSetLength = m_LifeBarSprites.Length;
+                var index = surplusSegments % colorSetLength;
+                var nextIndex = index == 0 ? colorSetLength - 1 : index - 1;
+
+                m_PrefaceGround.overrideSprite = m_LifeBarSprites[index];
+                m_MiddleGround.overrideSprite = m_LifeBarSprites[index];
+                m_BackGround.overrideSprite = m_LifeBarSprites[nextIndex];
+
+                m_BackGround.SetActive(surplusSegments > 1);
+
+                var chars = surplusSegments.ToString();
+                stringBuild.Remove(0, stringBuild.Length);
+                for (var i = 0; i < chars.Length; i++)
+                {
+                    var numChar = GetNumKey(chars[i]);
+                    if (numChar > 0)
+                    {
+                        stringBuild.Append((char)numChar);
+                    }
+                }
+
+                m_Surplus.text = stringBuild.ToString();
+            }
+        }
+
+        int GetNumKey(int _num)
+        {
+            var config = DamageNumConfig.Get("BossLifeBarSurplusNum");
+            return config.nums[_num - 48];
+        }
+
+
+        enum Pattern
+        {
+            None,
+            Add,
+            Reduce,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/BossLifeBar.cs.meta b/Main/Component/UI/Common/BossLifeBar.cs.meta
new file mode 100644
index 0000000..d525ed3
--- /dev/null
+++ b/Main/Component/UI/Common/BossLifeBar.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5b52630eb8ddad445b9b61b7c6c84a8d
+timeCreated: 1505095498
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/BoundedDrag.cs b/Main/Component/UI/Common/BoundedDrag.cs
new file mode 100644
index 0000000..d39a792
--- /dev/null
+++ b/Main/Component/UI/Common/BoundedDrag.cs
@@ -0,0 +1,260 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, September 06, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+using UnityEngine.EventSystems;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class BoundedDrag : MonoBehaviour, IEndDragHandler, IBeginDragHandler, IDragHandler
+    {
+
+        [SerializeField]
+        RectTransform m_Target;
+        public RectTransform target {
+            get { return m_Target; }
+            set {
+                m_Target = value;
+            }
+        }
+
+        public RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+        [SerializeField]
+        ScaleRange m_ScaleRange;
+        public ScaleRange scaleRange {
+            get { return m_ScaleRange; }
+            set { m_ScaleRange = value; }
+        }
+
+        [SerializeField]
+        float m_DefaultScale;
+        public float defaultScale { get { return m_DefaultScale; } }
+
+        [SerializeField]
+        float m_DestScale = 1f;
+        public float destScale {
+            get { return m_DestScale; }
+            set { m_DestScale = Mathf.Clamp(value, scaleRange.min, scaleRange.max); }
+        }
+
+        float refScale = 0f;
+
+        public float currentScale {
+            get {
+                return target.localScale.x;
+            }
+            set {
+                target.localScale = Vector3.one * Mathf.Clamp(value, scaleRange.min, scaleRange.max);
+            }
+        }
+
+        [SerializeField]
+        MoveArea m_MoveArea;
+        public MoveArea moveArea {
+            get { return m_MoveArea; }
+            set { m_MoveArea = value; }
+        }
+
+        [SerializeField]
+        Vector2 m_DestPosition = Vector2.zero;
+        public Vector2 destPosition {
+            get { return m_DestPosition; }
+            set { m_DestPosition = new Vector2(Mathf.Clamp(value.x, moveArea.Left * destScale, moveArea.Right * destScale), Mathf.Clamp(value.y, moveArea.Bottom * destScale, moveArea.Top * destScale)); }
+        }
+
+        Vector3 refPosition = Vector3.zero;
+
+        public Vector2 currentPosition {
+            get { return target.anchoredPosition; }
+            set { target.anchoredPosition = value; }
+        }
+
+        Vector2 startTouchPosition01;
+        Vector2 startGroundPosition;
+
+        Vector2 lastTouchPosition01;
+        Vector2 curTouchPosition01;
+        Vector2 lastTouchPosition02;
+        Vector2 curTouchPosition02;
+
+        [SerializeField]
+        UIEvent m_OnBeginDrag;
+        public UIEvent onBeginDrag {
+            get { return m_OnBeginDrag; }
+        }
+
+        bool m_Actionable = true;
+        public bool actionable {
+            get { return m_Actionable; }
+            set { m_Actionable = value; }
+        }
+
+        private void OnEnable()
+        {
+            destPosition = currentPosition = Vector3.zero;
+        }
+
+        public void OnBeginDrag(PointerEventData eventData)
+        {
+
+#if UNITY_EDITOR || UNITY_STANDALONE
+            if (Input.GetKey(KeyCode.LeftControl) && eventData.button == PointerEventData.InputButton.Left)
+            {
+                TwoFingerHandleBegin();
+            }
+            else if (eventData.button == PointerEventData.InputButton.Left)
+            {
+                OneFingerHandleBegin(eventData);
+            }
+#else
+        if (Input.touchCount == 2) {
+            TwoFingerHandleBegin();
+        }
+        if (Input.touchCount == 1) {
+            OneFingerHandleBegin(eventData);
+        }
+#endif
+            if (onBeginDrag != null)
+            {
+                onBeginDrag.Invoke();
+            }
+        }
+
+        public void OnDrag(PointerEventData eventData)
+        {
+#if UNITY_EDITOR || UNITY_STANDALONE
+            if (Input.GetKey(KeyCode.LeftControl) && eventData.button == PointerEventData.InputButton.Left)
+            {
+                TwoFingerHandle();
+            }
+            else if (eventData.button == PointerEventData.InputButton.Left)
+            {
+                OneFingerHandle(eventData);
+            }
+#else
+        if (Input.touchCount == 2) {
+            TwoFingerHandle();
+        }
+        if (Input.touchCount == 1) {
+            OneFingerHandle(eventData);
+        }
+#endif
+        }
+
+        public void OnEndDrag(PointerEventData eventData)
+        {
+        }
+
+        void LateUpdate()
+        {
+            if (!actionable)
+            {
+                return;
+            }
+
+            if (Mathf.Abs(currentScale - destScale) > 0.01f)
+            {
+                float newScale = Mathf.SmoothDamp(currentScale, destScale, ref refScale, 0.15f);
+                currentScale = newScale;
+            }
+
+            if (Vector2.Distance(currentPosition, destPosition) > 0.1f)
+            {
+                Vector2 newPosition = Vector3.SmoothDamp(currentPosition, destPosition, ref refPosition, 0.15f);
+                currentPosition = newPosition;
+            }
+        }
+
+        private void OneFingerHandleBegin(PointerEventData eventData)
+        {
+            startTouchPosition01 = Vector2.zero;
+            RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out startTouchPosition01);
+            startGroundPosition = currentPosition;
+
+        }
+
+        private void OneFingerHandle(PointerEventData eventData)
+        {
+            Vector2 localMouse;
+            if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out localMouse))
+            {
+                var pointerDelta = localMouse - startTouchPosition01;
+                destPosition = startGroundPosition + pointerDelta;
+            }
+        }
+
+        private void TwoFingerHandle()
+        {
+            // 鏂逛究PC璋冭瘯閫昏緫
+#if UNITY_EDITOR || UNITY_STANDALONE
+            curTouchPosition01 = new Vector2(Screen.width / 2, Screen.height / 2);
+            curTouchPosition02 = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
+#else
+        Touch touchFirst = Input.touches[0];
+        Touch touchSecond = Input.touches[1];
+        curTouchPosition01 = touchFirst.position;
+        curTouchPosition02 = touchSecond.position;
+#endif
+
+            float lastLength = Vector2.Distance(lastTouchPosition01, lastTouchPosition02);
+            float curLength = Vector2.Distance(curTouchPosition01, curTouchPosition02);
+            destScale *= curLength / Mathf.Clamp(lastLength, 1, float.MaxValue);
+
+            lastTouchPosition01 = curTouchPosition01;
+            lastTouchPosition02 = curTouchPosition02;
+        }
+
+        private void TwoFingerHandleBegin()
+        {
+            // 鏂逛究PC璋冭瘯閫昏緫
+#if UNITY_EDITOR || UNITY_STANDALONE
+            curTouchPosition01 = new Vector2(Screen.width / 2, Screen.height / 2);
+            curTouchPosition02 = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
+#else
+        Touch touchFirst = Input.touches[0];
+        Touch touchSecond = Input.touches[1];
+        curTouchPosition01 = touchFirst.position;
+        curTouchPosition02 = touchSecond.position;
+#endif
+
+            lastTouchPosition01 = curTouchPosition01;
+            lastTouchPosition02 = curTouchPosition02;
+        }
+
+        [Serializable]
+        public struct ScaleRange
+        {
+            public float min;
+            public float max;
+        }
+
+        [Serializable]
+        public struct MoveArea
+        {
+            public float Left;
+            public float Right;
+            public float Top;
+            public float Bottom;
+
+            public MoveArea(float _left, float _right, float _top, float _bottom)
+            {
+                this.Left = _left;
+                this.Right = _right;
+                this.Top = _top;
+                this.Bottom = _bottom;
+            }
+
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/BoundedDrag.cs.meta b/Main/Component/UI/Common/BoundedDrag.cs.meta
new file mode 100644
index 0000000..8ef9acc
--- /dev/null
+++ b/Main/Component/UI/Common/BoundedDrag.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1806d95e6c5bebe4899c912fb2bab4f0
+timeCreated: 1504698278
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ButtonClickInterval.cs b/Main/Component/UI/Common/ButtonClickInterval.cs
new file mode 100644
index 0000000..f8ca274
--- /dev/null
+++ b/Main/Component/UI/Common/ButtonClickInterval.cs
@@ -0,0 +1,31 @@
+锘縰sing System;
+using UnityEngine;
+using UnityEngine.UI;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+    
+    public class ButtonClickInterval : MonoBehaviour
+    {
+        [SerializeField] float interval = 1f;
+        [SerializeField] Button targetBtn;
+
+        private void Awake()
+        {
+            targetBtn.AddListener(OnClick);
+        }
+
+        private void OnClick()
+        {
+            targetBtn.enabled = false;
+            StartCoroutine(DelayClick());
+        }
+
+        IEnumerator DelayClick()
+        {
+            yield return new WaitForSeconds(interval);
+            targetBtn.enabled = true;
+        }
+    }
+}
diff --git a/Main/Component/UI/Common/ButtonClickInterval.cs.meta b/Main/Component/UI/Common/ButtonClickInterval.cs.meta
new file mode 100644
index 0000000..e049995
--- /dev/null
+++ b/Main/Component/UI/Common/ButtonClickInterval.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4761530da641c6b49ae3d21a397bea40
+timeCreated: 1547433750
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/CanvasRaycastFilter.cs b/Main/Component/UI/Common/CanvasRaycastFilter.cs
new file mode 100644
index 0000000..8e5a66c
--- /dev/null
+++ b/Main/Component/UI/Common/CanvasRaycastFilter.cs
@@ -0,0 +1,28 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 02, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class CanvasRaycastFilter : MonoBehaviour, ICanvasRaycastFilter
+    {
+
+        [SerializeField] bool m_RaycastTarget = true;
+        public bool raycastTarget { get { return m_RaycastTarget; } set { m_RaycastTarget = value; } }
+
+        public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
+        {
+            return raycastTarget;
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/CanvasRaycastFilter.cs.meta b/Main/Component/UI/Common/CanvasRaycastFilter.cs.meta
new file mode 100644
index 0000000..4c0b50d
--- /dev/null
+++ b/Main/Component/UI/Common/CanvasRaycastFilter.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9db247f61e9c9d840a3ba88a4cbc7e7d
+timeCreated: 1530536414
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/CircleMoveTo.cs b/Main/Component/UI/Common/CircleMoveTo.cs
new file mode 100644
index 0000000..d2b3ded
--- /dev/null
+++ b/Main/Component/UI/Common/CircleMoveTo.cs
@@ -0,0 +1,96 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+public class CircleMoveTo : MonoBehaviour
+{
+    public float circleTime = 1f;
+    public float duration = 2f;
+    public float ratio = 3;
+    public float accelerate = 0.2f;
+
+    [SerializeField]
+    Vector3 m_Desitination = Vector3.zero;
+    public Vector3 destination {
+        get { return m_Desitination; }
+        private set {
+            m_Desitination = value;
+        }
+    }
+
+    Vector3 forward = Vector3.zero;
+    float timer = 0f;
+    float endTime = 0f;
+    float velocity = 0f;
+
+    bool windUp = false;
+    Vector3 refPosition = Vector3.zero;
+    Action onReach;
+    bool beginMove = false;
+
+    public void MoveTo(Vector3 _destination, Action _callBack = null)
+    {
+        this.SetActive(true);
+        windUp = false;
+        velocity = 0f;
+        destination = _destination;
+        beginMove = true;
+        endTime = Time.time + duration;
+        refPosition = Vector3.zero;
+        onReach = _callBack;
+    }
+
+    void FixedUpdate()
+    {
+        if (!beginMove)
+        {
+            return;
+        }
+
+        if (Time.time > endTime && !windUp)
+        {
+            var normalize1 = Vector3.Normalize(destination.SetZ(0));
+            var normalize2 = Vector3.Normalize(this.transform.position.SetZ(0));
+            var dot = Vector3.Dot(normalize1, normalize1 - normalize2);
+            if (dot > -0.15f && dot < 0.15f)
+            {
+                windUp = true;
+            }
+        }
+
+        if (windUp)
+        {
+            var newPosition = Vector3.SmoothDamp(this.transform.position, destination, ref refPosition, 0.25f);
+            this.transform.position = newPosition;
+            this.transform.localPosition = this.transform.localPosition.SetZ(0);
+            if (Vector3.Distance(this.transform.position.SetZ(0), destination.SetZ(0)) < 0.01f)
+            {
+                if (onReach != null)
+                {
+                    onReach();
+                    onReach = null;
+                }
+
+                beginMove = false;
+                this.SetActive(false);
+            }
+        }
+        else
+        {
+            velocity += Time.deltaTime * accelerate;
+            timer += Time.deltaTime;
+            if (timer > circleTime)
+            {
+                timer = timer - circleTime;
+            }
+
+            var t = Mathf.Clamp01(timer / circleTime);
+            forward = new Vector3(Mathf.Sin(2 * t * Mathf.PI), Mathf.Cos(2 * t * Mathf.PI), 0f);
+            this.transform.position += Vector3.Normalize(forward) * Mathf.Pow(velocity, ratio);
+        }
+
+    }
+
+
+}
diff --git a/Main/Component/UI/Common/CircleMoveTo.cs.meta b/Main/Component/UI/Common/CircleMoveTo.cs.meta
new file mode 100644
index 0000000..5936020
--- /dev/null
+++ b/Main/Component/UI/Common/CircleMoveTo.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ed1761cc20fe6764ca6b2c08c4ca874c
+timeCreated: 1510890860
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ClickScreenOtherSpace.cs b/Main/Component/UI/Common/ClickScreenOtherSpace.cs
new file mode 100644
index 0000000..6ffd267
--- /dev/null
+++ b/Main/Component/UI/Common/ClickScreenOtherSpace.cs
@@ -0,0 +1,67 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System;
+using UnityEngine.Events;
+
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(RectTransform))]
+    public class ClickScreenOtherSpace : MonoBehaviour
+    {
+        [SerializeField]
+        bool m_DeActiveSelf = true;
+        public bool deActiveSelf {
+            get { return m_DeActiveSelf; }
+            set { m_DeActiveSelf = value; }
+        }
+
+        [SerializeField]
+        RespondType m_RespondType = RespondType.Out;
+        public RespondType respondType {
+            get { return m_RespondType; }
+            set { m_RespondType = value; }
+        }
+
+        UIEvent m_ClickOtherEvent = new UIEvent();
+
+        public void AddListener(UnityAction _callBack)
+        {
+            m_ClickOtherEvent.AddListener(_callBack);
+        }
+
+        public void RemoveAllListeners()
+        {
+            m_ClickOtherEvent.RemoveAllListeners();
+        }
+
+        private void LateUpdate()
+        {
+            if (Input.GetMouseButtonDown(0)) {
+                var sp = Input.mousePosition;
+                switch (m_RespondType) {
+                    case RespondType.In:
+                        if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) {
+                            m_ClickOtherEvent.Invoke();
+                            this.SetActive(!m_DeActiveSelf);
+                        }
+                        break;
+                    case RespondType.Out:
+                        if (!RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) {
+                            m_ClickOtherEvent.Invoke();
+                            this.SetActive(!m_DeActiveSelf);
+                        }
+                        break;
+                }
+            }
+        }
+
+        public enum RespondType
+        {
+            In,
+            Out,
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/ClickScreenOtherSpace.cs.meta b/Main/Component/UI/Common/ClickScreenOtherSpace.cs.meta
new file mode 100644
index 0000000..faaaba8
--- /dev/null
+++ b/Main/Component/UI/Common/ClickScreenOtherSpace.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: bbd081375ffd6a84090873b1eff76ac2
+timeCreated: 1507970529
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/CoolDownBehaviour.cs b/Main/Component/UI/Common/CoolDownBehaviour.cs
new file mode 100644
index 0000000..0b858d0
--- /dev/null
+++ b/Main/Component/UI/Common/CoolDownBehaviour.cs
@@ -0,0 +1,89 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, October 24, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class CoolDownBehaviour : MonoBehaviour
+    {
+        [SerializeField]
+        ButtonEx m_ButtonEx;
+
+        [SerializeField]
+        Text m_OriginalText;
+
+        [SerializeField]
+        Text m_CoolDownText;
+
+        [SerializeField]
+        ImageEx m_GrayImage;
+
+        float timer = 0f;
+        protected virtual void OnEnable()
+        {
+            timer = 0f;
+        }
+
+        protected virtual void LateUpdate()
+        {
+            if (m_ButtonEx == null)
+            {
+                return;
+            }
+
+            if (m_ButtonEx.ableTime > Time.realtimeSinceStartup)
+            {
+                if (m_CoolDownText != null && !m_CoolDownText.gameObject.activeInHierarchy)
+                {
+                    m_CoolDownText.SetActive(true);
+                }
+
+                if (m_OriginalText != null && m_OriginalText.gameObject.activeInHierarchy)
+                {
+                    m_OriginalText.SetActive(false);
+                }
+
+                if (m_GrayImage != null)
+                {
+                    m_GrayImage.gray = true;
+                }
+
+                timer -= Time.deltaTime;
+                if (timer < 0f)
+                {
+                    timer = 1f;
+                    var seconds = Mathf.RoundToInt(m_ButtonEx.ableTime - Time.realtimeSinceStartup);
+                    m_CoolDownText.text = StringUtility.Contact(seconds, Language.Get("RealmWin_Bewrite_35"));
+                }
+            }
+            else
+            {
+                if (m_CoolDownText != null && m_CoolDownText.gameObject.activeInHierarchy)
+                {
+                    m_CoolDownText.SetActive(false);
+                }
+
+                if (m_OriginalText != null && !m_OriginalText.gameObject.activeInHierarchy)
+                {
+                    m_OriginalText.SetActive(true);
+                }
+
+                if (m_GrayImage != null)
+                {
+                    m_GrayImage.gray = false;
+                }
+            }
+
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/CoolDownBehaviour.cs.meta b/Main/Component/UI/Common/CoolDownBehaviour.cs.meta
new file mode 100644
index 0000000..e221ad1
--- /dev/null
+++ b/Main/Component/UI/Common/CoolDownBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ce87e30b0f3a6414f8e3e5198f566aa4
+timeCreated: 1508836469
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/CyclicScroll.cs b/Main/Component/UI/Common/CyclicScroll.cs
new file mode 100644
index 0000000..1ae202f
--- /dev/null
+++ b/Main/Component/UI/Common/CyclicScroll.cs
@@ -0,0 +1,762 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System;
+
+[DisallowMultipleComponent]
+
+public class CyclicScroll : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
+{
+    [SerializeField] RectTransform m_Content;
+    public RectTransform content { get { return m_Content; } }
+
+    [SerializeField] protected BoundOffset m_BoundOffset;
+    [SerializeField] protected Vector2 m_CellSize = new Vector2(100, 100);
+    public Vector2 cellSize { get { return m_CellSize; } }
+
+    [SerializeField] protected Vector2 m_Spacing;
+    public Vector2 spacing { get { return m_Spacing; } }
+
+    [SerializeField] Align m_Align = Align.Top;
+    public Align align { get { return m_Align; } }
+
+    [SerializeField] bool m_ElasticityOn = true;
+    public bool elasticityOn { get { return m_ElasticityOn; } }
+
+    [SerializeField] private float m_Elasticity = 0.1f;
+    public float elasticity { get { return m_Elasticity; } }
+
+    [SerializeField] private float m_DecelerationRate = 0.135f;
+    public float decelerationRate { get { return m_DecelerationRate; } }
+
+    [SerializeField] string m_ChildPrefabName = string.Empty;
+    [SerializeField] string m_ChildDisplayName = string.Empty;
+    [SerializeField] int m_ChildCount = 5;
+
+    public float normalizedPosition {
+        get {
+            if (content == null)
+            {
+                return 0f;
+            }
+
+            var offset = (dataMaxOffset - dataMinOffset);
+            switch (align)
+            {
+                case Align.Top:
+                case Align.Bottom:
+                    return Mathf.Clamp01(Mathf.Abs((content.anchoredPosition.y - dataMinOffset.y) / offset.y));
+                case Align.Left:
+                case Align.Right:
+                    return Mathf.Clamp01(Mathf.Abs((content.anchoredPosition.x - dataMinOffset.x) / offset.x));
+                default:
+                    return 0f;
+            }
+        }
+        set {
+            if (content == null)
+            {
+                return;
+            }
+
+            value = Mathf.Clamp01(value);
+            var normalize = 0f;
+            var offset = (dataMaxOffset - dataMinOffset);
+            switch (align)
+            {
+                case Align.Top:
+                case Align.Bottom:
+                    normalize = (content.anchoredPosition.y - dataMinOffset.y) / offset.y;
+                    if (Mathf.Abs(normalize - value) > 0.0001f)
+                    {
+                        targetOffset = dataMinOffset + new Vector2(0, dataMaxOffset.y * value);
+                        velocity = 0f;
+                        autoLerp = true;
+                        refAutoLerpPosition = Vector2.zero;
+                    }
+                    break;
+                case Align.Left:
+                case Align.Right:
+                    normalize = (content.anchoredPosition.x - dataMinOffset.x) / offset.x;
+                    if (Mathf.Abs(normalize - value) > 0.0001f)
+                    {
+                        targetOffset = dataMinOffset + new Vector2(dataMaxOffset.x * value, 0);
+                        velocity = 0f;
+                        autoLerp = true;
+                        refAutoLerpPosition = Vector2.zero;
+                    }
+                    break;
+            }
+        }
+    }
+
+    protected Vector2 dataMaxOffset = Vector2.zero;
+    protected Vector2 dataMinOffset = Vector2.zero;
+
+    public bool autoLerp { get; private set; }
+
+    Vector2 targetOffset = Vector2.zero;
+    Vector2 refAutoLerpPosition = Vector2.zero;
+
+    protected IList datas;
+    protected List<ScrollItem> infiniteItems = new List<ScrollItem>();
+    List<ScrollItem> tempList = new List<ScrollItem>();
+
+    Vector2 startMousePosition = Vector2.zero;
+    Vector2 startContentPosition = Vector2.zero;
+    Vector2 prevPosition = Vector2.zero;
+
+    protected float velocity = 0f;
+    protected bool dragging = false;
+
+    public int dataCount {
+        get {
+            return datas == null ? 0 : datas.Count;
+        }
+    }
+    bool moveNextable {
+        get {
+            return hostIndex < dataCount - 1;
+        }
+    }
+    bool moveLastable {
+        get {
+            return preIndex > 0;
+        }
+    }
+
+    public RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+    private Vector2 maxOffset { get { return rectTransform.GetMaxReferencePosition(rectTransform); } }
+    private Vector2 minOffset { get { return rectTransform.GetMinReferencePosition(rectTransform); } }
+
+    protected int preIndex {
+        get; set;
+    }
+
+    protected int hostIndex {
+        get; set;
+    }
+
+    public void LuaInit(int[] indexs, bool stepByStep)
+    {
+        Init(new List<int>(indexs), stepByStep);
+    }
+
+    public virtual void Init<T>(List<T> _datas, bool _stepByStep = false)
+    {
+        if (_datas == null)
+        {
+            this.SetActive(false);
+            return;
+        }
+
+        datas = _datas;
+
+        ReArrange();
+        FillBatchData(0);
+
+        if (_stepByStep)
+        {
+            for (int i = 0; i < infiniteItems.Count; i++)
+            {
+                var infiniteItem = infiniteItems[i];
+                if (infiniteItem != null)
+                {
+                    infiniteItem.SetActive(false);
+                }
+            }
+        }
+
+        this.SetActive(true);
+
+        dataMinOffset = content.anchoredPosition;
+        var totalOffset = dataCount == 0 ? Vector2.zero : cellSize * dataCount + spacing * (dataCount - 1)
+            + new Vector2(m_BoundOffset.left + m_BoundOffset.right, m_BoundOffset.top + m_BoundOffset.bottom);
+
+        var longer = Mathf.Abs(totalOffset.x) > Mathf.Abs(rectTransform.rect.width);
+        var higher = Mathf.Abs(totalOffset.y) > Mathf.Abs(rectTransform.rect.height);
+        switch (align)
+        {
+            case Align.Left:
+                dataMaxOffset = longer ? dataMinOffset - new Vector2(totalOffset.x - rectTransform.rect.width, 0) : dataMinOffset;
+                break;
+            case Align.Right:
+                dataMaxOffset = longer ? dataMinOffset + new Vector2(totalOffset.x - rectTransform.rect.width, 0) : dataMinOffset;
+                break;
+            case Align.Top:
+                dataMaxOffset = higher ? dataMinOffset + new Vector2(0, totalOffset.y - rectTransform.rect.height) : dataMinOffset;
+                break;
+            case Align.Bottom:
+                dataMaxOffset = higher ? dataMinOffset - new Vector2(0, totalOffset.y - rectTransform.rect.height) : dataMinOffset;
+                break;
+        }
+
+        if (_stepByStep)
+        {
+            StartCoroutine("Co_StepByStepAppear");
+        }
+    }
+
+    public void Dispose()
+    {
+        velocity = 0f;
+        StopAllCoroutines();
+        for (int i = 0; i < infiniteItems.Count; i++)
+        {
+            var infiniteItem = infiniteItems[i];
+            if (infiniteItem != null)
+            {
+                infiniteItem.Dispose();
+            }
+        }
+    }
+
+    public void HideAll()
+    {
+        StopAllCoroutines();
+        for (int i = 0; i < content.childCount; i++)
+        {
+            content.GetChild(i).SetActive(false);
+        }
+    }
+
+    IEnumerator Co_StepByStepAppear()
+    {
+        for (int i = 0; i < infiniteItems.Count; i++)
+        {
+            var infiniteItem = infiniteItems[i];
+            if (infiniteItem != null && i < datas.Count)
+            {
+                infiniteItem.SetActive(true);
+                infiniteItem.OpeningShow();
+                yield return WaitingForSecondConst.WaitMS100;
+            }
+        }
+    }
+
+    public void MoveToCenter(int _dataIndex)
+    {
+        if (_dataIndex < 0 || _dataIndex >= dataCount)
+        {
+            return;
+        }
+
+        switch (align)
+        {
+            case Align.Left:
+                var leftOffsetX = Mathf.Clamp(m_BoundOffset.left + (_dataIndex + 0.5f) * cellSize.x + _dataIndex * spacing.x - rectTransform.rect.width * 0.5f, 0, Mathf.Abs(dataMaxOffset.x));
+                targetOffset = new Vector2(dataMinOffset.x - leftOffsetX, 0);
+                break;
+            case Align.Right:
+                var rightOffsetX = Mathf.Clamp(m_BoundOffset.right + (_dataIndex + 0.5f) * cellSize.x + _dataIndex * spacing.x - rectTransform.rect.width * 0.5f, 0, Mathf.Abs(dataMaxOffset.x));
+                targetOffset = new Vector2(dataMinOffset.x + rightOffsetX, 0);
+                break;
+            case Align.Top:
+                var topOffsetY = Mathf.Clamp(m_BoundOffset.top + (_dataIndex + 0.5f) * cellSize.y + _dataIndex * spacing.y - rectTransform.rect.height * 0.5f, 0, Mathf.Abs(dataMaxOffset.y));
+                targetOffset = new Vector2(0, dataMinOffset.y + topOffsetY);
+                break;
+            case Align.Bottom:
+                var bottomOffsetY = Mathf.Clamp(m_BoundOffset.bottom + (_dataIndex + 0.5f) * cellSize.y + _dataIndex * spacing.y - rectTransform.rect.height * 0.5f, 0, Mathf.Abs(dataMaxOffset.y));
+                targetOffset = new Vector2(0, dataMinOffset.y - bottomOffsetY);
+                break;
+        }
+
+        autoLerp = true;
+    }
+
+    #region Drag Process
+
+    public void OnBeginDrag(PointerEventData eventData)
+    {
+        if (autoLerp || eventData.button != PointerEventData.InputButton.Left)
+        {
+            return;
+        }
+
+        startMousePosition = Vector2.zero;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out startMousePosition);
+        prevPosition = startContentPosition = content.anchoredPosition;
+        velocity = 0f;
+        dragging = true;
+    }
+
+    public void OnDrag(PointerEventData eventData)
+    {
+        if (vnxbqy.UI.NewBieCenter.Instance.inGuiding)
+        {
+            return;
+        }
+
+        if (autoLerp || eventData.button != PointerEventData.InputButton.Left)
+        {
+            return;
+        }
+
+        var localMouse = new Vector2();
+        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out localMouse))
+        {
+            var pointerDelta = localMouse - startMousePosition;
+            var position = startContentPosition + pointerDelta;
+            SetContentAnchoredPosition(position, align);
+        }
+    }
+
+    public void OnEndDrag(PointerEventData eventData)
+    {
+        if (autoLerp || eventData.button != PointerEventData.InputButton.Left)
+        {
+            return;
+        }
+
+        dragging = false;
+    }
+    #endregion
+
+    private void Update()
+    {
+        if (autoLerp && Vector2.Distance(content.anchoredPosition, targetOffset) > 0.1f)
+        {
+            var newPosition = Vector2.SmoothDamp(content.anchoredPosition, targetOffset, ref refAutoLerpPosition, m_Elasticity, Mathf.Infinity, Time.unscaledDeltaTime);
+            SetContentAnchoredPosition(newPosition, align);
+        }
+        else
+        {
+            autoLerp = false;
+        }
+    }
+
+    protected virtual void LateUpdate()
+    {
+        if (content == null)
+        {
+            return;
+        }
+
+        var deltaTime = Time.unscaledDeltaTime;
+        var offset = CalculateOffset(align);
+
+        if (!dragging && (velocity != 0f || Vector2.SqrMagnitude(offset - Vector2.zero) > 0.1f))
+        {
+            Vector2 position = content.anchoredPosition;
+            if (Vector2.SqrMagnitude(offset - Vector2.zero) > 0.1f)
+            {
+                float speed = velocity;
+                switch (align)
+                {
+                    case Align.Left:
+                    case Align.Right:
+                        position[0] = Mathf.SmoothDamp(content.anchoredPosition[0], content.anchoredPosition[0] - offset.x, ref speed, m_Elasticity, Mathf.Infinity, deltaTime);
+                        break;
+                    case Align.Bottom:
+                    case Align.Top:
+                        position[1] = Mathf.SmoothDamp(content.anchoredPosition[1], content.anchoredPosition[1] - offset.y, ref speed, m_Elasticity, Mathf.Infinity, deltaTime);
+                        break;
+                }
+
+                if (Mathf.Abs(speed) < 1)
+                {
+                    speed = 0f;
+                }
+                velocity = speed;
+            }
+            else
+            {
+                velocity *= Mathf.Pow(m_DecelerationRate, deltaTime);
+                if (Mathf.Abs(velocity) < 50)
+                {
+                    velocity = 0;
+                }
+                switch (align)
+                {
+                    case Align.Left:
+                    case Align.Right:
+                        position[0] += velocity * deltaTime;
+                        break;
+                    case Align.Bottom:
+                    case Align.Top:
+                        position[1] += velocity * deltaTime;
+                        break;
+                }
+
+            }
+
+            SetContentAnchoredPosition(position, align);
+        }
+
+        if (dragging /*&& content.anchoredPosition != prevPosition*/)
+        {
+            var newVelocity = 0f;
+            switch (align)
+            {
+                case Align.Left:
+                case Align.Right:
+                    newVelocity = (content.anchoredPosition[0] - prevPosition[0]) / deltaTime;
+                    break;
+                case Align.Bottom:
+                case Align.Top:
+                    newVelocity = (content.anchoredPosition[1] - prevPosition[1]) / deltaTime;
+                    break;
+            }
+
+            velocity = Mathf.Lerp(velocity, newVelocity, deltaTime * 10);
+            prevPosition = content.anchoredPosition;
+        }
+
+    }
+
+    protected virtual void ProcessMoveNext()
+    {
+        ScrollItem lastRect = null;
+        ScrollItem item = null;
+
+        tempList.Clear();
+        for (int i = 0; i < infiniteItems.Count; i++)
+        {
+            tempList.Add(infiniteItems[i]);
+        }
+        if (tempList.Count <= 0)
+        {
+            return;
+        }
+        lastRect = tempList[tempList.Count - 1];
+        for (int i = 0; i < tempList.Count; i++)
+        {
+            item = tempList[i];
+            var able = moveNextable && TestMoveNext(align, item);
+            if (able)
+            {
+                infiniteItems.Remove(item);
+                infiniteItems.Add(item);
+                var offset = CalculateElementOffset(align);
+                item.rectTransform.anchoredPosition = lastRect.rectTransform.anchoredPosition + offset;
+                lastRect = item;
+
+                hostIndex++;
+                preIndex++;
+                item.Dispose();
+                item.LuaDispose();
+                item.Display(datas[hostIndex]);
+                item.LuaDisplay(hostIndex);
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+
+    protected virtual void ProcessMoveLast()
+    {
+        ScrollItem firstRect = null;
+        ScrollItem item = null;
+
+        tempList.Clear();
+        for (int i = 0; i < infiniteItems.Count; i++)
+        {
+            tempList.Add(infiniteItems[i]);
+        }
+
+        firstRect = tempList[0];
+        for (int i = tempList.Count - 1; i >= 0; i--)
+        {
+            item = tempList[i];
+            var able = moveLastable && TestMoveLast(align, item);
+            if (able)
+            {
+                infiniteItems.Remove(item);
+                infiniteItems.Insert(0, item);
+                var offset = CalculateElementOffset(align);
+                item.rectTransform.anchoredPosition = firstRect.rectTransform.anchoredPosition - offset;
+                firstRect = item;
+                hostIndex--;
+                preIndex--;
+                item.Dispose();
+                item.LuaDispose();
+                item.Display(datas[preIndex]);
+                item.LuaDisplay(preIndex);
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+
+    private void SetContentAnchoredPosition(Vector2 _position, Align _align)
+    {
+        if (_position == content.anchoredPosition)
+        {
+            return;
+        }
+
+        if (!elasticityOn)
+        {
+            _position.y = Mathf.Clamp(_position.y, dataMinOffset.y, dataMaxOffset.y);
+            _position.x = Mathf.Clamp(_position.x, dataMinOffset.x, dataMaxOffset.x);
+        }
+
+        var offset = _position - content.anchoredPosition;
+
+        switch (_align)
+        {
+            case Align.Left:
+            case Align.Right:
+                _position[1] = content.anchoredPosition[1];
+                content.anchoredPosition = _position;
+                break;
+            case Align.Top:
+            case Align.Bottom:
+                _position[0] = content.anchoredPosition[0];
+                content.anchoredPosition = _position;
+                break;
+        }
+
+        var moveNext = (_align == Align.Left && offset.x < 0f) || (_align == Align.Right && offset.x > 0f) ||
+            (_align == Align.Top && offset.y > 0f) || (_align == Align.Bottom && offset.y < 0f);
+
+        if (moveNext)
+        {
+            ProcessMoveNext();
+        }
+        else
+        {
+            ProcessMoveLast();
+        }
+    }
+
+    private Vector2 CalculateOffset(Align _align)
+    {
+        var offset = Vector2.zero;
+        switch (_align)
+        {
+            case Align.Left:
+                if (content.anchoredPosition.x > dataMinOffset.x)
+                {
+                    offset = content.anchoredPosition - dataMinOffset;
+                }
+                else if (content.anchoredPosition.x < dataMaxOffset.x)
+                {
+                    offset = content.anchoredPosition - dataMaxOffset;
+                }
+                break;
+            case Align.Right:
+                if (content.anchoredPosition.x < dataMinOffset.x)
+                {
+                    offset = content.anchoredPosition - dataMinOffset;
+                }
+                else if (content.anchoredPosition.x > dataMaxOffset.x)
+                {
+                    offset = content.anchoredPosition - dataMaxOffset;
+                }
+                break;
+            case Align.Bottom:
+                if (content.anchoredPosition.y > dataMinOffset.y)
+                {
+                    offset = content.anchoredPosition - dataMinOffset;
+                }
+                else if (content.anchoredPosition.y < dataMaxOffset.y)
+                {
+                    offset = content.anchoredPosition - dataMaxOffset;
+                }
+                break;
+            case Align.Top:
+                if (content.anchoredPosition.y < dataMinOffset.y)
+                {
+                    offset = content.anchoredPosition - dataMinOffset;
+                }
+                else if (content.anchoredPosition.y > dataMaxOffset.y)
+                {
+                    offset = content.anchoredPosition - dataMaxOffset;
+                }
+                break;
+        }
+
+        return offset;
+    }
+
+    [ContextMenu("Arrange")]
+    public virtual void ReArrange()
+    {
+        velocity = 0f;
+        autoLerp = false;
+        CreateElements();
+        ElementsMatch();
+        Arrange(align);
+    }
+
+    private void CreateElements()
+    {
+        var items = this.content.GetComponentsInChildren<ScrollItem>(true);
+        if (items.Length < m_ChildCount)
+        {
+            var dif = m_ChildCount - items.Length;
+            if (!string.IsNullOrEmpty(m_ChildPrefabName) && !string.IsNullOrEmpty(m_ChildDisplayName))
+            {
+                for (var i = 0; i < dif; i++)
+                {
+                    var instance = UIUtility.CreateWidget(m_ChildPrefabName, m_ChildDisplayName);
+                    instance.transform.SetParentEx(this.m_Content, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+            }
+        }
+    }
+
+    private void Arrange(Align _align)
+    {
+        var head = infiniteItems[0];
+
+        var offset1 = Vector2.zero;
+        switch (_align)
+        {
+            case Align.Left:
+                offset1 = new Vector2(-content.rect.width * 0.5f + head.rectTransform.rect.width * 0.5f + m_BoundOffset.left, 0);
+                break;
+            case Align.Right:
+                offset1 = new Vector2(content.rect.width * 0.5f - head.rectTransform.rect.width * 0.5f - m_BoundOffset.right, 0);
+                break;
+            case Align.Top:
+                offset1 = new Vector2(0f, content.rect.height * 0.5f - head.rectTransform.rect.height * 0.5f - m_BoundOffset.top);
+                break;
+            case Align.Bottom:
+                offset1 = new Vector2(0f, -content.rect.height * 0.5f + head.rectTransform.rect.height * 0.5f + m_BoundOffset.bottom);
+                break;
+        }
+
+        head.rectTransform.anchoredPosition = content.anchoredPosition + offset1;
+
+        var offset2 = CalculateElementOffset(_align);
+        for (int i = 1; i < infiniteItems.Count; i++)
+        {
+            var item = infiniteItems[i];
+            item.rectTransform.anchoredPosition = head.rectTransform.anchoredPosition + offset2 * i;
+        }
+    }
+
+    private void ElementsMatch()
+    {
+        if (content == null)
+        {
+            DebugEx.Log("Content 涓嶈兘涓虹┖锛�");
+            return;
+        }
+
+        infiniteItems.Clear();
+        for (int i = 0; i < content.childCount; i++)
+        {
+            var infiniteItem = content.GetChild(i).GetComponent<ScrollItem>();
+            if (infiniteItem != null)
+            {
+                infiniteItems.Add(infiniteItem);
+                infiniteItem.rectTransform.sizeDelta = cellSize;
+                infiniteItem.rectTransform.anchorMax = Vector2.one * 0.5f;
+                infiniteItem.rectTransform.anchorMin = Vector2.one * 0.5f;
+                infiniteItem.rectTransform.pivot = Vector2.one * 0.5f;
+            }
+        }
+
+        content.anchorMax = content.anchorMin = content.pivot = Vector2.one * 0.5f;
+        content.sizeDelta = rectTransform.sizeDelta;
+        content.anchoredPosition = Vector2.zero;
+    }
+
+    private void FillBatchData(int _startIndex)
+    {
+        int min = Mathf.Min(infiniteItems.Count, dataCount);
+        preIndex = Mathf.Clamp(_startIndex, 0, dataCount - min);
+        hostIndex = preIndex + min - 1;
+
+        for (int i = 0; i < infiniteItems.Count; i++)
+        {
+            var item = infiniteItems[i];
+            if (i <= hostIndex - preIndex)
+            {
+                item.SetActive(true);
+                item.Display(datas[preIndex + i]);
+                item.LuaDisplay(preIndex + i);
+            }
+            else
+            {
+                item.SetActive(false);
+                item.Dispose();
+                item.LuaDispose();
+            }
+        }
+    }
+
+    private Vector2 CalculateElementOffset(Align _align)
+    {
+        switch (_align)
+        {
+            case Align.Left:
+                return new Vector2(cellSize.x + spacing.x, 0);
+            case Align.Right:
+                return new Vector2(-cellSize.x - spacing.x, 0);
+            case Align.Top:
+                return new Vector2(0, -cellSize.y - spacing.y);
+            case Align.Bottom:
+                return new Vector2(0, cellSize.y + spacing.y);
+            default:
+                return Vector2.zero;
+        }
+    }
+
+    private bool TestMoveNext(Align _align, ScrollItem _item)
+    {
+        var itemMinPosition = _item.rectTransform.GetMinReferencePosition(rectTransform);
+        var itemMaxPosition = _item.rectTransform.GetMaxReferencePosition(rectTransform);
+
+        switch (_align)
+        {
+            case Align.Left:
+                return itemMaxPosition.x < minOffset.x;
+            case Align.Bottom:
+                return itemMaxPosition.y < minOffset.y;
+            case Align.Right:
+                return itemMinPosition.x > maxOffset.x;
+            case Align.Top:
+                return itemMinPosition.y > maxOffset.y;
+            default:
+                return false;
+        }
+    }
+
+    private bool TestMoveLast(Align _align, ScrollItem _item)
+    {
+        var itemMinPosition = _item.rectTransform.GetMinReferencePosition(rectTransform);
+        var itemMaxPosition = _item.rectTransform.GetMaxReferencePosition(rectTransform);
+
+        switch (_align)
+        {
+            case Align.Left:
+                return itemMinPosition.x > maxOffset.x;
+            case Align.Bottom:
+                return itemMinPosition.y > maxOffset.y;
+            case Align.Right:
+                return itemMaxPosition.x < minOffset.x;
+            case Align.Top:
+                return itemMaxPosition.y < minOffset.y;
+            default:
+                return false;
+        }
+    }
+
+    public enum Align
+    {
+        Left,
+        Right,
+        Top,
+        Bottom,
+    }
+
+    [Serializable]
+    public struct BoundOffset
+    {
+        public float left;
+        public float right;
+        public float top;
+        public float bottom;
+    }
+
+}
diff --git a/Main/Component/UI/Common/CyclicScroll.cs.meta b/Main/Component/UI/Common/CyclicScroll.cs.meta
new file mode 100644
index 0000000..d9b6dc3
--- /dev/null
+++ b/Main/Component/UI/Common/CyclicScroll.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b06f319fa42d27842a9a846678d1f3a1
+timeCreated: 1497864198
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/DragContainer.cs b/Main/Component/UI/Common/DragContainer.cs
new file mode 100644
index 0000000..94da996
--- /dev/null
+++ b/Main/Component/UI/Common/DragContainer.cs
@@ -0,0 +1,19 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI {
+
+    public class DragContainer:MonoBehaviour {
+
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/DragContainer.cs.meta b/Main/Component/UI/Common/DragContainer.cs.meta
new file mode 100644
index 0000000..1d51479
--- /dev/null
+++ b/Main/Component/UI/Common/DragContainer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3bb6ceb590c3b4149b31c2e5734a224f
+timeCreated: 1501505038
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/DragItem.cs b/Main/Component/UI/Common/DragItem.cs
new file mode 100644
index 0000000..0e6f8da
--- /dev/null
+++ b/Main/Component/UI/Common/DragItem.cs
@@ -0,0 +1,62 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.EventSystems;
+using System;
+
+namespace vnxbqy.UI {
+
+    public class DragItem:MonoBehaviour,ICanvasRaycastFilter,IBeginDragHandler,IDragHandler,IEndDragHandler {
+
+        [SerializeField]
+        RectTransform m_Area;
+        public RectTransform area { get { return m_Area; } }
+
+        [SerializeField]
+        bool m_RaycastTarget = true;
+        public bool raycastTarget {
+            get { return m_RaycastTarget; }
+            private set { m_RaycastTarget = value; }
+        }
+
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+        public void OnBeginDrag(PointerEventData eventData) {
+            raycastTarget = false;
+            this.transform.position = UIUtility.ClampWorldPosition(area,eventData);
+        }
+
+        public void OnDrag(PointerEventData eventData) {
+            this.transform.position = UIUtility.ClampWorldPosition(area,eventData);
+        }
+
+        public void OnEndDrag(PointerEventData eventData) {
+            raycastTarget = true;
+            if(eventData.pointerEnter == null) {
+                return;
+            }
+
+            var container = eventData.pointerEnter.GetComponent<DragContainer>();
+            if(container == null) {
+                return;
+            }
+
+            var contain = UIUtility.RectTransformContain(eventData.pointerEnter.transform as RectTransform,rectTransform);
+            if(contain) {
+                rectTransform.position = eventData.pointerEnter.transform.position;
+            }
+        }
+
+        public bool IsRaycastLocationValid(Vector2 sp,Camera eventCamera) {
+            return raycastTarget;
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/DragItem.cs.meta b/Main/Component/UI/Common/DragItem.cs.meta
new file mode 100644
index 0000000..a07ada0
--- /dev/null
+++ b/Main/Component/UI/Common/DragItem.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a88319d1c60196045a187a17b2bd893a
+timeCreated: 1501505017
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/DynamicCyclicScroll.cs b/Main/Component/UI/Common/DynamicCyclicScroll.cs
new file mode 100644
index 0000000..5e63227
--- /dev/null
+++ b/Main/Component/UI/Common/DynamicCyclicScroll.cs
@@ -0,0 +1,44 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, August 14, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI
+{
+
+    public class DynamicCyclicScroll : CyclicScroll
+    {
+        [SerializeField] int m_MaxDynamicElements;
+
+        public override void Init<T>(List<T> _datas, bool _stepByStep = false)
+        {
+            var maxCount = Mathf.Min(m_MaxDynamicElements, _datas.Count);
+            var beyond = _datas.Count > m_MaxDynamicElements;
+            switch (align)
+            {
+                case Align.Bottom:
+                case Align.Top:
+                    var height = m_BoundOffset.top + m_BoundOffset.bottom + maxCount * m_CellSize.y + (maxCount - 1) * m_Spacing.y + (beyond ? m_CellSize.y * 0.5f : 0f);
+                    rectTransform.sizeDelta = rectTransform.sizeDelta.SetY(height);
+                    break;
+                case Align.Left:
+                case Align.Right:
+                    var width = m_BoundOffset.left + m_BoundOffset.right + maxCount * m_CellSize.x + (maxCount - 1) * m_Spacing.x + (beyond ? m_CellSize.x * 0.5f : 0f);
+                    rectTransform.sizeDelta = rectTransform.sizeDelta.SetX(width);
+                    break;
+            }
+
+            this.enabled = beyond;
+            base.Init(_datas, _stepByStep);
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/DynamicCyclicScroll.cs.meta b/Main/Component/UI/Common/DynamicCyclicScroll.cs.meta
new file mode 100644
index 0000000..c67f35f
--- /dev/null
+++ b/Main/Component/UI/Common/DynamicCyclicScroll.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0e6d0c1b00a0f8d46998042f6368a2a8
+timeCreated: 1534227370
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/EnableAccordingToMap.cs b/Main/Component/UI/Common/EnableAccordingToMap.cs
new file mode 100644
index 0000000..612feb1
--- /dev/null
+++ b/Main/Component/UI/Common/EnableAccordingToMap.cs
@@ -0,0 +1,88 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, January 10, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+
+namespace vnxbqy.UI
+{
+
+    public class EnableAccordingToMap : MonoBehaviour
+    {
+        [SerializeField] EnableType m_EnableType;
+        [SerializeField] MonoBehaviour m_Component;
+
+        private void Awake()
+        {
+            DTC0403_tagPlayerLoginLoadOK.mapInitOkEvent += OnMapInitOk;
+        }
+
+        private void OnDestroy()
+        {
+            DTC0403_tagPlayerLoginLoadOK.mapInitOkEvent -= OnMapInitOk;
+        }
+
+        private void OnEnable()
+        {
+            OnMapInitOk();
+        }
+
+        private void OnMapInitOk()
+        {
+            if (PlayerDatas.Instance.baseData.MapID == 0)
+            {
+                return;
+            }
+
+            var dungeonModel = ModelCenter.Instance.GetModel<DungeonModel>();
+            var dataMapId = dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID);
+
+            if (dataMapId != 0)
+            {
+                var config = DungeonOpenTimeConfig.Get(dataMapId);
+                switch (m_EnableType)
+                {
+                    case EnableType.PlayerMove:
+                        m_Component.SetActive(config.Movable == 1);
+                        break;
+                    case EnableType.PlayerSkill:
+                        m_Component.enabled = config.Skillable == 1;
+                        break;
+                    case EnableType.SelectPlayer:
+                        m_Component.enabled = config.SelectPlayerable == 1;
+                        break;
+                }
+            }
+            else
+            {
+                switch (m_EnableType)
+                {
+                    case EnableType.PlayerMove:
+                        m_Component.SetActive(true);
+                        break;
+                    case EnableType.PlayerSkill:
+                        m_Component.enabled = true;
+                        break;
+                    case EnableType.SelectPlayer:
+                        m_Component.enabled = true;
+                        break;
+                }
+            }
+        }
+
+        public enum EnableType
+        {
+            PlayerMove,
+            PlayerSkill,
+            SelectPlayer,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/EnableAccordingToMap.cs.meta b/Main/Component/UI/Common/EnableAccordingToMap.cs.meta
new file mode 100644
index 0000000..d6e912e
--- /dev/null
+++ b/Main/Component/UI/Common/EnableAccordingToMap.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 98aa2216d9434214589fdeff3c10dda2
+timeCreated: 1515568744
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/EnableButtonConfig.cs b/Main/Component/UI/Common/EnableButtonConfig.cs
new file mode 100644
index 0000000..20c8160
--- /dev/null
+++ b/Main/Component/UI/Common/EnableButtonConfig.cs
@@ -0,0 +1,51 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using UnityEngine.UI;
+[CreateAssetMenu(menuName = "Config/EnableButtonConfig")]
+public class EnableButtonConfig : ScriptableObject
+{
+    [SerializeField] EnableButtonType type;
+    [SerializeField] EnableButtonStyle enableButton;
+    [SerializeField] EnableButtonStyle unEnableButton;
+
+    public static Dictionary<EnableButtonType, EnableButtonConfig> dict = new Dictionary<EnableButtonType, EnableButtonConfig>();
+
+    public static void SetEnable(Button _btn, Text _text, bool _enable, EnableButtonType _type)
+    {
+        var _cfg = GetEnableButtonCfg(_type);
+        var _btnStyle = _enable ? _cfg.enableButton : _cfg.unEnableButton;
+        _btn.interactable = _enable;
+        var _colors = _btn.colors;
+        _colors.disabledColor = Color.white;
+        _btn.colors = _colors;
+        _btn.image.SetSprite(_btnStyle.iconKey);
+        _text.fontSize = _btnStyle.fontSize;
+        _text.color = _btnStyle.fontColor;
+    }
+
+    public static EnableButtonConfig GetEnableButtonCfg(EnableButtonType _type)
+    {
+        if (dict.ContainsKey(_type))
+        {
+            return dict[_type];
+        }
+        var _cfg= BuiltInLoader.LoadScriptableObject<EnableButtonConfig>(StringUtility.Contact("EnableButton_", _type));
+        dict.Add(_type, _cfg);
+        return _cfg;
+    }
+
+    [Serializable]
+    public struct EnableButtonStyle
+    {
+        public string iconKey;
+        public Color fontColor;
+        public int fontSize;
+    }
+
+    public enum EnableButtonType
+    {
+        Default,
+    }
+}
diff --git a/Main/Component/UI/Common/EnableButtonConfig.cs.meta b/Main/Component/UI/Common/EnableButtonConfig.cs.meta
new file mode 100644
index 0000000..4bac7e2
--- /dev/null
+++ b/Main/Component/UI/Common/EnableButtonConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f39348838e93ba147aa8e4435c5aa70c
+timeCreated: 1516686490
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ErrorProcessor.cs b/Main/Component/UI/Common/ErrorProcessor.cs
new file mode 100644
index 0000000..b7c1214
--- /dev/null
+++ b/Main/Component/UI/Common/ErrorProcessor.cs
@@ -0,0 +1,56 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+public class ErrorProcessor:MonoBehaviour {
+
+    [SerializeField]
+    ErrorInfo[] errors = null;
+
+    public void Process(int _error) {
+        ErrorInfo info;
+        if(FindError(_error,out info)) {
+            switch(info.type) {
+                case ErrorType.PopupTip:
+                    break;
+                case ErrorType.DiamondLack:
+                    break;
+                case ErrorType.GoldLack:
+                    break;
+                case ErrorType.ItemLack:
+                    break;
+            }
+        }
+    }
+
+    bool FindError(int _error,out ErrorInfo _errorInFo) {
+        var result = false;
+        for(int i = 0;i < errors.Length;i++) {
+            var error = errors[i];
+            if(error.error == _error) {
+                _errorInFo = error;
+                result = true;
+                break;
+            }
+        }
+
+        _errorInFo = new ErrorInfo();
+        return result;
+    }
+
+    [Serializable]
+    public struct ErrorInfo {
+        public int error;
+        public ErrorType type;
+        public string parameter;
+    }
+
+    public enum ErrorType {
+        PopupTip,
+        DiamondLack,
+        GoldLack,
+        ItemLack,
+    }
+
+}
diff --git a/Main/Component/UI/Common/ErrorProcessor.cs.meta b/Main/Component/UI/Common/ErrorProcessor.cs.meta
new file mode 100644
index 0000000..e85f5f9
--- /dev/null
+++ b/Main/Component/UI/Common/ErrorProcessor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b1c64b544574e684481d269e396214f0
+timeCreated: 1498989137
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FakeButton.cs b/Main/Component/UI/Common/FakeButton.cs
new file mode 100644
index 0000000..c328acd
--- /dev/null
+++ b/Main/Component/UI/Common/FakeButton.cs
@@ -0,0 +1,75 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, November 25, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(RectTransform))]
+    public class FakeButton : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler
+    {
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform { get { return m_RectTransform ?? (m_RectTransform = this.transform as RectTransform); } }
+
+        UIEvent m_OnClick = new UIEvent();
+
+        public void AddListener(UnityAction _callBack)
+        {
+            m_OnClick.AddListener(_callBack);
+        }
+
+        public void RemoveAllListeners()
+        {
+            m_OnClick.RemoveAllListeners();
+        }
+
+        public void OnPointerUp(PointerEventData eventData)
+        {
+            PassEvent(eventData, ExecuteEvents.pointerUpHandler);
+        }
+
+        public void OnPointerDown(PointerEventData eventData)
+        {
+            PassEvent(eventData, ExecuteEvents.pointerDownHandler);
+        }
+
+        public void OnDrag(PointerEventData eventData)
+        {
+            PassEvent(eventData, ExecuteEvents.dragHandler);
+        }
+
+        public void OnPointerClick(PointerEventData eventData)
+        {
+            m_OnClick.Invoke();
+            PassEvent(eventData, ExecuteEvents.submitHandler);
+            PassEvent(eventData, ExecuteEvents.pointerClickHandler);
+        }
+
+        public void PassEvent<T>(PointerEventData data, ExecuteEvents.EventFunction<T> function) where T : IEventSystemHandler
+        {
+            List<RaycastResult> results = new List<RaycastResult>();
+            EventSystem.current.RaycastAll(data, results);
+            GameObject current = data.pointerCurrentRaycast.gameObject;
+            for (int i = 0; i < results.Count; i++)
+            {
+                if (current != results[i].gameObject)
+                {
+                    if (ExecuteEvents.Execute(results[i].gameObject, data, function))
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/FakeButton.cs.meta b/Main/Component/UI/Common/FakeButton.cs.meta
new file mode 100644
index 0000000..6b624e3
--- /dev/null
+++ b/Main/Component/UI/Common/FakeButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0484034fdef19a64e84cb1cae7a608c3
+timeCreated: 1511596744
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FakeButton2.cs b/Main/Component/UI/Common/FakeButton2.cs
new file mode 100644
index 0000000..30aaa1a
--- /dev/null
+++ b/Main/Component/UI/Common/FakeButton2.cs
@@ -0,0 +1,62 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, November 25, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.Events;
+
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(RectTransform))]
+    public class FakeButton2 : MonoBehaviour
+    {
+
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform { get { return m_RectTransform ?? (m_RectTransform = this.transform as RectTransform); } }
+
+        float overTime = float.MaxValue;
+        UIEvent m_OnClick = new UIEvent();
+
+        public void AddListener(UnityAction _callBack)
+        {
+            m_OnClick.AddListener(_callBack);
+        }
+
+        public void RemoveAllListeners()
+        {
+            m_OnClick.RemoveAllListeners();
+        }
+
+        private void LateUpdate()
+        {
+            if (Input.GetMouseButtonDown(0))
+            {
+                var sp = Input.mousePosition;
+                if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera))
+                {
+                    overTime = Time.realtimeSinceStartup + 0.03f;
+                }
+            }
+
+            if (Input.GetMouseButtonUp(0))
+            {
+                var sp = Input.mousePosition;
+                if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera))
+                {
+                    if (Time.realtimeSinceStartup > overTime)
+                    {
+                        m_OnClick.Invoke();
+                        overTime = float.MaxValue;
+                    }
+                }
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/FakeButton2.cs.meta b/Main/Component/UI/Common/FakeButton2.cs.meta
new file mode 100644
index 0000000..9bf7cbe
--- /dev/null
+++ b/Main/Component/UI/Common/FakeButton2.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5fc2d82dc84af784699eb18eb48db8f3
+timeCreated: 1517044126
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FontColorSizeConfig.cs b/Main/Component/UI/Common/FontColorSizeConfig.cs
new file mode 100644
index 0000000..5e481ab
--- /dev/null
+++ b/Main/Component/UI/Common/FontColorSizeConfig.cs
@@ -0,0 +1,32 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+[CreateAssetMenu(menuName = "Config/FontColorSizeConfig")]
+public class FontColorSizeConfig : ScriptableObject
+{
+    [SerializeField] FontColorSize[] m_ColorSizes;
+
+    public FontColorSize GetColorSize(string _pattern)
+    {
+        for (int i = 0; i < m_ColorSizes.Length; i++)
+        {
+            if (m_ColorSizes[i].pattern == _pattern)
+            {
+                return m_ColorSizes[i];
+            }
+        }
+
+        return default(FontColorSize);
+    }
+
+    [System.Serializable]
+    public struct FontColorSize
+    {
+        public string pattern;
+        public Color color;
+        public int fontSize;
+    }
+
+
+}
diff --git a/Main/Component/UI/Common/FontColorSizeConfig.cs.meta b/Main/Component/UI/Common/FontColorSizeConfig.cs.meta
new file mode 100644
index 0000000..689e4cb
--- /dev/null
+++ b/Main/Component/UI/Common/FontColorSizeConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: cc4487af4243a7a468e2f5ffd8ba0f0a
+timeCreated: 1514627092
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FontSwitch.cs b/Main/Component/UI/Common/FontSwitch.cs
new file mode 100644
index 0000000..d82cc72
--- /dev/null
+++ b/Main/Component/UI/Common/FontSwitch.cs
@@ -0,0 +1,36 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+[ExecuteAlways]
+public class FontSwitch : MonoBehaviour
+{
+    [SerializeField] FontType m_FontType = FontType.Preferred;
+    public FontType fontType { get { return m_FontType; } set { m_FontType = value; } }
+
+    Text m_Text;
+    public Text text { get { return m_Text ?? (m_Text = this.GetComponent<Text>()); } }
+
+    [ExecuteAlways]
+    private void Awake()
+    {
+        switch (m_FontType)
+        {
+            case FontType.Preferred:
+                text.font = FontUtility.preferred;
+                break;
+            case FontType.Secondary:
+                text.font = FontUtility.secondary;
+                break;
+        }
+    }
+
+    public enum FontType
+    {
+        None,
+        Preferred,
+        Secondary
+    }
+
+}
diff --git a/Main/Component/UI/Common/FontSwitch.cs.meta b/Main/Component/UI/Common/FontSwitch.cs.meta
new file mode 100644
index 0000000..d0a4068
--- /dev/null
+++ b/Main/Component/UI/Common/FontSwitch.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 86fc6ccc6ab08fa4783e669416af443c
+timeCreated: 1524751930
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FrameEffect.cs b/Main/Component/UI/Common/FrameEffect.cs
new file mode 100644
index 0000000..88563e3
--- /dev/null
+++ b/Main/Component/UI/Common/FrameEffect.cs
@@ -0,0 +1,98 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Sunday, December 10, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class FrameEffect : MonoBehaviour
+    {
+        [SerializeField] Image m_Behaviour;
+        [SerializeField] Sprite[] m_Sprites;
+
+        float interval = 0.1f;
+        int index = 0;
+        float timer = 0f;
+        float tempSumTime = 1f;
+
+        [SerializeField] float onceTime = 1f;
+        [SerializeField] float sumTime = 1f;
+        [SerializeField] int aniIndex = 0;
+        public bool loop = true;
+
+        public event Action<int> CompleteAct;
+
+        private void OnEnable()
+        {
+            if (m_Sprites != null && m_Sprites.Length > 0)
+            {
+                interval = onceTime / m_Sprites.Length;
+                index = 0;
+                timer = 0f;
+                tempSumTime = sumTime;
+
+                m_Behaviour.overrideSprite = m_Sprites[index];
+            }
+        }
+
+        private void LateUpdate()
+        {
+            timer += Time.deltaTime;
+            tempSumTime -= Time.deltaTime;
+
+            if (m_Sprites == null || m_Sprites.Length == 0)
+            {
+                return;
+            }
+
+            if(tempSumTime > 0)
+            {
+                if (timer > interval)
+                {
+                    m_Behaviour.overrideSprite = m_Sprites[index];
+                    index = (++index) % m_Sprites.Length;
+                    timer -= interval;
+                }
+            }
+            else
+            {
+                if(loop)
+                {
+                    tempSumTime = sumTime;
+                }
+
+                if(CompleteAct != null)
+                {
+                    CompleteAct(aniIndex);
+                }
+            }
+        }
+
+        public void SetSprites(Sprite[] sprites,float _totalTime)
+        {
+            m_Sprites = sprites;
+            onceTime = _totalTime;
+            sumTime = _totalTime;
+            if (m_Sprites != null && m_Sprites.Length > 0)
+            {
+                interval = onceTime / m_Sprites.Length;
+                index = 0;
+                timer = 0f;
+                tempSumTime = sumTime;
+
+                m_Behaviour.sprite = m_Sprites[index];
+                m_Behaviour.overrideSprite = m_Sprites[index];
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/FrameEffect.cs.meta b/Main/Component/UI/Common/FrameEffect.cs.meta
new file mode 100644
index 0000000..0d752df
--- /dev/null
+++ b/Main/Component/UI/Common/FrameEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 34be87e10df140447985e4dd33c62ed8
+timeCreated: 1512874078
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FuncEnable.cs b/Main/Component/UI/Common/FuncEnable.cs
new file mode 100644
index 0000000..1f46340
--- /dev/null
+++ b/Main/Component/UI/Common/FuncEnable.cs
@@ -0,0 +1,43 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+
+using UnityEngine;
+namespace vnxbqy.UI
+{
+    public class FuncEnable : MonoBehaviour
+    {
+        [SerializeField] int funcOpenKey;
+
+        private void Awake()
+        {
+            FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        }
+
+        private void OnEnable()
+        {
+            SetState();
+        }
+
+        private void OnFuncStateChangeEvent(int _key)
+        {
+            if (funcOpenKey == _key)
+            {
+                SetState();
+            }
+        }
+
+        void SetState()
+        {
+            var _funcOpenCfg = FuncOpenLVConfig.Get(funcOpenKey);
+            if (_funcOpenCfg != null && _funcOpenCfg.open == 0)
+            {
+                gameObject.SetActive(false);
+                return;
+            }
+
+            gameObject.SetActive(true);
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/FuncEnable.cs.meta b/Main/Component/UI/Common/FuncEnable.cs.meta
new file mode 100644
index 0000000..383dea1
--- /dev/null
+++ b/Main/Component/UI/Common/FuncEnable.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e034d1a3f772bb44bbbcd4273f5084e1
+timeCreated: 1516430103
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FuncOpen.cs b/Main/Component/UI/Common/FuncOpen.cs
new file mode 100644
index 0000000..39af433
--- /dev/null
+++ b/Main/Component/UI/Common/FuncOpen.cs
@@ -0,0 +1,255 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using LitJson;
+
+namespace vnxbqy.UI
+{
+    
+    public class FuncOpen
+    {
+        private static FuncOpen _inst = null;
+        public static FuncOpen Instance {
+            get {
+                if (_inst == null)
+                {
+                    _inst = new FuncOpen();
+                }
+                return _inst;
+            }
+        }
+
+        protected FuncOpen()
+        {
+            if (Application.isEditor)
+            {
+                if (!Application.isPlaying) return;
+            }
+
+            var allKeys = FuncOpenLVConfig.GetKeys();
+            funcArray = new int[allKeys.Count];
+            int _index = 0;
+            foreach (var key in allKeys)
+            {
+                int func = int.Parse(key);
+                funcOpenState[func] = false;
+                funcArray[_index] = func;
+                _index++;
+            }
+
+            DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += BeforePlayerDataInitializeEvent;
+            DTC0102_tagCDBPlayer.switchAccountEvent += SwitchAccountEvent;
+
+            funcClientLVLimitDict.Clear();
+            var jsonConfig = JsonMapper.ToObject(FuncConfigConfig.Get("FuncLevelLimitClient").Numerical1);
+            foreach (var key in jsonConfig.Keys)
+            {
+                funcClientLVLimitDict[int.Parse(key)] = int.Parse(jsonConfig[key].ToString());
+            }
+        }
+
+        private void BeforePlayerDataInitializeEvent()
+        {
+            for (int i = 0; i < funcArray.Length; i++)
+            {
+                funcOpenState[funcArray[i]] = false;
+            }
+        }
+
+        private void SwitchAccountEvent()
+        {
+            for (int i = 0; i < funcArray.Length; i++)
+            {
+                funcOpenState[funcArray[i]] = false;
+                if (OnFuncStateChangeEvent != null)
+                {
+                    OnFuncStateChangeEvent(funcArray[i]);
+                }
+            }
+        }
+
+        TaskModel m_TaskModel;
+        TaskModel taskmodel { get { return m_TaskModel ?? (m_TaskModel = ModelCenter.Instance.GetModel<TaskModel>()); } }
+        private static Dictionary<int, bool> funcOpenState = new Dictionary<int, bool>();
+        private int[] funcArray;
+
+        public event Action<int> OnFuncStateChangeEvent;
+
+        //绾鎴风鐨勫姛鑳界瓑绾ч檺鍒�, key 浠ュ姛鑳介厤缃〃鐨凢uncLevelLimitClient涓哄噯
+        //1. 绮惧僵娲诲姩-鍏ㄦ湇绾㈠寘鏄剧ず绛夌骇
+        public Dictionary<int, int> funcClientLVLimitDict = new Dictionary<int, int>();
+        public bool IsClientLVLimit(int key)
+        {
+            if (!funcClientLVLimitDict.ContainsKey(key))
+                return true;
+
+            if (PlayerDatas.Instance.baseData.LV >= funcClientLVLimitDict[key])
+                return true;
+
+            return false;
+        }
+
+
+        public void UpdateFuncState(HA302_tagMCFuncOpenStateList vNetData)
+        {
+            for (int i = 0; i < vNetData.FuncCount; i++)
+            {
+                
+                var funcState = vNetData.FuncStateList[i];
+
+                bool bPerFuncIsOpen = false;
+                bool bAfterFuncIsOpen = false;
+
+                if (!funcOpenState.ContainsKey(funcState.FuncID))
+                {
+                    funcOpenState.Add(funcState.FuncID, funcState.State == 1);
+                    bAfterFuncIsOpen = true;
+                }
+                else
+                {
+                    bPerFuncIsOpen = funcOpenState[funcState.FuncID];
+                    funcOpenState[funcState.FuncID] = funcState.State == 1;
+                    bAfterFuncIsOpen = funcOpenState[funcState.FuncID];
+                }
+                if (OnFuncStateChangeEvent != null)
+                {
+                    OnFuncStateChangeEvent(funcState.FuncID);
+                }
+            }
+        }
+
+        private bool IsFuncOpen(int key, out int errorCode)
+        {
+            errorCode = 0;
+            var config = FuncOpenLVConfig.Get(key);
+            if (config == null)
+            {
+                return false;
+            }
+            if (config.LimitMagicWeapon > 0)
+            {
+                Treasure treasure = null;
+                var _stage = config.LimitMagicWeapon % 100;
+                ModelCenter.Instance.GetModel<TreasureModel>().TryGetTreasure(config.LimitMagicWeapon / 100, out treasure);
+                if (treasure == null || treasure.state != TreasureState.Collected || treasure.level < _stage)
+                {
+                    errorCode = 2;
+                    return false;
+                }
+            }
+            if (config.LimitMissionID > 0)
+            {
+                MissionDetailDates missionDetailDates = null;
+                taskmodel.allMissionDict.TryGetValue(config.LimitMissionID, out missionDetailDates);
+                if (missionDetailDates == null || missionDetailDates.MissionState != 3)
+                {
+                    errorCode = 4;
+                    return false;
+                }
+            }
+            if (config.LimiRealmLV > 0 && PlayerDatas.Instance.baseData.realmLevel < config.LimiRealmLV)
+            {
+                errorCode = 3;
+                return false;
+            }
+            if (config.LimitLV > 0 && PlayerDatas.Instance.baseData.LV < config.LimitLV)
+            {
+                errorCode = 1;
+                return false;
+            }
+            return true;
+        }
+
+        public bool IsFuncOpen(int key, bool tip = false)
+        {
+            bool isOpen = false;
+            if (funcOpenState.ContainsKey(key))
+                isOpen = funcOpenState[key];
+            if (!isOpen && tip)
+                ProcessorFuncErrorTip(key);
+            return isOpen;
+        }
+
+        public void ProcessorFuncErrorTip(int key)
+        {
+            var config = FuncOpenLVConfig.Get(key);
+            if (config != null)
+            {
+                SoundPlayer.Instance.PlayUIAudio(SoundPlayer.defaultClickNegativeAudio);
+                if (config.Tip.Equals("FuncLimit_Level"))
+                {
+                    SysNotifyMgr.Instance.ShowTip(config.Tip);
+                    return;
+                }
+                var errorCode = 0;
+                if (!IsFuncOpen(key, out errorCode))
+                {
+                    switch (errorCode)
+                    {
+                        case 1:
+                            SysNotifyMgr.Instance.ShowTip(config.Tip, Language.Get("OpenFunc4", config.LimitLV));
+                            break;
+                        case 2:
+                            var treasureConfig = TreasureConfig.Get(config.LimitMagicWeapon / 100);
+                            SysNotifyMgr.Instance.ShowTip(config.Tip, Language.Get("OpenFunc1", treasureConfig != null ? treasureConfig.Name : string.Empty));
+                            break;
+                        case 3:
+                            SysNotifyMgr.Instance.ShowTip(config.Tip, UIHelper.GetRealmName(config.LimiRealmLV, true));
+                            break;
+                        case 4:
+                            if (config.LimitLV > 0)
+                            {
+                                SysNotifyMgr.Instance.ShowTip(config.Tip, Language.Get("OpenFunc2", config.LimitLV));
+                            }
+                            else
+                            {
+                                SysNotifyMgr.Instance.ShowTip(config.Tip, Language.Get("OpenFunc3"));
+                            }
+                            break;
+                    }
+                }
+            }
+        }
+
+        public int GetLimitLv(int key)
+        {
+            FuncOpenLVConfig tagFuncOpenLVModel = FuncOpenLVConfig.Get(key);
+            if (tagFuncOpenLVModel.LimitLV != 0)
+            {
+                return tagFuncOpenLVModel.LimitLV;
+            }
+            if (tagFuncOpenLVModel.LimitMissionID != 0)
+            {
+                var TaskConfig = PyTaskConfig.Get(tagFuncOpenLVModel.LimitMissionID);
+                return TaskConfig.lv;
+            }
+
+            return 1;
+        }
+
+        Dictionary<int, ICheckFuncOpen> m_CheckFuncDict = new Dictionary<int, ICheckFuncOpen>();
+        public void Register(int _key, ICheckFuncOpen _check)
+        {
+            if (!m_CheckFuncDict.ContainsKey(_key))
+            {
+                m_CheckFuncDict.Add(_key, _check);
+            }
+        }
+
+        public bool CheckFuncOpen(int _key)
+        {
+            if (m_CheckFuncDict.ContainsKey(_key))
+            {
+                return m_CheckFuncDict[_key].CheckFunc();
+            }
+            return true;
+        }
+    }
+
+    public interface ICheckFuncOpen
+    {
+        bool CheckFunc();
+    }
+}
+
diff --git a/Main/Component/UI/Common/FuncOpen.cs.meta b/Main/Component/UI/Common/FuncOpen.cs.meta
new file mode 100644
index 0000000..d977f74
--- /dev/null
+++ b/Main/Component/UI/Common/FuncOpen.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d02ef6a56ee8e9c478eb73f53d73574c
+timeCreated: 1510986767
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FunctionButton.cs b/Main/Component/UI/Common/FunctionButton.cs
new file mode 100644
index 0000000..73a3f74
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButton.cs
@@ -0,0 +1,262 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, October 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+
+using System;
+
+namespace vnxbqy.UI
+{
+
+    
+    public class FunctionButton : Button
+    {
+        [SerializeField] int m_Order = 0;
+        public int order {
+            get { return m_Order; }
+            set {
+                m_Order = value;
+            }
+        }
+
+        [SerializeField] int m_FunctionId = -1;
+        public int functionId {
+            get { return m_FunctionId; }
+            set {
+                m_FunctionId = value;
+                OnFunctionUnLockStateChange();
+            }
+        }
+
+        [SerializeField] TitleBtnState m_State = TitleBtnState.Normal;
+        public TitleBtnState state {
+            get { return m_State; }
+            set {
+                if (m_State != value)
+                {
+                    m_State = value;
+                    OnStateChange();
+                }
+            }
+        }
+
+        [SerializeField] Button m_Button;
+        public Button button {
+            get { return m_Button; }
+            set { m_Button = value; }
+        }
+
+        [SerializeField] ImageEx m_Icon;
+        public ImageEx icon {
+            get { return this.m_Icon; }
+            set { this.m_Icon = value; }
+        }
+
+        [SerializeField] TextEx m_Title;
+        public TextEx title {
+            get { return this.m_Title; }
+            set { this.m_Title = value; }
+        }
+
+        [SerializeField] RedpointBehaviour m_Redpoint;
+        public RedpointBehaviour redpoint {
+            get { return m_Redpoint; }
+            set { m_Redpoint = value; }
+        }
+
+        [SerializeField] Shadow m_Shadow;
+        public Shadow shadow {
+            get { return this.m_Shadow; }
+            set { this.m_Shadow = value; }
+        }
+
+        [SerializeField] Transform m_Locked;
+        public Transform locked {
+            get { return this.m_Locked; }
+            set { this.m_Locked = value; }
+        }
+
+        [SerializeField] int m_Audio = 1;
+        public int clickAudio {
+            get { return this.m_Audio; }
+            set { this.m_Audio = value; }
+        }
+
+        [SerializeField] bool m_UseDefaultConfig = true;
+        public bool useDefaultConfig {
+            get { return this.m_UseDefaultConfig; }
+            set { this.m_UseDefaultConfig = value; }
+        }
+
+        [SerializeField] FunctionButtonConfig m_AlternativeConfig;
+        public FunctionButtonConfig alternativeConfig { get { return m_AlternativeConfig; } set { m_AlternativeConfig = value; } }
+
+        [SerializeField]
+        FunctionButtonGroup m_Group;
+        public FunctionButtonGroup group {
+            get { return m_Group; }
+            set {
+                if (m_Group != null)
+                {
+                    m_Group.UnRegister(this);
+                }
+                m_Group = value;
+                if (m_Group != null)
+                {
+                    m_Group.Register(this);
+                }
+            }
+        }
+
+        public event Action<string> OnPointClickLockFunc;
+        public event Action repeatClickFunc;
+
+        protected override void Awake()
+        {
+#if UNITY_EDITOR
+            if (!Application.isPlaying) return;
+#endif
+            OnFunctionUnLockStateChange();
+            FuncOpen.Instance.OnFuncStateChangeEvent += OnFunctionUnLockStateChange;
+        }
+
+        protected override void OnEnable()
+        {
+            base.OnEnable();
+
+            if (group != null)
+            {
+                group.Register(this);
+            }
+
+            OnStateChange();
+        }
+
+        protected override void OnDisable()
+        {
+            base.OnDisable();
+
+            if (group != null)
+            {
+                group.UnRegister(this);
+            }
+        }
+
+        protected override void OnDestroy()
+        {
+#if UNITY_EDITOR
+            if (!Application.isPlaying) return;
+#endif
+            FuncOpen.Instance.OnFuncStateChangeEvent -= OnFunctionUnLockStateChange;
+        }
+
+        bool invokeForce = false;
+
+        public void Invoke(bool _force)
+        {
+            invokeForce = _force;
+            OnPointerClick(null);
+            invokeForce = false;
+        }
+
+        public override void OnPointerClick(PointerEventData eventData)
+        {
+            if (state == TitleBtnState.Locked)
+            {
+                if (OnPointClickLockFunc != null)
+                {
+                    OnPointClickLockFunc(this.gameObject.name);
+                }
+                else
+                {
+                    FuncOpen.Instance.ProcessorFuncErrorTip(functionId);
+                }
+                return;
+            }
+
+            if (!invokeForce && state == TitleBtnState.Click)
+            {
+                if (repeatClickFunc != null)
+                {
+                    repeatClickFunc();
+                }
+                return;
+            }
+
+            if (base.onClick != null)
+            {
+                base.onClick.Invoke();
+                if (eventData != null)
+                {
+                    SoundPlayer.Instance.PlayUIAudio(clickAudio);
+                }
+            }
+
+            state = TitleBtnState.Click;
+        }
+
+        private void OnStateChange()
+        {
+            var config = useDefaultConfig ? FunctionButtonConfig.GetDefault() : m_AlternativeConfig;
+            if (Application.isPlaying)
+            {
+                icon.SetSprite(config.GetIconKey(state));
+            }
+
+            title.color = config.GetFontColor(state);
+            title.fontSize = config.GetFontSize(state);
+
+            if (shadow != null)
+            {
+                shadow.enabled = state == TitleBtnState.Locked || state == TitleBtnState.Normal;
+            }
+
+            if (locked != null)
+            {
+                locked.SetActive(state == TitleBtnState.Locked);
+            }
+
+            if (group != null && state == TitleBtnState.Click)
+            {
+                group.NotifyToggleOn(this);
+            }
+        }
+
+        private void OnFunctionUnLockStateChange(int _functionId)
+        {
+            if (m_FunctionId == _functionId)
+            {
+                OnFunctionUnLockStateChange();
+            }
+        }
+
+        private void OnFunctionUnLockStateChange()
+        {
+            if (m_FunctionId == 0)
+            {
+                return;
+            }
+
+            var isOpen = m_FunctionId == -1 || FuncOpen.Instance.IsFuncOpen(m_FunctionId);
+            state = isOpen ? state == TitleBtnState.Click ? TitleBtnState.Click : TitleBtnState.Normal : TitleBtnState.Locked;
+        }
+
+#if UNITY_EDITOR
+        protected override void OnValidate()
+        {
+            base.OnValidate();
+            OnStateChange();
+        }
+#endif
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/FunctionButton.cs.meta b/Main/Component/UI/Common/FunctionButton.cs.meta
new file mode 100644
index 0000000..c8db50d
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 664d685950b154f46ad19f11eb19745d
+timeCreated: 1509430528
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FunctionButtonConfig.cs b/Main/Component/UI/Common/FunctionButtonConfig.cs
new file mode 100644
index 0000000..9891ba6
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButtonConfig.cs
@@ -0,0 +1,84 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+[CreateAssetMenu(menuName = "Config/FunctionButtonConfig")]
+public class FunctionButtonConfig : ScriptableObject
+{
+    public UIConfig normal = new UIConfig("Title_Normal", Color.white, 23);
+    public UIConfig selected = new UIConfig("Title_Clicked", Color.white, 24);
+    public UIConfig locked = new UIConfig("Title_Locked", Color.white, 23);
+
+    static FunctionButtonConfig m_Default;
+    public static FunctionButtonConfig GetDefault()
+    {
+        if (m_Default == null)
+        {
+            m_Default = BuiltInLoader.LoadScriptableObject<FunctionButtonConfig>("FunctionButton_Default");
+        }
+
+        return m_Default;
+    }
+
+    public string GetIconKey(TitleBtnState _state)
+    {
+        switch (_state)
+        {
+            case TitleBtnState.Click:
+                return selected.iconKey;
+            case TitleBtnState.Normal:
+                return normal.iconKey;
+            case TitleBtnState.Locked:
+                return locked.iconKey;
+            default:
+                return string.Empty;
+        }
+    }
+
+    public Color GetFontColor(TitleBtnState _state)
+    {
+        switch (_state)
+        {
+            case TitleBtnState.Click:
+                return selected.fontColor;
+            case TitleBtnState.Normal:
+                return normal.fontColor;
+            case TitleBtnState.Locked:
+                return locked.fontColor;
+            default:
+                return Color.white;
+        }
+    }
+
+    public int GetFontSize(TitleBtnState _state)
+    {
+        switch (_state)
+        {
+            case TitleBtnState.Click:
+                return selected.fontSize;
+            case TitleBtnState.Normal:
+                return normal.fontSize;
+            case TitleBtnState.Locked:
+                return locked.fontSize;
+            default:
+                return 24;
+        }
+    }
+
+    [System.Serializable]
+    public struct UIConfig
+    {
+        public string iconKey;
+        public Color fontColor;
+        public int fontSize;
+
+        public UIConfig(string _icon, Color _fontColor, int _fontSize)
+        {
+            this.iconKey = _icon;
+            this.fontColor = _fontColor;
+            this.fontSize = _fontSize;
+        }
+    }
+
+}
diff --git a/Main/Component/UI/Common/FunctionButtonConfig.cs.meta b/Main/Component/UI/Common/FunctionButtonConfig.cs.meta
new file mode 100644
index 0000000..f55a3a7
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButtonConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 88e7803e2c32f7941bdda580ca116d80
+timeCreated: 1513476401
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/FunctionButtonGroup.cs b/Main/Component/UI/Common/FunctionButtonGroup.cs
new file mode 100644
index 0000000..4fe1177
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButtonGroup.cs
@@ -0,0 +1,269 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, October 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+using UnityEngine.Events;
+
+namespace vnxbqy.UI
+{
+
+    public class FunctionButtonGroup : MonoBehaviour
+    {
+        [SerializeField] ScrollRect m_ScrollRect;
+        [SerializeField] RectTransform m_Container;
+
+        public int unLockedCount {
+            get {
+                var count = 0;
+                foreach (var button in functionButtons.Values)
+                {
+                    if (button.state != TitleBtnState.Locked)
+                    {
+                        count++;
+                    }
+                }
+
+                return count;
+            }
+        }
+
+        int currentOrder = 0;
+        List<int> orders = new List<int>();
+        Dictionary<int, FunctionButton> functionButtons = new Dictionary<int, FunctionButton>();
+
+        public void Register(FunctionButton button)
+        {
+            functionButtons[button.order] = button;
+            if (!orders.Contains(button.order))
+            {
+                orders.Add(button.order);
+                orders.Sort(OrderCompare);
+            }
+
+            if (m_ScrollRect != null)
+            {
+                m_ScrollRect.horizontal = functionButtons.Count > 5;
+            }
+        }
+
+        public void ChangeHorizontal(bool move)
+        {
+            if (m_ScrollRect != null)
+            {
+                m_ScrollRect.horizontal = move;
+            }
+        }
+
+        public void ChangeHorizontalPos(float index)
+        {
+            if (m_ScrollRect != null)
+            {
+                m_ScrollRect.horizontalNormalizedPosition = index;
+            }
+        }
+        public void UnRegister(FunctionButton button)
+        {
+            if (functionButtons.ContainsKey(button.order))
+            {
+                functionButtons.Remove(button.order);
+            }
+
+            if (orders.Contains(button.order))
+            {
+                orders.Remove(button.order);
+                orders.Sort(OrderCompare);
+            }
+
+            if (m_ScrollRect != null)
+            {
+                m_ScrollRect.horizontal = functionButtons.Count > 5;
+            }
+        }
+
+        public void NotifyToggleOn(FunctionButton button)
+        {
+
+            if (button.state == TitleBtnState.Click)
+            {
+                currentOrder = button.order;
+                for (int i = 0; i < orders.Count; i++)
+                {
+                    if (!functionButtons.ContainsKey(orders[i]))
+                    {
+                        Debug.LogFormat("<color=#ff0000ff>{0} {1}</color>", orders[i], button.name);
+                    }
+                    var functionButton = functionButtons[orders[i]];
+                    if (functionButton != button && functionButton.state != TitleBtnState.Locked)
+                    {
+                        functionButton.state = TitleBtnState.Normal;
+                    }
+                }
+            }
+        }
+
+        public void TriggerByOrder(int targetOrder)
+        {
+            for (int i = 0; i < orders.Count; i++)
+            {
+                var order = orders[i];
+                if (order == targetOrder)
+                {
+                    functionButtons[order].Invoke(true);
+                    break;
+                }
+            }
+        }
+
+        public void TriggerLast()
+        {
+            var index = orders.IndexOf(currentOrder);
+            if (index < 0)
+            {
+                return;
+            }
+
+            var loopTimes = 0;
+            while (loopTimes < 2)
+            {
+                index--;
+                if (index < 0)
+                {
+                    index = orders.Count - 1;
+                    loopTimes++;
+                }
+
+                var next = orders[index];
+                if (functionButtons[next].state != TitleBtnState.Locked)
+                {
+                    functionButtons[next].Invoke(false);
+                    break;
+                }
+            }
+
+        }
+
+        public void TriggerNext()
+        {
+            var index = orders.IndexOf(currentOrder);
+            if (index < 0)
+            {
+                return;
+            }
+
+            var loopTimes = 0;
+            while (loopTimes < 2)
+            {
+                index++;
+                if (index > orders.Count - 1)
+                {
+                    index = 0;
+                    loopTimes++;
+                }
+
+                var next = orders[index];
+                if (functionButtons[next].state != TitleBtnState.Locked)
+                {
+                    functionButtons[next].Invoke(false);
+                    break;
+                }
+            }
+        }
+
+        public bool IsFirst()
+        {
+            return orders.Count > 0 && currentOrder == orders[0];
+        }
+
+        public bool IsLast()
+        {
+            return orders.Count > 0 && currentOrder == orders[orders.Count - 1];
+        }
+
+        public void GotoOrder(int order)
+        {
+            if (m_ScrollRect != null)
+            {
+                var index = orders.IndexOf(order);
+                if (m_ScrollRect.horizontal)
+                {
+                    m_ScrollRect.horizontalNormalizedPosition = (float)index / orders.Count;
+                }
+                else if (m_ScrollRect.vertical)
+                {
+                    m_ScrollRect.verticalNormalizedPosition = (float)index / orders.Count;
+                }
+            }
+        }
+
+        private int OrderCompare(int a, int b)
+        {
+            return a < b ? -1 : 1;
+        }
+
+        public FunctionButton AddFunction(string pattern, int order, int functionId, string title, int redpointId)
+        {
+            if (m_Container == null)
+            {
+                return null;
+            }
+
+            var instance = UIUtility.CreateWidget(pattern, string.Concat("Function_", order));
+            instance.transform.SetParentEx(this.m_Container, Vector3.zero, Quaternion.identity, Vector3.one);
+
+            var functionButton = instance.GetComponent<FunctionButton>();
+            functionButton.functionId = functionId;
+            functionButton.order = order;
+            functionButton.title.text = title;
+
+            functionButton.group = this;
+            functionButton.redpoint.redpointId = redpointId;
+            functionButtons[order] = functionButton;
+
+            functionButton.SetActive(functionButton.functionId != -1);
+            return functionButton;
+        }
+
+        public void SetFunctionListener(int order, UnityAction callBack)
+        {
+            if (functionButtons.ContainsKey(order))
+            {
+                functionButtons[order].SetListener(callBack);
+            }
+        }
+
+        public void SetFunctionButtonActive(int order, bool isShow)
+        {
+            if (functionButtons.ContainsKey(order))
+            {
+                functionButtons[order].SetActive(isShow);
+            }
+        }
+
+        public RedPointState GetFunctionButtonRedPointState(int order)
+        {
+            if (functionButtons.ContainsKey(order))
+            {
+                return RedpointCenter.Instance.GetRedpointState(functionButtons[order].redpoint.redpointId);
+            }
+
+            return RedPointState.None;
+        }
+
+        public FunctionButton GetFunctionBtn(int order)
+        {
+            if (functionButtons.ContainsKey(order))
+            {
+                return functionButtons[order];
+            }
+            return null;
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/FunctionButtonGroup.cs.meta b/Main/Component/UI/Common/FunctionButtonGroup.cs.meta
new file mode 100644
index 0000000..207d75d
--- /dev/null
+++ b/Main/Component/UI/Common/FunctionButtonGroup.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 79a8f4e83ded1f4408e67512d4f46769
+timeCreated: 1509430798
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/GameObjectDefaultActive.cs b/Main/Component/UI/Common/GameObjectDefaultActive.cs
new file mode 100644
index 0000000..8dd9e8e
--- /dev/null
+++ b/Main/Component/UI/Common/GameObjectDefaultActive.cs
@@ -0,0 +1,27 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI {
+    public class GameObjectDefaultActive:MonoBehaviour {
+
+        [SerializeField]
+        bool m_DefaultActive = true;
+        public bool defaultActive {
+            get { return m_DefaultActive; }
+        }
+
+
+        void Awake() {
+            this.SetActive(defaultActive);
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/GameObjectDefaultActive.cs.meta b/Main/Component/UI/Common/GameObjectDefaultActive.cs.meta
new file mode 100644
index 0000000..2fb7d56
--- /dev/null
+++ b/Main/Component/UI/Common/GameObjectDefaultActive.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 528a3bd28e7b61a49bae6f4ddcce6b92
+timeCreated: 1501494446
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/GestureCatcher.cs b/Main/Component/UI/Common/GestureCatcher.cs
new file mode 100644
index 0000000..35ce333
--- /dev/null
+++ b/Main/Component/UI/Common/GestureCatcher.cs
@@ -0,0 +1,42 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, March 16, 2019
+//--------------------------------------------------------
+using System;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+
+public class GestureCatcher : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
+{
+    Action<Vector2> m_OnDrag;
+    Vector2 prePosition = Vector2.zero;
+
+    public void SetDragListener(Action<Vector2> callBack)
+    {
+        m_OnDrag = callBack;
+    }
+
+    public void RemoveListener()
+    {
+        m_OnDrag = null;
+    }
+
+    public void OnBeginDrag(PointerEventData eventData)
+    {
+        prePosition = eventData.position;
+    }
+
+    public void OnDrag(PointerEventData eventData)
+    {
+        var deltaPosition = eventData.position - prePosition;
+        m_OnDrag.Invoke(deltaPosition);
+        prePosition = eventData.position;
+    }
+
+    public void OnEndDrag(PointerEventData eventData)
+    {
+        prePosition = eventData.position;
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Common/GestureCatcher.cs.meta b/Main/Component/UI/Common/GestureCatcher.cs.meta
new file mode 100644
index 0000000..3f39bc4
--- /dev/null
+++ b/Main/Component/UI/Common/GestureCatcher.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c25c35ceba2cf9140a2ed7743a3e6dec
+timeCreated: 1552721974
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/InputSpecialWordLimit.cs b/Main/Component/UI/Common/InputSpecialWordLimit.cs
new file mode 100644
index 0000000..815479f
--- /dev/null
+++ b/Main/Component/UI/Common/InputSpecialWordLimit.cs
@@ -0,0 +1,44 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using UnityEngine;
+using UnityEngine.UI;
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(InputField))]
+    public class InputSpecialWordLimit : MonoBehaviour
+    {
+        [SerializeField, Header("鏄惁闄愬埗绌烘牸")] bool m_SpaceLimit = false;
+        private void Awake()
+        {
+            var _input = GetComponent<InputField>();
+            _input.onValidateInput = OnValidateInput;
+        }
+
+        private char OnValidateInput(string text, int charIndex, char addedChar)
+        {
+            if (char.GetUnicodeCategory(addedChar) == UnicodeCategory.Surrogate
+                || char.GetUnicodeCategory(addedChar) == UnicodeCategory.OtherSymbol
+                || char.GetUnicodeCategory(addedChar) == UnicodeCategory.OtherNumber
+                || char.GetUnicodeCategory(addedChar) == UnicodeCategory.MathSymbol
+                || char.GetUnicodeCategory(addedChar) == UnicodeCategory.OtherNotAssigned
+                || addedChar == '\n')
+            {
+                return (char)0;
+            }
+            if (m_SpaceLimit)
+            {
+                if (addedChar == ' '
+                 || addedChar == '銆�'
+                 || char.GetUnicodeCategory(addedChar) == UnicodeCategory.SpaceSeparator)
+                {
+                    return (char)0;
+                }
+            }
+            return addedChar;
+        }
+    }
+}
+
+
diff --git a/Main/Component/UI/Common/InputSpecialWordLimit.cs.meta b/Main/Component/UI/Common/InputSpecialWordLimit.cs.meta
new file mode 100644
index 0000000..7f6a1fd
--- /dev/null
+++ b/Main/Component/UI/Common/InputSpecialWordLimit.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fc537d01fab44c84eb4278864f36a914
+timeCreated: 1519545424
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ItemBaseEffect.cs b/Main/Component/UI/Common/ItemBaseEffect.cs
new file mode 100644
index 0000000..8ef1f64
--- /dev/null
+++ b/Main/Component/UI/Common/ItemBaseEffect.cs
@@ -0,0 +1,157 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+namespace vnxbqy.UI
+{
+    public class ItemBaseEffect : MonoBehaviour
+    {
+        [SerializeField] UIEffect m_SuitEffect;
+        
+        int itemId = 0;
+
+        private void OnEnable()
+        {
+            Display(itemId);
+        }
+
+        public void Display(int itemId, bool dirty = false)
+        {
+            this.itemId = itemId;
+            var curItem = ItemConfig.Get(this.itemId);
+            bool isPlay = true;
+            if (curItem == null)
+            {
+                isPlay = false;
+                return;
+            }
+
+            int effectId = 0;
+            switch (curItem.ItemColor)
+            {
+                case 4:
+                    effectId = 7119;
+                    break;
+                case 5:
+                    effectId = 7120;
+                    break;
+                case 6:
+                case 7:
+                case 8:
+                    effectId = 7121;
+                    break;
+            }
+
+            if (curItem.BaseEffectID != 0)
+            {
+                effectId = curItem.BaseEffectID;
+            }
+
+            if (m_SuitEffect.effect != effectId)
+            {
+                //鍚屼竴涓綅缃浛鎹㈢壒鏁堥渶瑕佸厛閲婃斁
+                m_SuitEffect.StopImediatly();
+            }
+            m_SuitEffect.effect = effectId;
+
+            if (m_SuitEffect.effect == 0)
+            {
+                isPlay = false;
+            }
+            if (isPlay)
+            {
+                m_SuitEffect.Play();
+            }
+            else
+            {
+                m_SuitEffect.StopImediatly();
+            }
+
+            if (dirty)
+            {
+                SnxxzGame.Instance.StartCoroutine(Co_SetOrder(this, transform as RectTransform));
+            }
+        }
+
+        public static ItemBaseEffect Create(RectTransform transform)
+        {
+            var go = UIUtility.CreateWidget("ItemBaseEffect", "ItemBaseEffect");
+            var behaviour = go.GetComponent<ItemBaseEffect>();
+
+            SnxxzGame.Instance.StartCoroutine(Co_SetOrder(behaviour, transform));
+
+            var scale = 1f;
+            var itemBasic = transform.GetComponentInParent<CommonItemBaisc>();
+            if (itemBasic == null)
+                itemBasic = transform.GetComponentInParent<ItemCell>();
+            if (itemBasic != null)
+            {
+                scale = GetEffectScale(itemBasic.format);
+            }
+            else
+            {
+                var itemBehaviour = transform.GetComponentInParent<ItemBehaviour>();
+                if (itemBehaviour != null)
+                {
+                    if (itemBehaviour.backGround != null)
+                    {
+                        var size = itemBehaviour.backGround.rectTransform.rect.width;
+                        scale = size / 84;
+                    }
+                }
+                else
+                {
+                    var findPreciousItemBehaviour = transform.GetComponentInParent<FindPreciousItemBehaviour>();
+                    if (findPreciousItemBehaviour != null)
+                    {
+                        scale = 0.86f;  //鏆備笖鍐欐
+                    }
+                }
+            }
+
+            var rect = go.transform as RectTransform;
+            go.transform.SetParentEx(transform, Vector3.zero, Quaternion.identity, Vector3.one);
+            rect.MatchWhith(transform);
+            go.transform.localScale = Vector3.one * scale;
+            go.transform.SetAsLastSibling();
+
+            return behaviour;
+        }
+
+        static IEnumerator Co_SetOrder(ItemBaseEffect behaviour, RectTransform transform)
+        {
+            yield return null;
+
+            if (transform == null || behaviour == null)
+            {
+                yield break;
+            }
+
+            Canvas canva = transform.GetComponentInParent<Canvas>();
+            if (canva != null)
+            {
+                behaviour.m_SuitEffect.ResetOrder(canva.sortingOrder + 1);
+            }
+
+            if (behaviour.m_SuitEffect.maskArea == null)
+            {
+                behaviour.m_SuitEffect.SetMask();
+            }
+        }
+
+        static float GetEffectScale(ItemCellformat format)
+        {
+            switch (format)
+            {
+                case ItemCellformat.Format_80x80:
+                    return 0.95f;
+                case ItemCellformat.Format_70x70:
+                    return 0.83f;
+                case ItemCellformat.Format_64x64:
+                    return 0.76f;
+                default:
+                    return 1f;
+            }
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/ItemBaseEffect.cs.meta b/Main/Component/UI/Common/ItemBaseEffect.cs.meta
new file mode 100644
index 0000000..423ea25
--- /dev/null
+++ b/Main/Component/UI/Common/ItemBaseEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ad12bde7ddfa38e44aa5dc55f1075bc2
+timeCreated: 1603121065
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ItemBehaviour.cs b/Main/Component/UI/Common/ItemBehaviour.cs
new file mode 100644
index 0000000..21eb75f
--- /dev/null
+++ b/Main/Component/UI/Common/ItemBehaviour.cs
@@ -0,0 +1,199 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+
+using vnxbqy.UI;
+
+namespace vnxbqy.UI
+{
+    
+    public class ItemBehaviour : MonoBehaviour
+    {
+        
+
+        [SerializeField] ImageEx m_Icon;
+        public ImageEx icon { get { return m_Icon; } }
+
+        [SerializeField] ImageEx m_BackGround;
+        public ImageEx backGround { get { return m_BackGround; } }
+
+        [SerializeField] Transform m_CountContainer;
+        public Transform countContainer { get { return m_CountContainer; } }
+
+        [SerializeField] Text m_Count;
+        public Text count { get { return m_Count; } }
+
+        [SerializeField] Button m_ViewDetails;
+
+        [SerializeField] ItemType m_ItemType = ItemType.Rewards;
+
+        EquipSuitEffect m_EquipSuitEffect;
+        EquipSuitEffect equipSuitEffect
+        {
+            get
+            {
+                if (m_EquipSuitEffect == null)
+                {
+                    m_EquipSuitEffect = EquipSuitEffect.Create(transform as RectTransform);
+                }
+                return m_EquipSuitEffect;
+            }
+        }
+
+        //鐗╁搧鍩虹鐗规晥锛堢墿鍝佽〃锛�
+        ItemBaseEffect m_ItemBaseEffect;
+        ItemBaseEffect itemBaseEffect
+        {
+            get
+            {
+                if (m_ItemBaseEffect == null)
+                {
+                    m_ItemBaseEffect = ItemBaseEffect.Create(transform as RectTransform);
+                }
+                return m_ItemBaseEffect;
+            }
+        }
+
+        bool m_ShowCount = true;
+        public bool showCount {
+            get {
+                return m_ShowCount;
+            }
+            set {
+                if (m_ShowCount != value)
+                {
+                    m_ShowCount = value;
+                    DisplayCount();
+                }
+            }
+        }
+
+        public int itemId {
+            get; private set;
+        }
+
+        public int itemCount {
+            get; private set;
+        }
+
+        public int itemQuality { get; private set; }
+
+        private void Awake()
+        {
+            if (m_ViewDetails != null)
+            {
+                m_ViewDetails.SetListener(ViewDetails);
+            }
+        }
+
+        public void SetItem(Item _item)
+        {
+            SetItem(_item.id, _item.count, _item.quality);
+        }
+
+        public void SetItem(int _id, int _count, int _quality = 0)
+        {
+            itemId = _id;
+            itemCount = _count;
+            itemQuality = _quality;
+            DisplayBaseInfo();
+            DisplayCount();
+        }
+
+        public void SetCount(int _count)
+        {
+            itemCount = _count;
+            DisplayCount();
+        }
+
+        public void DisplayEmpty()
+        {
+            try
+            {
+                icon.SetActive(false);
+                backGround.SetActive(false);
+                if (countContainer != null)
+                {
+                    countContainer.SetActive(false);
+                }
+            }
+            catch (System.Exception ex)
+            {
+                DebugEx.Log(ex);
+            }
+        }
+
+        private void DisplayBaseInfo()
+        {
+            try
+            {
+                var itemInfo = ItemConfig.Get(itemId);
+                if (icon != null)
+                {
+                    icon.SetActive(true);
+                    icon.SetSprite(itemInfo.IconKey);
+                }
+
+                if (backGround != null)
+                {
+                    backGround.SetActive(true);
+                    backGround.SetItemBackGround(itemQuality != 0 ? itemQuality : itemInfo.ItemColor, itemInfo.QualityEchoType);
+                }
+
+                equipSuitEffect.Display(itemId);
+                itemBaseEffect.Display(itemId);
+            }
+            catch (Exception e)
+            {
+                DebugEx.Log(e);
+            }
+        }
+
+        private void DisplayCount()
+        {
+            if (countContainer == null)
+            {
+                return;
+            }
+            switch (m_ItemType)
+            {
+                case ItemType.Rewards:
+                    if (showCount && itemCount > 1)
+                    {
+                        countContainer.SetActive(true);
+                        count.text = UIHelper.ReplaceLargeNum((ulong)itemCount);
+                    }
+                    else
+                    {
+                        countContainer.SetActive(false);
+                    }
+                    break;
+                case ItemType.Use:
+                    var _itemCnt = ModelCenter.Instance.GetModel<PackModel>().GetItemCountByID(PackType.Item, itemId);
+                    count.text = StringUtility.Contact(_itemCnt >= itemCount ? "<color=#35e112>" : "<color=#ff0303>", _itemCnt,
+                        "</color><color=#f7f7f7>/", itemCount, "</color>");
+                    break;
+            }
+        }
+
+        private void ViewDetails()
+        {
+            ItemTipUtility.Show(itemId);
+        }
+
+        public enum ItemType
+        {
+            Rewards,
+            Use,
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/ItemBehaviour.cs.meta b/Main/Component/UI/Common/ItemBehaviour.cs.meta
new file mode 100644
index 0000000..cec07ae
--- /dev/null
+++ b/Main/Component/UI/Common/ItemBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a11c4ed088f00fb4baea8b08f0cfa42f
+timeCreated: 1501488202
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/LanguageReplace.cs b/Main/Component/UI/Common/LanguageReplace.cs
new file mode 100644
index 0000000..2a8a2ca
--- /dev/null
+++ b/Main/Component/UI/Common/LanguageReplace.cs
@@ -0,0 +1,23 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+namespace vnxbqy.UI
+{
+    //璁剧疆鏂囨湰锛屾潵婧愯鍙朖.杩涘叆娓告垙鍓嶇殑鎻愮ず.xlsx
+    public class LanguageReplace : MonoBehaviour
+    {
+        [SerializeField] int uiLanguage;
+        
+        private void Awake()
+        {
+            var textObj = this.transform.GetComponent<Text>();
+            if (textObj == null)
+                return;
+
+            textObj.text = Language.GetFromLocal(uiLanguage);
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Common/LanguageReplace.cs.meta b/Main/Component/UI/Common/LanguageReplace.cs.meta
new file mode 100644
index 0000000..7885f5f
--- /dev/null
+++ b/Main/Component/UI/Common/LanguageReplace.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 30a9b0ed6299778418f18a21755c0c09
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/LayoutElementSizeClamp.cs b/Main/Component/UI/Common/LayoutElementSizeClamp.cs
new file mode 100644
index 0000000..d41452b
--- /dev/null
+++ b/Main/Component/UI/Common/LayoutElementSizeClamp.cs
@@ -0,0 +1,42 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+[ExecuteAlways]
+public class LayoutElementSizeClamp : LayoutElement
+{
+    [SerializeField] bool m_ClampEnable;
+    public bool clampEnable { get { return m_ClampEnable; } set { m_ClampEnable = value; } }
+
+    [SerializeField] Clamp m_Clamp;
+    public Clamp clamp { get { return m_Clamp; } }
+
+    [SerializeField] RectTransform m_Target;
+
+    Vector2 targetSizeRef = Vector2.zero;
+
+    private void LateUpdate()
+    {
+        if (clampEnable && m_Target != null)
+        {
+            if (targetSizeRef != m_Target.sizeDelta)
+            {
+                preferredHeight = Mathf.Clamp(m_Target.rect.height, m_Clamp.minY, m_Clamp.maxY);
+                preferredWidth = Mathf.Clamp(m_Target.rect.width, m_Clamp.minX, m_Clamp.maxX);
+                targetSizeRef = new Vector2(preferredWidth, preferredHeight);
+            }
+        }
+    }
+
+    [System.Serializable]
+    public struct Clamp
+    {
+        public float minX;
+        public float maxX;
+        public float minY;
+        public float maxY;
+    }
+
+}
diff --git a/Main/Component/UI/Common/LayoutElementSizeClamp.cs.meta b/Main/Component/UI/Common/LayoutElementSizeClamp.cs.meta
new file mode 100644
index 0000000..361edcb
--- /dev/null
+++ b/Main/Component/UI/Common/LayoutElementSizeClamp.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2d8fad63d37034e4aad43225bd89f61c
+timeCreated: 1555667898
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/LongPressButton.cs b/Main/Component/UI/Common/LongPressButton.cs
new file mode 100644
index 0000000..a4d85a4
--- /dev/null
+++ b/Main/Component/UI/Common/LongPressButton.cs
@@ -0,0 +1,102 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using UnityEngine.Serialization;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    public class LongPressButton : ButtonEx
+    {
+        public class ButtonPressEvent : UnityEvent { }
+
+        [FormerlySerializedAs("onPress")]
+        [SerializeField]
+        private ButtonPressEvent m_OnPress = new ButtonPressEvent();
+        public ButtonPressEvent onPress
+        {
+            get { return m_OnPress; }
+            set { m_OnPress = value; }
+        }
+
+        [SerializeField]
+        float m_LongPressCheckTime = 0.5f;
+        public float longPressCheckTime
+        {
+            get { return m_LongPressCheckTime; }
+            set { m_LongPressCheckTime = value; }
+        }
+        [SerializeField]
+        float m_LongPressIntervalTime = 0.1f;
+        public float longPressIntervalTime
+        {
+            get { return m_LongPressIntervalTime; }
+            set { m_LongPressIntervalTime = value; }
+        }
+
+        float m_PressTime = 0.0f;
+        float m_PressIntervalTime = 0.0f;
+        bool m_LongPress = false;
+        bool m_IsButtonDown = false;
+
+        public override void OnPointerClick(PointerEventData eventData)
+        {
+            if (m_LongPress)
+            {
+                m_LongPress = false;
+                return;
+            }
+            base.OnPointerClick(eventData);
+        }
+
+        public override void OnPointerDown(PointerEventData eventData)
+        {
+            base.OnPointerDown(eventData);
+            m_PressTime = 0.0f;
+            m_PressIntervalTime = 0.0f;
+            m_IsButtonDown = true;
+        }
+
+        public override void OnPointerUp(PointerEventData eventData)
+        {
+            base.OnPointerUp(eventData);
+            m_IsButtonDown = false;
+        }
+
+        public override void OnPointerExit(PointerEventData eventData)
+        {
+            base.OnPointerExit(eventData);
+            m_IsButtonDown = false;
+            m_LongPress = false;
+        }
+
+        private void Update()
+        {
+            if (m_IsButtonDown)
+            {
+                m_PressTime += Time.deltaTime;
+                if (m_PressTime < m_LongPressCheckTime)
+                {
+                    return;
+                }
+                if (m_PressIntervalTime >= m_LongPressIntervalTime)
+                {
+                    onPress.Invoke();
+                    m_PressIntervalTime = 0.0f;
+                }
+                m_PressIntervalTime += Time.deltaTime;
+                m_LongPress = true;
+            }
+        }
+
+        protected override void OnEnable()
+        {
+            base.OnEnable();
+            m_LongPress = false;
+            m_IsButtonDown = false;
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/LongPressButton.cs.meta b/Main/Component/UI/Common/LongPressButton.cs.meta
new file mode 100644
index 0000000..dd6d8de
--- /dev/null
+++ b/Main/Component/UI/Common/LongPressButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c9dc3124c7d0a8e44b140cab8f1d5872
+timeCreated: 1519271319
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/MaterialsContainer.cs b/Main/Component/UI/Common/MaterialsContainer.cs
new file mode 100644
index 0000000..826eb20
--- /dev/null
+++ b/Main/Component/UI/Common/MaterialsContainer.cs
@@ -0,0 +1,37 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+[CreateAssetMenu(menuName = "Config/MaterialsContainer")]
+public class MaterialsContainer : ScriptableObject
+{
+    [SerializeField]
+    MaterialKeyValue[] materials;
+
+    public Material GetMaterial(string _name)
+    {
+        if (materials == null)
+        {
+            return null;
+        }
+
+        for (int i = 0; i < materials.Length; i++)
+        {
+            var materialKeyValue = materials[i];
+            if (materialKeyValue.materialName == _name)
+            {
+                return materialKeyValue.material;
+            }
+        }
+
+        return null;
+    }
+
+    [System.Serializable]
+    public struct MaterialKeyValue
+    {
+        public string materialName;
+        public Material material;
+    }
+}
+
diff --git a/Main/Component/UI/Common/MaterialsContainer.cs.meta b/Main/Component/UI/Common/MaterialsContainer.cs.meta
new file mode 100644
index 0000000..4649abc
--- /dev/null
+++ b/Main/Component/UI/Common/MaterialsContainer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8c237092e317c2b49a073891a0667836
+timeCreated: 1510653438
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/MultipleSmoothSlider.cs b/Main/Component/UI/Common/MultipleSmoothSlider.cs
new file mode 100644
index 0000000..5dc7eb8
--- /dev/null
+++ b/Main/Component/UI/Common/MultipleSmoothSlider.cs
@@ -0,0 +1,95 @@
+锘縰sing System.Collections;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    [DisallowMultipleComponent]
+    public class MultipleSmoothSlider : MonoBehaviour
+    {
+
+        [SerializeField]
+        SmoothSlider[] m_Sliders;
+        public SmoothSlider[] sliders
+        {
+            get
+            {
+                return this.m_Sliders;
+            }
+        }
+
+        [SerializeField]
+        [Range(0, 1)]
+        float m_Value;
+        public float value
+        {
+            get
+            {
+                return m_Value;
+            }
+            set
+            {
+                m_Value = Mathf.Clamp01(value);
+
+                if (this.sliders != null)
+                {
+                    for (var i = 0; i < sliders.Length; i++)
+                    {
+                        var slider = sliders[i];
+                        if (slider != null)
+                        {
+                            slider.value = m_Value;
+                        }
+                    }
+                }
+
+            }
+        }
+
+
+        public void ResetValue(float _value)
+        {
+            if (this.sliders != null)
+            {
+                for (var i = 0; i < sliders.Length; i++)
+                {
+                    var slider = sliders[i];
+                    if (slider != null)
+                    {
+                        slider.ResetValue(_value);
+                    }
+                }
+            }
+        }
+
+        public void UpdateDelayTimes(float[] _delayTimes)
+        {
+            if (sliders == null)
+            {
+                return;
+            }
+
+            if (_delayTimes == null)
+            {
+                return;
+            }
+
+            var min = Mathf.Min(_delayTimes.Length, sliders.Length);
+
+            for (var i = 0; i < min; i++)
+            {
+                sliders[i].delay = _delayTimes[i];
+            }
+
+        }
+
+        private void OnValidate()
+        {
+            value = m_Value;
+        }
+
+    }
+}
+
diff --git a/Main/Component/UI/Common/MultipleSmoothSlider.cs.meta b/Main/Component/UI/Common/MultipleSmoothSlider.cs.meta
new file mode 100644
index 0000000..993e312
--- /dev/null
+++ b/Main/Component/UI/Common/MultipleSmoothSlider.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f8ae1af806e889a40933505d9dadef07
+timeCreated: 1451785001
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/NestingScrollRect.cs b/Main/Component/UI/Common/NestingScrollRect.cs
new file mode 100644
index 0000000..75f5137
--- /dev/null
+++ b/Main/Component/UI/Common/NestingScrollRect.cs
@@ -0,0 +1,58 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(ScrollRect))]
+    public class NestingScrollRect : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
+    {
+        [SerializeField] ScrollRect m_ParentScrollRect;
+
+        ScrollRect m_ScrollRect;
+        ScrollRect scrollRect
+        {
+            get
+            {
+                if (m_ScrollRect == null)
+                {
+                    m_ScrollRect = GetComponent<ScrollRect>();
+                }
+                return m_ScrollRect;
+            }
+        }
+
+        public void OnBeginDrag(PointerEventData eventData)
+        {
+            m_ParentScrollRect.OnBeginDrag(eventData);
+        }
+
+        public void OnDrag(PointerEventData eventData)
+        {
+            float angle = Mathf.Abs(Vector2.Angle(eventData.delta, Vector2.up));
+
+            if (angle >= 45 && angle <= 135)
+            {
+                m_ParentScrollRect.enabled = m_ParentScrollRect.horizontal;
+                scrollRect.enabled = scrollRect.horizontal;
+            }
+            else
+            {
+                m_ParentScrollRect.enabled = m_ParentScrollRect.vertical;
+                scrollRect.enabled = scrollRect.vertical;
+            }
+
+            m_ParentScrollRect.OnDrag(eventData);
+        }
+
+        public void OnEndDrag(PointerEventData eventData)
+        {
+            scrollRect.enabled = true;
+            m_ParentScrollRect.enabled = true;
+            m_ParentScrollRect.OnEndDrag(eventData);
+            scrollRect.OnEndDrag(eventData);
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/NestingScrollRect.cs.meta b/Main/Component/UI/Common/NestingScrollRect.cs.meta
new file mode 100644
index 0000000..ec972b8
--- /dev/null
+++ b/Main/Component/UI/Common/NestingScrollRect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 263293fcb7dc8da43bbdac521d6a99a3
+timeCreated: 1554197131
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/NumKeyBoard.cs b/Main/Component/UI/Common/NumKeyBoard.cs
new file mode 100644
index 0000000..9fe0d63
--- /dev/null
+++ b/Main/Component/UI/Common/NumKeyBoard.cs
@@ -0,0 +1,260 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+using UnityEngine.Events;
+using vnxbqy.UI;
+namespace UnityEngine.UI
+{
+    [AddComponentMenu("UI/NumKeyBoard")]
+    [RequireComponent(typeof(RectTransform))]
+    public class NumKeyBoard : MonoBehaviour
+    {
+        [SerializeField]
+        NumKeyBoardType m_Type;
+        public NumKeyBoardType type
+        {
+            get { return m_Type; }
+        }
+        [SerializeField]
+        bool deActiveConfirm = false;
+        [SerializeField]
+        private uint m_Min;
+        public uint min
+        {
+            get { return m_Min; }
+            set { m_Min = value; }
+        }
+        [SerializeField]
+        private uint m_Max;
+        public uint max { get { return m_Max; } set { m_Max = value; } }
+        [SerializeField]
+        private int m_NumLimit;
+        public int limit { get { return m_NumLimit; } set { m_NumLimit = value; } }
+        [SerializeField]
+        private Button[] m_NumBtns = new Button[10];
+        [SerializeField]
+        private Button okBtn;
+        [SerializeField]
+        private Button cancelBtn;
+        [Serializable]
+        public class NumKeyboardEvent : UnityEvent { }
+        private NumKeyboardEvent m_OnValueChange = new NumKeyboardEvent();
+        public NumKeyboardEvent onValueChange
+        {
+            get { return m_OnValueChange; }
+        }
+        [Serializable]
+        public class NumKeyboardConfirmEvent : UnityEvent<bool> { }
+        private NumKeyboardConfirmEvent m_OnConfirm = new NumKeyboardConfirmEvent();
+        public NumKeyboardConfirmEvent onConfirm
+        {
+            get { return m_OnConfirm; }
+        }
+        public bool displayOutValue = true;
+        private StringBuilder m_Value = new StringBuilder();
+
+        [SerializeField] ClickScreenOtherSpace m_ClickOther;
+
+        public string Value
+        {
+            get { return m_Value.ToString(); }
+            set
+            {
+                switch (type)
+                {
+                    case NumKeyBoardType.Math:
+                        {
+                            if (!Regex.IsMatch(value, "[0-9]+"))
+                            {
+                                throw new Exception("No Correct Format!");
+                            }
+                            m_IntValue = uint.Parse(value);
+                            m_RealIntValue = m_IntValue;
+                        }
+                        break;
+                    case NumKeyBoardType.Password:
+                        {
+                            if (!Regex.IsMatch(value, "[0-9]*"))
+                            {
+                                throw new Exception("No Correct Format!");
+                            }
+                        }
+                        break;
+                }
+                m_Value.Length = 0;
+                m_Value.Append(value);
+                SetTargetTextValue();
+            }
+        }
+        private uint m_IntValue = 0;
+        private uint m_RealIntValue = 0;
+        private bool resetValue = false;
+        /// <summary>
+        /// 鐩爣鏄剧ず鏂囨湰缁勪欢
+        /// </summary>
+        public Text targetText;
+
+        private void Awake()
+        {
+            for (int i = 0; i < m_NumBtns.Length; i++)
+            {
+                if (m_NumBtns[i] != null)
+                {
+                    uint index = (uint)i;
+                    m_NumBtns[i].onClick.AddListener(() =>
+                    {
+                        OnClickNum(index);
+                    });
+                }
+            }
+            okBtn.onClick.AddListener(OnOkBtn);
+            cancelBtn.onClick.AddListener(OnCancelBtn);
+            ResetValue();
+            if (m_ClickOther != null)
+            {
+                m_ClickOther.AddListener(OnOkBtn);
+            }
+        }
+
+        private void ResetValue()
+        {
+            switch (type)
+            {
+                case NumKeyBoardType.Math:
+                    m_IntValue = (uint)Mathf.Max(0, min);
+                    m_RealIntValue = m_IntValue;
+                    m_Value.Length = 0;
+                    m_Value.Append(m_IntValue);
+                    break;
+                case NumKeyBoardType.Password:
+                    m_Value.Length = 0;
+                    break;
+            }
+            SetTargetTextValue();
+            resetValue = true;
+        }
+
+        private void OnEnable()
+        {
+            resetValue = true;
+        }
+
+        private void OnCancelBtn()
+        {
+            ResetValue();
+            onValueChange.Invoke();
+            onConfirm.Invoke(false);
+        }
+
+        private void OnOkBtn()
+        {
+            CheckValue();
+            onConfirm.Invoke(true);
+            if (deActiveConfirm)
+            {
+                gameObject.SetActive(false);
+            }
+        }
+
+        private void OnClickNum(uint index)
+        {
+            switch (type)
+            {
+                case NumKeyBoardType.Math:
+                    {
+                        if (resetValue)
+                        {
+                            m_RealIntValue = index;
+                            if (max > 0 && index > max)
+                            {
+                                index = max;
+                            }
+                            if (!displayOutValue && min > 0 && index < min)
+                            {
+                                index = min;
+                            }
+                            m_IntValue = index;
+                            resetValue = false;
+                        }
+                        else
+                        {
+                            uint _value = m_RealIntValue * 10 + index;
+                            m_RealIntValue = _value;
+                            if (max > 0 && _value > max)
+                            {
+                                _value = max;
+                            }
+                            var maxlength = LengthOf(max);
+                            var length = LengthOf(_value);
+                            if (min > 0 && _value < min && (!displayOutValue || (max > 0 && length == maxlength)))
+                            {
+                                _value = min;
+                            }
+                            if (_value == m_IntValue)
+                            {
+                                return;
+                            }
+                            m_IntValue = _value;
+                        }
+                        m_Value.Length = 0;
+                        m_Value.Append(m_IntValue);
+                        SetTargetTextValue();
+                    }
+                    break;
+                case NumKeyBoardType.Password:
+                    if (limit != 0 && m_Value.Length >= limit)
+                    {
+                        return;
+                    }
+                    m_Value.Append(index);
+                    SetTargetTextValue();
+                    break;
+            }
+            m_OnValueChange.Invoke();
+        }
+
+        private void CheckValue()
+        {
+            if (type == NumKeyBoardType.Math)
+            {
+                var value = 0;
+                int.TryParse(Value,out value);
+                if (max > 0 && value > max)
+                {
+                    Value = max.ToString();
+                }
+                if (min > 0 && value < min)
+                {
+                    Value = min.ToString();
+                }
+            }
+        }
+
+        void SetTargetTextValue()
+        {
+            if (targetText != null)
+            {
+                targetText.text = Value;
+            }
+        }
+
+        static int LengthOf(uint value)
+        {
+            for (int i = 0; i <= 10; i++)
+            {
+                if (value / (ulong)Mathf.Pow(10, i) < 1)
+                {
+                    return i;
+                }
+            }
+            return 0;
+        }
+    }
+    public enum NumKeyBoardType
+    {
+        Math,
+        Password,
+    }
+}
+
diff --git a/Main/Component/UI/Common/NumKeyBoard.cs.meta b/Main/Component/UI/Common/NumKeyBoard.cs.meta
new file mode 100644
index 0000000..17c19b5
--- /dev/null
+++ b/Main/Component/UI/Common/NumKeyBoard.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 95a1a64971aac184aaa6fd7d61de62d4
+timeCreated: 1508292193
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/OnOffToggle.cs b/Main/Component/UI/Common/OnOffToggle.cs
new file mode 100644
index 0000000..d9060d1
--- /dev/null
+++ b/Main/Component/UI/Common/OnOffToggle.cs
@@ -0,0 +1,63 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, August 23, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.Events;
+
+namespace vnxbqy.UI
+{
+
+    public class OnOffToggle : MonoBehaviour
+    {
+
+        [SerializeField] Button m_Button;
+        [SerializeField] RectTransform m_Handle;
+        [SerializeField] Image m_BackGround;
+        [SerializeField] RectTransform m_OnShow;
+        [SerializeField] RectTransform m_OffShow;
+        [SerializeField] Vector2 m_OnHandleOffset;
+        [SerializeField] Vector2 m_OffHandleOffset;
+
+        bool m_IsOn = false;
+        public bool isOn {
+            get { return m_IsOn; }
+            set {
+                m_IsOn = value;
+                SwitchShowState(m_IsOn);
+            }
+        }
+
+        public void AddListener(UnityAction _action)
+        {
+            if (m_Button != null)
+            {
+                m_Button.AddListener(_action);
+            }
+        }
+
+        public void RemoveAllListeners()
+        {
+            if (m_Button != null)
+            {
+                m_Button.RemoveAllListeners();
+            }
+        }
+
+        private void SwitchShowState(bool _isOn)
+        {
+            if (m_Handle == null)
+                return;
+            m_Handle.anchoredPosition = _isOn ? m_OnHandleOffset : m_OffHandleOffset;
+            m_BackGround.SetSprite(_isOn ? "SettingUpWin_NO" : "SettingUpWin_OFF");
+            m_OnShow.SetActive(_isOn);
+            m_OffShow.SetActive(!_isOn);
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/OnOffToggle.cs.meta b/Main/Component/UI/Common/OnOffToggle.cs.meta
new file mode 100644
index 0000000..39d7ebf
--- /dev/null
+++ b/Main/Component/UI/Common/OnOffToggle.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dd8929af600e643478d3f0a22d7e3c52
+timeCreated: 1535009068
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PlayerLifeBar.cs b/Main/Component/UI/Common/PlayerLifeBar.cs
new file mode 100644
index 0000000..434af77
--- /dev/null
+++ b/Main/Component/UI/Common/PlayerLifeBar.cs
@@ -0,0 +1,131 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, October 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class PlayerLifeBar : MonoBehaviour
+    {
+        [SerializeField] AvatarCell avatarCell;
+        [SerializeField] Text m_PlayerName;
+        [SerializeField] Text m_PlayerLevel;
+        [SerializeField] Text m_Hp;
+        [SerializeField] Text m_ShieldText;
+        [SerializeField] Image m_Shield;//鎶ょ浘鏄剧ず
+
+        [SerializeField] MultipleSmoothSlider m_MultipleSlider;
+        public MultipleSmoothSlider multipleSlider
+        {
+            get { return m_MultipleSlider; }
+        }
+
+        [SerializeField]
+        [Range(0, 10)]
+        float m_Delay;
+        public float delay
+        {
+            get { return m_Delay; }
+        }
+
+        float m_Value;
+        public float value
+        {
+            get
+            {
+                return m_Value;
+            }
+            set
+            {
+                m_Value = Mathf.Clamp01(value);
+                if (multipleSlider != null)
+                {
+                    multipleSlider.value = m_Value;
+                }
+            }
+        }
+
+        int playerIdBuf = 0;
+        float[] reduceHpDelay = new float[2];
+        float[] addHpDelay = new float[2];
+
+        int playerId = 0;
+
+        public void SetBaseInfo(int _playerId,int face,int facePic, int _job, int _jobRank, string _name, 
+            int _level, ulong _hp, ulong _maxHp, int shield, int maxShield)
+        {
+            playerId = _playerId;
+            avatarCell.InitUI(AvatarHelper.GetAvatarModel(_playerId, face, facePic, _job));
+            m_PlayerName.text = _name;
+            m_PlayerLevel.text = _level.ToString();
+
+            var targetValue = (float)_hp / _maxHp;
+            m_Hp.text = StringUtility.Contact(UIHelper.ReplaceLargeNum(_hp), "/", UIHelper.ReplaceLargeNum(_maxHp));
+            multipleSlider.ResetValue(targetValue);
+            ShowShield(shield, maxShield);
+        }
+
+        public void Show(ulong _hp, ulong _maxHp, int shield, int maxShield)
+        {
+            var targetValue = _hp / (float)_maxHp;
+            if (targetValue < this.value)
+            {
+                multipleSlider.UpdateDelayTimes(reduceHpDelay);
+            }
+            else
+            {
+                multipleSlider.UpdateDelayTimes(addHpDelay);
+            }
+
+            value = targetValue;
+            m_Hp.text = StringUtility.Contact(UIHelper.ReplaceLargeNum(_hp), "/", UIHelper.ReplaceLargeNum(_maxHp));
+            this.SetActive(true);
+            ShowShield(shield, maxShield);
+        }
+
+        void ShowShield(int shield, int maxShield)
+        {
+            var fillAmount = maxShield <= 0 ? 1f : (float)shield / maxShield;
+            m_Shield.fillAmount = fillAmount;
+            m_ShieldText.text = StringUtility.Contact(UIHelper.ReplaceLargeNumEx(shield), "/", UIHelper.ReplaceLargeNumEx(maxShield));
+        }
+
+        public void Hide()
+        {
+            this.SetActive(false);
+        }
+
+        void Awake()
+        {
+            reduceHpDelay[0] = 0f;
+            reduceHpDelay[1] = delay;
+
+            addHpDelay[0] = delay;
+            addHpDelay[1] = 0f;
+        }
+
+        private void OnEnable()
+        {
+            multipleSlider.ResetValue(value);
+            avatarCell.button.AddListener(ViewPlayer);
+        }
+
+        private void OnDisable()
+        {
+            avatarCell.button.RemoveAllListeners();
+        }
+
+        private void ViewPlayer()
+        {
+            PlayerDetails.ShowAreaPlayer(playerId);
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/PlayerLifeBar.cs.meta b/Main/Component/UI/Common/PlayerLifeBar.cs.meta
new file mode 100644
index 0000000..8c57a72
--- /dev/null
+++ b/Main/Component/UI/Common/PlayerLifeBar.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ba974cd686dad874cb284f41816c448c
+timeCreated: 1507991835
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PopupMessage.cs b/Main/Component/UI/Common/PopupMessage.cs
new file mode 100644
index 0000000..8860128
--- /dev/null
+++ b/Main/Component/UI/Common/PopupMessage.cs
@@ -0,0 +1,58 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, August 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    public class PopupMessage:MonoBehaviour {
+
+        [SerializeField]
+        Text m_Text;
+
+        public string content {
+            get; set;
+        }
+
+        bool m_Active;
+        public bool isActive {
+            get {
+                return this.m_Active;
+            }
+            set {
+                this.m_Active = value;
+            }
+        }
+
+
+        Vector3 m_TargetPosition;
+        public Vector3 targetPosition {
+            get {
+                return this.m_TargetPosition;
+            }
+            set {
+                this.m_TargetPosition = value;
+            }
+        }
+
+
+        private void LateUpdate() {
+
+            if(Vector3.Distance(targetPosition,this.transform.localPosition) > .1f) {
+
+            }
+
+
+        }
+
+
+    }
+
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/PopupMessage.cs.meta b/Main/Component/UI/Common/PopupMessage.cs.meta
new file mode 100644
index 0000000..10dc659
--- /dev/null
+++ b/Main/Component/UI/Common/PopupMessage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 12b037413c23d484b82d2c9f08dcd803
+timeCreated: 1502692695
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PopupMessageContainer.cs b/Main/Component/UI/Common/PopupMessageContainer.cs
new file mode 100644
index 0000000..cad23f1
--- /dev/null
+++ b/Main/Component/UI/Common/PopupMessageContainer.cs
@@ -0,0 +1,82 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, August 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI {
+
+    [RequireComponent(typeof(RectTransform))]
+    public class PopupMessageContainer:MonoBehaviour {
+
+        [SerializeField]
+        PopupMessage[] popupMessages;
+
+        [SerializeField]
+        Vector2 m_CellSize;
+
+
+        [SerializeField]
+        float interval = 1f;
+
+        float nextPopupTime = 0f;
+        Queue<string> contents = new Queue<string>();
+        Queue<PopupMessage> displayPopupMessages = new Queue<PopupMessage>();
+
+        Vector2 bottomPosition;
+        Vector2 topPosition;
+
+
+        public void Popup(string _content) {
+
+
+        }
+
+        private void LateUpdate() {
+            if(Time.time > nextPopupTime) {
+                if(contents.Count > 0) {
+                    nextPopupTime += interval;
+                    var content = contents.Dequeue();
+
+                    PopupMessage behaviour = null;
+                    for(var i = 0;i < popupMessages.Length;i++) {
+                        if(!popupMessages[i].isActive) {
+                            behaviour = popupMessages[i];
+                            break;
+                        }
+                    }
+
+                    if(behaviour == null) {
+                        behaviour = displayPopupMessages.Dequeue();
+                    }
+
+                    behaviour.transform.localPosition = bottomPosition;
+                    displayPopupMessages.Enqueue(behaviour);
+                }
+            }
+
+        }
+
+
+        private void OnValidate() {
+
+            var rectTransform = this.transform as RectTransform;
+
+            var width = rectTransform.rect.width;
+            var height = rectTransform.rect.height;
+
+            bottomPosition = new Vector2(0,-height * 0.5f + m_CellSize.y * 0.5f);
+            topPosition = new Vector2(0,height * 0.5f - m_CellSize.y * 0.5f);
+
+        }
+
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/PopupMessageContainer.cs.meta b/Main/Component/UI/Common/PopupMessageContainer.cs.meta
new file mode 100644
index 0000000..4b2ceac
--- /dev/null
+++ b/Main/Component/UI/Common/PopupMessageContainer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: aa0a8323b8804b241920cd34f86ba8e5
+timeCreated: 1502697425
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PostEffectBase.cs b/Main/Component/UI/Common/PostEffectBase.cs
new file mode 100644
index 0000000..0e087da
--- /dev/null
+++ b/Main/Component/UI/Common/PostEffectBase.cs
@@ -0,0 +1,36 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+//鎻愪緵涓�涓悗澶勭悊鐨勫熀绫伙紝涓昏鍔熻兘鍦ㄤ簬鐩存帴閫氳繃Inspector闈㈡澘鎷栧叆shader锛岀敓鎴恠hader瀵瑰簲鐨勬潗璐�
+public class PostEffectBase : MonoBehaviour
+{
+
+    //Inspector闈㈡澘涓婄洿鎺ユ嫋鍏�
+    public Shader shader = null;
+    private Material _material = null;
+    public Material _Material
+    {
+        get
+        {
+            if (_material == null)
+                _material = GenerateMaterial(shader);
+            return _material;
+        }
+    }
+
+    //鏍规嵁shader鍒涘缓鐢ㄤ簬灞忓箷鐗规晥鐨勬潗璐�
+    protected Material GenerateMaterial(Shader shader)
+    {
+        if (shader == null)
+            return null;
+        //闇�瑕佸垽鏂璼hader鏄惁鏀寔
+        if (shader.isSupported == false)
+            return null;
+        Material material = new Material(shader);
+        material.hideFlags = HideFlags.DontSave;
+        if (material)
+            return material;
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Common/PostEffectBase.cs.meta b/Main/Component/UI/Common/PostEffectBase.cs.meta
new file mode 100644
index 0000000..be3c250
--- /dev/null
+++ b/Main/Component/UI/Common/PostEffectBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f2e300967528bba4f8f43e418d5eb527
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PrepareWin.cs b/Main/Component/UI/Common/PrepareWin.cs
new file mode 100644
index 0000000..18e05e9
--- /dev/null
+++ b/Main/Component/UI/Common/PrepareWin.cs
@@ -0,0 +1,102 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, November 06, 2017
+//--------------------------------------------------------
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    /// <summary>
+    /// 涓嶱repareHandler閰嶅悎浣跨敤鐨勪竴涓繘搴︽潯绫�
+    /// </summary>
+    public class PrepareWin : Window
+    {
+        private float m_ProcessTime;
+        private float m_TotalTime;
+
+        public SmoothSlider m_Process;
+        public Text m_Content;
+
+        #region Built-in
+        protected sealed override void BindController()
+        {
+        }
+
+        protected sealed override void LateUpdate()
+        {
+            base.LateUpdate();
+            if (m_ProcessTime > m_TotalTime)
+            {
+                m_ProcessTime = m_TotalTime;
+                return;
+            }
+
+            m_ProcessTime += Time.deltaTime;
+            m_Process.value = m_ProcessTime / m_TotalTime;
+        }
+
+        protected sealed override void AddListeners()
+        {
+        }
+
+        protected sealed override void OnPreOpen()
+        {
+            PrepareHandler.ClientH0812 _prepareInfo = PrepareHandler.Instance.clientPrepareH0812;
+            PrepareHandler.E_PrepareType _type = (PrepareHandler.E_PrepareType)_prepareInfo.PrepareState;
+
+            // 鍒ゆ柇杩涘害鏉$被鍨�
+            switch (_type)
+            {
+                case PrepareHandler.E_PrepareType.pstSkill:
+
+                    HandlerSkillPrepare();
+
+                    break;
+            }
+            m_Process.value = m_ProcessTime = 0;
+            m_TotalTime = _prepareInfo.MaxTime;
+        }
+
+        protected sealed override void OnAfterOpen()
+        {
+        }
+
+        protected sealed override void OnPreClose()
+        {
+        }
+
+        protected sealed override void OnAfterClose()
+        {
+        }
+        #endregion
+
+        private void HandlerSkillPrepare()
+        {
+            PrepareHandler.ClientH0812 _prepareInfo = PrepareHandler.Instance.clientPrepareH0812;
+            GActorFight _actor = GAMgr.Instance.GetBySID(_prepareInfo.PlayerID) as GActorFight;
+            if (_actor == null)
+            {
+                Debug.Log("瑙掕壊涓嶅瓨鍦�");
+                return;
+            }
+            Skill _skill = _actor.SkillMgr.Get(_prepareInfo.PrepareID);
+            if (_skill == null)
+            {
+                Debug.Log("鎶�鑳戒笉瀛樺湪");
+                return;
+            }
+            m_Content.text = string.Format(Language.Get("SkillBuffer_Z"), _skill.skillInfo.config.SkillName);
+        }
+    }
+
+}
+
+
+
+
diff --git a/Main/Component/UI/Common/PrepareWin.cs.meta b/Main/Component/UI/Common/PrepareWin.cs.meta
new file mode 100644
index 0000000..632915f
--- /dev/null
+++ b/Main/Component/UI/Common/PrepareWin.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9bd6f9ce503725249a1518e3573992d0
+timeCreated: 1509959523
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PressTip.cs b/Main/Component/UI/Common/PressTip.cs
new file mode 100644
index 0000000..bae47f0
--- /dev/null
+++ b/Main/Component/UI/Common/PressTip.cs
@@ -0,0 +1,102 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class PressTip : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
+    {
+        [SerializeField] GameObject m_Container;
+        [SerializeField] float m_Delay = 0f;
+
+        float timer = 0f;
+        PointerState pointerState = PointerState.Up;
+        bool triggered = false;
+
+        private void OnEnable()
+        {
+            this.pointerState = PointerState.Up;
+            this.m_Container.SetActive(false);
+        }
+
+        private void OnDisable()
+        {
+            this.pointerState = PointerState.Up;
+            this.m_Container.SetActive(false);
+        }
+
+        public virtual void OnPointerDown(PointerEventData eventData)
+        {
+            this.pointerState = PointerState.Down;
+            this.timer = 0f;
+            triggered = false;
+        }
+
+        public virtual void OnPointerUp(PointerEventData eventData)
+        {
+            this.pointerState = PointerState.Up;
+            this.m_Container.SetActive(false);
+        }
+
+        private void LateUpdate()
+        {
+            if (this.pointerState != PointerState.Down)
+            {
+                return;
+            }
+
+            this.timer += Time.deltaTime;
+            if (this.timer > this.m_Delay && !triggered)
+            {
+                triggered = true;
+
+                if (this.m_Container != null)
+                {
+                    this.m_Container.SetActive(true);
+                    AdjustmentContainerPosition(this.m_Container.transform as RectTransform);
+                }
+            }
+
+        }
+
+        void AdjustmentContainerPosition(RectTransform _container)
+        {
+            if (_container == null)
+            {
+                return;
+            }
+
+            var viewPortPoint = CameraManager.uiCamera.ScreenToViewportPoint(Input.mousePosition);
+            var normalizedOffset = CalculateNormalizedOffset(_container);
+
+            var containerSize = new Vector2(_container.rect.width, _container.rect.height);
+            var xOffset = viewPortPoint.x < normalizedOffset.x ? 1 : viewPortPoint.x > (1 - normalizedOffset.x) ? -1 : 0;
+            var yOffset = viewPortPoint.y > (1 - normalizedOffset.y * 2) ? -1 : xOffset != 0 ? 0 : 1;
+
+            var uiposition = CameraManager.uiCamera.ViewportToWorldPoint(viewPortPoint);
+
+            _container.position = uiposition.SetZ(0);
+            _container.localPosition += new Vector3(xOffset * containerSize.x * 0.5f, yOffset * containerSize.y * 0.5f, -_container.localPosition.z);
+        }
+
+        Vector2 CalculateNormalizedOffset(RectTransform _rectTransform)
+        {
+            var offsetX = _rectTransform.rect.width / Constants.DESIGN_RESOLUTION.x * 0.5f;
+            var offsetY = _rectTransform.rect.height / Constants.DESIGN_RESOLUTION.y * 0.5f;
+
+            return new Vector2(offsetX, offsetY);
+        }
+
+        enum PointerState
+        {
+            Down,
+            Up
+        }
+
+    }
+
+}
+
diff --git a/Main/Component/UI/Common/PressTip.cs.meta b/Main/Component/UI/Common/PressTip.cs.meta
new file mode 100644
index 0000000..c470baf
--- /dev/null
+++ b/Main/Component/UI/Common/PressTip.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 270ecceea67cc2e4d8c257c3351c176b
+timeCreated: 1461772767
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/PriorityWindowConfig.cs b/Main/Component/UI/Common/PriorityWindowConfig.cs
new file mode 100644
index 0000000..9a2280a
--- /dev/null
+++ b/Main/Component/UI/Common/PriorityWindowConfig.cs
@@ -0,0 +1,21 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+[CreateAssetMenu(menuName = "Config/PriorityWindowConfig")]
+public class PriorityWindowConfig :ScriptableObject {
+
+    public List<string> priorityWindows;
+
+    static PriorityWindowConfig config;
+    public static PriorityWindowConfig Get()
+    {
+        if (config == null)
+        {
+            config = BuiltInLoader.LoadScriptableObject<PriorityWindowConfig>("PriorityWindowConfig");
+        }
+
+        return config;
+    }
+
+}
diff --git a/Main/Component/UI/Common/PriorityWindowConfig.cs.meta b/Main/Component/UI/Common/PriorityWindowConfig.cs.meta
new file mode 100644
index 0000000..ee4016b
--- /dev/null
+++ b/Main/Component/UI/Common/PriorityWindowConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0526ef20afb14c04ea62a22bc41884c9
+timeCreated: 1518335421
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/RandomImage.cs b/Main/Component/UI/Common/RandomImage.cs
new file mode 100644
index 0000000..de4b332
--- /dev/null
+++ b/Main/Component/UI/Common/RandomImage.cs
@@ -0,0 +1,25 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class RandomImage : MonoBehaviour
+{
+    [SerializeField]
+    string[] m_ImageKeys;
+    [SerializeField]
+    Image m_Image;
+
+    private void OnEnable()
+    {
+        var screenAspect = (Screen.width / (float)Screen.height) / (Constants.DESIGN_RESOLUTION.x / Constants.DESIGN_RESOLUTION.y);
+        this.transform.localScale = Mathf.Clamp(screenAspect, 1f, 2f) * Vector3.one;
+
+        if (m_ImageKeys != null && m_ImageKeys.Length > 0)
+        {
+            var index = Random.Range(0, m_ImageKeys.Length);
+            m_Image.SetSprite(m_ImageKeys[index]);
+        }
+    }
+
+}
diff --git a/Main/Component/UI/Common/RandomImage.cs.meta b/Main/Component/UI/Common/RandomImage.cs.meta
new file mode 100644
index 0000000..4bebbd9
--- /dev/null
+++ b/Main/Component/UI/Common/RandomImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: cc3c70b024be40c4cace078a109c1c12
+timeCreated: 1511869022
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/RandomTip.cs b/Main/Component/UI/Common/RandomTip.cs
new file mode 100644
index 0000000..e7fd3c2
--- /dev/null
+++ b/Main/Component/UI/Common/RandomTip.cs
@@ -0,0 +1,78 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, November 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class RandomTip : MonoBehaviour
+    {
+        int index = 0;
+        [SerializeField] UpdateType m_UpdateType;
+        [SerializeField] Text m_Content;
+        [SerializeField] float m_Interval = 2f;
+        [SerializeField] string[] m_LanguageKeys;
+
+        float timer = 0f;
+        private void OnEnable()
+        {
+            timer = 0f;
+            UpdateTip();
+        }
+
+        private void OnDisable()
+        {
+
+        }
+
+        private void LateUpdate()
+        {
+            timer += Time.deltaTime;
+            if (timer > m_Interval)
+            {
+                timer = 0f;
+                UpdateTip();
+            }
+        }
+
+        private void UpdateTip()
+        {
+            if (m_LanguageKeys == null || m_LanguageKeys.Length == 0)
+            {
+                return;
+            }
+
+            switch (m_UpdateType)
+            {
+                case UpdateType.Queue:
+                    index = (++index) % m_LanguageKeys.Length;
+                    m_Content.text = Language.Get(m_LanguageKeys[index]);
+                    break;
+                case UpdateType.Random:
+                    var randomIndex = index;
+                    while (index == randomIndex)
+                    {
+                        randomIndex = Random.Range(0, m_LanguageKeys.Length);
+                    }
+                    index = randomIndex;
+                    m_Content.text = Language.Get(m_LanguageKeys[index]);
+                    break;
+            }
+        }
+
+        public enum UpdateType
+        {
+            Queue,
+            Random,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/RandomTip.cs.meta b/Main/Component/UI/Common/RandomTip.cs.meta
new file mode 100644
index 0000000..a7ee359
--- /dev/null
+++ b/Main/Component/UI/Common/RandomTip.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e3fe96fe52c5fdf4881c108c09ce0b79
+timeCreated: 1510197164
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/RollNumber.cs b/Main/Component/UI/Common/RollNumber.cs
new file mode 100644
index 0000000..49ae6d4
--- /dev/null
+++ b/Main/Component/UI/Common/RollNumber.cs
@@ -0,0 +1,60 @@
+锘縰sing System;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    [RequireComponent(typeof(Text))]
+    public class RollNumber:MonoBehaviour {
+
+        [SerializeField]
+        Text m_Text;
+        public Text text {
+            get {
+                return m_Text;
+            }
+        }
+
+        float to = 0;
+        float from = 0;
+        float now = 0;
+
+        float duration = 0f;
+        float timer = 0f;
+        Action endCallBack = null;
+
+        public void Perform(int _from,int _to,float _duration,Action _callBack) {
+            ResetTimer();
+            duration = Mathf.Clamp(_duration,0f,float.MaxValue);
+            from = _from;
+            to = _to;
+            endCallBack = _callBack;
+        }
+
+        private void LateUpdate() {
+            if(timer < duration) {
+                timer += Time.deltaTime;
+                now = Mathf.Lerp(from,to,Mathf.Clamp01(timer / duration));
+                if(timer > duration) {
+                    ResetTimer();
+                    now = to;
+                    if(endCallBack != null) {
+                        endCallBack();
+                        endCallBack = null;
+                    }
+                }
+
+                if(text != null) {
+                    var nowInt = (int)now;
+                    text.text = nowInt.ToString();
+                }
+            }
+        }
+
+        private void ResetTimer() {
+            timer = 0f;
+            duration = 0f;
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/RollNumber.cs.meta b/Main/Component/UI/Common/RollNumber.cs.meta
new file mode 100644
index 0000000..dbd3a7b
--- /dev/null
+++ b/Main/Component/UI/Common/RollNumber.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c4cb285fdaadcce4bb939f36fa3902d7
+timeCreated: 1499240118
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ScreenDiffuseMove.cs b/Main/Component/UI/Common/ScreenDiffuseMove.cs
new file mode 100644
index 0000000..4363b7a
--- /dev/null
+++ b/Main/Component/UI/Common/ScreenDiffuseMove.cs
@@ -0,0 +1,161 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 07, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class ScreenDiffuseMove : MonoBehaviour
+    {
+
+        [SerializeField] DiffuseType m_MoveType = DiffuseType.MoveUp;
+        public DiffuseType moveType { get { return m_MoveType; } }
+
+        [SerializeField] float m_Speed = 10f;
+        public float speed {
+            get { return m_Speed; }
+            set { m_Speed = value; }
+        }
+
+        [SerializeField] TweenCurve m_SpeedRatioCurve;
+        [SerializeField] float m_Duration = 1f;
+        public float duration {
+            get { return m_Duration; }
+            set { m_Duration = value; }
+        }
+
+        [SerializeField] float m_Delay = 0f;
+        public float delay {
+            get { return m_Delay; }
+            set { m_Delay = value; }
+        }
+
+        [SerializeField] bool m_IsLocal = true;
+        public bool isLocal {
+            get { return m_IsLocal; }
+        }
+
+        float beginTime = 0f;
+        float endTime = 0f;
+        Vector2 direction = Vector2.up;
+        bool disableOnEnd = true;
+
+        public void Begin(bool _disableOnEnd = true)
+        {
+            beginTime = Time.time + delay;
+            endTime = Time.time + delay + duration;
+            disableOnEnd = _disableOnEnd;
+
+            switch (m_MoveType)
+            {
+                case DiffuseType.MoveUp:
+                    direction = Vector2.up * m_Speed;
+                    break;
+                case DiffuseType.MoveDown:
+                    direction = Vector2.down * m_Speed;
+                    break;
+                case DiffuseType.MoveLeft:
+                    direction = Vector2.left * m_Speed;
+                    break;
+                case DiffuseType.MoveRight:
+                    direction = Vector2.right * m_Speed;
+                    break;
+                case DiffuseType.RelativePosition:
+                    direction = new Vector2(this.transform.position.x, this.transform.position.y).normalized * m_Speed;
+                    break;
+                case DiffuseType.ReversalRelativePosition:
+                    direction = new Vector2(-this.transform.position.x, this.transform.position.y).normalized * m_Speed;
+                    break;
+            }
+
+            this.enabled = true;
+            if (!this.gameObject.activeInHierarchy)
+            {
+                this.SetActive(true);
+            }
+
+        }
+
+        public void Begin(Vector3 _direction, bool _disableOnEnd = true)
+        {
+            beginTime = Time.time + delay;
+            endTime = Time.time + delay + duration;
+            disableOnEnd = _disableOnEnd;
+
+            switch (m_MoveType)
+            {
+                case DiffuseType.MoveUp:
+                    direction = Vector2.up * m_Speed;
+                    break;
+                case DiffuseType.MoveDown:
+                    direction = Vector2.down * m_Speed;
+                    break;
+                case DiffuseType.MoveLeft:
+                    direction = Vector2.left * m_Speed;
+                    break;
+                case DiffuseType.MoveRight:
+                    direction = Vector2.right * m_Speed;
+                    break;
+                case DiffuseType.RelativePosition:
+                    direction = new Vector2(_direction.x, _direction.y).normalized * m_Speed;
+                    break;
+                case DiffuseType.ReversalRelativePosition:
+                    direction = new Vector2(_direction.x, -_direction.y).normalized * m_Speed;
+                    break;
+            }
+
+            this.enabled = true;
+            if (!this.gameObject.activeInHierarchy)
+            {
+                this.SetActive(true);
+            }
+        }
+
+        private void LateUpdate()
+        {
+            if (Time.time < beginTime)
+            {
+                return;
+            }
+
+            if (Time.time < endTime)
+            {
+                var delta = direction * Time.deltaTime * m_SpeedRatioCurve.Evaluate((Time.time - beginTime) / duration);
+                if (isLocal)
+                {
+                    this.transform.localPosition += new Vector3(delta.x, delta.y, 0);
+                }
+                else
+                {
+                    this.transform.position += new Vector3(delta.x, delta.y, 0);
+                }
+            }
+            else
+            {
+                if (disableOnEnd)
+                {
+                    this.enabled = false;
+                }
+            }
+        }
+
+
+        public enum DiffuseType
+        {
+            MoveUp,
+            MoveDown,
+            MoveLeft,
+            MoveRight,
+            RelativePosition,
+            ReversalRelativePosition,
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/ScreenDiffuseMove.cs.meta b/Main/Component/UI/Common/ScreenDiffuseMove.cs.meta
new file mode 100644
index 0000000..9cddba4
--- /dev/null
+++ b/Main/Component/UI/Common/ScreenDiffuseMove.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a6b7149d9e427da45b6bec92a44f0127
+timeCreated: 1504793300
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ScreenMoveTo.cs b/Main/Component/UI/Common/ScreenMoveTo.cs
new file mode 100644
index 0000000..8c71560
--- /dev/null
+++ b/Main/Component/UI/Common/ScreenMoveTo.cs
@@ -0,0 +1,170 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 07, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class ScreenMoveTo : MonoBehaviour
+    {
+
+        [SerializeField]
+        LerpType m_LerpType = LerpType.Linear;
+
+        [SerializeField]
+        Vector2 m_Destination;
+        public Vector2 destination {
+            get { return m_Destination; }
+            set { m_Destination = value; }
+        }
+
+        [SerializeField]
+        float m_Duration = 0.5f;
+        public float duration {
+            get { return m_Duration; }
+            set { m_Duration = value; }
+        }
+
+        [SerializeField]
+        bool m_IsLocal = true;
+        public bool isLocal {
+            get { return m_IsLocal; }
+        }
+
+        bool disableOnEnd = true;
+        float endTime = 0f;
+
+        Vector3 startPosition = Vector3.zero;
+        Vector3 startLocalPosition = Vector3.zero;
+        Vector3 refPosition = Vector3.zero;
+
+        bool end = false;
+        Action endCallBack = null;
+
+        public void Begin(bool _deActiveOnEnd = true)
+        {
+            endTime = Time.time + duration;
+            end = false;
+            disableOnEnd = _deActiveOnEnd;
+            startPosition = this.transform.position;
+            startLocalPosition = this.transform.localPosition;
+            refPosition = Vector3.zero;
+            endCallBack = null;
+
+            this.enabled = true;
+            if (!this.gameObject.activeInHierarchy)
+            {
+                this.SetActive(true);
+            }
+        }
+
+        public void Begin(Action _callBack, bool _disableOnEnd = true)
+        {
+            endTime = Time.time + duration;
+            end = false;
+            disableOnEnd = _disableOnEnd;
+            startPosition = this.transform.position;
+            startLocalPosition = this.transform.localPosition;
+            refPosition = Vector3.zero;
+            endCallBack = _callBack;
+
+            this.enabled = true;
+            if (!this.gameObject.activeInHierarchy)
+            {
+                this.SetActive(true);
+            }
+        }
+
+        private void LateUpdate()
+        {
+            switch (m_LerpType)
+            {
+                case LerpType.Linear:
+                    if (Time.time < endTime)
+                    {
+                        var t = Mathf.Clamp01(1f - (endTime - Time.time) / m_Duration);
+                        if (isLocal)
+                        {
+                            this.transform.localPosition = Vector3.Lerp(startLocalPosition, destination, t);
+                        }
+                        else
+                        {
+                            this.transform.position = Vector3.Lerp(startPosition, destination, t);
+                        }
+                    }
+                    else
+                    {
+                        end = true;
+                        if (isLocal)
+                        {
+                            this.transform.localPosition = destination;
+                        }
+                        else
+                        {
+                            this.transform.position = destination;
+                        }
+                    }
+                    break;
+                case LerpType.Smooth:
+
+                    if (isLocal)
+                    {
+                        if (Vector3.Distance(this.transform.localPosition, new Vector3(destination.x, destination.y)) > 1)
+                        {
+                            this.transform.localPosition = Vector3.SmoothDamp(this.transform.localPosition, destination, ref refPosition, duration);
+                        }
+                        else
+                        {
+                            this.transform.localPosition = destination;
+                            end = true;
+                        }
+                    }
+                    else
+                    {
+                        if (Vector3.Distance(this.transform.position, new Vector3(destination.x, destination.y)) > 1)
+                        {
+                            this.transform.position = Vector3.SmoothDamp(this.transform.position, destination, ref refPosition, duration);
+                        }
+                        else
+                        {
+                            this.transform.position = destination;
+                            end = true;
+                        }
+                    }
+                    break;
+            }
+
+            if (end)
+            {
+                if (endCallBack != null)
+                {
+                    endCallBack();
+                    endCallBack = null;
+                }
+            }
+
+            if (end && disableOnEnd)
+            {
+                this.enabled = false;
+            }
+
+        }
+
+
+        public enum LerpType
+        {
+            Linear,
+            Smooth,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/ScreenMoveTo.cs.meta b/Main/Component/UI/Common/ScreenMoveTo.cs.meta
new file mode 100644
index 0000000..a447629
--- /dev/null
+++ b/Main/Component/UI/Common/ScreenMoveTo.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3ca707687c4231e40994da414568afb7
+timeCreated: 1504795979
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ScrollItem.cs b/Main/Component/UI/Common/ScrollItem.cs
new file mode 100644
index 0000000..b7c4787
--- /dev/null
+++ b/Main/Component/UI/Common/ScrollItem.cs
@@ -0,0 +1,61 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+
+
+public class ScrollItem : MonoBehaviour
+{
+
+    RectTransform m_RectTransform;
+    public RectTransform rectTransform {
+        get {
+            if (m_RectTransform == null)
+            {
+                m_RectTransform = this.AddMissingComponent<RectTransform>();
+            }
+            return m_RectTransform;
+        }
+    }
+
+    public virtual void Display(object _data)
+    {
+        this.SetActive(true);
+    }
+
+    public virtual void Dispose()
+    {
+
+    }
+
+    public virtual void OpeningShow()
+    {
+
+    }
+
+    public void LuaDisplay(int index)
+    {
+        if (luaDisplay != null)
+        {
+            luaDisplay(index);
+        }
+    }
+
+    public void LuaDispose()
+    {
+        if (luaDispose != null)
+        {
+            luaDispose();
+        }
+    }
+
+    Action<int> luaDisplay;
+    Action luaDispose;
+    public void LuaRegister(Action<int> displayCallBack, Action disposeCallBack)
+    {
+        luaDisplay = displayCallBack;
+        luaDispose = disposeCallBack;
+    }
+
+}
diff --git a/Main/Component/UI/Common/ScrollItem.cs.meta b/Main/Component/UI/Common/ScrollItem.cs.meta
new file mode 100644
index 0000000..1bd2fbd
--- /dev/null
+++ b/Main/Component/UI/Common/ScrollItem.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e20842c038bc5a3488548d02df8250a0
+timeCreated: 1497924839
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/ScrollRectGroup.cs b/Main/Component/UI/Common/ScrollRectGroup.cs
new file mode 100644
index 0000000..164b91e
--- /dev/null
+++ b/Main/Component/UI/Common/ScrollRectGroup.cs
@@ -0,0 +1,157 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+public class ScrollRectGroup : MonoBehaviour, IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler
+{
+    [SerializeField] ScrollRect[] m_ScrollRects;
+    [SerializeField] Direction m_OnlyDirection;
+    [SerializeField] float m_Offset = 100f;
+
+    Dictionary<Direction, ScrollRect> scrollRects = new Dictionary<Direction, ScrollRect>();
+
+    Direction m_Direction = Direction.None;
+    Direction direction
+    {
+        get { return m_Direction; }
+        set
+        {
+            if (value != m_Direction)
+            {
+                m_Direction = value;
+
+                scrollRects[Direction.Horizontal].horizontal = direction == Direction.Horizontal
+                    || direction == Direction.Both;
+                scrollRects[Direction.Vertical].vertical = direction == Direction.Vertical
+                    || direction == Direction.Both;
+                scrollRects[Direction.Both].horizontal = direction == Direction.Horizontal
+                    || direction == Direction.Both;
+                scrollRects[Direction.Both].vertical = direction == Direction.Vertical
+                    || direction == Direction.Both;
+            }
+        }
+    }
+
+    Vector2 m_StartPosition = Vector2.zero;
+
+
+
+    private void Awake()
+    {
+        for (int i = 0; i < m_ScrollRects.Length; i++)
+        {
+            var scrollRect = m_ScrollRects[i];
+            if (scrollRect.horizontal && scrollRect.vertical)
+            {
+                scrollRects.Add(Direction.Both, scrollRect);
+            }
+            else if (scrollRect.horizontal)
+            {
+                scrollRects.Add(Direction.Horizontal, scrollRect);
+            }
+            else
+            {
+                scrollRects.Add(Direction.Vertical, scrollRect);
+            }
+        }
+
+        Initialize();
+    }
+
+    public void Initialize()
+    {
+        direction = Direction.Both;
+
+        scrollRects[Direction.Both].horizontalNormalizedPosition = 0f;
+        scrollRects[Direction.Both].verticalNormalizedPosition = 1f;
+        scrollRects[Direction.Horizontal].horizontalNormalizedPosition = 0f;
+        scrollRects[Direction.Vertical].verticalNormalizedPosition = 1f;
+    }
+
+    public void OnBeginDrag(PointerEventData eventData)
+    {
+        direction = Direction.Both;
+
+        foreach (var scrollRect in m_ScrollRects)
+        {
+            scrollRect.OnBeginDrag(eventData);
+        }
+
+        m_StartPosition = eventData.position;
+    }
+
+    public void OnDrag(PointerEventData eventData)
+    {
+        var position = eventData.position;
+        if (direction == Direction.Both)
+        {
+            if (m_OnlyDirection == Direction.Both)
+            {
+                var horizontal = Mathf.Abs(position.x - m_StartPosition.x) > m_Offset;
+                var vertical = !horizontal && Mathf.Abs(position.y - m_StartPosition.y) > m_Offset;
+                if (horizontal || vertical)
+                {
+                    var _direction = horizontal ? Direction.Horizontal : Direction.Vertical;
+                    if (_direction != direction)
+                    {
+                        direction = _direction;
+                        foreach (var scrollRect in m_ScrollRects)
+                        {
+                            scrollRect.OnBeginDrag(eventData);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                direction = m_OnlyDirection;
+            }
+        }
+
+        if (direction != Direction.Both)
+        {
+            foreach (var scrollRect in m_ScrollRects)
+            {
+                scrollRect.OnDrag(eventData);
+            }
+        }
+    }
+
+    public void OnEndDrag(PointerEventData eventData)
+    {
+        foreach (var scrollRect in m_ScrollRects)
+        {
+            scrollRect.OnEndDrag(eventData);
+        }
+    }
+
+    public void OnInitializePotentialDrag(PointerEventData eventData)
+    {
+        foreach (var scrollRect in m_ScrollRects)
+        {
+            scrollRect.OnInitializePotentialDrag(eventData);
+        }
+    }
+
+#if UNITY_EDITOR
+    [ContextMenu("CloseRayAccepter")]
+    void BatchCloseRayAccepter()
+    {
+        var componenst = transform.GetComponentsInChildren<Graphic>(true);
+        for (int i = 0; i < componenst.Length; i++)
+        {
+            componenst[i].raycastTarget = false;
+        }
+    }
+#endif
+
+    enum Direction
+    {
+        None,
+        Horizontal,
+        Vertical,
+        Both,
+    }
+}
diff --git a/Main/Component/UI/Common/ScrollRectGroup.cs.meta b/Main/Component/UI/Common/ScrollRectGroup.cs.meta
new file mode 100644
index 0000000..4b0afbe
--- /dev/null
+++ b/Main/Component/UI/Common/ScrollRectGroup.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a6e59bf3eba4a5b469f728041f8f421e
+timeCreated: 1559791936
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SecondFrameLoader.cs b/Main/Component/UI/Common/SecondFrameLoader.cs
new file mode 100644
index 0000000..517039c
--- /dev/null
+++ b/Main/Component/UI/Common/SecondFrameLoader.cs
@@ -0,0 +1,39 @@
+锘�/*
+    杩欐槸鏃х殑浜岀骇鐣岄潰鍔犺浇鍣紝宸插惎鐢紝璇蜂娇鐢⊿econdFrameLoader2
+*/
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    [ExecuteAlways]
+    public class SecondFrameLoader : UIPrefabLoader
+    {
+        [SerializeField] string m_TitleKey;
+
+        public override void Create()
+        {
+            base.Create();
+
+            if (Application.isPlaying)
+            {
+                var text = this.GetComponentInChildren<Text>();
+                if (text != null)
+                {
+                    text.fontSize = 24;
+                    text.resizeTextForBestFit = false;
+                    text.rectTransform.sizeDelta = new Vector2(24, 141);
+                    if (!string.IsNullOrEmpty(m_TitleKey))
+                        text.text = Language.Get(m_TitleKey);
+                }
+            }
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/SecondFrameLoader.cs.meta b/Main/Component/UI/Common/SecondFrameLoader.cs.meta
new file mode 100644
index 0000000..e3b1b02
--- /dev/null
+++ b/Main/Component/UI/Common/SecondFrameLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 28068c14282ee1a48953dc84be40db67
+timeCreated: 1557405564
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SecondFrameLoader2.cs b/Main/Component/UI/Common/SecondFrameLoader2.cs
new file mode 100644
index 0000000..b98425c
--- /dev/null
+++ b/Main/Component/UI/Common/SecondFrameLoader2.cs
@@ -0,0 +1,111 @@
+using UnityEngine;
+using UnityEngine.UI;
+/**
+杩欐槸鏂扮殑浜岀骇鐣岄潰鍔犺浇鍣�
+*/
+namespace vnxbqy.UI
+{
+
+    public enum FrameSize
+    {
+        Free,
+        XLarge,
+        Large,
+        Medium,
+        Small,
+    }
+
+    [ExecuteAlways]
+    public class SecondFrameLoader2 : UIPrefabLoader
+    {
+        [SerializeField] public FrameSize frameSize;
+
+        [SerializeField] public Vector2 size;
+
+        public string m_TitleKey;
+
+        public override string prefabName { get { return "SecondFrame"; } }
+
+        public override void Create()
+        {
+            base.Create();
+            UpdateSize();
+            InitUI();
+        }
+
+        private void Update()
+        {
+            if (Application.isPlaying)
+                return;
+            UpdateSize();
+        }
+
+        public void InitUI()
+        {
+            var button = this.GetComponentInChildren<ButtonEx>();
+            var window = this.GetComponentInParent<Window>();
+            button.AddListener(() =>//鍏抽棴鎸夐挳
+            {
+                DebugEx.Log("鍏抽棴绐楀彛");
+                window.Close();
+            });
+            var text = this.GetComponentInChildren<Text>();
+            if (text != null)
+            {
+                if (Application.isPlaying)
+                {
+                    text.fontSize = 24;
+                    text.resizeTextForBestFit = false;
+                    text.rectTransform.sizeDelta = new Vector2(24, 141);
+                    if (!string.IsNullOrEmpty(m_TitleKey))
+                        text.text = Language.Get(m_TitleKey);
+                }
+                else
+                    text.text = "褰撳墠鏍囬";
+            }
+    }
+
+        public void UpdateSize()
+        {
+            if (instance == null)
+                return;
+            switch (frameSize)
+            {
+                case FrameSize.XLarge:
+                    {
+                        SetSize(1000, 650);
+                        break;
+                    }
+                case FrameSize.Large:
+                    {
+                        SetSize(800, 650);
+                        break;
+                    }
+                case FrameSize.Medium:
+                    {
+                        SetSize(650, 650);
+                        break;
+                    }
+                case FrameSize.Small:
+                    {
+                        SetSize(550, 650);
+                        break;
+                    }
+                case FrameSize.Free:
+                    {
+                        SetSize(size.x, size.y);
+                        break;
+                    }
+            }
+        }
+
+        private void SetSize(float width, float height)
+        {
+            if (instance == null)
+                return;
+            (instance.transform as RectTransform).sizeDelta = new Vector2(width, height);
+        }
+
+    }
+
+}
diff --git a/Main/Component/UI/Common/SecondFrameLoader2.cs.meta b/Main/Component/UI/Common/SecondFrameLoader2.cs.meta
new file mode 100644
index 0000000..8ac5322
--- /dev/null
+++ b/Main/Component/UI/Common/SecondFrameLoader2.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 123a6f0275fc88d419990a7dfeb3dfcf
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SmoothMask.cs b/Main/Component/UI/Common/SmoothMask.cs
new file mode 100644
index 0000000..3907fcf
--- /dev/null
+++ b/Main/Component/UI/Common/SmoothMask.cs
@@ -0,0 +1,124 @@
+锘縰sing UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+[DisallowMultipleComponent]
+[ExecuteAlways]
+
+public class SmoothMask:UIBehaviour,ICanvasRaycastFilter {
+
+    [Range(0,1)]
+    [SerializeField]
+    private float m_Horizontal = 0f;
+    public float horizontal { get { return m_Horizontal; } }
+
+    [Range(0,1)]
+    [SerializeField]
+    private float m_Vertical = 0f;
+    public float vertical { get { return m_Vertical; } }
+
+    [SerializeField]
+    private Material[] m_ImageMaterials;
+    public Material[] imageMaterials { get { return m_ImageMaterials; } }
+
+    [SerializeField]
+    private Material[] m_TextMaterials;
+    public Material[] textMaterials { get { return m_TextMaterials; } }
+
+    [SerializeField]
+    private CanvasScaler m_CanvasScaler;
+    public CanvasScaler canvasScaler {
+        get {
+            return m_CanvasScaler ?? (m_CanvasScaler = GetComponentInParent<CanvasScaler>());
+        }
+    }
+
+    public RectTransform rectTransform {
+        get {
+            return this.transform as RectTransform;
+        }
+    }
+    private Vector2 leftBottom;
+    private Vector2 rightTop;
+
+    public bool IsRaycastLocationValid(Vector2 sp,Camera eventCamera) {
+        return RectTransformUtility.RectangleContainsScreenPoint(rectTransform,sp,eventCamera);
+    }
+
+    void LateUpdate() {
+        UpdateChildMaterialSmoothMask();
+    }
+
+    [ContextMenu("SetMaterial")]
+    public void UpdateChildrenMaterial() {
+        SetChildrenImageMaterial(this.transform);
+        SetChildrenTextMaterial(this.transform);
+    }
+
+    private void SetChildrenImageMaterial(Transform _transform) {
+        Image image;
+        Transform transform;
+        for(int i = 0;i < _transform.childCount;i++) {
+            transform = _transform.GetChild(i);
+            image = transform.GetComponent<Image>();
+            if(image != null) {
+                image.material = imageMaterials.Length > 0 ? imageMaterials[0] : null;
+            }
+            else
+            {
+                var imageex = transform.GetComponent<ImageEx>();
+                if (imageex != null)
+                {
+                    imageex.material = imageMaterials.Length > 0 ? imageMaterials[0] : null;
+                }
+            }
+
+            if(transform.childCount > 0) {
+                SetChildrenImageMaterial(transform);
+            }
+        }
+    }
+
+    private void SetChildrenTextMaterial(Transform _parent) {
+        Text text;
+        Transform transform;
+        for(int i = 0;i < _parent.childCount;i++) {
+            transform = _parent.GetChild(i);
+            text = transform.GetComponent<Text>();
+            if(text != null) {
+                text.material = textMaterials.Length > 0 ? textMaterials[0] : null;
+            }
+
+            if(transform.childCount > 0) {
+                SetChildrenTextMaterial(transform);
+            }
+        }
+    }
+
+    private void UpdateChildMaterialSmoothMask() {
+        var scaleX = canvasScaler.transform.localScale.x;
+        var scaleY = canvasScaler.transform.localScale.y;
+
+        leftBottom = scaleX == 0f ? Vector2.zero : rectTransform.GetMinWorldPosition() / scaleX;
+        rightTop = scaleY == 0f ? Vector2.zero : rectTransform.GetMaxWorldPosition() / scaleY;
+
+        if(imageMaterials != null) {
+            for(int i = 0;i < imageMaterials.Length;i++) {
+                SetSmoothMask(imageMaterials[i],leftBottom,rightTop,new Vector2(horizontal,vertical));
+            }
+        }
+
+        if(textMaterials != null) {
+            for(int i = 0;i < textMaterials.Length;i++) {
+                SetSmoothMask(textMaterials[i],leftBottom,rightTop,new Vector2(horizontal,vertical));
+            }
+        }
+    }
+
+    static void SetSmoothMask(Material material,Vector2 leftBottom,Vector2 rightTop,Vector2 smoothRect) {
+        material.SetVector("_LeftBottom",leftBottom);
+        material.SetVector("_RightTop",rightTop);
+        material.SetVector("_SmoothRect",smoothRect);
+    }
+}
+
diff --git a/Main/Component/UI/Common/SmoothMask.cs.meta b/Main/Component/UI/Common/SmoothMask.cs.meta
new file mode 100644
index 0000000..a11a540
--- /dev/null
+++ b/Main/Component/UI/Common/SmoothMask.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 86dc776f56a9adb4db2a8860c547a1e1
+timeCreated: 1498132046
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SmoothSlider.cs b/Main/Component/UI/Common/SmoothSlider.cs
new file mode 100644
index 0000000..95c2f29
--- /dev/null
+++ b/Main/Component/UI/Common/SmoothSlider.cs
@@ -0,0 +1,72 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    [DisallowMultipleComponent]
+    
+    public class SmoothSlider : MonoBehaviour
+    {
+
+        [SerializeField]
+        Slider m_Slider;
+        public Slider slider {
+            get { return m_Slider; }
+        }
+
+        [SerializeField]
+        [Range(0, 10)]
+        float m_Delay = 0.2f;
+        public float delay {
+            get { return m_Delay; }
+            set {
+                m_Delay = Mathf.Clamp(value, 0, 10);
+            }
+        }
+
+        [SerializeField]
+        [Range(0, 1)]
+        float m_Value = 0f;
+        public float value {
+            get {
+                return m_Value;
+            }
+            set {
+                m_Value = Mathf.Clamp01(value);
+            }
+        }
+
+        float refSpeed = 0f;
+
+        public void ResetValue(float _value)
+        {
+            value = _value;
+            if (slider != null)
+            {
+                slider.value = Mathf.Clamp01(_value);
+            }
+        }
+
+        void OnEnable()
+        {
+            refSpeed = 0f;
+        }
+
+        void LateUpdate()
+        {
+            if (slider == null)
+            {
+                return;
+            }
+            if (Mathf.Abs(slider.value - value) > 0.001f)
+            {
+                slider.value = Mathf.SmoothDamp(slider.value, value, ref refSpeed, delay);
+            }
+        }
+
+    }
+
+}
diff --git a/Main/Component/UI/Common/SmoothSlider.cs.meta b/Main/Component/UI/Common/SmoothSlider.cs.meta
new file mode 100644
index 0000000..0d59b29
--- /dev/null
+++ b/Main/Component/UI/Common/SmoothSlider.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4cb5797279ad23847bc1fe7940adc4a5
+timeCreated: 1500879264
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SortCell.cs b/Main/Component/UI/Common/SortCell.cs
new file mode 100644
index 0000000..f37b9ee
--- /dev/null
+++ b/Main/Component/UI/Common/SortCell.cs
@@ -0,0 +1,20 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace EnhancedUI.EnhancedScroller
+{
+    public class SortCell : CellView
+    {
+        [SerializeField] Text m_SortTypeTxt;
+        public Text sortTypeTxt
+        {
+            get
+            {
+                return m_SortTypeTxt;
+            }
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/SortCell.cs.meta b/Main/Component/UI/Common/SortCell.cs.meta
new file mode 100644
index 0000000..08c083e
--- /dev/null
+++ b/Main/Component/UI/Common/SortCell.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ec44b87b23896f7458cdf104fca85827
+timeCreated: 1517219415
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/SortTable.cs b/Main/Component/UI/Common/SortTable.cs
new file mode 100644
index 0000000..a4d5172
--- /dev/null
+++ b/Main/Component/UI/Common/SortTable.cs
@@ -0,0 +1,125 @@
+锘縰sing EnhancedUI.EnhancedScroller;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    public class SortTable : MonoBehaviour
+    {
+        [SerializeField] SortType m_SortType;
+        public SortType sortType
+        {
+            get
+            {
+                return m_SortType;
+            }
+            set
+            {
+                m_SortType = value;
+            }
+        }
+        [SerializeField] List<SortElement> m_SortElements;
+        [SerializeField] ScrollerController m_Controller;
+        [SerializeField] ClickScreenOtherSpace m_ClickOtherSpace;
+        [SerializeField] Text m_TargetDisplay;
+        public event Action<SortType, int> onSelectSortEvent;
+        public event Action onSortCloseEvent;
+        private void Awake()
+        {
+            m_Controller.OnRefreshCell += OnRefreshCell;
+        }
+
+        private void OnEnable()
+        {
+            m_Controller.Refresh();
+            if (m_SortElements != null)
+            {
+                for (int i = 0; i < m_SortElements.Count; i++)
+                {
+                    m_Controller.AddCell(ScrollerDataType.Header, i, OnSortSelect);
+                }
+            }
+            m_Controller.Restart();
+
+            if (m_ClickOtherSpace != null)
+            {
+                m_ClickOtherSpace.RemoveAllListeners();
+                m_ClickOtherSpace.AddListener(() =>
+                {
+                    if (onSortCloseEvent != null)
+                    {
+                        onSortCloseEvent();
+                    }
+                });
+            }
+        }
+        private void OnSortSelect(CellView _cell)
+        {
+            var _index = _cell.index;
+            var type = m_SortElements[_index].type;
+            if (onSelectSortEvent != null)
+            {
+                onSelectSortEvent(sortType,type);
+            }
+            if (onSortCloseEvent != null)
+            {
+                onSortCloseEvent();
+            }
+            if (m_TargetDisplay != null)
+            {
+                m_TargetDisplay.text = Language.Get(m_SortElements[_index].textKey);
+            }
+            this.SetActive(false);
+        }
+        private void OnRefreshCell(ScrollerDataType type, CellView cell)
+        {
+            var _sortCell = cell as SortCell;
+            _sortCell.sortTypeTxt.text = Language.Get(m_SortElements[cell.index].textKey);
+        }
+
+        public void SetDefault(int value = 0)
+        {
+            if(value == 0)
+            {
+                if (m_TargetDisplay != null && m_SortElements != null && m_SortElements.Count > 0)
+                {
+                    m_TargetDisplay.text = Language.Get(m_SortElements[0].textKey);
+                }
+            }
+            else
+            {
+                if (m_TargetDisplay != null && m_SortElements != null && m_SortElements.Count > 0)
+                {
+                    foreach(var key in m_SortElements)
+                    {
+                        if(key.type == value)
+                        {
+                            m_TargetDisplay.text = Language.Get(key.textKey);
+                            break;
+                        }
+                    }
+                  
+                }
+            }
+           
+        }
+    }
+
+    public enum SortType
+    {
+        EquipQuality,
+        EquipStar,
+        EquipLv,
+    }
+    [Serializable]
+    public struct SortElement
+    {
+        [Header("璇█琛╧ey")]
+        public string textKey;
+        public int type;
+    }
+}
+
diff --git a/Main/Component/UI/Common/SortTable.cs.meta b/Main/Component/UI/Common/SortTable.cs.meta
new file mode 100644
index 0000000..0b88864
--- /dev/null
+++ b/Main/Component/UI/Common/SortTable.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ed4b57f2a5f2ae9429557f7cc916287f
+timeCreated: 1517218252
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/TimeDownMgr.cs b/Main/Component/UI/Common/TimeDownMgr.cs
new file mode 100644
index 0000000..94d8c5f
--- /dev/null
+++ b/Main/Component/UI/Common/TimeDownMgr.cs
@@ -0,0 +1,122 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+
+public class TimeDownMgr : SingletonMonobehaviour<TimeDownMgr> {
+
+
+    public enum CoolTimeType
+    {
+        Test=0,
+        BagSort=1,
+        DepotSort=2,
+        DeadCD = 3, //璺濈鐜╁澶嶆椿鐨勬椂闂�
+        DeadTiredCD = 4, //璺濈娓呴櫎鐜╁澶嶆椿鐤插姵鐨勬椂闂� 
+        BossAutoReborn = 5, //鍦˙oss闄勮繎琚帺瀹跺嚮鏉�澶嶆椿
+        DuplicatesReborn = 6, //鍓湰姝讳骸绫诲瀷
+        SyncServerTime=7,//鍚屾鏈嶅姟鍣ㄦ椂闂�
+        HeavenBattleReaminTime = 8, //浠欓瓟涔嬩簤鍓╀綑鏃堕棿
+        prepareBetRemainTime = 9,  //鏈�缁堟瘮鍒嗛娴�
+        firstBetRemainTime = 10,  //绗竴闃舵姣斿垎棰勬祴
+        secondBetRemainTime = 11,  //绗簩闃舵姣斿垎棰勬祴
+        thirdBetRemainTime = 12,   //绗笁闃舵姣斿垎棰勬祴
+        BattlePrepareTime = 13, //鎴樻枟鍓嶅�掕鏃�
+        HappyFreeBestXB = 14,//鏋佸搧瀵诲疂鍏嶈垂鏃堕棿鍊掕鏃� 搴熷純
+        HappyFreeRuneXB = 15,  //绗﹀嵃瀵诲疂鍏嶈垂鏃堕棿鍊掕鏃� 搴熷純
+        HappyXBWarehouse = 16,  //瀵诲疂浠撳簱鏁寸悊鍊掕鏃�
+        FlashRushToBuyAppointment = 17, //闄愭椂鎶㈣喘棰勭害鍊掕鏃�
+        DungeonAssistCoolTime = 18, //鍓湰鍔╂垬涓�閿彫鍞ゅ�掕鏃�
+    }
+
+    public void Begin(CoolTimeType type, float duration,Action<float> func,float tick=1.0f)
+    {
+        CoolTimeData data = coolTimeList.Find((CoolTimeData x) => {
+            return x.type==type;
+        });
+        if (data != null)
+        {
+            coolTimeList.Remove(data);
+            data = null;
+        }
+        data = new CoolTimeData();
+        data.time = 0;
+        data.type = type;
+        data.tick = tick;
+        data.duration = duration;
+        data.func = func;
+        coolTimeList.Add(data);
+    }
+
+    public void Stop(CoolTimeType type)
+    {
+        CoolTimeData value = null;
+        if (Get(type,out value))
+        {
+            coolTimeList.Remove(value);
+        }
+    }
+
+    public bool Get(CoolTimeType type,out CoolTimeData value)
+    {
+        CoolTimeData data = coolTimeList.Find((CoolTimeData x) => {
+            return x.type == type;
+        });
+        value = null;
+        if (data!=null) {
+            value = data;
+            return true;
+        }
+        return false;
+    }
+
+    public class CoolTimeData
+    {
+        public CoolTimeType type;
+        public float tick;
+        public float duration;
+        public float time;
+        private Action<float> m_func;
+        public Action<float> func
+        {
+            get { return m_func; }
+            set
+            {
+                if (m_func == null) m_func = value;
+                else
+                {
+                    if (Array.IndexOf(m_func.GetInvocationList(), value) == -1)
+                    {
+                        m_func += value;
+                    }
+                }
+                
+            }
+        }
+
+
+    }
+
+    private List<CoolTimeData> coolTimeList = new List<CoolTimeData>();
+
+    private void LateUpdate()
+    {
+        for (int i = 0; i < coolTimeList.Count; i++) {
+            CoolTimeData data = coolTimeList[i];
+            data.time += Time.deltaTime;
+            if (data.time >= data.tick) {
+                if (data.func != null) data.func(Mathf.CeilToInt(data.duration-data.time));
+                data.tick += 1;
+                data.tick = Mathf.Min(data.tick, data.duration);
+            }
+            if (data.time >= data.duration) {
+                data = null;
+                coolTimeList.RemoveAt(i);
+                i--;
+            }
+        }
+    }
+
+
+}
diff --git a/Main/Component/UI/Common/TimeDownMgr.cs.meta b/Main/Component/UI/Common/TimeDownMgr.cs.meta
new file mode 100644
index 0000000..bfda687
--- /dev/null
+++ b/Main/Component/UI/Common/TimeDownMgr.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d3361c20bbaa0de4db1e732bca94193a
+timeCreated: 1508406806
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/TimerBehaviour.cs b/Main/Component/UI/Common/TimerBehaviour.cs
new file mode 100644
index 0000000..6064160
--- /dev/null
+++ b/Main/Component/UI/Common/TimerBehaviour.cs
@@ -0,0 +1,96 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, November 11, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class TimerBehaviour : MonoBehaviour
+    {
+        [SerializeField] protected Text m_TimeShow;
+        public Text timeShow { get { return m_TimeShow; } }
+
+        [SerializeField] Pattern m_Pattern = Pattern.English;
+
+        protected DateTime endTime;
+        Action onTime;
+
+        float secondTimer = 0f;
+
+        public void Begin(int seconds, Action _callBack = null)
+        {
+            endTime = TimeUtility.ServerNow + new TimeSpan(seconds * TimeSpan.TicksPerSecond);
+            onTime = _callBack;
+            if (endTime > TimeUtility.ServerNow)
+            {
+                this.SetActive(true);
+                UpdateTimeShow();
+            }
+            else
+            {
+                this.SetActive(false);
+            }
+        }
+
+        public void Stop()
+        {
+            endTime = DateTime.MinValue;
+            onTime = null;
+            this.SetActive(false);
+        }
+
+        private void LateUpdate()
+        {
+            if (TimeUtility.ServerNow > endTime)
+            {
+                if (onTime != null)
+                {
+                    onTime();
+                    onTime = null;
+                }
+
+                this.SetActive(false);
+            }
+            else
+            {
+                secondTimer += Time.deltaTime;
+                if (secondTimer > 1f)
+                {
+                    secondTimer = 0f;
+                    UpdateTimeShow();
+                }
+            }
+        }
+
+        protected virtual void UpdateTimeShow()
+        {
+            var lastSecond = (float)(endTime - TimeUtility.ServerNow).TotalSeconds;
+
+            switch (m_Pattern)
+            {
+                case Pattern.English:
+                    m_TimeShow.text = TimeUtility.SecondsToHMS(Mathf.RoundToInt(lastSecond));
+                    break;
+                case Pattern.Chinese:
+                    m_TimeShow.text = TimeUtility.SecondsToDHMSCHS(Mathf.RoundToInt(lastSecond));
+                    break;
+            }
+        }
+
+        public enum Pattern
+        {
+            English = 0,
+            Chinese = 1,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/TimerBehaviour.cs.meta b/Main/Component/UI/Common/TimerBehaviour.cs.meta
new file mode 100644
index 0000000..efb2b0d
--- /dev/null
+++ b/Main/Component/UI/Common/TimerBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ae59f1337ccfa9e44bed8f4894c711d0
+timeCreated: 1510385285
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/TimerToChsBehaviour.cs b/Main/Component/UI/Common/TimerToChsBehaviour.cs
new file mode 100644
index 0000000..cd4d046
--- /dev/null
+++ b/Main/Component/UI/Common/TimerToChsBehaviour.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+namespace vnxbqy.UI
+{
+    public class TimerToChsBehaviour : TimerBehaviour
+    {
+        [HideInInspector]
+        public string addtionInfo = string.Empty;
+
+        protected override void UpdateTimeShow()
+        {
+            var lastSecond = (endTime - TimeUtility.ServerNow).TotalSeconds;
+            m_TimeShow.text = StringUtility.Contact(TimeUtility.SecondsToDHMSCHS((int)lastSecond), addtionInfo);
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/TimerToChsBehaviour.cs.meta b/Main/Component/UI/Common/TimerToChsBehaviour.cs.meta
new file mode 100644
index 0000000..a2d5164
--- /dev/null
+++ b/Main/Component/UI/Common/TimerToChsBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c897ae06a0dfbe94b9383ea97c6852b9
+timeCreated: 1515229585
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/Treasure3DConfig.cs b/Main/Component/UI/Common/Treasure3DConfig.cs
new file mode 100644
index 0000000..a08ca53
--- /dev/null
+++ b/Main/Component/UI/Common/Treasure3DConfig.cs
@@ -0,0 +1,49 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+using System;
+using vnxbqy.UI;
+
+public class Treasure3DConfig : ScriptableObject
+{
+    public int treasureId = 0;
+
+    public string treasureNamePrefab = string.Empty;
+
+    public TreasureParam nameParam;
+    public TreasureParam modelParam;
+    public TreasureParam bottomParam;
+    public TreasureParam lockSfxParam;
+    public TreasureParam specialSfxParam;
+    [Header("鎽勫儚澶存媺杩戜綅缃�")]
+    public TreasureParam cameraTweenParam;
+    public TreasureParam renderCameraParam;
+
+    [Serializable]
+    public struct TreasureParam
+    {
+        public Vector3 position;
+        public Vector3 rotation;
+        public Vector3 scale;
+    }
+}
+
+#if UNITY_EDITOR
+public class Treasure3DConfigEditor : Editor
+{
+    [MenuItem("绛栧垝宸ュ叿/鐢熸垚娉曞疂閰嶇疆鏂囦欢")]
+    static void BuildConfig()
+    {
+        Treasure3DConfig _config = CreateInstance<Treasure3DConfig>();
+        string _path = StringUtility.Contact("Assets/ResourcesOut/Refdata/ScriptableObject/SoTreasure3D/",
+                                      "SoTreasure3D_",
+                                      ".asset");
+        AssetDatabase.CreateAsset(_config, _path);
+        AssetDatabase.Refresh();
+        ProjectWindowUtil.ShowCreatedAsset(_config);
+    }
+}
+#endif
diff --git a/Main/Component/UI/Common/Treasure3DConfig.cs.meta b/Main/Component/UI/Common/Treasure3DConfig.cs.meta
new file mode 100644
index 0000000..6046922
--- /dev/null
+++ b/Main/Component/UI/Common/Treasure3DConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1eb4e0f45cdb1c94495adb21558ee75e
+timeCreated: 1525857023
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/TreasureMeridianConfig.cs b/Main/Component/UI/Common/TreasureMeridianConfig.cs
new file mode 100644
index 0000000..00b7dfd
--- /dev/null
+++ b/Main/Component/UI/Common/TreasureMeridianConfig.cs
@@ -0,0 +1,152 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using System;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+public class TreasureMeridianConfig : ScriptableObject
+{
+    [SerializeField] int m_TreasureId = 0;
+    [SerializeField] int m_StagePointCount = 0;
+    [SerializeField] List<StagePoint> m_StagePoints = new List<StagePoint>();
+
+    public StagePoint this[int _index]
+    {
+        get
+        {
+            if (_index < m_StagePoints.Count)
+            {
+                return m_StagePoints[_index];
+            }
+            return null;
+        }
+    }
+
+    public int treasureId
+    {
+        get { return m_TreasureId; }
+        set { m_TreasureId = value; }
+    }
+
+    public int stagePointNum
+    {
+        get
+        {
+            return m_StagePointCount;
+        }
+        set
+        {
+            m_StagePointCount = value;
+            if (m_StagePointCount != m_StagePoints.Count)
+            {
+                if (m_StagePointCount > m_StagePoints.Count)
+                {
+                    for (int i = m_StagePoints.Count; i < m_StagePointCount; i++)
+                    {
+                        m_StagePoints.Add(new StagePoint());
+                    }
+                }
+                else
+                {
+                    for (int i = m_StagePoints.Count - 1; i >= m_StagePointCount; i--)
+                    {
+                        StagePoint _point = m_StagePoints[i];
+                        m_StagePoints.RemoveAt(i);
+                        _point = null;
+                    }
+                }
+            }
+        }
+    }
+
+    [Serializable]
+    public class StagePoint
+    {
+        public Vector2 position = Vector2.zero;
+        public float scale = 1f;
+        public int effect = 0;
+        public float scaleTweenDelay = 0f;
+        public float scaleTweenTo = 0.5f;
+    }
+
+#if UNITY_EDITOR
+    public List<RectTransform> m_Meridians = new List<RectTransform>();
+#endif
+}
+
+#if UNITY_EDITOR
+[CustomEditor(typeof(TreasureMeridianConfig))]
+public class TreasureMeridianConfigEditor : Editor
+{
+    public override void OnInspectorGUI()
+    {
+        var _target = target as TreasureMeridianConfig;
+        GUILayout.BeginHorizontal();
+        GUILayout.Label("娉曞疂id");
+        _target.treasureId = EditorGUILayout.IntField(_target.treasureId);
+        GUILayout.FlexibleSpace();
+        GUILayout.EndHorizontal();
+
+        GUILayout.BeginHorizontal();
+        GUILayout.Label("缁忕粶涓暟");
+        _target.stagePointNum = EditorGUILayout.IntField(_target.stagePointNum);
+        GUILayout.FlexibleSpace();
+        GUILayout.EndHorizontal();
+
+        for (int i = 0; i < _target.stagePointNum; i++)
+        {
+            _target[i].position = EditorGUILayout.Vector2Field(StringUtility.Contact("缁忕粶", i), _target[i].position);
+            _target[i].scale = EditorGUILayout.FloatField("缂╂斁姣斾緥", _target[i].scale);
+            _target[i].effect = EditorGUILayout.IntField("鐗规晥ID", _target[i].effect);
+            _target[i].scaleTweenDelay = EditorGUILayout.FloatField("缂╂斁寤惰繜", _target[i].scaleTweenDelay);
+            _target[i].scaleTweenTo = EditorGUILayout.FloatField("缂╂斁澶у皬", _target[i].scaleTweenTo);
+            GUILayout.Space(15);
+        }
+
+        if (GUILayout.Button("鍦ㄧ晫闈笂鐢熸垚"))
+        {
+            _target.m_Meridians.Clear();
+            GameObject parent = GameObject.Find("TreasureLevelUpWin/Container_Default/Container_Display/Container_Level/Container_Meridian");
+            if (parent != null)
+            {
+                for (int i = 0; i < _target.stagePointNum; i++)
+                {
+                    GameObject go = new GameObject(i.ToString());
+                    _target.m_Meridians.Add(go.AddMissingComponent<RectTransform>());
+                    _target.m_Meridians[i].SetParentEx(parent.transform, Vector3.zero, Quaternion.identity, Vector3.one);
+                    _target.m_Meridians[i].localPosition = _target[i].position;
+                    _target.m_Meridians[i].localScale = _target[i].scale * Vector3.one;
+                }
+            }
+        }
+
+        if (_target.m_Meridians.Count > 0 
+            && _target.m_Meridians[0] == null)
+        {
+            _target.m_Meridians.Clear();
+        }
+        for (int i = 0; i < _target.m_Meridians.Count; i++)
+        {
+            if (i < _target.stagePointNum)
+            {
+                _target[i].position = _target.m_Meridians[i].localPosition;
+                _target[i].scale = _target.m_Meridians[i].localScale.x;
+            }
+        }
+    }
+
+    [MenuItem("绛栧垝宸ュ叿/鐢熸垚娉曞疂缁忕粶閰嶇疆鏂囦欢")]
+    static void BuildMeridianConfig()
+    {
+        TreasureMeridianConfig _config = CreateInstance<TreasureMeridianConfig>();
+        string _path = StringUtility.Contact("Assets/ResourcesOut/Refdata/ScriptableObject/SoTreasureMeridian/",
+                                      "SoTreasureMeridian_",
+                                      ".asset");
+        AssetDatabase.CreateAsset(_config, _path);
+        AssetDatabase.Refresh();
+        ProjectWindowUtil.ShowCreatedAsset(_config);
+    }
+}
+#endif
diff --git a/Main/Component/UI/Common/TreasureMeridianConfig.cs.meta b/Main/Component/UI/Common/TreasureMeridianConfig.cs.meta
new file mode 100644
index 0000000..679e004
--- /dev/null
+++ b/Main/Component/UI/Common/TreasureMeridianConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 898e5c58dfa959847940f9699a9ea9ee
+timeCreated: 1525347370
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DHeroSkillShow.cs b/Main/Component/UI/Common/UI3DHeroSkillShow.cs
new file mode 100644
index 0000000..655ecfd
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DHeroSkillShow.cs
@@ -0,0 +1,358 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    public class UI3DHeroSkillShow : MonoBehaviour
+    {
+        static UI3DHeroSkillShow m_Instance = null;
+        public static UI3DHeroSkillShow Instance {
+            get {
+                if (m_Instance == null)
+                {
+                    var gameObject = Instantiate(UILoader.LoadTreasure("Misc", "UI3DHeroSkillShow"));
+                    m_Instance = gameObject.GetComponent<UI3DHeroSkillShow>();
+                    Instance.transform.position = new Vector3(0, 4000, 5000);
+                    m_Instance.name = "UI3DHeroSkillShow";
+                    m_Instance.SetActive(true);
+                    DontDestroyOnLoad(gameObject);
+                }
+
+                return m_Instance;
+            }
+        }
+
+        [SerializeField] Transform m_Stage;
+        [SerializeField] Camera m_ShowCamera;
+        [SerializeField] Animator m_CameraAnimator;
+        [SerializeField] List<RuntimeAnimatorController> m_HeroShowControllers;
+        [SerializeField] List<TreasureSkill> m_TreasureSkills;
+        [SerializeField] List<SkillAct> m_SkillActs;
+
+        UI3DShowHero m_HeroShow = new UI3DShowHero();
+
+        PackModel playerPack { get { return ModelCenter.Instance.GetModel<PackModel>(); } }
+
+        Transform m_HeroPoint;
+        public Transform hero {
+            get {
+                return m_HeroPoint;
+            }
+        }
+
+        Animator m_HeroAnimator;
+
+        Action m_HeroSkillCompletet;
+
+        SFXController m_SkillExtraSfx;
+
+        public int cacheSkillId { get; private set; }
+
+        public Camera showCamera { get { return m_ShowCamera; } }
+
+        public SFXController skillEffect;
+
+        public Transform MP_Name1 {
+            get {
+                var mp_name = hero.GetChildTransformDeeply("A_Name2");
+                if (!mp_name)
+                {
+                    return hero;
+                }
+                return mp_name;
+            }
+        }
+
+        public Transform MP_Weapon {
+            get {
+                var mp_weapon = hero.GetChildTransformDeeply(WEAPON_NODE);
+                if (mp_weapon != null)
+                {
+                    if (mp_weapon.childCount > 0)
+                    {
+                        return mp_weapon.GetChild(0);
+                    }
+                    return mp_weapon;
+                }
+                return hero;
+            }
+        }
+
+        const string WEAPON_NODE = "Bip001 Prop1";
+
+
+        private void ShowHeroSkill(int _skillId, string _clip)
+        {
+            if (UI3DTreasureSelectStage.Instance.IsOpen)
+            {
+                UI3DTreasureSelectStage.Instance.showCamera.enabled = false;
+            }
+
+            cacheSkillId = _skillId;
+
+            var _job = PlayerDatas.Instance.baseData.Job;
+
+            #region 瑁呭
+            var appearance = ModelCenter.Instance.GetModel<EquipModel>().GetAppearance();
+
+            var _clothesId = appearance.clothes;
+            var _wingsId = appearance.wings;
+            var _secondaryId = appearance.secondary;
+            var _weaponId = appearance.weapon;
+            var fashionClothesId = appearance.fashionClothes;
+            var fashionWeaponId = appearance.fashionWeapon;
+            var fashionSecondaryId = appearance.fashionSecondary;
+
+            int _suitLevel = 0;
+            #endregion
+
+            UI3DPlayerExhibitionData data = new UI3DPlayerExhibitionData()
+            {
+                job = _job,
+                fashionClothesId = fashionClothesId,
+                clothesId = _clothesId,
+                suitLevel = _suitLevel,
+                fashionWeaponId = fashionWeaponId,
+                weaponId = _weaponId,
+                wingsId = _wingsId,
+                fashionSecondaryId = fashionSecondaryId,
+                secondaryId = _secondaryId,
+                isDialogue = false,
+            };
+
+            var _hero = m_HeroShow.Show(data, m_Stage);
+            if (_hero != null)
+            {
+                m_HeroPoint = _hero.transform;
+                m_HeroAnimator = _hero.GetComponent<Animator>();
+                if (m_HeroAnimator != null)
+                {
+                    m_HeroAnimator.runtimeAnimatorController = m_HeroShowControllers[_job - 1];
+                    StartCoroutine(Co_PlaySkill());
+                }
+            }
+
+            m_Stage.localEulerAngles = Vector3.zero;
+            m_ShowCamera.SetActive(true);
+
+            m_CameraAnimator.Play(_clip, 0, 0);
+            m_CameraAnimator.speed = 0;
+        }
+
+        public void ShowTreasureSkill(int _treasureId, Action callback)
+        {
+            StopShow();
+
+            Treasure _treasure;
+            ModelCenter.Instance.GetModel<TreasureModel>().TryGetTreasure(_treasureId, out _treasure);
+            if (_treasure != null)
+            {
+                m_HeroSkillCompletet = callback;
+                var _skillId = _treasure.skillId;
+                var _index = m_TreasureSkills.FindIndex((x) =>
+                {
+                    return x.treasureId == _treasureId;
+                });
+                var _treasureSkill = _index != -1 ? m_TreasureSkills[_index] : m_TreasureSkills[0];
+                _index = _treasureSkill.clip.FindIndex((x) =>
+                {
+                    return (int)x.job == PlayerDatas.Instance.baseData.Job;
+                });
+                var _clip = _index != -1 ? _treasureSkill.clip[_index] : _treasureSkill.clip[0];
+                ShowHeroSkill(_skillId, _clip.clip);
+                if (_treasureSkill.effects != null && _treasureSkill.effects.Count > 0)
+                {
+                    _index = _treasureSkill.effects.FindIndex((x) =>
+                    {
+                        return (int)x.job == PlayerDatas.Instance.baseData.Job;
+                    });
+                    var _effect = _index != -1 ? _treasureSkill.effects[_index] : _treasureSkill.effects[0];
+                    StartCoroutine(Co_PlayExtraEffect(_effect));
+                }
+            }
+        }
+
+        private void StartPlaySkill(int _skillId)
+        {
+            var config = SkillConfig.Get(_skillId);
+            if (config == null)
+            {
+                return;
+            }
+            var skillActMark = config.Skillactmark;
+
+            var index = m_SkillActs.FindIndex((x) =>
+            {
+                return x.skillId == _skillId;
+            });
+
+            if (index != -1)
+            {
+                skillActMark = m_SkillActs[index].mark;
+            }
+
+            if (skillActMark > 0 && skillActMark < 20)
+            {
+                switch (config.Skillactmark)
+                {
+                    case 10:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Attack1Hash, 0);
+                        break;
+                    case 11:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Attack2Hash, 0);
+                        break;
+                    case 12:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Attack3Hash, 0);
+                        break;
+                    case 13:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Attack4Hash, 0);
+                        break;
+                }
+            }
+            else
+            {
+                switch (skillActMark)
+                {
+                    case 21:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill21, 0);
+                        break;
+                    case 22:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill22, 0);
+                        break;
+                    case 23:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill23, 0);
+                        break;
+                    case 24:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill24, 0);
+                        break;
+                    case 25:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill25, 0);
+                        break;
+                    case 26:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill26, 0);
+                        break;
+                    case 27:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill27, 0);
+                        break;
+                    case 28:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill28, 0);
+                        break;
+                    case 29:
+                        m_HeroAnimator.Play(GAStaticDefine.State_Skill29, 0);
+                        break;
+                    case 99:
+                        m_HeroAnimator.Play(GAStaticDefine.State_RollHash, 0);
+                        break;
+                }
+            }
+
+
+        }
+
+        IEnumerator Co_PlaySkill()
+        {
+            yield return WaitingForSecondConst.WaitMS1000;
+            if (m_HeroAnimator != null)
+            {
+                StartPlaySkill(cacheSkillId);
+            }
+
+            m_CameraAnimator.speed = 1;
+            yield return null;
+            var _showTime = m_CameraAnimator.GetCurrentAnimatorStateInfo(0).length;
+            yield return new WaitForSeconds(_showTime);
+            if (m_HeroSkillCompletet != null)
+            {
+                m_HeroSkillCompletet();
+            }
+            StopShow();
+        }
+
+        IEnumerator Co_PlayExtraEffect(Effect effect)
+        {
+            yield return new WaitForSeconds(effect.startTime);
+            if (m_SkillExtraSfx != null)
+            {
+                SFXPlayUtility.Instance.Release(m_SkillExtraSfx);
+                m_SkillExtraSfx = null;
+            }
+            var parent = hero;
+            if (!string.IsNullOrEmpty(effect.parentName) && hero != null)
+            {
+                parent = hero.GetChildTransformDeeply(effect.parentName, true);
+            }
+            m_SkillExtraSfx = SFXPlayUtility.Instance.Play(effect.id, parent);
+            if (m_SkillExtraSfx != null)
+            {
+                m_SkillExtraSfx.duration = effect.duration;
+                m_SkillExtraSfx.transform.localPosition = effect.position;
+            }
+        }
+
+        public void StopShow()
+        {
+            if (UI3DTreasureSelectStage.Instance.IsOpen)
+            {
+                UI3DTreasureSelectStage.Instance.showCamera.enabled = true;
+            }
+            m_ShowCamera.SetActive(false);
+            m_HeroSkillCompletet = null;
+            m_HeroShow.Dispose();
+            if (m_SkillExtraSfx != null)
+            {
+                SFXPlayUtility.Instance.Release(m_SkillExtraSfx);
+                m_SkillExtraSfx = null;
+            }
+
+            if (skillEffect != null)
+            {
+                SFXPlayUtility.Instance.Release(skillEffect);
+                skillEffect = null;
+            }
+        }
+
+        [Serializable]
+        public struct CameraClip
+        {
+            public PlayerJob job;
+            public string clip;
+        }
+
+        [Serializable]
+        public struct Effect
+        {
+            public PlayerJob job;
+            public int id;
+            public float startTime;
+            public float duration;
+            public string parentName;
+            public Vector3 position;
+        }
+
+        [Serializable]
+        public struct TreasureSkill
+        {
+            public int treasureId;
+            public List<CameraClip> clip;
+            public List<Effect> effects;
+        }
+
+        [Serializable]
+        public struct SkillAct
+        {
+            public int skillId;
+            public int mark;
+        }
+
+        public enum PlayerJob
+        {
+            Qiang = 1,
+            Fashi,
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/UI3DHeroSkillShow.cs.meta b/Main/Component/UI/Common/UI3DHeroSkillShow.cs.meta
new file mode 100644
index 0000000..1915aeb
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DHeroSkillShow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 25df4c1b0d67ec646be407d927845b1d
+timeCreated: 1525425915
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DModelExhibition.cs b/Main/Component/UI/Common/UI3DModelExhibition.cs
new file mode 100644
index 0000000..a44413e
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelExhibition.cs
@@ -0,0 +1,977 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, September 09, 2017
+//--------------------------------------------------------
+using vnxbqy.UI;
+using System.Collections;
+using System.Collections.Generic;
+
+using UnityEngine;
+using UnityEngine.UI;
+using UnityStandardAssets.ImageEffects;
+
+namespace vnxbqy.UI
+{
+    
+    public class UI3DModelExhibition : MonoBehaviour
+    {
+        [SerializeField] Transform m_PlayerShowPoint;
+        [SerializeField] Transform m_HorseShowPoint;
+        [SerializeField] Transform m_WingShowPoint;
+        [SerializeField] Transform m_NPCShowPoint;
+        [SerializeField] Transform m_DialogPoint;
+        [SerializeField] Transform m_EquipmentPoint;
+        [SerializeField] Camera m_ShowCamera;
+        [SerializeField] ColorCorrectionCurves m_CameraColor;
+
+        public bool interactable { get; set; }
+
+        UI3DShowHero playerModel = new UI3DShowHero();
+
+        int m_HorseModelId = 0;
+        GameObject horseModel = null;
+        public GameObject NpcModelHorse {
+            get { return horseModel; }
+            set { horseModel = value; }
+        }
+
+        int m_NPCId = 0;
+        GameObject npcModel = null;
+        SFXController m_NpcEffect;
+        readonly List<SFXController> m_BindEffectList = new List<SFXController>();
+        public GameObject NpcModelPet {
+            get { return npcModel; }
+            set { npcModel = value; }
+        }
+
+        int m_WingModelId = 0;
+        GameObject wingModel = null;
+
+        int m_EquipmentModelId = 0;
+        GameObject equipmentModel = null;
+
+        SFXController godWeaponEffect = null;
+
+        SFXController horsePetEffect = null;
+
+        Coroutine m_SwtichAnimationCoroutine = null;
+
+        bool isShowingPlayer = false;
+        bool isShowingHorse = false;
+        bool isShowingNPC = false;
+        bool isShowingPet = false;
+        bool isShowinEquipment = false;
+
+        EquipModel equipModel { get { return ModelCenter.Instance.GetModel<EquipModel>(); } }
+        ReikiRootModel reikiRootModel { get { return ModelCenter.Instance.GetModel<ReikiRootModel>(); } }
+        PetModel petModel { get { return ModelCenter.Instance.GetModel<PetModel>(); } }
+
+        TitleModel titleModel { get { return ModelCenter.Instance.GetModel<TitleModel>(); } }
+
+        static UI3DModelExhibition m_Instance = null;
+        public static UI3DModelExhibition Instance {
+            get {
+                if (m_Instance == null)
+                {
+                    CreateStage();
+                }
+
+                return m_Instance;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone1 = null;
+        public static UI3DModelExhibition InstanceClone1 {
+            get {
+                if (m_InstanceClone1 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone1, 1);
+                }
+                return m_InstanceClone1;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone2 = null;
+        public static UI3DModelExhibition InstanceClone2
+        {
+            get
+            {
+                if (m_InstanceClone2 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone2, 2);
+                }
+                return m_InstanceClone2;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone3 = null;
+        public static UI3DModelExhibition InstanceClone3
+        {
+            get
+            {
+                if (m_InstanceClone3 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone3, 3);
+                }
+                return m_InstanceClone3;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone4 = null;
+        public static UI3DModelExhibition InstanceClone4
+        {
+            get
+            {
+                if (m_InstanceClone4 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone4, 4);
+                }
+                return m_InstanceClone4;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone5 = null;
+        public static UI3DModelExhibition InstanceClone5
+        {
+            get
+            {
+                if (m_InstanceClone5 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone5, 5);
+                }
+                return m_InstanceClone5;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone6 = null;
+        public static UI3DModelExhibition InstanceClone6
+        {
+            get
+            {
+                if (m_InstanceClone6 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone6, 6);
+                }
+                return m_InstanceClone6;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone7 = null;
+        public static UI3DModelExhibition InstanceClone7
+        {
+            get
+            {
+                if (m_InstanceClone7 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone7, 7);
+                }
+                return m_InstanceClone7;
+            }
+        }
+
+        static UI3DModelExhibition m_InstanceClone8 = null;
+        public static UI3DModelExhibition InstanceClone8
+        {
+            get
+            {
+                if (m_InstanceClone8 == null)
+                {
+                    CreateCloneStageEx(ref m_InstanceClone8, 8);
+                }
+                return m_InstanceClone8;
+            }
+        }
+
+        static void CreateStage()
+        {
+            var prefab = BuiltInLoader.LoadPrefab("UI3DModelExhibitionStage");
+            var gameObject = GameObject.Instantiate(prefab);
+            m_Instance = gameObject.GetComponent<UI3DModelExhibition>();
+            m_Instance.transform.position = new Vector3(1000, 2000, 3000);
+            m_Instance.name = "UI3DModelExhibitionStage";
+            m_Instance.SetActive(true);
+            m_Instance.m_ShowCamera.enabled = false;
+            DontDestroyOnLoad(gameObject);
+        }
+
+        static void CreateCloneStage()
+        {
+            var prefab = BuiltInLoader.LoadPrefab("UI3DModelExhibitionStage");
+            var gameObject = GameObject.Instantiate(prefab);
+            m_InstanceClone1 = gameObject.GetComponent<UI3DModelExhibition>();
+            m_InstanceClone1.transform.position = new Vector3(2000, 4000, 5000);
+            m_InstanceClone1.name = "UI3DModelExhibitionStage(clone1)";
+            m_InstanceClone1.SetActive(true);
+            m_InstanceClone1.m_ShowCamera.enabled = false;
+            DontDestroyOnLoad(gameObject);
+        }
+
+        static void CreateCloneStageEx(ref UI3DModelExhibition instance, int index)
+        {
+            var prefab = BuiltInLoader.LoadPrefab("UI3DModelExhibitionStage");
+            var gameObject = GameObject.Instantiate(prefab);
+            instance = gameObject.GetComponent<UI3DModelExhibition>();
+            instance.transform.position = new Vector3(1000 + index * 200, 1000 + index * 200, 5000);
+            instance.name = "UI3DModelExhibitionStage(clone" + index + ")";
+            instance.SetActive(true);
+            instance.m_ShowCamera.enabled = false;
+            DontDestroyOnLoad(gameObject);
+        }
+
+        public string GetName()
+        {
+            return this.name;
+        }
+
+        public void ShowPlayerBodyEffect(int effectId, float scale = 1)
+        {
+            if (playerModel != null)
+            {
+                playerModel.ShowTitleBodyEffect(effectId, scale);
+            }
+        }
+
+        public void HidePlayerBodyEffect()
+        {
+            if (playerModel != null)
+            {
+                playerModel.HideTitleRootEffect();
+            }
+        }
+
+        //鐜╁鑷繁鐨刄I妯″瀷灞曠ず
+        public void ShowPlayer(RawImage rawImage, int job, bool isDialogue = false, float scale = 0)
+        {
+            var apperance = equipModel.GetAppearance();
+            var reikiRootEffectId = PlayerDatas.Instance.baseData.reikiRootEffectId;
+
+            var data = new UI3DPlayerExhibitionData
+            {
+                job = job,
+                fashionClothesId = apperance.fashionClothes,
+                fashionWeaponId = apperance.fashionWeapon,
+                fashionSecondaryId = apperance.fashionSecondary,
+                clothesId = apperance.clothes,
+                weaponId = apperance.weapon,
+                secondaryId = apperance.secondary,
+                wingsId = apperance.wings,
+                suitLevel = apperance.isSuit ? 1 : 0,
+                reikiRootEffectId = isDialogue ? 0 : reikiRootEffectId,
+                isDialogue = isDialogue,
+                equipLevel = PlayerDatas.Instance.baseData.suitLevel,
+                scale = scale,
+                titleID = PlayerDatas.Instance.baseData.TitleID
+
+            };
+
+            DrawPlayer(rawImage, data);
+        }
+
+        public void ShowPlayer(RawImage rawImage, UI3DPlayerExhibitionData data)
+        {
+            DrawPlayer(rawImage, data);
+        }
+
+        public void ShowSitDownPlayer(RawImage rawImage, int job)
+        {
+            ShowPlayer(rawImage, job, false);
+            if (playerModel != null)
+            {
+                playerModel.SitDown();
+            }
+        }
+
+        void DrawPlayer(RawImage rawImage, UI3DPlayerExhibitionData data)
+        {
+            StopShow();
+
+            var isDialogue = data.isDialogue;
+            var instance = playerModel.Show(data, isDialogue ? m_DialogPoint : m_PlayerShowPoint);
+            interactable = !isDialogue;
+
+            if (!data.keepRotation)
+            {
+                m_PlayerShowPoint.localEulerAngles = Vector3.zero;
+            }
+
+            if (isDialogue)
+            {
+                instance.transform.localPosition = GeneralDefine.heroDialogueOffset;
+                instance.transform.localEulerAngles = GeneralDefine.heroDialogueRotation;
+                if (data.scale <= 0)
+                    instance.transform.localScale = GeneralDefine.heroDialogueScale * Vector3.one;
+                else
+                    instance.transform.localScale = GeneralDefine.heroDialogueScale * data.scale * Vector3.one;
+            }
+            else
+            {
+                if (data.scale > 0)
+                    instance.transform.localScale = data.scale * Vector3.one;
+            }
+
+            m_ShowCamera.enabled = true;
+            isShowingPlayer = true;
+            ResetCameraColor();
+
+            if (playerModel != null)
+            {
+                playerModel.StandUp();
+            }
+
+            BindGestureCatcher(rawImage, interactable);
+        }
+
+        public void ShowHourse(int modelId, RawImage rawImage)
+        {
+            StopShow();
+            m_ShowCamera.enabled = true;
+
+            var instance = UI3DModelFactory.LoadUIHorse(modelId);
+            if (instance == null)
+            {
+                return;
+            }
+
+            isShowingHorse = true;
+            interactable = true;
+
+            m_HorseModelId = modelId;
+            horseModel = instance;
+
+            m_HorseShowPoint.rotation = Quaternion.identity;
+
+            var modelConfig = ModelResConfig.Get(modelId);
+            var position = modelConfig.UIOffset;
+            var rotation = modelConfig.UIRotation;
+            instance.transform.SetParentEx(m_HorseShowPoint, position, rotation, modelConfig.UIScale);
+            instance.SetActive(true);
+            ResetCameraColor();
+
+            ShowNpcEffect(instance.transform, modelConfig.ResourcesName);
+
+            BindGestureCatcher(rawImage, interactable);
+        }
+
+        public void ShowHourse(UI3DHorsePetData data, RawImage rawImage)
+        {
+            StopShow();
+            m_ShowCamera.enabled = true;
+
+            var horseConfig = HorseConfig.Get(data.id);
+            if (horseConfig == null)
+            {
+                return;
+            }
+
+            var instance = UI3DModelFactory.LoadUIHorse(horseConfig.Model);
+            if (instance == null)
+            {
+                return;
+            }
+
+            isShowingHorse = true;
+            interactable = true;
+
+            m_HorseModelId = horseConfig.Model;
+            horseModel = instance;
+
+            m_HorseShowPoint.rotation = Quaternion.identity;
+
+            var modelConfig = ModelResConfig.Get(horseConfig.Model);
+            var position = modelConfig.UIOffset;
+            var rotation = modelConfig.UIRotation;
+            instance.transform.SetParentEx(m_HorseShowPoint, position, rotation, modelConfig.UIScale);
+            instance.SetActive(true);
+            ResetCameraColor();
+
+            ShowNpcEffect(instance.transform, modelConfig.ResourcesName);
+
+            if (horseModel && data.isRun)
+            {
+                var animator = horseModel.GetComponentInChildren<Animator>();
+                if (animator != null)
+                {
+                    m_SwtichAnimationCoroutine = StartCoroutine(Co_SwitchAnimation(animator, GAStaticDefine.State_RunHash));
+                }
+            }
+
+            if (horseModel && data.skinIndex > 0)
+            {
+                var horsePetEffectId = petModel.GetPetHorseEffect(data.id, data.skinIndex);
+                if (horsePetEffectId != 0)
+                {
+                    horsePetEffect = SFXPlayUtility.Instance.Play(horsePetEffectId, horseModel.transform);
+                    if (horsePetEffect != null)
+                    {
+                        horsePetEffect.duration = 0f;
+                        horsePetEffect.SetParticleEmissionRateOverTime(2f);
+                    }
+                }
+            }
+
+            BindGestureCatcher(rawImage, interactable);
+        }
+
+        private GameObject ObjEquipment;
+        public void ShowEquipment(int modelId, Vector3 localEulerAngles, float scale, RawImage rawImage, bool interactable = false)
+        {
+            var instance = UI3DModelFactory.LoadUIWing(modelId);
+            ObjEquipment = instance;
+            if (instance == null)
+            {
+                return;
+            }
+
+            StopShow();
+
+            isShowinEquipment = true;
+            m_ShowCamera.enabled = true;
+            m_EquipmentModelId = modelId;
+            equipmentModel = instance;
+            instance.transform.SetParentEx(m_EquipmentPoint, Vector3.zero, localEulerAngles, Vector3.one * scale);
+            instance.SetActive(true);
+            ResetCameraColor();
+            BindGestureCatcher(rawImage, interactable);
+        }
+
+        public void ShowWing(int _modelId, RawImage _rawImage)
+        {
+            StopShow();
+
+            var instance = UI3DModelFactory.LoadUIWing(_modelId);
+            if (instance == null)
+            {
+                return;
+            }
+
+            m_ShowCamera.enabled = true;
+            interactable = true;
+
+            m_WingModelId = _modelId;
+            wingModel = instance;
+
+            m_WingShowPoint.rotation = Quaternion.identity;
+            var modelConfig = ModelResConfig.Get(_modelId);
+            var position = modelConfig.UIOffset;
+            var rotation = modelConfig.UIRotation;
+            instance.transform.SetParentEx(m_WingShowPoint, position, rotation, modelConfig.UIScale);
+
+            instance.SetActive(true);
+            ResetCameraColor();
+            var animator = instance.GetComponent<Animator>();
+            if (animator != null)
+            {
+                animator.Play("UI_Idle_Single");
+            }
+
+            BindGestureCatcher(_rawImage, interactable);
+        }
+
+        public void ShowNPC(RawImage rawImage, UI3DNPCExhibitionData data)
+        {
+            StopShow();
+            ResetCameraColor();
+            var config = NPCConfig.Get(data.npcId);
+            m_NPCId = data.npcId;
+            var job = 0;
+            if (config.MODE.Contains("A_Zs"))
+            {
+                job = 1;
+            }
+            else if (config.MODE.Contains("A_Fs"))
+            {
+                job = 2;
+            }
+
+            var offset = config.UIModeLOffset;
+            var eulerAngles = config.UIModelRotation;
+            var scale = Vector3.one * config.UIModeLProportion;
+
+            var isPlayer = job != 0;
+            if (isPlayer)
+            {
+                var instance = UI3DModelFactory.LoadUINPC(data.npcId);
+                if (instance == null)
+                {
+                    DebugEx.LogFormat("鏃犳硶鑾峰緱npc妯″瀷璧勬簮锛宨d :{0}", data.npcId);
+                    return;
+                }
+
+                instance.transform.SetParentEx(data.isDialogue ? m_DialogPoint : m_NPCShowPoint, offset, eulerAngles, scale);
+                npcModel = instance;
+                isShowingNPC = true;
+
+                var _configName = string.Empty;
+
+                if (job == 1)
+                {
+                    _configName = config.MODE.Substring(config.MODE.LastIndexOf("A_"));
+                }
+                else if (job == 2)
+                {
+                    _configName = config.MODE.Substring(config.MODE.LastIndexOf("A_"));
+                }
+
+                if (!string.IsNullOrEmpty(_configName))
+                {
+                    var _renderer = instance.GetComponentInChildren<SkinnedMeshRenderer>();
+                    if (_renderer)
+                    {
+                        MaterialLoader.Release(_renderer.material);
+
+                        var _modelResConfig = ModelResConfig.GetClothesConfig(_configName);
+                        if (_modelResConfig != null)
+                        {
+                            _renderer.material = MaterialLoader.LoadClothesMaterial(_modelResConfig.ID, false, false);
+                        }
+                    }
+                }
+
+                var ids = config.Equips.Split('|');
+                var weaponId = int.Parse(ids[0]);
+                var secondaryId = ids.Length > 1 ? int.Parse(ids[1]) : 0;
+                var wingId = ids.Length > 3 ? int.Parse(ids[3]) : 0;
+
+                playerModel.Show(instance, job, weaponId, wingId, secondaryId, m_PlayerShowPoint);
+                playerModel.StandUp();
+
+                m_PlayerShowPoint.localEulerAngles = Vector3.zero;
+                isShowingPlayer = true;
+
+                interactable = true;
+                m_ShowCamera.enabled = true;
+                BindGestureCatcher(rawImage, interactable);
+            }
+            else
+            {
+                ShowNPC(data.npcId, offset, eulerAngles, rawImage, data.gray, data.isDialogue);
+            }
+        }
+
+        public void ShowNPC(int _npcId, Vector3 _localEulerAngles, RawImage _rawImage, bool _gray = false, bool _isDialogue = false)
+        {
+            ShowNPC(_npcId, Vector3.zero, _localEulerAngles, _rawImage, _gray, _isDialogue);
+        }
+
+        public void ShowNPC(int _npcId, Vector3 _offset, Vector3 _localEulerAngles, RawImage _rawImage, bool _gray = false, bool _isDialogue = false)
+        {
+            StopShow();
+            m_ShowCamera.enabled = true;
+            m_NPCId = _npcId;
+
+            var instance = UI3DModelFactory.LoadUINPC(_npcId);
+            if (instance == null)
+            {
+                return;
+            }
+
+            interactable = !_isDialogue;
+            isShowingNPC = true;
+
+            if (!_isDialogue)
+            {
+                m_NPCShowPoint.localEulerAngles = _localEulerAngles;
+            }
+
+            npcModel = instance;
+            var config = NPCConfig.Get(_npcId);
+            instance.transform.SetParentEx(_isDialogue ? m_DialogPoint : m_NPCShowPoint, _offset, Quaternion.identity, Vector3.one * config.UIModeLProportion);
+            if (config.NPCEffect != 0)
+            {
+                var effectConfig = EffectConfig.Get(config.NPCEffect);
+                var parent = instance.transform;
+                if (!string.IsNullOrEmpty(effectConfig.nodeName))
+                {
+                    parent = instance.transform.GetChildTransformDeeply(effectConfig.nodeName);
+                }
+                m_NpcEffect = SFXPlayUtility.Instance.PlayBattleEffect(config.NPCEffect, parent);
+            }
+
+            if (_isDialogue)
+            {
+                instance.transform.localEulerAngles = _localEulerAngles;
+            }
+
+            instance.SetActive(true);
+
+            if (npcModel)
+            {
+                ShowNpcEffect(npcModel.transform, config.MODE);
+            }
+
+            ResetCameraColor(_gray);
+            m_CameraColor.saturation = _gray ? 0.08f : 1f;
+
+            if (_npcId == 10104001)
+            {
+                _rawImage.SetActive(false);
+                UI3DModelShowSpecialNPC.Display(npcModel);
+            }
+            else
+            {
+                BindGestureCatcher(_rawImage, interactable);
+            }
+        }
+
+        public void ShowPet(UI3DHorsePetData data, RawImage _rawImage)
+        {
+            StopShow();
+            m_ShowCamera.enabled = true;
+            m_NPCId = data.id;
+
+            var instance = UI3DModelFactory.LoadUINPC(data.id);
+            if (instance == null)
+            {
+                return;
+            }
+
+            interactable = true;
+            isShowingPet = true;
+
+            m_NPCShowPoint.localEulerAngles = data.localEulerAngles;
+
+            npcModel = instance;
+            var config = NPCConfig.Get(data.id);
+            instance.transform.SetParentEx(m_NPCShowPoint, data.offset, Quaternion.identity, Vector3.one * config.UIModeLProportion);
+            if (config.NPCEffect != 0)
+            {
+                var effectConfig = EffectConfig.Get(config.NPCEffect);
+                var parent = instance.transform;
+                if (!string.IsNullOrEmpty(effectConfig.nodeName))
+                {
+                    parent = instance.transform.GetChildTransformDeeply(effectConfig.nodeName);
+                }
+                m_NpcEffect = SFXPlayUtility.Instance.PlayBattleEffect(config.NPCEffect, parent);
+            }
+
+            instance.SetActive(true);
+
+            if (npcModel && data.skinIndex == 0)
+            {
+                ShowNpcEffect(npcModel.transform, config.MODE);
+            }
+            else
+            {
+                HideNpcEffect();
+            }
+
+            if (npcModel && data.isRun)
+            {
+                var animator = npcModel.GetComponentInChildren<Animator>();
+                if (animator != null)
+                {
+                    m_SwtichAnimationCoroutine = StartCoroutine(Co_SwitchAnimation(animator, GAStaticDefine.State_RunHash));
+                }
+            }
+
+            if (npcModel && data.skinIndex > 0)
+            {
+                var horsePetEffectId = petModel.GetPetHorseEffect(data.id, data.skinIndex);
+                var effectNode = petModel.GetPetHorseEffectNode(data.id, data.skinIndex);
+                if (horsePetEffectId != 0)
+                {
+                    var parent = instance.transform;
+                    if (!string.IsNullOrEmpty(effectNode))
+                    {
+                        parent = npcModel.transform.GetChildTransformDeeply(effectNode);
+                    }
+                    horsePetEffect = SFXPlayUtility.Instance.Play(horsePetEffectId, parent);
+                    if (horsePetEffect != null)
+                    {
+                        horsePetEffect.duration = 0f;
+                    }
+                }
+            }
+
+            ResetCameraColor();
+
+            if (data.id == 10104001)
+            {
+                _rawImage.SetActive(false);
+                UI3DModelShowSpecialNPC.Display(npcModel);
+            }
+            else
+            {
+                BindGestureCatcher(_rawImage, interactable);
+            }
+        }
+
+        public void StopShow()
+        {
+            m_ShowCamera.enabled = false;
+
+            playerModel.Dispose();
+            isShowingPlayer = false;
+
+            if (m_SwtichAnimationCoroutine != null)
+            {
+                StopCoroutine(m_SwtichAnimationCoroutine);
+                m_SwtichAnimationCoroutine = null;
+            }
+
+            if (m_NPCId != 0)
+            {
+                var config = NPCConfig.Get(m_NPCId);
+                if (config != null)
+                {
+                    var job = 0;
+                    if (config.MODE.Contains("A_Zs"))
+                    {
+                        job = 1;
+                    }
+                    else if (config.MODE.Contains("A_Fs"))
+                    {
+                        job = 2;
+                    }
+                    if (job != 0)
+                    {
+                        var _renderer = npcModel.GetComponentInChildren<SkinnedMeshRenderer>();
+                        if (_renderer)
+                        {
+                            MaterialLoader.Release(_renderer.material);
+                            _renderer.material = _renderer.sharedMaterial = null;
+                            _renderer.materials = _renderer.sharedMaterials = new Material[0];
+                        }
+                    }
+                }
+            }
+
+
+            if (horsePetEffect != null)
+            {
+                if (horseModel != null)
+                {
+                    horsePetEffect.SetParticleEmissionRateOverTime(0f);
+
+                }
+                SFXPlayUtility.Instance.Release(horsePetEffect);
+                horsePetEffect = null;
+            }
+
+            if (npcModel != null)
+            {
+                npcModel.transform.localScale = Vector3.one;
+                if (m_NpcEffect != null)
+                {
+                    SFXPlayUtility.Instance.Release(m_NpcEffect);
+                    m_NpcEffect = null;
+                }
+
+                if (isShowingPet)
+                {
+                    var animator = npcModel.GetComponentInChildren<Animator>();
+                    if (animator != null)
+                    {
+                        animator.Play(GAStaticDefine.State_IdleHash, 0);
+                    }
+                }
+
+                UI3DModelFactory.ReleaseUINPC(m_NPCId, npcModel);
+                npcModel = null;
+            }
+
+            m_NPCId = 0;
+            isShowingNPC = false;
+            isShowingPet = false;
+
+            if (horseModel != null)
+            {
+                horseModel.transform.localScale = Vector3.one;
+                var animator = horseModel.GetComponentInChildren<Animator>();
+                if (animator != null)
+                {
+                    animator.Play(GAStaticDefine.State_IdleHash, 0);
+                }
+                UI3DModelFactory.ReleaseUIHourse(m_HorseModelId, horseModel);
+                horseModel = null;
+            }
+            m_HorseModelId = 0;
+            isShowingHorse = false;
+
+            if (wingModel != null)
+            {
+                wingModel.transform.localScale = Vector3.one;
+                UI3DModelFactory.ReleaseUIWing(m_WingModelId, wingModel);
+                wingModel = null;
+            }
+            m_WingModelId = 0;
+
+            if (equipmentModel != null)
+            {
+                UI3DModelFactory.ReleaseUIWing(m_EquipmentModelId, equipmentModel);
+                equipmentModel = null;
+            }
+            m_EquipmentModelId = 0;
+            isShowinEquipment = false;
+
+            if (godWeaponEffect != null)
+            {
+                SFXPlayUtility.Instance.Release(godWeaponEffect);
+                godWeaponEffect = null;
+            }
+
+            UI3DModelShowSpecialNPC.Dispose();
+            interactable = false;
+        }
+
+        public void ResetCameraColor(bool _enable = false)
+        {
+            m_CameraColor.enabled = _enable;
+        }
+
+        private void LateUpdate()
+        {
+            if (isShowinEquipment && ObjEquipment != null)
+            {
+                if (WindowCenter.Instance.IsOpen("FirstTimeRechargeWin"))
+                {
+                    ObjEquipment.transform.Rotate(WindowCenter.Instance.Get<FirstTimeRechargeWin>().RotateVector * 1f, Space.Self);
+                }
+                if (WindowCenter.Instance.IsOpen("FirstChargeTrialWin"))
+                {
+                    ObjEquipment.transform.Rotate(WindowCenter.Instance.Get<FirstChargeTrialWin>().RotateVector * 1f, Space.Self);
+                }
+            }
+        }
+
+        private void OnDrag3DModel(Vector2 deltaPosition)
+        {
+            if (!interactable)
+            {
+                return;
+            }
+
+            if (isShowingPlayer)
+            {
+                m_PlayerShowPoint.localEulerAngles += new Vector3(0, -deltaPosition.x, 0);
+            }
+
+            if (isShowingHorse)
+            {
+                m_HorseShowPoint.localEulerAngles += new Vector3(0, -deltaPosition.x, 0);
+            }
+
+            if (isShowingNPC)
+            {
+                m_NPCShowPoint.localEulerAngles += new Vector3(0, -deltaPosition.x, 0);
+            }
+
+
+            if (isShowingPet)
+            {
+                m_NPCShowPoint.localEulerAngles += new Vector3(0, -deltaPosition.x, 0);
+            }
+        }
+
+        private void ShowNpcEffect(Transform parent, string modelName)
+        {
+            HideNpcEffect();
+
+            var _boneList = ModelResConfig.GetBoneList(modelName);
+            var _effectlist = ModelResConfig.GetEffectList(modelName);
+
+            if (_boneList != null && _effectlist != null)
+            {
+                for (int i = 0; i < _boneList.Count; ++i)
+                {
+                    if (_boneList[i].Equals("null"))
+                    {
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent);
+                        m_BindEffectList.Add(_ctrl);
+                    }
+                    else
+                    {
+
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent.GetChildTransformDeeply(_boneList[i]));
+                        m_BindEffectList.Add(_ctrl);
+                    }
+                }
+            }
+        }
+
+        private void HideNpcEffect()
+        {
+            foreach (var _ctrl in m_BindEffectList)
+            {
+                SFXPlayUtility.Instance.Release(_ctrl);
+            }
+            m_BindEffectList.Clear();
+        }
+
+        private void BindGestureCatcher(RawImage rawImage, bool interable)
+        {
+            if (rawImage == null)
+            {
+                return;
+            }
+
+            var x = rawImage.rectTransform.rect.height * 4f / 3;
+            var y = rawImage.rectTransform.rect.height;
+            rawImage.rectTransform.sizeDelta = new Vector2(x, y);
+            rawImage.texture = m_ShowCamera.targetTexture;
+            rawImage.material = MaterialUtility.GetGUIRenderTextureMaterial();
+            rawImage.SetActive(true);
+
+            if (interable)
+            {
+                rawImage.raycastTarget = true;
+                var gestureCatcher = rawImage.AddMissingComponent<GestureCatcher>();
+                gestureCatcher.SetDragListener(OnDrag3DModel);
+            }
+            else
+            {
+                rawImage.raycastTarget = false;
+            }
+        }
+
+        IEnumerator Co_SwitchAnimation(Animator animator,int stateHash)
+        {
+            yield return null;
+            yield return null;
+            if (animator != null)
+            {
+                animator.Play(stateHash, 0);
+            }
+        }
+
+    }
+
+    public struct UI3DPlayerExhibitionData
+    {
+        public int job;
+        public int clothesId;
+        public int suitLevel;
+        public int weaponId;
+        public int wingsId;
+        public int secondaryId;
+        public int fashionClothesId;
+        public int fashionWeaponId;
+        public int fashionSecondaryId;
+        public int reikiRootEffectId;
+        public bool isDialogue;
+        public bool keepRotation;
+        public int equipLevel;
+        public float scale;
+        public int titleID;
+    }
+
+    public struct UI3DNPCExhibitionData
+    {
+        public int npcId;
+        public bool gray;
+        public bool isDialogue;
+    }
+
+    
+    public struct UI3DHorsePetData
+    {
+        public int id;
+        public int skinIndex;
+        public bool isRun;
+        public Vector3 offset;
+        public Vector3 localEulerAngles;
+    }
+}
+
+
+
diff --git a/Main/Component/UI/Common/UI3DModelExhibition.cs.meta b/Main/Component/UI/Common/UI3DModelExhibition.cs.meta
new file mode 100644
index 0000000..384d29b
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelExhibition.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2490dca483bc10b4cbed43afd7e179c8
+timeCreated: 1504955255
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DModelFactory.cs b/Main/Component/UI/Common/UI3DModelFactory.cs
new file mode 100644
index 0000000..95316fb
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelFactory.cs
@@ -0,0 +1,372 @@
+锘縰sing UnityEngine;
+using System.Collections.Generic;
+using System;
+
+public class UI3DModelFactory
+{
+    static UI3DModelFactory()
+    {
+        GlobalTimeEvent.Instance.minuteEvent += OnPerMinute;
+    }
+
+    public static GameObject LoadUINPC(int id)
+    {
+        if (!NPCConfig.Has(id))
+        {
+            return null;
+        }
+
+        try
+        { 
+            var config = NPCConfig.Get(id);
+            var model = GameObjectPoolManager.Instance.RequestNpcGameObject(id);
+
+            if (!model && config.NPCType == (int)E_NpcType.Func)
+            {
+                model = GameObjectPoolManager.Instance.RequestDefaultFuncNpc();
+            }
+
+            if (!model)
+            {
+                return null;
+            }
+
+            var animator = model.GetComponent<Animator>();
+            if (animator != null)
+            {
+                var suffix = AnimatorControllerLoader.controllerUISuffix;
+                var _modeName = config.MODE;
+                if (config.MODE.StartsWith("A_Zs"))
+                {
+                    _modeName = "A_Zs";
+                }
+                else if (config.MODE.StartsWith("A_Fs"))
+                {
+                    _modeName = "A_Fs";
+                }
+                var animatorController = AnimatorControllerLoader.LoadMobController(suffix, _modeName);
+                if (animatorController != null)
+                {
+                    animator.runtimeAnimatorController = animatorController;
+                }
+
+                var isDance = false;
+                if (config.NPCType == (int)E_NpcType.Func)
+                {
+                    var clipInfos = animator.runtimeAnimatorController.animationClips;
+                    foreach (var item in clipInfos)
+                    {
+                        if (item.name == "Idle2")
+                        {
+                            isDance = true;
+                            break;
+                        }
+                    }
+                }
+
+                animator.enabled = true;
+                if (isDance)
+                {
+                    animator.Play(GAStaticDefine.State_Dance);
+                }
+                else
+                {
+                    animator.SetInteger(GAStaticDefine.Param_Action, GAStaticDefine.Act_Idle);
+                    animator.Play(GAStaticDefine.State_IdleHash);
+                }
+            }
+
+            LayerUtility.SetLayer(model, LayerUtility.Monster, true);
+            return model;
+        }
+        catch (Exception e)
+        {
+            Debug.Log("LoadUINPC Error: " + e.Message);
+            return null;
+        }
+    }
+
+    public static void ReleaseUINPC(int id, GameObject model)
+    {
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            ResetRealmBossAnimator(id, animator);
+            animator.enabled = false;
+        }
+
+        if (model)
+        {
+            model.transform.localScale = Vector3.one;
+        }
+
+        var prefab = InstanceResourcesLoader.LoadNpcPrefab(id);
+        if (prefab)
+        {
+            GameObjectPoolManager.Instance.ReleaseGameObject(prefab, model);
+        }
+        else
+        {
+            GameObjectPoolManager.Instance.ReleaseDefaultFuncNPC(model);
+        }
+    }
+
+    private static void ResetRealmBossAnimator(int _id, Animator animator)
+    {
+        if (RealmLVUPTaskConfig.IsRealmBoss(_id))
+        {
+            var npcConfig = NPCConfig.Get(_id);
+            if (npcConfig != null)
+            {
+                var runtimeController = AnimatorControllerLoader.LoadMobController(AnimatorControllerLoader.controllerSuffix, npcConfig.MODE);
+                if (runtimeController != null)
+                {
+                    animator.runtimeAnimatorController = runtimeController;
+                }
+            }
+        }
+    }
+
+    public static GameObject LoadUIHorse(int id)
+    {
+        var prefab = InstanceResourcesLoader.LoadModelRes(id, false);
+        if (prefab == null)
+        {
+            return null;
+        }
+
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        var model = pool.Request();
+
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            var config = ModelResConfig.Get(id);
+            var suffix = AnimatorControllerLoader.controllerUISuffix;
+            var animatorController = AnimatorControllerLoader.LoadMobController(suffix, config.ResourcesName);
+            if (animatorController != null)
+            {
+                animator.runtimeAnimatorController = animatorController;
+            }
+
+            animator.enabled = true;
+            animator.SetInteger(GAStaticDefine.Param_Action, GAStaticDefine.Act_Idle);
+            animator.Play(GAStaticDefine.State_IdleHash);
+        }
+
+        return model;
+    }
+
+    public static void ReleaseUIHourse(int id, GameObject model)
+    {
+        var prefab = InstanceResourcesLoader.LoadModelRes(id, false);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = false;
+        }
+
+        pool.Release(model);
+    }
+
+    static Dictionary<int, GameObject> treasureModels = new Dictionary<int, GameObject>();
+    static Dictionary<int, DateTime> treasureModelReleaseTimes = new Dictionary<int, DateTime>();
+
+    public static GameObject LoadUITreasure(int _id)
+    {
+        GameObject instance = null;
+        if (treasureModels.ContainsKey(_id))
+        {
+            instance = treasureModels[_id];
+            if (instance == null)
+            {
+                treasureModels.Remove(_id);
+            }
+        }
+
+        if (instance == null)
+        {
+            var config = TreasureConfig.Get(_id);
+            var folder = string.Empty;
+            switch ((TreasureCategory)config.Category)
+            {
+                case TreasureCategory.Human:
+                    folder = "RenZu";
+                    break;
+                case TreasureCategory.Demon:
+                    folder = "MoZu";
+                    break;
+                case TreasureCategory.Fairy:
+                    folder = "XianZu";
+                    break;
+                case TreasureCategory.King:
+                    folder = "WangZhe";
+                    break;
+                default:
+                    break;
+            }
+
+            var prefab = UILoader.LoadTreasure(folder, config.Model);
+            instance = GameObject.Instantiate(prefab);
+            treasureModels[_id] = instance;
+
+            UILoader.UnLoadTreasure(folder, config.Model);
+        }
+
+        var animator = instance.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = true;
+        }
+
+        LayerUtility.SetLayer(instance, LayerUtility.UILayer, true);
+        if (treasureModelReleaseTimes.ContainsKey(_id))
+        {
+            treasureModelReleaseTimes.Remove(_id);
+        }
+        return instance;
+    }
+
+    public static void ReleaseUITreasure(int _id, GameObject _model)
+    {
+        treasureModelReleaseTimes[_id] = DateTime.Now;
+        var animator = _model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = false;
+        }
+
+        _model.SetActive(false);
+    }
+
+    private static void OnPerMinute()
+    {
+        var keys = new List<int>(treasureModelReleaseTimes.Keys);
+        for (int i = 0; i < keys.Count; i++)
+        {
+            var key = keys[i];
+            var releaseTime = treasureModelReleaseTimes[key];
+            if ((DateTime.Now - releaseTime).TotalSeconds > Constants.UnUsedRes_Unload_Delay)
+            {
+                if (treasureModels.ContainsKey(key))
+                {
+                    var model = treasureModels[key];
+                    treasureModels.Remove(key);
+                    if (model != null)
+                    {
+                        GameObject.Destroy(model);
+                    }
+                }
+            }
+        }
+    }
+
+    //娉曞櫒
+    public static GameObject LoadUIFaqi(string pathName, string modelName)
+    {
+        var prefab = UILoader.LoadFaqi(pathName, modelName);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        var model = pool.Request();
+
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = true;
+        }
+
+        LayerUtility.SetLayer(model, LayerUtility.UILayer, true);
+        return model;
+    }
+
+    public static GameObject LoadUIGodWeapon(int _type)
+    {
+        var prefab = UILoader.LoadGodWeapon(GeneralDefine.godWeaponMobs[_type]);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        var model = pool.Request();
+
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = true;
+        }
+
+        LayerUtility.SetLayer(model, LayerUtility.UILayer, true);
+        return model;
+    }
+
+    public static void ReleaseUIGodWeapon(int _type, GameObject _model)
+    {
+        if (!GameObjectPoolManager.IsValid())
+        {
+            return;
+        }
+        if (!GeneralDefine.godWeaponMobs.ContainsKey(_type))
+        {
+            return;
+        }
+        var prefab = UILoader.LoadGodWeapon(GeneralDefine.godWeaponMobs[_type]);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+
+        var animator = _model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = false;
+        }
+
+        pool.Release(_model);
+    }
+
+    public static void ReleaseUIFaqi(string pathName, string modelName, GameObject _model)
+    {
+        if (!GameObjectPoolManager.IsValid())
+        {
+            return;
+        }
+
+        var prefab = UILoader.LoadFaqi(pathName, modelName);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+
+        var animator = _model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = false;
+        }
+
+        pool.Release(_model);
+    }
+
+
+
+    public static GameObject LoadUIWing(int _id)
+    {
+        var prefab = InstanceResourcesLoader.LoadModelRes(_id, false);
+        if (prefab == null)
+        {
+            return null;
+        }
+
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        var model = pool.Request();
+        var animator = model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = true;
+        }
+        return model;
+    }
+
+    public static void ReleaseUIWing(int _id, GameObject _model)
+    {
+        var prefab = InstanceResourcesLoader.LoadModelRes(_id, false);
+        var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        var animator = _model.GetComponent<Animator>();
+        if (animator != null)
+        {
+            animator.enabled = false;
+        }
+
+        pool.Release(_model);
+    }
+}
diff --git a/Main/Component/UI/Common/UI3DModelFactory.cs.meta b/Main/Component/UI/Common/UI3DModelFactory.cs.meta
new file mode 100644
index 0000000..a3cafb3
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelFactory.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 71d6de4139acab94aaf4efa6c9fc358f
+timeCreated: 1504955834
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DModelInteractProcessor.cs b/Main/Component/UI/Common/UI3DModelInteractProcessor.cs
new file mode 100644
index 0000000..a6b65dc
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelInteractProcessor.cs
@@ -0,0 +1,110 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Sunday, September 10, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class UI3DModelInteractProcessor : MonoBehaviour
+    {
+        public event Action clickEvent;
+        public event Action<Vector2> beginDragEvent;
+        public event Action<Vector2> endDragEvent;
+        public event Action<Vector2> dragingEvent;
+
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform {
+            get { return m_RectTransform; }
+            set {
+                m_RectTransform = value;
+            }
+        }
+
+        bool isDown = false;
+        float downTime = 0f;
+
+        private void LateUpdate()
+        {
+            if (Input.GetMouseButtonDown(0))
+            {
+                OnPointerDown();
+            }
+
+            if (Input.GetMouseButton(0))
+            {
+                OnPointerDrag();
+            }
+
+            if (Input.GetMouseButtonUp(0))
+            {
+                OnPointerUp();
+            }
+        }
+
+        void OnPointerDown()
+        {
+            if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition, CameraManager.uiCamera))
+            {
+                isDown = true;
+                downTime = Time.time;
+                if (beginDragEvent != null)
+                {
+                    beginDragEvent(Input.mousePosition);
+                }
+            }
+
+        }
+
+        void OnPointerDrag()
+        {
+            if (!isDown)
+            {
+                return;
+            }
+
+            if (dragingEvent != null)
+            {
+                dragingEvent(Input.mousePosition);
+            }
+        }
+
+        void OnPointerUp()
+        {
+            if (isDown)
+            {
+                if (Time.time - downTime < 0.3f)
+                {
+                    if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition, CameraManager.uiCamera))
+                    {
+                        OnPointerClick();
+                    }
+                }
+
+                if (endDragEvent != null)
+                {
+                    endDragEvent(Input.mousePosition);
+                }
+            }
+
+            isDown = false;
+        }
+
+        void OnPointerClick()
+        {
+            if (clickEvent != null)
+            {
+                clickEvent();
+            }
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/UI3DModelInteractProcessor.cs.meta b/Main/Component/UI/Common/UI3DModelInteractProcessor.cs.meta
new file mode 100644
index 0000000..11016fe
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelInteractProcessor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a39ec84bacd381e4e9e286a1a8d6123a
+timeCreated: 1505052429
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs b/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs
new file mode 100644
index 0000000..77616d8
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Friday, May 17, 2019
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    /// <summary>
+    /// 杩欎釜浠呬粎鏄粰浠欑殗娈嬮瓊鐢ㄧ殑
+    /// </summary>
+    public class UI3DModelShowSpecialNPC : MonoBehaviour
+    {
+        [SerializeField] Transform m_StandPoint;
+        public Transform standPoint { get { return m_StandPoint; } }
+
+        static UI3DModelShowSpecialNPC showPlatform;
+
+        public static void Display(GameObject model)
+        {
+            if (showPlatform == null)
+            {
+                var prefab = BuiltInLoader.LoadPrefab("UI3DModelShowSpecialNPC");
+                var instance = Instantiate(prefab);
+                instance.transform.position = new Vector3(1000, 3000, 5000);
+                showPlatform = instance.GetComponent<UI3DModelShowSpecialNPC>();
+                showPlatform.gameObject.name = "UI3DModelShowSpecialNPC";
+            }
+
+            model.transform.SetParentEx(showPlatform.standPoint, Vector3.zero, Quaternion.identity, Vector3.one);
+        }
+
+        public static void Dispose()
+        {
+            if (showPlatform != null)
+            {
+                DestroyImmediate(showPlatform);
+                showPlatform = null;
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs.meta b/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs.meta
new file mode 100644
index 0000000..c11e06e
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DModelShowSpecialNPC.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f7b8d7e81351bcd4d909f10df6a26ee1
+timeCreated: 1558072373
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DShowHero.cs b/Main/Component/UI/Common/UI3DShowHero.cs
new file mode 100644
index 0000000..3ac0af7
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DShowHero.cs
@@ -0,0 +1,828 @@
+锘�//--------------------------------------------------------
+//   [Author]:           绗簩涓栫晫
+//   [  Date ]:           Friday, September 22, 2017
+//--------------------------------------------------------
+using UnityEngine;
+
+using System.Collections.Generic;
+using LitJson;
+
+namespace vnxbqy.UI
+{
+
+    public class UI3DShowHero
+    {
+        int weaponId;
+        int clothesId;
+        int wingsId;
+        int secondaryId;
+        int extraSecondaryId;
+        int job;
+
+        GameObject weaponModel;
+        GameObject clothesModel;
+        GameObject wingsModel;
+        GameObject secondaryModel;
+        GameObject extraSecondaryModel;
+
+        Animator wingsAnimator;
+        Animator clothesAnimator;
+        RuntimeAnimatorController cacheClothedAC;
+
+        Transform showPoint;
+        List<SFXController> godWeaponSFXList = new List<SFXController>();
+
+        GameObject reikiRootShowPoint = null;
+        SFXController reikiRootEffect = null;   //寮哄寲澶у笀鐗规晥
+        SFXController titleRootEffect = null;   //绉板彿鍏ㄨ韩鐗规晥
+
+        bool isSuit = false;
+        public GameObject Show(UI3DPlayerExhibitionData data, Transform showPoint)
+        {
+            this.showPoint = showPoint;
+            this.job = data.job;
+
+            var clothes = data.fashionClothesId > 0 ? data.fashionClothesId : data.clothesId;
+            isSuit = data.suitLevel > 0;
+            var weaponId = data.fashionWeaponId > 0 ? data.fashionWeaponId : data.weaponId;
+            var wingsId = data.wingsId;
+            var secondaryId = data.fashionSecondaryId > 0 ? data.fashionSecondaryId : data.secondaryId;
+
+            var jobConfig = JobSetupConfig.Get(job);
+
+            var clothesResId = 0;
+            if (clothes == 0)
+            {
+                clothesResId = jobConfig.BaseEquip[0];
+            }
+            else
+            {
+                var item = ItemConfig.Get(clothes);
+                clothesResId = item == null ? clothesResId = jobConfig.BaseEquip[0] : item.ChangeOrd;
+            }
+            PutOnClothes(job, clothesResId);
+
+            var weaponResId = 0;
+            if (weaponId == 0)
+            {
+                weaponResId = jobConfig.BaseEquip[1];
+            }
+            else
+            {
+                var item = ItemConfig.Get(weaponId);
+                weaponResId = item == null ? weaponResId = jobConfig.BaseEquip[1] : item.ChangeOrd;
+            }
+            PutOnWeapon(job, weaponResId);
+
+            var secondaryResId = 0;
+            if (secondaryId == 0)
+            {
+                if (data.fashionClothesId == 0)
+                {
+                    if (this.job == 1)
+                    {
+                        secondaryResId = ModelResConfig.GetHandByClothesID(clothesId);
+                    }
+                    else if (this.job == 2)
+                    {
+                        secondaryResId = jobConfig.BaseEquip[2];
+                    }
+                }
+            }
+            else
+            {
+                var item = ItemConfig.Get(secondaryId);
+                if (item != null)
+                {
+                    secondaryResId = item.ChangeOrd;
+                }
+            }
+
+            if (secondaryResId != 0)
+            {
+                PutOnSecondary(job, secondaryResId);
+            }
+
+            var extraSecondaryId = 0;
+            if (data.job == 1)
+            {
+                extraSecondaryId = ModelResConfig.GetHandByClothesID(0);
+                if (data.fashionClothesId > 0)
+                {
+                    var _item = ItemConfig.Get(data.fashionClothesId);
+                    if (_item != null)
+                    {
+                        extraSecondaryId = ModelResConfig.GetHandByClothesID(_item.ChangeOrd);
+                    }
+                }
+                else if (data.clothesId > 0)
+                {
+                    var _item = ItemConfig.Get(data.clothesId);
+                    if (_item != null)
+                    {
+                        extraSecondaryId = ModelResConfig.GetHandByClothesID(_item.ChangeOrd);
+                    }
+                }
+
+                if (secondaryResId == 0
+                 || (data.fashionClothesId != 0 && data.fashionSecondaryId > 0)
+                 || (data.fashionClothesId == 0 && data.fashionSecondaryId > 0))
+                {
+                    PutOnExtraSecondary(job, extraSecondaryId);
+                }
+            }
+
+            var wingsResId = 0;
+            if (wingsId != 0)
+            {
+                var item = ItemConfig.Get(wingsId);
+                wingsResId = item == null ? 0 : item.ChangeOrd;
+            }
+
+            PutOnWing(wingsResId);
+            ShowBodyEffect(data);
+            
+            LoadClothesEffect();
+            return clothesModel;
+        }
+
+        public GameObject Show(GameObject clothesModel, int job, int weaponResId, int wingsResId, int secondaryResId, Transform showPoint)
+        {
+            this.showPoint = showPoint;
+            this.job = job;
+            this.clothesModel = clothesModel;
+            SwitchMaterial(false);
+            PutOnWeapon(job, weaponResId);
+            PutOnSecondary(job, secondaryResId);
+            PutOnWing(wingsResId);
+            LoadClothesEffect();
+            return clothesModel;
+        }
+
+        public void Dispose()
+        {
+            GameObject prefab = null;
+            GameObjectPoolManager.GameObjectPool pool = null;
+
+            HideWeaponEffect();
+            HideSecondaryEffect();
+            HideSuitEffect();
+            HideReikiRootEffect();
+            HideTitleRootEffect();
+
+            if (weaponId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(weaponId);
+                if (prefab)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pool.Release(weaponModel);
+                }
+                weaponModel = null;
+            }
+
+            if (secondaryId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(secondaryId);
+                if (prefab)
+                {
+                    if (secondaryModel)
+                    {
+                        secondaryModel.SetActive(true);
+                    }
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pool.Release(secondaryModel);
+                }
+                secondaryModel = null;
+            }
+
+            if (extraSecondaryId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(extraSecondaryId);
+                if (prefab)
+                {
+                    if (extraSecondaryModel)
+                    {
+                        extraSecondaryModel.SetActive(true);
+                    }
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pool.Release(extraSecondaryModel);
+                }
+                extraSecondaryModel = null;
+            }
+
+            if (wingsId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(wingsId);
+                if (prefab)
+                {
+                    wingsModel.transform.localScale = Vector3.one;
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pool.Release(wingsModel);
+                }
+                wingsModel = null;
+                wingsAnimator = null;
+            }
+
+            if (clothesId != 0)
+            {
+                if (clothesModel)
+                {
+                    var smRenderer = clothesModel.GetComponentInChildren<SkinnedMeshRenderer>();
+                    if (smRenderer != null)
+                    {
+                        MaterialLoader.Release(smRenderer.material);
+                        smRenderer.material = smRenderer.sharedMaterial = null;
+                        smRenderer.materials = smRenderer.sharedMaterials = new Material[0];
+                    }
+                }
+
+                prefab = InstanceResourcesLoader.LoadModelRes(clothesId, true);
+                if (prefab)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pool.Release(clothesModel);
+                }
+                clothesModel = null;
+                if (clothesAnimator)
+                {
+                    if (cacheClothedAC)
+                    {
+                        clothesAnimator.runtimeAnimatorController = cacheClothedAC;
+                        cacheClothedAC = null;
+                    }
+                    clothesAnimator.enabled = false;
+                    clothesAnimator = null;
+                }
+            }
+
+            clothesModel = null;
+            clothesId = 0;
+            weaponId = 0;
+            wingsId = 0;
+            secondaryId = 0;
+            extraSecondaryId = 0;
+        }
+
+        public void StandUp()
+        {
+            if (clothesModel != null)
+            {
+                var animator = clothesModel.GetComponent<Animator>();
+                if (animator)
+                {
+                    animator.Play(GAStaticDefine.State_IdleHash);
+                    animator.SetInteger(GAStaticDefine.Param_Action, GAStaticDefine.Act_Idle);
+                }
+            }
+        }
+
+        public void SitDown()
+        {
+            if (clothesModel != null)
+            {
+                var animator = clothesModel.GetComponent<Animator>();
+                if (animator)
+                {
+                    animator.SetInteger(GAStaticDefine.Param_Action, GAStaticDefine.Act_Dazuo);
+                }
+            }
+
+            if (weaponModel != null)
+            {
+                GameObject prefab = InstanceResourcesLoader.LoadModelRes(weaponId, false);
+                if (prefab)
+                {
+                    GameObjectPoolManager.Instance.ReleaseGameObject(prefab, weaponModel);
+                }
+                weaponModel = null;
+            }
+
+            if (job == 2)
+            {
+                if (secondaryModel)
+                {
+                    secondaryModel.SetActive(false);
+                }
+            }
+        }
+
+        private void PutOnClothes(int _job, int clothesResId)
+        {
+            var config = JobSetupConfig.Get(_job);
+            if (clothesId == clothesResId)
+            {
+                return;
+            }
+
+            if (clothesId != 0)
+            {
+                UnloadClothes();
+            }
+
+            var _prefab = InstanceResourcesLoader.LoadModelRes(clothesResId, true);
+            if (!_prefab)
+            {
+                clothesResId = config.BaseEquip[0];
+            }
+
+            LoadClothes(clothesResId);
+            clothesId = clothesResId;
+
+            if (clothesModel)
+            {
+                if (weaponModel)
+                {
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.WeaponBindBoneName);
+                    weaponModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+
+                if (wingsModel)
+                {
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.WingBindBoneName);
+                    wingsModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+
+                if (secondaryModel)
+                {
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.SecondaryBindBoneName[job - 1]);
+                    wingsModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+            }
+        }
+
+        private void LoadClothes(int resID)
+        {
+            var prefab = InstanceResourcesLoader.LoadModelRes(resID, true);
+            if (prefab)
+            {
+                var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                clothesModel = pool.Request();
+
+                LayerUtility.SetLayer(clothesModel, LayerUtility.Player, false);
+                var skinnedMeshRenderer = clothesModel.GetComponentInChildren<SkinnedMeshRenderer>(true);
+                LayerUtility.SetLayer(skinnedMeshRenderer.gameObject, LayerUtility.Player, false);
+                clothesModel.SetActive(true);
+                clothesModel.transform.SetParentEx(showPoint, Vector3.zero, Quaternion.identity, Vector3.one);
+                clothesAnimator = clothesModel.GetComponent<Animator>();
+
+                // 鍔ㄧ敾鐘舵�佹満淇敼
+                if (clothesAnimator)
+                {
+                    cacheClothedAC = clothesAnimator.runtimeAnimatorController;
+                    RuntimeAnimatorController _controller = AnimatorControllerLoader.Load(AnimatorControllerLoader.controllerUISuffix, resID);
+                    clothesAnimator.runtimeAnimatorController = _controller;
+                    clothesAnimator.enabled = true;
+                }
+                else
+                {
+                    DebugEx.LogErrorFormat("瑙掕壊璧勬簮: {0} 娌℃湁鍔ㄧ敾鎺у埗鍣�", resID);
+                }
+            }
+        }
+
+        private void UnloadClothes()
+        {
+            if (clothesModel == null)
+            {
+                return;
+            }
+
+            var smRenderer = clothesModel.GetComponentInChildren<SkinnedMeshRenderer>();
+            if (smRenderer != null)
+            {
+                MaterialLoader.Release(smRenderer.material);
+                smRenderer.material = smRenderer.sharedMaterial = null;
+                smRenderer.materials = smRenderer.sharedMaterials = new Material[0];
+            }
+
+            var prefab = InstanceResourcesLoader.LoadModelRes(clothesId, true);
+            var pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+            pool.Release(clothesModel);
+            clothesModel = null;
+            if (clothesAnimator != null)
+            {
+                if (cacheClothedAC)
+                {
+                    clothesAnimator.runtimeAnimatorController = cacheClothedAC;
+                    cacheClothedAC = null;
+                }
+                clothesAnimator.enabled = false;
+                clothesAnimator = null;
+            }
+        }
+
+        private void PutOnWeapon(int _job, int resoureceId)
+        {
+            var config = JobSetupConfig.Get(_job);
+
+            var oldWeapon = weaponId;
+            if (oldWeapon == resoureceId)
+            {
+                return;
+            }
+
+            GameObject prefab = null;
+            GameObjectPoolManager.GameObjectPool pool = null;
+
+            if (oldWeapon != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(oldWeapon);
+                pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                pool.Release(weaponModel);
+                weaponModel = null;
+            }
+
+            prefab = InstanceResourcesLoader.LoadModelRes(resoureceId);
+
+            if (!prefab)
+            {
+                resoureceId = config.BaseEquip[1];
+                prefab = InstanceResourcesLoader.LoadModelRes(resoureceId);
+            }
+
+            if (prefab)
+            {
+                pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                weaponModel = pool.Request();
+
+                LayerUtility.SetLayer(weaponModel, LayerUtility.Player, false);
+                if (clothesModel)
+                {
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.WeaponBindBoneName);
+                    weaponModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+
+                var _resConfig = ModelResConfig.Get(resoureceId);
+                ShowSecondaryEffect(weaponModel.transform, _resConfig.ResourcesName);
+            }
+
+            weaponId = resoureceId;
+        }
+
+        private void PutOnExtraSecondary(int job, int extraSecondaryId)
+        {
+            var oldSecondary = this.extraSecondaryId;
+            if (oldSecondary == extraSecondaryId)
+            {
+                return;
+            }
+
+            GameObject prefab = null;
+            GameObjectPoolManager.GameObjectPool pool = null;
+
+            if (oldSecondary != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(oldSecondary);
+                pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                pool.Release(extraSecondaryModel);
+                extraSecondaryModel = null;
+            }
+
+            if (extraSecondaryId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(extraSecondaryId);
+                if (!prefab)
+                {
+                    var config = JobSetupConfig.Get(job);
+                    extraSecondaryId = config.BaseEquip[2];
+                    prefab = InstanceResourcesLoader.LoadModelRes(extraSecondaryId);
+                }
+
+                if (prefab)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    extraSecondaryModel = pool.Request();
+
+                    var parent = this.clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.SecondaryBindBoneName[this.job - 1]);
+                    extraSecondaryModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+            }
+
+            this.extraSecondaryId = extraSecondaryId;
+        }
+
+        private void PutOnSecondary(int _job, int secondaryResId)
+        {
+            var oldSecondary = secondaryId;
+            if (oldSecondary == secondaryResId)
+            {
+                return;
+            }
+
+            GameObject prefab = null;
+            GameObjectPoolManager.GameObjectPool pool = null;
+
+            if (oldSecondary != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(oldSecondary);
+                pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                pool.Release(secondaryModel);
+                secondaryModel = null;
+            }
+
+            if (secondaryResId != 0)
+            {
+                var _resConfig = ModelResConfig.Get(secondaryResId);
+                prefab = InstanceResourcesLoader.LoadModelRes(secondaryResId);
+                if (!prefab)
+                {
+                    var config = JobSetupConfig.Get(_job);
+                    secondaryResId = config.BaseEquip[2];
+                    prefab = InstanceResourcesLoader.LoadModelRes(secondaryResId);
+                }
+
+                if (prefab)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    secondaryModel = pool.Request();
+
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.SecondaryBindBoneName[job - 1]);
+                    secondaryModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, Vector3.one);
+                }
+
+                ShowSecondaryEffect(secondaryModel.transform, _resConfig.ResourcesName);
+            }
+
+            secondaryId = secondaryResId;
+        }
+
+        private void PutOnWing(int resourceId)
+        {
+            var config = JobSetupConfig.Get(job);
+            var oldWings = wingsId;
+            if (resourceId == oldWings)
+            {
+                return;
+            }
+
+            GameObject prefab = null;
+            GameObjectPoolManager.GameObjectPool pool = null;
+
+            if (oldWings != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(oldWings);
+                pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                pool.Release(wingsModel);
+                wingsModel = null;
+            }
+
+            if (resourceId != 0)
+            {
+                prefab = InstanceResourcesLoader.LoadModelRes(resourceId);
+
+                if (!prefab)
+                {
+                    resourceId = config.BaseEquip[3];
+                    prefab = InstanceResourcesLoader.LoadModelRes(resourceId);
+                }
+
+                if (prefab)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    wingsModel = pool.Request();
+
+                    wingsModel.layer = LayerUtility.Player;
+                    SkinnedMeshRenderer _renderer = wingsModel.GetComponentInChildren<SkinnedMeshRenderer>();
+                    if (_renderer)
+                    {
+                        _renderer.gameObject.layer = LayerUtility.Player;
+                    }
+
+                    var parent = clothesModel.transform.GetChildTransformDeeply(GAStaticDefine.WingBindBoneName);
+                    var modelResConfig = ModelResConfig.Get(resourceId);
+                    wingsModel.transform.SetParentEx(parent, Vector3.zero, Quaternion.identity, modelResConfig.UIScale);
+
+                    wingsAnimator = wingsModel.GetComponent<Animator>();
+                    if (wingsAnimator == null)
+                    {
+                        DebugEx.LogErrorFormat("缈呰唨璧勬簮{0}娌℃湁鍔ㄧ敾鎺у埗鍣�", resourceId);
+                    }
+                    wingsAnimator.enabled = true;
+                    wingsAnimator.Play("UI_Idle", 0);
+                }
+            }
+
+            wingsId = resourceId;
+        }
+
+        private void LoadClothesEffect()
+        {
+            SwitchMaterial(isSuit);
+            HideSuitEffect();
+            if (isSuit)
+            {
+                var _modelResConfig = ModelResConfig.Get(clothesId);
+                if (_modelResConfig != null)
+                {
+                    var _boneList = ModelResConfig.GetBoneList(_modelResConfig.ResourcesName);
+                    var _effectList = ModelResConfig.GetEffectList(_modelResConfig.ResourcesName);
+                    if (_boneList != null)
+                    {
+                        Transform _node = null;
+                        SFXController _sfx = null;
+                        for (int i = 0; i < _boneList.Count; ++i)
+                        {
+                            _node = clothesModel.transform.GetChildTransformDeeply(_boneList[i]);
+                            if (_node)
+                            {
+                                _sfx = SFXPlayUtility.Instance.PlayEffectAsync(_effectList[i], _node);
+                                if (_sfx)
+                                {
+                                    m_SuitEffectList.Add(_sfx);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        private List<SFXController> m_SuitEffectList = new List<SFXController>();
+        private List<SFXController> m_WeaponEffectList = new List<SFXController>();
+        private List<SFXController> m_SecondaryEffectList = new List<SFXController>();
+
+        private void ShowWeaponEffect(Transform parent, string modelName)
+        {
+            HideWeaponEffect();
+
+            var _boneList = ModelResConfig.GetBoneList(modelName);
+            var _effectlist = ModelResConfig.GetEffectList(modelName);
+
+            if (_boneList != null && _effectlist != null)
+            {
+                for (int i = 0; i < _boneList.Count; ++i)
+                {
+                    if (_boneList[i].Equals("null"))
+                    {
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent);
+                        m_WeaponEffectList.Add(_ctrl);
+                    }
+                    else
+                    {
+
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent.GetChildTransformDeeply(_boneList[i]));
+                        m_WeaponEffectList.Add(_ctrl);
+                    }
+                }
+            }
+        }
+
+        private void ShowSecondaryEffect(Transform parent, string modelName)
+        {
+            HideWeaponEffect();
+
+            var _boneList = ModelResConfig.GetBoneList(modelName);
+            var _effectlist = ModelResConfig.GetEffectList(modelName);
+
+            if (_boneList != null && _effectlist != null)
+            {
+                for (int i = 0; i < _boneList.Count; ++i)
+                {
+                    if (_boneList[i].Equals("null"))
+                    {
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent);
+                        m_SecondaryEffectList.Add(_ctrl);
+                    }
+                    else
+                    {
+
+                        var _ctrl = SFXPlayUtility.Instance.PlayBattleEffect(_effectlist[i], parent.GetChildTransformDeeply(_boneList[i]));
+                        m_SecondaryEffectList.Add(_ctrl);
+                    }
+                }
+            }
+        }
+
+        private void HideSecondaryEffect()
+        {
+            foreach (var _ctrl in m_SecondaryEffectList)
+            {
+                SFXPlayUtility.Instance.Release(_ctrl);
+            }
+            m_SecondaryEffectList.Clear();
+        }
+
+        private void HideWeaponEffect()
+        {
+            foreach (var _ctrl in m_WeaponEffectList)
+            {
+                SFXPlayUtility.Instance.Release(_ctrl);
+            }
+            m_WeaponEffectList.Clear();
+        }
+
+        private void HideSuitEffect()
+        {
+            foreach (var _ctrl in m_SuitEffectList)
+            {
+                SFXPlayUtility.Instance.Release(_ctrl);
+            }
+            m_SuitEffectList.Clear();
+        }
+
+        void ShowBodyEffect(UI3DPlayerExhibitionData data)
+        {
+            ShowReikiRootEffect(data.equipLevel, data.reikiRootEffectId);
+            int effectID = 0;
+            ModelCenter.Instance.GetModel<EquipModel>().equipAddEffect.TryGetValue(data.titleID, out effectID);
+            ShowTitleBodyEffect(effectID, data.scale > 0 ? data.scale*0.5f : 0.5f);
+        }
+
+        private void ShowReikiRootEffect(int equipLevel,int id)
+        {
+            //鏀规垚寮哄寲澶у笀鐗规晥 id涓哄己鍖栧ぇ甯堢瓑绾�
+            HideReikiRootEffect();
+            var config = ItemPlusMasterConfig.TryGetMasterInfo(equipLevel, id);
+            if (id != 0 && config != null && clothesModel)
+            {
+                if (reikiRootShowPoint == null && showPoint.parent != null)
+                {
+                    reikiRootShowPoint = new GameObject("ReikiRootShowPoint");
+                    reikiRootShowPoint.transform.SetParentEx(showPoint.parent, showPoint.localPosition, showPoint.rotation, showPoint.localScale);
+                }
+                reikiRootEffect = SFXPlayUtility.Instance.Play(config.effect, reikiRootShowPoint == null ? showPoint : reikiRootShowPoint.transform);
+                if (reikiRootEffect != null)
+                {
+                    var scale = config.uiScale/100f;
+                    var offsetY = config.offsetY/100f;
+                    reikiRootEffect.transform.localScale = Vector3.one * scale * 0.6f;
+                    reikiRootEffect.transform.localPosition = reikiRootEffect.transform.localPosition.SetY(offsetY);
+                }
+            }
+        }
+
+        private void HideReikiRootEffect()
+        {
+            if (reikiRootEffect != null)
+            {
+                reikiRootEffect.transform.localPosition = Vector3.zero;
+                reikiRootEffect.transform.localScale = Vector3.zero;
+                SFXPlayUtility.Instance.Release(reikiRootEffect);
+                reikiRootEffect = null;
+            }
+        }
+
+
+        public void HideTitleRootEffect()
+        {
+            if (titleRootEffect != null)
+            {
+                titleRootEffect.transform.localPosition = Vector3.zero;
+                titleRootEffect.transform.localScale = Vector3.zero;
+                SFXPlayUtility.Instance.Release(titleRootEffect);
+                titleRootEffect = null;
+            }
+        }
+
+
+        //灞曠ず绉板彿鐨勫叏韬壒鏁�
+        public void ShowTitleBodyEffect(int effectID, float scale = 1)
+        {
+            HideTitleRootEffect();
+            if (effectID == 0) return;
+            if (clothesModel)
+            {
+                if (reikiRootShowPoint == null && showPoint.parent != null)
+                {
+                    reikiRootShowPoint = new GameObject("ReikiRootShowPoint");
+                    reikiRootShowPoint.transform.SetParentEx(showPoint.parent, showPoint.localPosition, showPoint.rotation, showPoint.localScale);
+                }
+                titleRootEffect = SFXPlayUtility.Instance.Play(effectID, reikiRootShowPoint == null ? showPoint : reikiRootShowPoint.transform);
+                if (titleRootEffect != null)
+                {
+                    titleRootEffect.duration = 0;
+                    titleRootEffect.transform.localScale = Vector3.one * scale;
+                    titleRootEffect.transform.localRotation = Quaternion.Euler(0, 40, 0);//鍚庣画浼樺寲浼犲弬
+                }
+            }
+        }
+
+        public void SwitchMaterial(bool isSuit)
+        {
+            if (clothesModel == null)
+            {
+                return;
+            }
+
+            var smRenderer = clothesModel.GetComponentInChildren<SkinnedMeshRenderer>();
+            if (smRenderer == null)
+            {
+                return;
+            }
+
+            MaterialLoader.Release(smRenderer.material);
+
+            var newMat = MaterialLoader.LoadClothesMaterial(this.clothesId, true, isSuit);
+            if (newMat != null)
+            {
+                smRenderer.material = newMat;
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/UI3DShowHero.cs.meta b/Main/Component/UI/Common/UI3DShowHero.cs.meta
new file mode 100644
index 0000000..4e4ee4b
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DShowHero.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 92189ab278e134645bc0a3682f03ad3c
+timeCreated: 1506068242
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UI3DTreasureExhibition.cs b/Main/Component/UI/Common/UI3DTreasureExhibition.cs
new file mode 100644
index 0000000..068c98c
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DTreasureExhibition.cs
@@ -0,0 +1,203 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, October 12, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+
+namespace vnxbqy.UI
+{
+
+    public class UI3DTreasureExhibition : MonoBehaviour
+    {
+        const string EFFECT_BONE = "Bone_effect";
+
+        [SerializeField] Transform m_ShowPoint;
+        [SerializeField] Camera m_ShowCamera;
+
+        //娉曞疂
+        int m_TreasureId = 0;
+        GameObject treasureModel = null;
+        SFXController effect;
+
+        //娉曞櫒
+        string m_FaqiPathName;
+        string m_FaqiModelName;
+        GameObject faqiModel = null;
+
+        GameObject weaponModel = null;
+        int m_GodWeaponType = 0;
+
+        static UI3DTreasureExhibition m_Instance = null;
+        public static UI3DTreasureExhibition Instance {
+            get {
+                if (m_Instance == null)
+                {
+					var gameObject = Instantiate(BuiltInLoader.LoadPrefab("UI3DTreasureExhibitionStage"));
+                    m_Instance = gameObject.GetComponent<UI3DTreasureExhibition>();
+                    Instance.transform.position = new Vector3(0, 2000, 3000);
+                    m_Instance.name = "UI3DTreasureExhibitionStage";
+                    m_Instance.SetActive(true);
+                    m_Instance.m_ShowCamera.enabled = false;
+                    DontDestroyOnLoad(gameObject);
+                }
+
+                return m_Instance;
+            }
+        }
+
+
+        public void ShowFaQiModel(string pathName, string modelName, RawImage _rawImage, int effectID)
+        {
+            var instance = UI3DModelFactory.LoadUIFaqi(pathName, modelName);
+            if (instance == null)
+            {
+                return;
+            }
+
+            Stop();
+
+            m_ShowCamera.enabled = true;
+            m_FaqiPathName = pathName;
+            m_FaqiModelName = modelName;
+            faqiModel = instance;
+            instance.transform.SetParentEx(m_ShowPoint, Vector3.zero, Quaternion.identity, Vector3.one);
+            instance.SetActive(true);
+
+            var fbPoint = faqiModel.transform.GetChildTransformDeeply(EFFECT_BONE);
+            if (fbPoint == null)
+            {
+                fbPoint = faqiModel.transform;
+            }
+
+            effect = SFXPlayUtility.Instance.Play(effectID, fbPoint);
+            if (effect != null)
+            {
+                LayerUtility.SetLayer(effect.gameObject, LayerUtility.UILayer, true);
+            }
+
+            if (_rawImage != null)
+            {
+                _rawImage.texture = m_ShowCamera.targetTexture;
+                _rawImage.material = MaterialUtility.GetGUIRenderTextureMaterial();
+            }
+        }
+
+
+        public void ShowTreasure(int _treasureId, RawImage _rawImage)
+        {
+            var instance = UI3DModelFactory.LoadUITreasure(_treasureId);
+            if (instance == null)
+            {
+                return;
+            }
+
+            Stop();
+
+            m_ShowCamera.enabled = true;
+            m_TreasureId = _treasureId;
+            treasureModel = instance;
+
+            var config = TreasureConfig.Get(_treasureId);
+
+            var scale = (config == null || config.UIScale == 0) ? 100 : config.UIScale;
+            instance.transform.SetParentEx(m_ShowPoint, Vector3.zero, Quaternion.identity, Vector3.one * ((float)scale / 100));
+            instance.SetActive(true);
+
+            var mountPoint = treasureModel.transform.GetChildTransformDeeply(EFFECT_BONE);
+            if (mountPoint == null)
+            {
+                mountPoint = treasureModel.transform;
+            }
+
+            effect = SFXPlayUtility.Instance.Play(config.EffectID, mountPoint);
+            if (effect != null)
+            {
+                LayerUtility.SetLayer(effect.gameObject, LayerUtility.UILayer, true);
+            }
+
+            if (_rawImage != null)
+            {
+                _rawImage.texture = m_ShowCamera.targetTexture;
+                _rawImage.material = MaterialUtility.GetGUIRenderTextureMaterial();
+            }
+        }
+
+        public void ShowGodWeapon(int _type, RawImage _rawImage)
+        {
+            var instance = UI3DModelFactory.LoadUIGodWeapon(_type);
+            if (instance == null)
+            {
+                return;
+            }
+
+            Stop();
+
+            m_ShowCamera.enabled = true;
+            m_GodWeaponType = _type;
+            weaponModel = instance;
+            instance.transform.SetParentEx(m_ShowPoint, Vector3.zero, Quaternion.identity, Vector3.one);
+            instance.SetActive(true);
+
+            if (_rawImage != null)
+            {
+                _rawImage.texture = m_ShowCamera.targetTexture;
+                _rawImage.material = MaterialUtility.GetGUIRenderTextureMaterial();
+            }
+        }
+
+        public void Stop()
+        {
+            m_ShowCamera.enabled = false;
+            if (effect != null)
+            {
+                SFXPlayUtility.Instance.Release(effect);
+                effect = null;
+            }
+
+            if (weaponModel != null)
+            {
+                UI3DModelFactory.ReleaseUIGodWeapon(m_GodWeaponType, weaponModel);
+                weaponModel = null;
+                m_GodWeaponType = 0;
+            }
+
+            if (treasureModel != null)
+            {
+                UI3DModelFactory.ReleaseUITreasure(m_TreasureId, treasureModel);
+                treasureModel = null;
+                m_TreasureId = 0;
+            }
+
+            if (faqiModel != null)
+            {
+                UI3DModelFactory.ReleaseUIFaqi(m_FaqiPathName, m_FaqiModelName, faqiModel);
+                faqiModel = null;
+                m_FaqiPathName = string.Empty;
+                m_FaqiModelName = string.Empty;
+            }
+        }
+
+        private void Awake()
+        {
+            OnQualityChange();
+            SystemSetting.Instance.qualityLevelChangeEvent += OnQualityChange;
+        }
+
+        private void OnDestroy()
+        {
+            SystemSetting.Instance.qualityLevelChangeEvent -= OnQualityChange;
+        }
+
+        private void OnQualityChange()
+        {
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/UI3DTreasureExhibition.cs.meta b/Main/Component/UI/Common/UI3DTreasureExhibition.cs.meta
new file mode 100644
index 0000000..c0f5a3b
--- /dev/null
+++ b/Main/Component/UI/Common/UI3DTreasureExhibition.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 674a66b010e39974db01d315e509a3ac
+timeCreated: 1507775902
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UIDragDropBehaviour.cs b/Main/Component/UI/Common/UIDragDropBehaviour.cs
new file mode 100644
index 0000000..46c0b0c
--- /dev/null
+++ b/Main/Component/UI/Common/UIDragDropBehaviour.cs
@@ -0,0 +1,84 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+
+
+public class UIDragDropBehaviour : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IPointerEnterHandler
+{
+    public static bool draging = false;
+    public static int dragData = 0;
+
+    [HideInInspector] public int data;
+
+    const float dragDelay = 0.2f;
+
+    bool m_AllowDragDrop = true;
+    bool m_OnPress = false;
+    bool m_AllowClick = false;
+    float m_Time = 0.0f;
+
+    public event Action<int> onClick;
+
+    public void Init(int data)
+    {
+        this.data = data;
+    }
+
+    public void SetDragDropState(bool allow)
+    {
+        m_AllowDragDrop = allow;
+    }
+
+    public void OnPointerDown(PointerEventData eventData)
+    {
+        draging = false;
+        m_AllowClick = true;
+        m_Time = 0f;
+        if (!m_AllowDragDrop)
+        {
+            return;
+        }
+        m_OnPress = true;
+    }
+
+    public void OnPointerEnter(PointerEventData eventData)
+    {
+        m_AllowClick = true;
+    }
+
+    public void OnPointerExit(PointerEventData eventData)
+    {
+        m_AllowClick = false;
+    }
+
+    public void OnPointerUp(PointerEventData eventData)
+    {
+        var position = Input.mousePosition;
+        if (!draging && m_AllowClick)
+        {
+            if (onClick != null)
+            {
+                onClick(data);
+            }
+        }
+        m_OnPress = false;
+    }
+
+    private void LateUpdate()
+    {
+        if (m_OnPress && !draging)
+        {
+            m_Time += Time.deltaTime;
+            if (m_Time > dragDelay)
+            {
+                dragData = data;
+                draging = true;
+                m_Time = 0;
+                m_OnPress = false;
+            }
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Common/UIDragDropBehaviour.cs.meta b/Main/Component/UI/Common/UIDragDropBehaviour.cs.meta
new file mode 100644
index 0000000..209ea2e
--- /dev/null
+++ b/Main/Component/UI/Common/UIDragDropBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9210057b649c7f94ca264627a90ab320
+timeCreated: 1561516753
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UIFuncOpen.cs b/Main/Component/UI/Common/UIFuncOpen.cs
new file mode 100644
index 0000000..8a27084
--- /dev/null
+++ b/Main/Component/UI/Common/UIFuncOpen.cs
@@ -0,0 +1,99 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Friday, September 29, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+using UnityEngine.EventSystems;
+
+namespace vnxbqy.UI
+{
+    public class UIFuncOpen : MonoBehaviour, IPointerClickHandler
+    {
+        [SerializeField] int funcOpenKey;
+        [SerializeField] GameObject LockImg;
+        [SerializeField] bool active = true;
+        public int id { get { return funcOpenKey; } }
+
+        private Button funcBtn;
+
+        private void Awake()
+        {
+            funcBtn = GetComponent<Button>();
+
+            FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        }
+
+        public void OnPointerClick(PointerEventData eventData)
+        {
+            if (!FuncOpen.Instance.IsFuncOpen(funcOpenKey))
+            {
+                FuncOpen.Instance.ProcessorFuncErrorTip(funcOpenKey);
+                return;
+            }
+        }
+
+        private void OnEnable()
+        {
+            SetState();
+        }
+
+        private void OnFuncStateChangeEvent(int func)
+        {
+            if (funcOpenKey == func)
+            {
+                SetState();
+            }
+        }
+
+        private void OnDestroy()
+        {
+            FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
+        }
+        private void SetState()
+        {
+            var IsOpen = FuncOpen.Instance.IsFuncOpen(funcOpenKey);
+            var _funcOpenCfg = FuncOpenLVConfig.Get(funcOpenKey);
+
+            if (_funcOpenCfg == null)
+            {
+                IsOpen = true;
+                active = true;
+            }
+
+            if (funcBtn != null)
+            {
+                funcBtn.interactable = IsOpen;
+            }
+            
+           
+            if (LockImg != null)
+            {
+                LockImg.SetActive(!IsOpen);
+            }
+
+            if (_funcOpenCfg != null && _funcOpenCfg.open == 0)
+            {
+                gameObject.SetActive(false);
+                return;
+            }
+
+            if (!active)
+            {
+                gameObject.SetActive(IsOpen);
+            }
+            else
+            {
+                if (!gameObject.activeSelf)
+                {
+                    gameObject.SetActive(true);
+                }
+            }
+        }
+    }
+}
+
+
+
diff --git a/Main/Component/UI/Common/UIFuncOpen.cs.meta b/Main/Component/UI/Common/UIFuncOpen.cs.meta
new file mode 100644
index 0000000..03434c1
--- /dev/null
+++ b/Main/Component/UI/Common/UIFuncOpen.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fe467017cf4c98749ae675c385c32352
+timeCreated: 1506654557
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UIPlaySound.cs b/Main/Component/UI/Common/UIPlaySound.cs
new file mode 100644
index 0000000..26d14df
--- /dev/null
+++ b/Main/Component/UI/Common/UIPlaySound.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, December 07, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class UIPlaySound : MonoBehaviour
+    {
+        [SerializeField] TriggerType m_TriggerType = TriggerType.Manual;
+        [SerializeField] int m_Audio = 1;
+
+        public void Play()
+        {
+            SoundPlayer.Instance.PlayUIAudio(m_Audio);
+        }
+
+        private void OnEnable()
+        {
+            if (m_TriggerType == TriggerType.OnEnable)
+            {
+                Play();
+            }
+        }
+
+        private void Start()
+        {
+            if (m_TriggerType == TriggerType.OnStart)
+            {
+                Play();
+            }
+        }
+
+        public enum TriggerType
+        {
+            OnEnable,
+            OnStart,
+            Manual
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Common/UIPlaySound.cs.meta b/Main/Component/UI/Common/UIPlaySound.cs.meta
new file mode 100644
index 0000000..f21211e
--- /dev/null
+++ b/Main/Component/UI/Common/UIPlaySound.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e6620cf3cc6bac4489880d72239744ae
+timeCreated: 1512618753
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UIPrefabLoader.cs b/Main/Component/UI/Common/UIPrefabLoader.cs
new file mode 100644
index 0000000..d3f290d
--- /dev/null
+++ b/Main/Component/UI/Common/UIPrefabLoader.cs
@@ -0,0 +1,51 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, March 19, 2019
+//--------------------------------------------------------
+using UnityEngine;
+
+[ExecuteAlways]
+[RequireComponent(typeof(RectTransform))]
+public class UIPrefabLoader : MonoBehaviour
+{
+    [SerializeField] protected string m_PrefabName;
+    public virtual string prefabName { get { return m_PrefabName; } }
+
+    protected GameObject instance;
+
+    [ExecuteAlways]
+    private void Awake()
+    {
+        Create();
+    }
+    public void Reload()
+    {
+        instance = null;
+        this.transform.ClearAllChilds();
+        Create();
+    }
+
+    [ContextMenu("Create")]
+    public virtual void Create()
+    {
+        if (instance != null)
+            return;
+
+        if (string.IsNullOrEmpty(prefabName))
+            return;
+
+        var find = this.transform.Find(prefabName);
+        if (find)
+        {
+            instance = find.gameObject;
+            return;
+        }
+        instance = UIUtility.CreateWidget(prefabName, prefabName);
+        instance.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one);
+    }
+
+}
+
+
+
+
diff --git a/Main/Component/UI/Common/UIPrefabLoader.cs.meta b/Main/Component/UI/Common/UIPrefabLoader.cs.meta
new file mode 100644
index 0000000..216b9fd
--- /dev/null
+++ b/Main/Component/UI/Common/UIPrefabLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dabca296a3c10864b8107dca62b132e4
+timeCreated: 1552974474
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UIRoot.cs b/Main/Component/UI/Common/UIRoot.cs
new file mode 100644
index 0000000..eea8ba2
--- /dev/null
+++ b/Main/Component/UI/Common/UIRoot.cs
@@ -0,0 +1,121 @@
+锘縰sing UnityEngine;
+using UnityEngine.EventSystems;
+
+namespace vnxbqy.UI
+{
+
+    [DisallowMultipleComponent]
+    public class UIRoot : MonoBehaviour
+    {
+        [SerializeField] RectTransform m_RecycleBin;
+        public RectTransform recycleBin { get { return m_RecycleBin; } }
+
+        [SerializeField] FightCanvasGroup m_FightCanvasGroup;
+        public FightCanvasGroup fightCanvasGroup { get { return m_FightCanvasGroup; } }
+
+        [SerializeField] private RectTransform m_BossShowCanvas;
+        public RectTransform bossShowCanvas { get { return m_BossShowCanvas; } }
+
+        [SerializeField] private RectTransform m_NameCanvas;
+        public RectTransform nameCanvas { get { return m_NameCanvas; } }
+
+        [SerializeField] private RectTransform m_LifeBarCanvas;
+        public RectTransform lifeBarCanvas { get { return m_LifeBarCanvas; } }
+
+        [SerializeField] private RectTransform m_BaseCanvas;
+        public RectTransform baseCanvas { get { return m_BaseCanvas; } }
+
+        [SerializeField] private RectTransform m_NormalCanvas;
+        public RectTransform normalCanvas { get { return m_NormalCanvas; } }
+
+        [SerializeField] private RectTransform m_ModalCanvas;
+        public RectTransform modalCanvas { get { return m_ModalCanvas; } }
+
+        [SerializeField] private RectTransform m_TipsCanvas;
+        public RectTransform tipsCanvas { get { return m_TipsCanvas; } }
+
+        [SerializeField] private RectTransform m_SystemCanvas;
+        public RectTransform systemCanvas { get { return m_SystemCanvas; } }
+
+        [SerializeField] private RectTransform m_LoadingCanvas;
+        public RectTransform loadingCanvas { get { return m_LoadingCanvas; } }
+
+        [SerializeField] private Camera m_UICamera;
+        public Camera uicamera { get { return m_UICamera; } set { m_UICamera = value; } }
+
+        [SerializeField] EventSystem m_EventSystem;
+        public EventSystem eventSystem { get { return m_EventSystem; } }
+
+        private void Awake()
+        {
+            CameraManager.uiCamera = uicamera;
+        }
+
+        private void LateUpdate()
+        {
+
+            if (Input.GetKeyDown(KeyCode.F4))
+            {
+                C320C_tagCGMCMD gmCmd = new C320C_tagCGMCMD();
+                gmCmd.Cmd = "KillScreenNPC";
+                gmCmd.CmdLen = 13;
+                if (CrossServerUtility.IsCrossServer())
+                {
+                    GameNetSystem.Instance.SendToCrossServer(gmCmd);
+                }
+                else
+                {
+                    GameNetSystem.Instance.SendInfo(gmCmd);
+                }
+            }
+
+            if (StageLoad.Instance.currentStage != null)
+            {
+
+
+                if (Input.GetKeyDown(KeyCode.Escape))
+                {
+#if UNITY_EDITOR
+                    WindowCenter.Instance.Open<ExitGameWin>();
+#endif
+                }
+            }
+
+        }
+
+        [System.Serializable]
+        public class FightCanvasGroup
+        {
+            public RectTransform[] damageNumGroups;
+        }
+
+        private void EnableCanvas(Transform parent, bool _enabled)
+        {
+            if (parent != m_RecycleBin)
+            {
+                var canvas = parent.GetComponent<Canvas>();
+                if (canvas != null)
+                {
+                    canvas.enabled = _enabled;
+                }
+            }
+
+            foreach (Transform child in parent)
+            {
+                EnableCanvas(child, _enabled);
+            }
+        }
+
+        public void EnableCanvas(bool _enabled, params Transform[] _canvas)
+        {
+            if (_canvas != null && _canvas.Length > 0)
+            {
+                for (int i = 0; i < _canvas.Length; i++)
+                {
+                    EnableCanvas(_canvas[i], _enabled);
+                }
+            }
+        }
+    }
+
+}
diff --git a/Main/Component/UI/Common/UIRoot.cs.meta b/Main/Component/UI/Common/UIRoot.cs.meta
new file mode 100644
index 0000000..69c43c4
--- /dev/null
+++ b/Main/Component/UI/Common/UIRoot.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f4f3aba9cf184074aa15b95cd26ef6ad
+timeCreated: 1458743886
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UITextMark.cs b/Main/Component/UI/Common/UITextMark.cs
new file mode 100644
index 0000000..69919de
--- /dev/null
+++ b/Main/Component/UI/Common/UITextMark.cs
@@ -0,0 +1,16 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+namespace vnxbqy.UI
+{
+    //缁橢ditor鐜涓嬩娇鐢紝鍙槸鎵撴爣璁扮敤锛岃鍙栫殑鏄痀.璇█琛�
+    //閫氳繃宸ュ叿缁欏凡鎵撴爣璁扮殑棰勫埗浣撹緭鍏ユ枃鏈唴瀹癸紝闈炴父鎴忚繍琛屾椂浣跨敤
+    //姣斿鍦ㄨ秺鍗楃増鏈紙鍚庣画鍙樻垚鍒濆鐗堟湰锛夌粰棰勫埗浣撴墦鏍囪锛岀劧鍚庤嫳鏂囩増鏈憳鍙栧悗锛岀粰鎵撴爣璁扮殑棰勫埗浣撹繘琛岀炕璇�
+    public class UITextMark : MonoBehaviour
+    {
+        [SerializeField] public string language;
+
+    }
+}
diff --git a/Main/Component/UI/Common/UITextMark.cs.meta b/Main/Component/UI/Common/UITextMark.cs.meta
new file mode 100644
index 0000000..da85a2e
--- /dev/null
+++ b/Main/Component/UI/Common/UITextMark.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ce86e2e711a995b4ab51f002ac632cc9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/UITextReplace.cs b/Main/Component/UI/Common/UITextReplace.cs
new file mode 100644
index 0000000..2c2c161
--- /dev/null
+++ b/Main/Component/UI/Common/UITextReplace.cs
@@ -0,0 +1,23 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+namespace vnxbqy.UI
+{
+    //鍙敤浜嶵ext缁勪欢锛岃ˉ鍏呰缃枃鏈紝璇诲彇鐨勬槸Y.璇█琛�;娓告垙杩愯浼氳缃枃鏈唴瀹�
+    public class UITextReplace : MonoBehaviour
+    {
+        [SerializeField] string language;
+        
+        private void Awake()
+        {
+            var textObj = this.transform.GetComponent<Text>();
+            if (textObj == null)
+                return;
+
+            textObj.text = Language.Get(language);
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Common/UITextReplace.cs.meta b/Main/Component/UI/Common/UITextReplace.cs.meta
new file mode 100644
index 0000000..ad7ee5f
--- /dev/null
+++ b/Main/Component/UI/Common/UITextReplace.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3cdb8d4db738d7f4c9e0db0ff395d44d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/WaterWaveOnCamera.cs b/Main/Component/UI/Common/WaterWaveOnCamera.cs
new file mode 100644
index 0000000..40afb4d
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveOnCamera.cs
@@ -0,0 +1,22 @@
+锘縰sing UnityEngine;
+using UnityStandardAssets.ImageEffects;
+
+public class WaterWaveOnCamera : MonoBehaviour
+{
+    [SerializeField] WaterWaveOnUI wave;
+
+    void OnEnable()
+    {
+        ClientSceneManager.Instance.ClientSceneChangeEvent += OnClientSceneChange;
+    }
+
+    void OnDisable()
+    {
+        ClientSceneManager.Instance.ClientSceneChangeEvent -= OnClientSceneChange;
+    }
+
+    void OnClientSceneChange()
+    {
+        wave.StartWave();
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Common/WaterWaveOnCamera.cs.meta b/Main/Component/UI/Common/WaterWaveOnCamera.cs.meta
new file mode 100644
index 0000000..04203d5
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveOnCamera.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 105914d4abcd80a48ba73c6d0ce4ac41
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/WaterWaveOnUI.cs b/Main/Component/UI/Common/WaterWaveOnUI.cs
new file mode 100644
index 0000000..f020739
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveOnUI.cs
@@ -0,0 +1,47 @@
+锘縰sing UnityEngine;
+using UnityStandardAssets.ImageEffects;
+
+public class WaterWaveOnUI : PostEffectBase
+{
+    //璺濈绯绘暟
+    public float distanceFactor = 60.0f;
+    //鏃堕棿绯绘暟
+    public float timeFactor = -30.0f;
+    //sin鍑芥暟缁撴灉绯绘暟
+    public float totalFactor = 1.0f;
+
+    //娉㈢汗瀹藉害
+    public float waveWidth = 0.3f;
+    //娉㈢汗鎵╂暎鐨勯�熷害
+    public float waveSpeed = 0.3f;
+
+    private float waveStartTime;
+
+    public void StartWave()
+    {
+        enabled = true;
+        //璁剧疆startTime
+        waveStartTime = Time.time;
+    }
+
+    void OnRenderImage(RenderTexture source, RenderTexture destination)
+    {
+        if (Time.time - waveStartTime > 1)
+        {
+            //濡傛灉鏃堕棿瓒呰繃1s锛屽叧闂尝绾规晥鏋�
+            enabled = false;
+            return;
+        }
+        //璁$畻娉㈢汗绉诲姩鐨勮窛绂伙紝鏍规嵁enable鍒扮洰鍓嶇殑鏃堕棿*閫熷害姹傝В
+        float curWaveDistance = (Time.time - waveStartTime) * waveSpeed;
+        //璁剧疆涓�绯诲垪鍙傛暟
+        _Material.SetFloat("_distanceFactor", distanceFactor);
+        _Material.SetFloat("_timeFactor", timeFactor);
+        _Material.SetFloat("_totalFactor", totalFactor);
+        _Material.SetFloat("_waveWidth", waveWidth);
+        _Material.SetFloat("_curWaveDis", curWaveDistance);
+
+        Graphics.Blit(source, destination, _Material);
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Common/WaterWaveOnUI.cs.meta b/Main/Component/UI/Common/WaterWaveOnUI.cs.meta
new file mode 100644
index 0000000..22c4b21
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveOnUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fceacda37a001474993a90396e2bfe90
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/WaterWaveSlider.cs b/Main/Component/UI/Common/WaterWaveSlider.cs
new file mode 100644
index 0000000..0f95792
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveSlider.cs
@@ -0,0 +1,41 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+public class WaterWaveSlider : MonoBehaviour
+{
+    [SerializeField]
+    [Range(0, 1)]
+    float m_Progress = 0f;
+    public float progress {
+        get {
+            return m_Progress;
+        }
+        set {
+            if (m_Progress != value)
+            {
+                m_Progress = value;
+                if (materials != null)
+                {
+                    for (int i = 0; i < materials.Length; i++)
+                    {
+                        materials[i].SetFloat("_Progress", m_Progress == 0f ? 0f : Mathf.Clamp(m_Progress, 0.2f, 1f));
+                    }
+                }
+            }
+        }
+    }
+
+    [SerializeField] Material[] m_Materials;
+    public Material[] materials {
+        get {
+            return m_Materials;
+        }
+    }
+
+    private void Start()
+    {
+        progress = 0f;
+    }
+
+}
diff --git a/Main/Component/UI/Common/WaterWaveSlider.cs.meta b/Main/Component/UI/Common/WaterWaveSlider.cs.meta
new file mode 100644
index 0000000..9feb33f
--- /dev/null
+++ b/Main/Component/UI/Common/WaterWaveSlider.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5bb67d1aa5abcba459559e32871d5602
+timeCreated: 1512704618
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Common/WindowConfig.cs b/Main/Component/UI/Common/WindowConfig.cs
new file mode 100644
index 0000000..6ec3bc1
--- /dev/null
+++ b/Main/Component/UI/Common/WindowConfig.cs
@@ -0,0 +1,168 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+[CreateAssetMenu(menuName = "Config/WindowConfig")]
+public class WindowConfig : ScriptableObject
+{
+    public WindowTable[] windows;
+
+    [NonSerialized] public Dictionary<string, List<string>> parentChildrenTable = new Dictionary<string, List<string>>();
+    [NonSerialized] public List<string> childWindows = new List<string>();
+
+    static WindowConfig config;
+    static WindowConfig Get()
+    {
+        if (config == null)
+        {
+            config = BuiltInLoader.LoadScriptableObject<WindowConfig>("WindowConfig");
+            foreach (var table in config.windows)
+            {
+                var children = config.parentChildrenTable[table.parent] = new List<string>();
+                foreach (var info in table.orderTables)
+                {
+                    children.Add(info.window);
+                }
+
+                config.childWindows.AddRange(children);
+            }
+        }
+
+        return config;
+    }
+
+    public static void Release()
+    {
+        config = null;
+    }
+
+    public static bool FindParentWindow(string child, out string parent)
+    {
+        foreach (var table in Get().windows)
+        {
+            foreach (var orderTable in table.orderTables)
+            {
+                if (orderTable.window == child)
+                {
+                    parent = table.parent;
+                    return true;
+                }
+            }
+        }
+
+        parent = string.Empty;
+        return false;
+    }
+
+    public static List<string> GetChildWindows(string parent)
+    {
+        if (Get().parentChildrenTable.ContainsKey(parent))
+        {
+            return Get().parentChildrenTable[parent];
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static bool IsParentWindow(string name)
+    {
+        foreach (var window in Get().windows)
+        {
+            if (window.parent == name)
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static bool IsChildWindow(string name)
+    {
+        return Get().childWindows.Contains(name);
+    }
+
+    public static WindowLevel GetWindowLevel(string name)
+    {
+        foreach (var window in Get().windows)
+        {
+            if (window.parent == name)
+            {
+                return window.level;
+            }
+        }
+
+        return WindowLevel.None;
+    }
+
+    public static string GetWindowPattern(string name)
+    {
+        foreach (var window in Get().windows)
+        {
+            if (window.parent == name)
+            {
+                return window.pattern;
+            }
+        }
+
+        return string.Empty;
+    }
+
+    public static List<OrderTable> GetWindowFunctionInfos(string parent)
+    {
+        foreach (var table in Get().windows)
+        {
+            if (table.parent == parent)
+            {
+                return new List<OrderTable>(table.orderTables);
+            }
+        }
+
+        return null;
+    }
+
+    public static string GetTitleIconKey(string name)
+    {
+        foreach (var window in Get().windows)
+        {
+            if (window.parent == name)
+            {
+                return window.titleIconKey;
+            }
+        }
+
+        return string.Empty;
+    }
+
+    [Serializable]
+    public struct WindowTable
+    {
+        public string parent;
+        public string titleIconKey;
+        public WindowLevel level;
+        public string pattern;
+        public OrderTable[] orderTables;
+    }
+
+    [Serializable]
+    public struct OrderTable
+    {
+        public int order;
+        public int functionId;
+        public int redPointId;
+        public string titleKey;
+        public string window;
+    }
+
+    public enum WindowLevel
+    {
+        None,
+        OneLevel,
+        SecondLevel,
+        ThirdLevel,
+    }
+
+}
diff --git a/Main/Component/UI/Common/WindowConfig.cs.meta b/Main/Component/UI/Common/WindowConfig.cs.meta
new file mode 100644
index 0000000..8c55723
--- /dev/null
+++ b/Main/Component/UI/Common/WindowConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dfa5c93d9f8790242a9db3d3bb1815bc
+timeCreated: 1513665060
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core.meta b/Main/Component/UI/Core.meta
new file mode 100644
index 0000000..1fa1ece
--- /dev/null
+++ b/Main/Component/UI/Core.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 8d915c9ab2807e642ae2ab41c1dbbb03
+folderAsset: yes
+timeCreated: 1497860585
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ButtonEx.cs b/Main/Component/UI/Core/ButtonEx.cs
new file mode 100644
index 0000000..d70c07c
--- /dev/null
+++ b/Main/Component/UI/Core/ButtonEx.cs
@@ -0,0 +1,73 @@
+锘縰sing UnityEngine.UI;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System;
+
+
+public class ButtonEx : Button
+{
+
+    public event Action ableTimeChangeEvent;
+
+    public float interval;
+    public bool customPositiveSound = false;
+    public bool customNegativeSound = false;
+    public int positiveSound = 0;
+    public int negativeSound = 0;
+
+    float m_AbleTime = 0f;
+    public float ableTime {
+        get { return m_AbleTime; }
+        private set {
+            m_AbleTime = value;
+            if (ableTimeChangeEvent != null)
+            {
+                ableTimeChangeEvent();
+            }
+        }
+    }
+
+    public override void OnPointerClick(PointerEventData eventData)
+    {
+        if (Time.realtimeSinceStartup < ableTime)
+        {
+            PlayNegativeSound();
+            return;
+        }
+
+        base.OnPointerClick(eventData);
+
+        PlayPositiveSound();
+        ableTime = Time.realtimeSinceStartup + Mathf.Clamp(interval, 0, float.MaxValue);
+    }
+
+    protected override void Awake()
+    {
+        base.Awake();
+    }
+
+    private void PlayPositiveSound()
+    {
+        if (customPositiveSound)
+        {
+            SoundPlayer.Instance.PlayUIAudio(positiveSound);
+        }
+        else
+        {
+            SoundPlayer.Instance.PlayUIAudio(SoundPlayer.defaultClickPositiveAudio);
+        }
+    }
+
+    private void PlayNegativeSound()
+    {
+        if (customNegativeSound)
+        {
+            SoundPlayer.Instance.PlayUIAudio(negativeSound);
+        }
+        else
+        {
+            SoundPlayer.Instance.PlayUIAudio(SoundPlayer.defaultClickNegativeAudio);
+        }
+    }
+
+}
diff --git a/Main/Component/UI/Core/ButtonEx.cs.meta b/Main/Component/UI/Core/ButtonEx.cs.meta
new file mode 100644
index 0000000..9c5e0ea
--- /dev/null
+++ b/Main/Component/UI/Core/ButtonEx.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4b71190bf06931745ae72221994579ef
+timeCreated: 1497863781
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/CanvasAddition.cs b/Main/Component/UI/Core/CanvasAddition.cs
new file mode 100644
index 0000000..d9ce2f4
--- /dev/null
+++ b/Main/Component/UI/Core/CanvasAddition.cs
@@ -0,0 +1,113 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using vnxbqy.UI;
+
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Canvas))]
+public class CanvasAddition : MonoBehaviour
+{
+    [SerializeField]
+    Canvas m_Canvas;
+    public Canvas canvas {
+        get {
+            return this.m_Canvas ?? (this.m_Canvas = this.GetComponent<Canvas>());
+        }
+    }
+
+    [SerializeField]
+    CullingFullScreenType m_Culling = CullingFullScreenType.None;
+
+    Material m_SpriteGrayMaterial;
+    public Material spriteGrayMaterial {
+        get {
+            return this.m_SpriteGrayMaterial ?? (this.m_SpriteGrayMaterial = MaterialUtility.GetInstantiatedSpriteGrayMaterial());
+        }
+    }
+
+    private void Awake()
+    {
+        m_Canvas = this.GetComponent<Canvas>();
+
+        WindowCenter.Instance.windowAfterOpenEvent += OnWindowOpen;
+        WindowCenter.Instance.windowAfterCloseEvent += OnWindowClose;
+    }
+
+    private void OnDestroy()
+    {
+        WindowCenter.Instance.windowAfterOpenEvent -= OnWindowOpen;
+        WindowCenter.Instance.windowAfterCloseEvent -= OnWindowClose;
+    }
+
+    private void OnWindowOpen(Window _window)
+    {
+        var culling = false;
+        switch (m_Culling)
+        {
+            case CullingFullScreenType.None:
+                culling = false;
+                break;
+            case CullingFullScreenType.Any:
+                culling = WindowCenter.Instance.ExistAnyFullScreenOrMaskWin();
+                break;
+            default:
+                culling = WindowCenter.Instance.ExistAnyFullScreenOrMaskWinLEqual((WindowType)m_Culling);
+                break;
+        }
+
+        canvas.gameObject.SetLayer(culling ? LayerUtility.DevisableUI : LayerUtility.UILayer, false);
+    }
+
+    private void OnWindowClose(Window _window)
+    {
+        var culling = false;
+        switch (m_Culling)
+        {
+            case CullingFullScreenType.None:
+                culling = false;
+                break;
+            case CullingFullScreenType.Any:
+                culling = WindowCenter.Instance.ExistAnyFullScreenOrMaskWin();
+                break;
+            default:
+                culling = WindowCenter.Instance.ExistAnyFullScreenOrMaskWinLEqual((WindowType)m_Culling);
+                break;
+        }
+
+        canvas.gameObject.SetLayer(culling ? LayerUtility.DevisableUI : LayerUtility.UILayer, false);
+    }
+
+    private void Start()
+    {
+        var canvasScaler = this.GetComponent<CanvasScaler>();
+        if (canvasScaler != null && canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight)
+        {
+            var screenAspect = Screen.width / (float)Screen.height;
+            var referenceAspect = canvasScaler.referenceResolution.x / (float)canvasScaler.referenceResolution.y;
+
+            if ((screenAspect - referenceAspect) > 0.0001f)
+            {
+                canvasScaler.matchWidthOrHeight = 1f;
+            }
+            else
+            {
+                canvasScaler.matchWidthOrHeight = 0f;
+            }
+        }
+
+    }
+
+    public enum CullingFullScreenType
+    {
+        Base = 0,
+        Normal = 1,
+        Modal = 2,
+        Tip = 3,
+        System = 4,
+        Loading = 5,
+        None = 6,
+        Any = 7,
+    }
+
+}
diff --git a/Main/Component/UI/Core/CanvasAddition.cs.meta b/Main/Component/UI/Core/CanvasAddition.cs.meta
new file mode 100644
index 0000000..998c3be
--- /dev/null
+++ b/Main/Component/UI/Core/CanvasAddition.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 357f6eb33e379654495bdbe619f863b5
+timeCreated: 1499324448
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/DebugCanvasAddition.cs b/Main/Component/UI/Core/DebugCanvasAddition.cs
new file mode 100644
index 0000000..dae8105
--- /dev/null
+++ b/Main/Component/UI/Core/DebugCanvasAddition.cs
@@ -0,0 +1,39 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using vnxbqy.UI;
+
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Canvas))]
+public class DebugCanvasAddition : MonoBehaviour
+{
+
+    [SerializeField]
+    Canvas m_Canvas;
+    public Canvas canvas {
+        get {
+            return this.m_Canvas ?? (this.m_Canvas = this.GetComponent<Canvas>());
+        }
+    }
+
+    void Start()
+    {
+        var canvasScaler = this.GetComponent<CanvasScaler>();
+        if (canvasScaler != null && canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight)
+        {
+            var screenAspect = Screen.width / (float)Screen.height;
+            var referenceAspect = canvasScaler.referenceResolution.x / (float)canvasScaler.referenceResolution.y;
+
+            if ((screenAspect - referenceAspect) > 0.0001f)
+            {
+                canvasScaler.matchWidthOrHeight = 1f;
+            }
+            else
+            {
+                canvasScaler.matchWidthOrHeight = 0f;
+            }
+        }
+    }
+
+}
diff --git a/Main/Component/UI/Core/DebugCanvasAddition.cs.meta b/Main/Component/UI/Core/DebugCanvasAddition.cs.meta
new file mode 100644
index 0000000..2defbc5
--- /dev/null
+++ b/Main/Component/UI/Core/DebugCanvasAddition.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0a4efa371fcd965448800bd3b9d54a27
+timeCreated: 1543993370
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/DelayButton.cs b/Main/Component/UI/Core/DelayButton.cs
new file mode 100644
index 0000000..b04b01a
--- /dev/null
+++ b/Main/Component/UI/Core/DelayButton.cs
@@ -0,0 +1,59 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+
+using UnityEngine;
+using System.Collections;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    /// <summary>
+    /// 寤惰繜瑙﹀彂鐐瑰嚮浜嬩欢鐨勬寜閽紝鐢ㄤ簬闀挎寜浜嬩欢
+    /// </summary>
+    public class DelayButton:MonoBehaviour,IPointerDownHandler,IPointerUpHandler {
+
+        [SerializeField]
+        float m_Delay = 0.5f;
+        public float delay { get { return m_Delay; } }
+
+        [SerializeField]
+        UIEvent m_OnClick;
+        public UIEvent onClick { get { return m_OnClick; } }
+
+        float timer = 0f;
+        bool down = false;
+
+        public void OnPointerDown(PointerEventData eventData) {
+            timer = 0f;
+            down = true;
+        }
+
+        public void OnPointerUp(PointerEventData eventData) {
+            down = false;
+        }
+
+        private void OnEnable() {
+            timer = 0f;
+            down = false;
+        }
+
+        private void LateUpdate() {
+            if(down && timer < delay) {
+                timer += Time.deltaTime;
+                if(timer > delay) {
+                    if(onClick != null) {
+                        onClick.Invoke();
+                    }
+                }
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Core/DelayButton.cs.meta b/Main/Component/UI/Core/DelayButton.cs.meta
new file mode 100644
index 0000000..3596531
--- /dev/null
+++ b/Main/Component/UI/Core/DelayButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f91c143a16d59de4b80b2b0ffbb455e4
+timeCreated: 1501494723
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/GrayGroup.cs b/Main/Component/UI/Core/GrayGroup.cs
new file mode 100644
index 0000000..d76089b
--- /dev/null
+++ b/Main/Component/UI/Core/GrayGroup.cs
@@ -0,0 +1,48 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class GrayGroup : MonoBehaviour
+    {
+
+        Image[] m_Images;
+        Image[] images {
+            get {
+                if (m_Images == null)
+                {
+                    m_Images = this.GetComponentsInChildren<Image>();
+                }
+                return m_Images;
+            }
+        }
+
+        bool m_Gray = false;
+        public bool gray {
+            get { return m_Gray; }
+            set {
+                m_Gray = value;
+
+                for (int i = 0; i < images.Length; i++)
+                {
+                    var image = images[i];
+                    if (this.m_Gray)
+                    {
+                        image.material = MaterialUtility.GetDefaultSpriteGrayMaterial();
+                    }
+                    else
+                    {
+                        image.material = MaterialUtility.GetUIDefaultGraphicMaterial();
+                    }
+
+                }
+            }
+        }
+
+    }
+
+}
+
diff --git a/Main/Component/UI/Core/GrayGroup.cs.meta b/Main/Component/UI/Core/GrayGroup.cs.meta
new file mode 100644
index 0000000..276620d
--- /dev/null
+++ b/Main/Component/UI/Core/GrayGroup.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7d3cfdaee9bc01c449fdfddb691a769d
+timeCreated: 1522301907
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ImageEx.cs b/Main/Component/UI/Core/ImageEx.cs
new file mode 100644
index 0000000..f93f64d
--- /dev/null
+++ b/Main/Component/UI/Core/ImageEx.cs
@@ -0,0 +1,66 @@
+锘縰sing UnityEngine.UI;
+using UnityEngine;
+
+
+
+public class ImageEx : Image
+{
+
+    CanvasAddition m_CanvasAddition;
+    public CanvasAddition canvasAddition {
+        get {
+            return this.m_CanvasAddition ?? (this.m_CanvasAddition = this.GetComponentInParent<CanvasAddition>());
+        }
+    }
+
+    Material materialRecorder;
+
+    [SerializeField]
+    bool m_Gray = false;
+    public bool gray {
+        get {
+            return this.m_Gray;
+        }
+        set {
+            if (this.gray == value)
+            {
+                return;
+            }
+
+            this.m_Gray = value;
+            if (!inited)
+            {
+                return;
+            }
+
+            if (this.m_Gray)
+            {
+                this.material = this.canvasAddition == null ? MaterialUtility.GetDefaultSpriteGrayMaterial() : this.canvasAddition.spriteGrayMaterial;
+            }
+            else
+            {
+                this.material = materialRecorder;
+            }
+        }
+    }
+
+    [SerializeField] string m_IconKey = string.Empty;
+
+    bool inited = false;
+    protected override void Awake()
+    {
+        base.Awake();
+        materialRecorder = this.material;
+        inited = true;
+        if (this.m_Gray)
+        {
+            this.material = this.canvasAddition == null ? MaterialUtility.GetDefaultSpriteGrayMaterial() : this.canvasAddition.spriteGrayMaterial;
+        }
+
+        if (!string.IsNullOrEmpty(m_IconKey))
+        {
+            this.SetSprite(m_IconKey);
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Core/ImageEx.cs.meta b/Main/Component/UI/Core/ImageEx.cs.meta
new file mode 100644
index 0000000..1c26bb6
--- /dev/null
+++ b/Main/Component/UI/Core/ImageEx.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5eec31867c0c74f4aa2eeade969eec0e
+timeCreated: 1497863897
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ImageUV1.cs b/Main/Component/UI/Core/ImageUV1.cs
new file mode 100644
index 0000000..6be09fe
--- /dev/null
+++ b/Main/Component/UI/Core/ImageUV1.cs
@@ -0,0 +1,45 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ImageUV1 : BaseMeshEffect
+{
+
+    public override void ModifyMesh(VertexHelper vh)
+    {
+        var vertexs = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexs);
+
+        if (vertexs == null || vertexs.Count == 0)
+        {
+            return;
+        }
+
+        vh.Clear();
+
+        var newVertexs = new UIVertex[vertexs.Count];
+        var vertex = vertexs[0];
+        vertex.normal = vertex.normal.SetX(1);
+        vertex.uv1 = vertex.uv0;
+        newVertexs[0] = vertex;
+
+        vertex = vertexs[1];
+        vertex.normal = vertex.normal.SetX(1);
+        vertex.uv1 = vertex.uv0;
+        newVertexs[1] = vertex;
+
+        vertex = vertexs[2];
+        vertex.normal = vertex.normal.SetX(1);
+        vertex.uv1 = vertex.uv0;
+        newVertexs[2] = vertex;
+
+        vertex = vertexs[4];
+        vertex.normal = vertex.normal.SetX(1);
+        vertex.uv1 = vertex.uv0;
+        newVertexs[3] = vertex;
+
+        vh.AddUIVertexQuad(newVertexs);
+    }
+
+}
diff --git a/Main/Component/UI/Core/ImageUV1.cs.meta b/Main/Component/UI/Core/ImageUV1.cs.meta
new file mode 100644
index 0000000..1ac1231
--- /dev/null
+++ b/Main/Component/UI/Core/ImageUV1.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: aee3770851372694aba74c71be00d770
+timeCreated: 1524188344
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/PointerDownUp.cs b/Main/Component/UI/Core/PointerDownUp.cs
new file mode 100644
index 0000000..8215625
--- /dev/null
+++ b/Main/Component/UI/Core/PointerDownUp.cs
@@ -0,0 +1,110 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, July 31, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.EventSystems;
+using UnityEngine.Events;
+
+namespace vnxbqy.UI
+{
+
+    public class PointerDownUp : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
+    {
+
+        [SerializeField]
+        UIEvent m_OnPointerDown;
+        public UIEvent onPointerDown { get { return m_OnPointerDown; } }
+
+        [SerializeField]
+        UIEvent m_OnPointerUp;
+        public UIEvent onPointerUp { get { return m_OnPointerUp; } }
+
+        [SerializeField]
+        UIEvent m_OnPointerClick;
+        public UIEvent onPointerClick {
+            get {
+                return m_OnPointerClick;
+            }
+        }
+
+        public void OnPointerUp(PointerEventData eventData)
+        {
+            if (onPointerUp != null)
+            {
+                onPointerUp.Invoke();
+            }
+        }
+
+        public void OnPointerDown(PointerEventData eventData)
+        {
+            if (onPointerDown != null)
+            {
+                onPointerDown.Invoke();
+            }
+        }
+
+        public void OnPointerClick(PointerEventData eventData)
+        {
+            if (onPointerClick != null)
+            {
+                onPointerClick.Invoke();
+            }
+        }
+
+        public void AddPointerDownListener(UnityAction _action)
+        {
+            if (onPointerDown != null)
+            {
+                onPointerDown.AddListener(_action);
+            }
+        }
+
+        public void AddPointerUpListener(UnityAction _action)
+        {
+            if (onPointerUp != null)
+            {
+                onPointerUp.AddListener(_action);
+            }
+        }
+
+        public void AddPointerClickListener(UnityAction _action)
+        {
+            if (onPointerClick != null)
+            {
+                onPointerClick.AddListener(_action);
+            }
+        }
+
+        public void RemoveAllPointerDownListeners()
+        {
+            if (onPointerDown != null)
+            {
+                onPointerDown.RemoveAllListeners();
+            }
+        }
+
+        public void RemoveAllPointerUpListeners()
+        {
+            if (onPointerUp != null)
+            {
+                onPointerUp.RemoveAllListeners();
+            }
+        }
+
+        public void RemoveAllPointerClickListeners()
+        {
+            if (onPointerClick != null)
+            {
+                onPointerClick.RemoveAllListeners();
+            }
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Core/PointerDownUp.cs.meta b/Main/Component/UI/Core/PointerDownUp.cs.meta
new file mode 100644
index 0000000..e75e1ba
--- /dev/null
+++ b/Main/Component/UI/Core/PointerDownUp.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6174ddaaab0a61d42b1cc8a3c7127944
+timeCreated: 1501492587
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/RepeatedButton.cs b/Main/Component/UI/Core/RepeatedButton.cs
new file mode 100644
index 0000000..f5dfac7
--- /dev/null
+++ b/Main/Component/UI/Core/RepeatedButton.cs
@@ -0,0 +1,112 @@
+锘�//--------------------------------------------------------
+//    [Author]:                   Wu Xijin
+//    [Date]   :           Monday, October 10, 2016
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using System;
+
+public class RepeatedButton:MonoBehaviour, IPointerDownHandler, IPointerUpHandler {
+
+    #region Fields
+
+    bool m_IsMouseDown = false;
+    public bool isMouseDown {
+        get {
+            return m_IsMouseDown;
+        }
+        private set {
+            m_IsMouseDown = value;
+        }
+    }
+
+    float nextTriggerTime = 0f;
+
+    [SerializeField]
+    float m_IntervalTime = 0.1f;
+    public float intervalTime {
+        get {
+            return m_IntervalTime;
+        }
+        set {
+            m_IntervalTime = Mathf.Clamp(value,0f,float.MaxValue);
+        }
+    }
+
+    [SerializeField]
+    UnityEvent m_OnClick = new UnityEvent();
+    public UnityEvent onClick {
+        get {
+            return m_OnClick;
+        }
+    }
+
+    #endregion
+
+    public RepeatedButton AddListener(UnityAction _action) {
+        onClick.AddListener(_action);
+        return this;
+    }
+
+    public RepeatedButton RemoveListener(UnityAction _action) {
+        onClick.RemoveListener(_action);
+        return this;
+    }
+
+    public RepeatedButton RemoveAllListener() {
+        onClick.RemoveAllListeners();
+        return this;
+    }
+
+    #region Built-In
+    void Awake() {
+
+    }
+
+    void Start() {
+
+    }
+
+    private void OnEnable() {
+        isMouseDown = false;
+    }
+
+    private void OnDisable() {
+        isMouseDown = false;
+    }
+
+    void LateUpdate() {
+        if(isMouseDown) {
+            if(Time.time > nextTriggerTime) {
+                nextTriggerTime += intervalTime;
+                if(onClick != null) {
+                    onClick.Invoke();
+                }
+            }
+        }
+    }
+
+    public void OnPointerDown(PointerEventData eventData) {
+        if(eventData.button != PointerEventData.InputButton.Left) {
+            return;
+        }
+
+        isMouseDown = true;
+        nextTriggerTime = Time.time;
+    }
+
+    public void OnPointerUp(PointerEventData eventData) {
+        if(eventData.button != PointerEventData.InputButton.Left) {
+            return;
+        }
+
+        isMouseDown = false;
+    }
+    #endregion
+
+}
+
+
+
diff --git a/Main/Component/UI/Core/RepeatedButton.cs.meta b/Main/Component/UI/Core/RepeatedButton.cs.meta
new file mode 100644
index 0000000..04df422
--- /dev/null
+++ b/Main/Component/UI/Core/RepeatedButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 981d79d2e4cb87045b3ad9f3c91d48b4
+timeCreated: 1476068571
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/TextEx.cs b/Main/Component/UI/Core/TextEx.cs
new file mode 100644
index 0000000..e1adbec
--- /dev/null
+++ b/Main/Component/UI/Core/TextEx.cs
@@ -0,0 +1,102 @@
+锘縰sing UnityEngine.UI;
+using System.Text;
+using UnityEngine;
+
+public class TextEx : Text
+{
+    [SerializeField]
+    bool m_IsKey = false;
+    public bool isKey
+    {
+        get
+        {
+            return m_IsKey;
+        }
+        set
+        {
+            m_IsKey = value;
+        }
+    }
+
+    [SerializeField]
+    private string m_KeyName;
+    public string keyName
+    {
+        get { return m_KeyName; }
+        set { m_KeyName = value; }
+    }
+
+    [SerializeField]
+    TextColType m_ColorType = TextColType.None;
+    public TextColType colorType
+    {
+        get { return m_ColorType; }
+        set
+        {
+            if (m_ColorType != value)
+            {
+                m_ColorType = value;
+                if (m_ColorType == TextColType.None)
+                    return;
+                this.color = UIHelper.GetUIColor(value, bgColorType == BackGroundColorType.Bright);
+            }
+        }
+    }
+
+    [SerializeField]
+    private BackGroundColorType m_BGColorType = BackGroundColorType.Dark;
+    public BackGroundColorType bgColorType
+    {
+        get { return m_BGColorType; }
+        set { 
+            m_BGColorType = value;
+            if (m_ColorType == TextColType.None)
+                return;
+            this.color = UIHelper.GetUIColor(colorType, m_BGColorType == BackGroundColorType.Bright);
+        }
+    }
+
+    public enum BackGroundColorType
+    {
+        Dark,
+        Bright,
+    }
+
+
+    protected override void Awake()
+    {
+        if (Application.isPlaying)
+        {
+            //璁剧疆榛樿鐨勫瓧浣�
+            if (isKey)
+            {
+                if (!string.IsNullOrEmpty(keyName))
+                {
+                    this.text = UIHelper.ReplaceNewLine(Language.Get(keyName));
+                }
+                else
+                {
+                    Debug.LogError("绋嬪簭璇锋鏌ヨ繎鏈熺殑鐣岄潰鏂囨湰鏄惁姝g‘璁剧疆璇█琛� TextEx keyName is null: " + this.name);
+                }
+            }
+
+            Language.languageChangeEvent += OnLanguageSwitch;
+        }
+
+        if (colorType != TextColType.None)
+        {
+            this.color = UIHelper.GetUIColor(colorType, bgColorType == BackGroundColorType.Bright);
+        }
+    }
+
+    protected override void OnDestroy()
+    {
+        Language.languageChangeEvent -= OnLanguageSwitch;
+    }
+
+    private void OnLanguageSwitch()
+    {
+        //閲嶆柊鍔犺浇瀛椾綋
+    }
+
+}
diff --git a/Main/Component/UI/Core/TextEx.cs.meta b/Main/Component/UI/Core/TextEx.cs.meta
new file mode 100644
index 0000000..51feeeb
--- /dev/null
+++ b/Main/Component/UI/Core/TextEx.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8c90b724ae1ce3c4495afe6ba6005ae0
+timeCreated: 1497863917
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/TextImage.cs b/Main/Component/UI/Core/TextImage.cs
new file mode 100644
index 0000000..3ec8ae7
--- /dev/null
+++ b/Main/Component/UI/Core/TextImage.cs
@@ -0,0 +1,80 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.Sprites;
+
+public class TextImage : TextEx
+{
+    [SerializeField] Sprite m_Sprite;
+
+    public Sprite sprite {
+        get { return m_Sprite; }
+        set {
+            m_Sprite = value;
+            SetVerticesDirty();
+        }
+    }
+
+    protected override void Awake()
+    {
+        base.Awake();
+        base.font = FontUtility.preferred;
+        base.material = MaterialUtility.hudMaterial;
+
+        if (sprite != null)
+        {
+            base.material.SetTexture("_Tex2", sprite.texture);
+        }
+    }
+
+    protected override void OnPopulateMesh(VertexHelper vh)
+    {
+        if (sprite != null)
+        {
+            vh.Clear();
+        }
+
+        base.OnPopulateMesh(vh);
+
+        if (sprite != null)
+        {
+            var size = new Vector2(rectTransform.rect.width, rectTransform.rect.height);
+            var positions = new Vector3[4];
+            var uvs = new Vector2[4];
+
+            var uv = sprite != null ? DataUtility.GetOuterUV(sprite) : Vector4.zero;
+            var width = rectTransform.rect.width;
+            var height = rectTransform.rect.height;
+
+            var uvCenterX = (uv.x + uv.z) * 0.5f;
+            var uvCenterY = (uv.y + uv.w) * 0.5f;
+            var uvScaleX = (uv.z - uv.x) / width;
+            var uvScaleY = (uv.w - uv.y) / height;
+
+            var position = positions[0] = new Vector2(-size.x * 0.5f, -size.y * 0.5f);
+            uvs[0] = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+
+            position = positions[1] = new Vector2(size.x * 0.5f, -size.y * 0.5f);
+            uvs[1] = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+
+            position = positions[2] = new Vector2(size.x * 0.5f, size.y * 0.5f);
+            uvs[2] = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+
+            position = positions[3] = new Vector2(-size.x * 0.5f, size.y * 0.5f);
+            uvs[3] = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+
+            for (var i = 0; i < 4; i++)
+            {
+                vh.AddVert(positions[i], color, uvs[i], uvs[i], new Vector3(1, 0, -1), new Vector4(1, 0, 0, -1));
+            }
+
+            vh.AddTriangle(0, 1, 2);
+            vh.AddTriangle(2, 3, 0);
+        }
+
+    }
+
+
+
+}
diff --git a/Main/Component/UI/Core/TextImage.cs.meta b/Main/Component/UI/Core/TextImage.cs.meta
new file mode 100644
index 0000000..ccf528b
--- /dev/null
+++ b/Main/Component/UI/Core/TextImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 008f723e1ff5d4a4d80a044caaf86dfc
+timeCreated: 1524205400
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ToggleButton.cs b/Main/Component/UI/Core/ToggleButton.cs
new file mode 100644
index 0000000..830bc5c
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleButton.cs
@@ -0,0 +1,129 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+using UnityEngine.Events;
+
+public class ToggleButton : MonoBehaviour
+{
+    [SerializeField]
+    Button m_Button;
+    public Button button { get { return m_Button; } }
+
+    [SerializeField]
+    bool m_IsOn = false;
+    public bool isOn {
+        get { return m_IsOn; }
+        set {
+            if (m_IsOn != value)
+            {
+                m_IsOn = value;
+
+                selected.SetActive(m_IsOn);
+                if (group != null && m_IsOn)
+                {
+                    group.NotifyToggleOn(this);
+                }
+
+                if (onValueChange != null)
+                {
+                    onValueChange(m_IsOn);
+                }
+            }
+        }
+    }
+
+    [SerializeField]
+    Image m_Selected;
+    public Image selected { get { return m_Selected; } }
+
+    [SerializeField]
+    ToggleButtonGroup m_Group;
+    public ToggleButtonGroup group {
+        get { return m_Group; }
+        set {
+            if (m_Group != null)
+            {
+                m_Group.UnRegister(this);
+            }
+            m_Group = value;
+            if (m_Group != null)
+            {
+                m_Group.Register(this);
+            }
+        }
+    }
+
+    UnityAction<bool> onValueChange;
+
+    private void OnEnable()
+    {
+        selected.SetActive(m_IsOn);
+        if (group != null)
+        {
+            group.Register(this);
+            if (m_IsOn)
+            {
+                group.NotifyToggleOn(this);
+            }
+        }
+    }
+
+    private void OnDisable()
+    {
+        if (group != null)
+        {
+            group.UnRegister(this);
+        }
+    }
+
+    public void SetListener(UnityAction action )
+    {
+        if (button != null)
+        {
+            button.SetListener(action);
+        }
+    }
+
+    public void AddListener(UnityAction _action)
+    {
+        if (button != null)
+        {
+            button.AddListener(_action);
+        }
+    }
+
+    public void RemoveListener()
+    {
+        if (button != null)
+        {
+            button.RemoveAllListeners();
+        }
+    }
+
+    public void OnValueChange(UnityAction<bool> _action)
+    {
+        onValueChange = _action;
+    }
+
+    public void RemoveOnValueChange()
+    {
+        onValueChange = null;
+    }
+
+    private void OnValidate()
+    {
+#if UNITY_EDITOR
+        if (selected != null)
+        {
+            selected.SetActive(isOn);
+        }
+
+        if (group != null)
+        {
+            group.NotifyToggleOn(this);
+        }
+#endif
+    }
+}
diff --git a/Main/Component/UI/Core/ToggleButton.cs.meta b/Main/Component/UI/Core/ToggleButton.cs.meta
new file mode 100644
index 0000000..2a7446b
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleButton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 36af0a90f01359349bcf5fa66f27d472
+timeCreated: 1498297788
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ToggleButtonGroup.cs b/Main/Component/UI/Core/ToggleButtonGroup.cs
new file mode 100644
index 0000000..a79df36
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleButtonGroup.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, October 10, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+public class ToggleButtonGroup : MonoBehaviour
+{
+
+    List<ToggleButton> toggleButtons = new List<ToggleButton>();
+
+    public void Register(ToggleButton _toggleButton)
+    {
+        if (!toggleButtons.Contains(_toggleButton))
+        {
+            toggleButtons.Add(_toggleButton);
+        }
+    }
+
+    public void UnRegister(ToggleButton _toggleButton)
+    {
+        if (toggleButtons.Contains(_toggleButton))
+        {
+            toggleButtons.Remove(_toggleButton);
+        }
+    }
+
+    public void NotifyToggleOn(ToggleButton _toggleButton)
+    {
+        if (_toggleButton.isOn)
+        {
+            for (int i = 0; i < toggleButtons.Count; i++)
+            {
+                var toggleButton = toggleButtons[i];
+                if (toggleButton != _toggleButton)
+                {
+                    toggleButton.isOn = false;
+                }
+            }
+        }
+    }
+
+}
+
+
+
+
diff --git a/Main/Component/UI/Core/ToggleButtonGroup.cs.meta b/Main/Component/UI/Core/ToggleButtonGroup.cs.meta
new file mode 100644
index 0000000..4f86949
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleButtonGroup.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0be97ef3523d6fc4e97d0095122152f0
+timeCreated: 1507607507
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Core/ToggleEx.cs b/Main/Component/UI/Core/ToggleEx.cs
new file mode 100644
index 0000000..824d223
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleEx.cs
@@ -0,0 +1,27 @@
+锘縰sing UnityEngine.UI;
+using System;
+using UnityEngine;
+using UnityEngine.EventSystems;
+
+public class ToggleEx : Toggle
+{
+    [SerializeField]
+    int m_Audio;
+    public int clickAudio {
+        get { return this.m_Audio; }
+        set { this.m_Audio = value; }
+    }
+
+    protected override void OnEnable()
+    {
+        base.OnEnable();
+    }
+
+    public override void OnPointerClick(PointerEventData eventData)
+    {
+        base.OnPointerClick(eventData);
+
+        SoundPlayer.Instance.PlayUIAudio(clickAudio);
+    }
+
+}
diff --git a/Main/Component/UI/Core/ToggleEx.cs.meta b/Main/Component/UI/Core/ToggleEx.cs.meta
new file mode 100644
index 0000000..3cd31e6
--- /dev/null
+++ b/Main/Component/UI/Core/ToggleEx.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f5822cd0af64b954b9842d404a6da6f6
+timeCreated: 1497863968
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate.meta b/Main/Component/UI/Decorate.meta
new file mode 100644
index 0000000..9308e4f
--- /dev/null
+++ b/Main/Component/UI/Decorate.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 1679d4360959b614d8087543adb7df55
+folderAsset: yes
+timeCreated: 1500621794
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect.meta b/Main/Component/UI/Decorate/Effect.meta
new file mode 100644
index 0000000..cc8d09d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: bd73d5aa1020a8b4982ff2beb104a2aa
+folderAsset: yes
+timeCreated: 1503373236
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs b/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs
new file mode 100644
index 0000000..2e33f1d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs
@@ -0,0 +1,79 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+[AddComponentMenu("UI/Effects/HorizontalColorGradual")]
+public class HorizontalColorGradual:BaseMeshEffect {
+
+    [SerializeField]
+    private Color32 m_LeftColor = Color.white;
+    public Color32 leftColor {
+        get {
+            return m_LeftColor;
+        }
+        set {
+            m_LeftColor = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    [SerializeField]
+    private Color32 m_RightColor = Color.black;
+    public Color32 rightColor {
+        get {
+            return m_RightColor;
+        }
+        set {
+            m_RightColor = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    [Range(-1,1)]
+    [SerializeField]
+    private float m_Center = 0f;
+    public float center {
+        get {
+            return m_Center;
+        }
+        set {
+            m_Center = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    public override void ModifyMesh(VertexHelper vh) {
+        var vertexList = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexList);
+
+        int count = vertexList.Count;
+        if(count > 0) {
+            var rightX = vertexList[0].position.y;
+            var leftX = vertexList[0].position.y;
+
+            for(int i = 1;i < count;i++) {
+                var x = vertexList[i].position[0];
+                if(x < leftX) {
+                    leftX = x;
+                }
+                else if(x > rightX) {
+                    rightX = x;
+                }
+            }
+
+            var width = rightX - leftX;
+            for(int i = 0;i < count;i++) {
+                var vertex = vertexList[i];
+                vertex.color = Color32.Lerp(leftColor,rightColor,Mathf.Clamp01((vertex.position[0] - (leftX + width * center)) / width));
+                vertexList[i] = vertex;
+            }
+        }
+
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(vertexList);
+    }
+
+
+
+}
diff --git a/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs.meta b/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs.meta
new file mode 100644
index 0000000..0c66fe9
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/HorizontalColorGradual.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5245ff2847254fd489bdb3ecd7c8ccb1
+timeCreated: 1499245503
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect/Reflection.cs b/Main/Component/UI/Decorate/Effect/Reflection.cs
new file mode 100644
index 0000000..514f8a1
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/Reflection.cs
@@ -0,0 +1,83 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+using System.Collections.Generic;
+
+[DisallowMultipleComponent]
+[AddComponentMenu("UI/Effects/Reflection")]
+public class Reflection:BaseMeshEffect {
+
+    [Range(0,30)]
+    [SerializeField]
+    float m_Distance;
+    public float distance {
+        get {
+            return m_Distance;
+        }
+    }
+
+    [Range(0,1)]
+    [SerializeField]
+    float m_HeightScale = 1f;
+    public float heightScale {
+        get {
+            return m_HeightScale;
+        }
+    }
+
+    [Range(0,1)]
+    [SerializeField]
+    float m_Virtualness;
+    public float virtualness {
+        get {
+            return m_Virtualness;
+        }
+    }
+
+    [SerializeField]
+    float m_OffsetX = 0;
+    public float offsetX {
+        get {
+            return m_OffsetX;
+        }
+    }
+
+
+    public override void ModifyMesh(VertexHelper vh) {
+        if(!IsActive() || vh.currentVertCount == 0) {
+            return;
+        }
+
+        var vertexs = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexs);
+
+        var count = vertexs.Count;
+        var edge = UIUtility.GetEdge(vertexs,1);
+        var height = (edge[1] - edge[0]) * heightScale;
+        if(height == 0) {
+            return;
+        }
+
+        var mirrorMinY = (edge[0] - edge[1]) * heightScale + edge[0] - distance;
+        var color = this.graphic.color;
+        var top = color.SetA(1 - virtualness);
+        var bottom = color.SetA(0);
+
+        for(var i = 0;i < count;i++) {
+            var vertex = vertexs[i];
+            vertexs.Add(vertex);
+            var position = vertex.position;
+            position.y = edge[0] - distance + (edge[0] - position.y) * heightScale;
+            position.x += offsetX * (1 - Mathf.Abs((position.y - mirrorMinY) / height));
+            vertex.position = position;
+
+            var colort = Mathf.Abs((position.y - mirrorMinY) / height);
+            vertex.color = Color32.Lerp(bottom,top,colort);
+            vertexs[i + count] = vertex;
+        }
+
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(vertexs);
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Decorate/Effect/Reflection.cs.meta b/Main/Component/UI/Decorate/Effect/Reflection.cs.meta
new file mode 100644
index 0000000..3fd78c7
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/Reflection.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0c43d7b5ffa4553489f85d3de4767455
+timeCreated: 1498272473
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect/SpriteEffect.cs b/Main/Component/UI/Decorate/Effect/SpriteEffect.cs
new file mode 100644
index 0000000..d2724bd
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/SpriteEffect.cs
@@ -0,0 +1,69 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, August 22, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    [RequireComponent(typeof(Image))]
+    public class SpriteEffect:MonoBehaviour {
+
+        [SerializeField]
+        Effect m_Effect = Effect.None;
+
+        CanvasAddition m_CanvasAddition;
+        public CanvasAddition canvasAddition {
+            get {
+                return this.m_CanvasAddition ?? (this.m_CanvasAddition = this.GetComponentInParent<CanvasAddition>());
+            }
+        }
+
+        Image m_Image;
+        public Image image {
+            get {
+                return m_Image ?? (m_Image = this.AddMissingComponent<Image>());
+            }
+        }
+
+        Material m_TwinkleMaterial;
+        Material twinleMaterial {
+            get {
+                return m_TwinkleMaterial??(m_TwinkleMaterial=MaterialUtility.GetDefaultSpriteGrayMaterial());
+            }
+        }
+
+
+
+        private void OnEnable() {
+            if(this.image != null) {
+                switch(this.m_Effect) {
+                    case Effect.Gray:
+                        this.image.material = canvasAddition.spriteGrayMaterial;
+                        break;
+                    case Effect.Twinkle:
+                        this.image.material = this.canvasAddition.spriteGrayMaterial;
+                        break;
+                    case Effect.None:
+                        this.image.material = null;
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public enum Effect {
+            None,
+            Gray,
+            Twinkle,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Effect/SpriteEffect.cs.meta b/Main/Component/UI/Decorate/Effect/SpriteEffect.cs.meta
new file mode 100644
index 0000000..3de804e
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/SpriteEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b5b01b47727aaee4d9a97bc8bde04bf4
+timeCreated: 1503373224
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs b/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs
new file mode 100644
index 0000000..b2955fd
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs
@@ -0,0 +1,61 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Text))]
+public class TypeWriterEffect:MonoBehaviour {
+
+    [SerializeField]
+    [Range(0,1)]
+    float m_Speed;
+    public float speed { get { return m_Speed; } }
+
+    [SerializeField]
+    [Range(0.05f,5.0f)]
+    float m_Interval;
+    public float interval { get { return m_Interval; } }
+
+    float m_Progresss = 0f;
+    public float progress {
+        get { return m_Progresss; }
+        set {
+            m_Progresss = Mathf.Clamp01(value);
+            if(material != null) {
+                material.SetFloat("_FillAmount",m_Progresss);
+            }
+        }
+    }
+
+    Text m_Text;
+    public Text text { get { return m_Text ?? (m_Text = this.GetComponent<Text>()); } }
+
+    Material material { get { return text.material; } }
+
+    float timer = 0f;
+    void OnEnable() {
+        timer = 0f;
+        progress = 0f;
+    }
+
+    public void StartTypeWriter(float _progress) {
+        progress = _progress;
+        timer = 0f;
+    }
+
+    void LateUpdate() {
+        if(progress >= 1f) {
+            return;
+        }
+
+        timer += Time.deltaTime;
+        if(timer > interval) {
+            timer = 0;
+            progress += speed;
+        }
+    }
+
+
+
+}
diff --git a/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs.meta b/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs.meta
new file mode 100644
index 0000000..f67f13d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/TypeWriterEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: af5dc47eff1644d4fb64bac3d1d3d0e6
+timeCreated: 1500621802
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs b/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs
new file mode 100644
index 0000000..4cc4fa7
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs
@@ -0,0 +1,79 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+[AddComponentMenu("UI/Effects/VerticalColorGradual")]
+public class VerticalColorGradual:BaseMeshEffect {
+
+    [SerializeField]
+    private Color32 m_TopColor = Color.white;
+    public Color32 topColor {
+        get {
+            return m_TopColor;
+        }
+        set {
+            m_TopColor = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    [SerializeField]
+    private Color32 m_BottomColor = Color.black;
+    public Color32 bottomColor {
+        get {
+            return m_BottomColor;
+        }
+        set {
+            m_BottomColor = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    [Range(-1,1)]
+    [SerializeField]
+    private float m_Center = 0f;
+    public float center {
+        get {
+            return m_Center;
+        }
+        set {
+            m_Center = value;
+            this.graphic.SetVerticesDirty();
+        }
+    }
+
+    public override void ModifyMesh(VertexHelper vh) {
+        var vertexList = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexList);
+
+        int count = vertexList.Count;
+        if(count > 0) {
+            var bottomY = vertexList[0].position.y;
+            var topY = vertexList[0].position.y;
+
+            for(int i = 1;i < count;i++) {
+                var y = vertexList[i].position.y;
+                if(y > topY) {
+                    topY = y;
+                }
+                else if(y < bottomY) {
+                    bottomY = y;
+                }
+            }
+
+            var height = topY - bottomY;
+            for(int i = 0;i < count;i++) {
+                var uiVertex = vertexList[i];
+                uiVertex.color = Color32.Lerp(bottomColor,topColor,Mathf.Clamp01((uiVertex.position.y - (bottomY + height * center)) / height));
+                vertexList[i] = uiVertex;
+            }
+        }
+
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(vertexList);
+    }
+
+
+
+}
diff --git a/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs.meta b/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs.meta
new file mode 100644
index 0000000..c5691d3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Effect/VerticalColorGradual.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5d2983f853ad08d4ea6abca1d8dafe02
+timeCreated: 1499245503
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph.meta b/Main/Component/UI/Decorate/Graph.meta
new file mode 100644
index 0000000..ea4ba8f
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: b4973d4c57dbe3c4884e02d658e1697b
+folderAsset: yes
+timeCreated: 1500864630
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs b/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs
new file mode 100644
index 0000000..d8174f3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs
@@ -0,0 +1,128 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+[AddComponentMenu("UI/Custom/CircleHollow Image")]
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Image))]
+public class CircleHollowImage:BaseMeshEffect,ICanvasRaycastFilter {
+
+    [SerializeField]
+    Vector2 m_Center=Vector2.zero;
+    public Vector2 center {
+        get { return m_Center; }
+        set {
+            m_Center = value;
+            if(this.graphic != null) {
+                this.graphic.SetVerticesDirty();
+            }
+        }
+    }
+
+    [SerializeField]
+    Vector2 m_HollowArea=new Vector2(50,50);
+    public Vector2 hollowArea {
+        get { return m_HollowArea; }
+        set {
+            m_HollowArea = value;
+            if(this.graphic != null) {
+                this.graphic.SetVerticesDirty();
+            }
+        }
+    }
+
+    [Range(32,128)]
+    [SerializeField]
+    int m_Segements = 32;
+    public int segements { get { return m_Segements; } }
+
+    private Image m_Image;
+    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } }
+
+    private List<Vector3> innerVertices;
+    private List<Vector3> outterVertices;
+
+    protected override void Awake() {
+        innerVertices = new List<Vector3>();
+        outterVertices = new List<Vector3>();
+    }
+
+    public override void ModifyMesh(VertexHelper vh) {
+        vh.Clear();
+        innerVertices.Clear();
+        outterVertices.Clear();
+
+        var degreeDelta = (float)(2 * Mathf.PI / segements);
+        var realSegements = segements;
+
+        var width = image.rectTransform.rect.width;
+        var height = image.rectTransform.rect.height;
+        var outerArea = new Vector2(0.5f * width,0.5f * height);
+
+        var realCenter = new Vector2(Mathf.Clamp(center.x,-width * 0.5f + hollowArea.x,width * 0.5f - hollowArea.x),
+            Mathf.Clamp(center.y,-height * 0.5f + hollowArea.y,height * 0.5f - hollowArea.y));
+
+        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero;
+
+        var uvCenterX = (uv.x + uv.z) * 0.5f;
+        var uvCenterY = (uv.y + uv.w) * 0.5f;
+        var uvScaleX = (uv.z - uv.x) / width;
+        var uvScaleY = (uv.w - uv.y) / height;
+
+        UIVertex uiVertex;
+        var degree = Mathf.PI * 0.5f;
+        var position = Vector2.zero;
+        var uv0 = Vector2.zero;
+
+        var verticeCount = 0;
+        var triangleCount = 0;
+
+        verticeCount = realSegements * 2;
+        for(int i = 0;i < verticeCount;i += 2) {
+            var cosA = Mathf.Cos(degree);
+            var sinA = Mathf.Sin(degree);
+            degree = degree - degreeDelta;
+
+            position = new Vector3(realCenter.x + cosA * hollowArea.x,realCenter.y + sinA * hollowArea.y);
+            uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            uiVertex = UIUtility.PackageUIVertex(position,uv0,image.color);
+            vh.AddVert(uiVertex);
+            innerVertices.Add(position);
+
+            position = new Vector3(Mathf.Sign(cosA * 2f) * outerArea.x,Mathf.Sign(sinA * 2f) * outerArea.y);
+            uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            uiVertex = UIUtility.PackageUIVertex(position,uv0,image.color);
+            vh.AddVert(uiVertex);
+            outterVertices.Add(position);
+        }
+
+        triangleCount = realSegements * 3 * 2;
+        for(int i = 0,vIdx = 0;i < triangleCount - 6;i += 6,vIdx += 2) {
+            vh.AddTriangle(vIdx + 1,vIdx,vIdx + 3);
+            vh.AddTriangle(vIdx,vIdx + 2,vIdx + 3);
+        }
+        vh.AddTriangle(verticeCount - 1,verticeCount - 2,1);
+        vh.AddTriangle(verticeCount - 2,0,1);
+
+    }
+
+    public virtual bool IsRaycastLocationValid(Vector2 screenPoint,Camera eventCamera) {
+        var sprite = image.overrideSprite;
+        if(sprite == null) {
+            return true;
+        }
+
+        Vector2 local;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform,screenPoint,eventCamera,out local);
+        return Contains(local,outterVertices,innerVertices);
+    }
+
+    private bool Contains(Vector2 p,List<Vector3> outterVertices,List<Vector3> innerVertices) {
+        var crossNumber = 0;
+        crossNumber += UIUtility.RayCrossingCount(p,innerVertices);
+        crossNumber += UIUtility.RayCrossingCount(p,outterVertices);
+        return (crossNumber & 1) == 1;
+    }
+
+}
diff --git a/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs.meta b/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs.meta
new file mode 100644
index 0000000..61ef9a9
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CircleHollowImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9fd9b47065ead3340a6e9819c7dc459b
+timeCreated: 1498189099
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/CircleImage.cs b/Main/Component/UI/Decorate/Graph/CircleImage.cs
new file mode 100644
index 0000000..a469fd3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CircleImage.cs
@@ -0,0 +1,164 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+[AddComponentMenu("UI/Custom/Circle Image")]
+[RequireComponent(typeof(Image))]
+public class CircleImage : BaseMeshEffect, ICanvasRaycastFilter {
+
+    [Range(0, 1)]
+    [SerializeField]
+    float m_FillPercent = 1f;
+    public float fillPercent { get { return m_FillPercent; } }
+
+    [SerializeField]
+    private bool m_Reversed = false;
+    public bool reversed { get { return m_Reversed; } }
+
+    [SerializeField]
+    Align m_Align = Align.Top;
+    public Align align { get { return m_Align; } }
+
+    [SerializeField]
+    bool m_FullFill = true;
+    public bool fullFill { get { return m_FullFill; } }
+
+    [Range(0, 1)]
+    [SerializeField]
+    float m_Thickness = 0f;
+    public float thickness {
+        get { return m_Thickness; }
+        set { m_Thickness = value; }
+    }
+
+    [Range(4, 128)]
+    [SerializeField]
+    int m_Segements = 30;
+    public int segements { get { return m_Segements; } }
+
+    private Image m_Image;
+    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } }
+
+    private List<Vector3> innerVertices;
+    private List<Vector3> outterVertices;
+
+    protected override void Awake() {
+        innerVertices = new List<Vector3>();
+        outterVertices = new List<Vector3>();
+    }
+
+    public override void ModifyMesh(VertexHelper vh) {
+        vh.Clear();
+        innerVertices.Clear();
+        outterVertices.Clear();
+
+        var degreeDelta = (float)(2 * Mathf.PI / segements);
+        var realSegements = (int)(segements * fillPercent);
+
+        var width = image.rectTransform.rect.width;
+        var height = image.rectTransform.rect.height;
+        var outerArea = new Vector2(0.5f * width, 0.5f * height);
+        var innerArea = outerArea - thickness * outerArea;
+
+        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero;
+
+        var uvCenterX = (uv.x + uv.z) * 0.5f;
+        var uvCenterY = (uv.y + uv.w) * 0.5f;
+        var uvScaleX = (uv.z - uv.x) / width;
+        var uvScaleY = (uv.w - uv.y) / height;
+
+        UIVertex uiVertex;
+        var degree = Mathf.PI * 0.5f * (int)align;
+        var position = Vector2.zero;
+        var uv0 = Vector2.zero;
+
+        var verticeCount = 0;
+        var triangleCount = 0;
+
+        if (fullFill) {
+            verticeCount = realSegements + 1;
+            uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+            uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+            vh.AddVert(uiVertex);
+
+            for (int i = 1; i < verticeCount; i++) {
+                var cosA = Mathf.Cos(degree);
+                var sinA = Mathf.Sin(degree);
+                degree = reversed ? degree + degreeDelta : degree - degreeDelta;
+
+                position = new Vector2(cosA * outerArea.x, sinA * outerArea.y);
+                uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+                uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+                vh.AddVert(uiVertex);
+
+                outterVertices.Add(position);
+            }
+
+            triangleCount = realSegements * 3;
+            for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++) {
+                vh.AddTriangle(vIdx, 0, vIdx + 1);
+            }
+            if (fillPercent == 1) {
+                vh.AddTriangle(verticeCount - 1, 0, 1);
+            }
+        }
+        else {
+            verticeCount = realSegements * 2;
+            for (int i = 0; i < verticeCount; i += 2) {
+                var cosA = Mathf.Cos(degree);
+                var sinA = Mathf.Sin(degree);
+                degree = reversed ? degree + degreeDelta : degree - degreeDelta;
+
+                position = new Vector3(cosA * innerArea.x, sinA * innerArea.y);
+                uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+                uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+                vh.AddVert(uiVertex);
+                innerVertices.Add(position);
+
+                position = new Vector3(cosA * outerArea.x, sinA * outerArea.y);
+                uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+                uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+                vh.AddVert(uiVertex);
+                outterVertices.Add(position);
+            }
+
+            triangleCount = realSegements * 3 * 2;
+            for (int i = 0, vIdx = 0; i < triangleCount - 6; i += 6, vIdx += 2) {
+                vh.AddTriangle(vIdx + 1, vIdx, vIdx + 3);
+                vh.AddTriangle(vIdx, vIdx + 2, vIdx + 3);
+            }
+            if (fillPercent == 1) {
+                vh.AddTriangle(verticeCount - 1, verticeCount - 2, 1);
+                vh.AddTriangle(verticeCount - 2, 0, 1);
+            }
+        }
+
+    }
+
+    public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) {
+        var sprite = image.overrideSprite;
+        if (sprite == null) {
+            return true;
+        }
+
+        Vector2 local;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, screenPoint, eventCamera, out local);
+        return Contains(local, outterVertices, innerVertices);
+    }
+
+    private bool Contains(Vector2 p, List<Vector3> outterVertices, List<Vector3> innerVertices) {
+        var crossNumber = 0;
+        crossNumber += UIUtility.RayCrossingCount(p, innerVertices);
+        crossNumber += UIUtility.RayCrossingCount(p, outterVertices);
+        return (crossNumber & 1) == 1;
+    }
+
+    public enum Align {
+        Top = 1,
+        Left = 2,
+        Bottom = 3,
+        Right = 4,
+    }
+
+}
diff --git a/Main/Component/UI/Decorate/Graph/CircleImage.cs.meta b/Main/Component/UI/Decorate/Graph/CircleImage.cs.meta
new file mode 100644
index 0000000..29f725a
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CircleImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 86177bef100c94a4ba23b6c25aaa7fa4
+timeCreated: 1498189099
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/CustomImage.cs b/Main/Component/UI/Decorate/Graph/CustomImage.cs
new file mode 100644
index 0000000..48e835c
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CustomImage.cs
@@ -0,0 +1,81 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, August 10, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using UnityEngine.Sprites;
+using System;
+
+namespace vnxbqy.UI {
+
+    [DisallowMultipleComponent]
+    [RequireComponent(typeof(Image))]
+    public class CustomImage:BaseMeshEffect {
+
+        [SerializeField]
+        Vector2[] m_Points;
+        public Vector2[] points {
+            get {
+                return this.m_Points;
+            }
+            set {
+                this.m_Points = value;
+                SetVerticesDirty();
+            }
+        }
+
+        private Image m_Image;
+        public Image image {
+            get {
+                return this.m_Image ?? (this.m_Image = this.AddMissingComponent<Image>());
+            }
+        }
+
+        public void SetVerticesDirty() {
+            this.graphic.SetVerticesDirty();
+        }
+
+        public override void ModifyMesh(VertexHelper vh) {
+            vh.Clear();
+
+            if(this.image == null) {
+                throw new NullReferenceException();
+            }
+
+            if(this.points == null || this.points.Length < 3) {
+                return;
+            }
+
+            var width = this.image.rectTransform.rect.width;
+            var height = this.image.rectTransform.rect.height;
+
+            var uv = this.image.overrideSprite != null ? DataUtility.GetOuterUV(this.image.overrideSprite) : Vector4.zero;
+            var uvcenterX = (uv.x + uv.z) * 0.5f;
+            var uvcenterY = (uv.y + uv.w) * 0.5f;
+            var uvscaleX = (uv.z - uv.x) / width;
+            var uvscaleY = (uv.w - uv.y) / height;
+
+            for(var i = 0;i < this.points.Length;i++) {
+                var point = this.points[i];
+
+                var position = new Vector2(point.x,point.y);
+                var uv0 = new Vector2(position.x * uvscaleX + uvcenterX,position.y * uvscaleY + uvcenterY);
+                var vertex = UIUtility.PackageUIVertex(position,uv0,this.image.color);
+                vh.AddVert(vertex);
+            }
+
+            var vertexCount = this.points.Length;
+            var index = 0;
+            for(;index < vertexCount - 2;index++) {
+                vh.AddTriangle(index,index + 1,index + 2);
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/CustomImage.cs.meta b/Main/Component/UI/Decorate/Graph/CustomImage.cs.meta
new file mode 100644
index 0000000..5af009a
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/CustomImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e1461144b148f82429d7b88578392b48
+timeCreated: 1502349270
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/DivideImage.cs b/Main/Component/UI/Decorate/Graph/DivideImage.cs
new file mode 100644
index 0000000..ae2dcea
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/DivideImage.cs
@@ -0,0 +1,107 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+[RequireComponent(typeof(Image))]
+public class DivideImage : BaseMeshEffect, ICanvasRaycastFilter
+{
+    [SerializeField]
+    int m_Divide = 5;
+    public int Divide { get { return m_Divide; } }
+
+    [SerializeField]
+    int m_CurrentDivide = 1;
+    public int CurrenDivide { get { return m_CurrentDivide; } }
+
+    [Range(0, 1)]
+    [SerializeField]
+    float m_FillPercent = 1f;
+    public float fillPercent { get { return m_FillPercent; } }
+
+    [Range(4, 128)]
+    [SerializeField]
+    int m_Segements = 30;
+    public int segements { get { return m_Segements; } }
+
+    private Image m_Image;
+    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } }
+
+    private List<Vector3> outterVertices;
+
+    protected override void Awake()
+    {
+        outterVertices = new List<Vector3>();
+    }
+
+    public override void ModifyMesh(VertexHelper vh)
+    {
+        vh.Clear();
+        outterVertices.Clear();
+        var degreeDelta = (float)(2 * Mathf.PI / segements);
+        var realSegements = (int)(segements * fillPercent);
+        var width = image.rectTransform.rect.width;
+        var height = image.rectTransform.rect.height;
+        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero;
+        var uvCenterX = (uv.x + uv.z) * 0.5f;
+        var uvCenterY = (uv.y + uv.w) * 0.5f;
+        var uvScaleX = (uv.z - uv.x) / width;
+        var uvScaleY = (uv.w - uv.y) / height;
+        var outerArea = new Vector2(0.5f * width, 0.5f * height);
+        UIVertex uiVertex;
+        var position = Vector2.zero;
+        var uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+        uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+        vh.AddVert(uiVertex);
+        var everyRad = (float)(2 * Mathf.PI / Divide);
+        var currentRad = everyRad*CurrenDivide - Mathf.PI*0.1f;
+        var verticeCount = 0;
+        var triangleCount = 0;
+        verticeCount = realSegements + 1;
+        uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+        uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+        vh.AddVert(uiVertex);
+
+        for (int i = 1; i < verticeCount; i++)
+        {
+            var cosA = Mathf.Cos(currentRad);
+            var sinA = Mathf.Sin(currentRad);
+            currentRad = currentRad - degreeDelta;
+            position = new Vector2(cosA * outerArea.x, sinA * outerArea.y);
+            uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+            uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+            vh.AddVert(uiVertex);
+            outterVertices.Add(position);
+        }
+
+        triangleCount = realSegements * 3;
+        for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++)
+        {
+            vh.AddTriangle(vIdx, 0, vIdx + 1);
+        }
+        if (fillPercent == 1)
+        {
+            vh.AddTriangle(verticeCount - 1, 0, 1);
+        }
+    }
+
+    public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
+    {
+        var sprite = image.overrideSprite;
+        if (sprite == null)
+        {
+            return true;
+        }
+
+        Vector2 local;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, screenPoint, eventCamera, out local);
+        return Contains(local, outterVertices);
+    }
+
+    private bool Contains(Vector2 p, List<Vector3> outterVertices)
+    {
+        var crossNumber = 0;
+        crossNumber += UIUtility.RayCrossingCount(p, outterVertices);
+        return (crossNumber & 1) == 1;
+    }
+}
diff --git a/Main/Component/UI/Decorate/Graph/DivideImage.cs.meta b/Main/Component/UI/Decorate/Graph/DivideImage.cs.meta
new file mode 100644
index 0000000..08b5788
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/DivideImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c9a3ad38778aa9e42b4520232ebb3d73
+timeCreated: 1541142002
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/FlipImage.cs b/Main/Component/UI/Decorate/Graph/FlipImage.cs
new file mode 100644
index 0000000..af0a403
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/FlipImage.cs
@@ -0,0 +1,70 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Image))]
+public class FlipImage : BaseMeshEffect
+{
+    [SerializeField] bool m_FlipHorizontal = false;
+    [SerializeField] bool m_FlipVertical = false;
+
+    public bool flipHorizontal
+    {
+        get { return m_FlipHorizontal; }
+        set
+        {
+            m_FlipHorizontal = value;
+            graphic.SetVerticesDirty();
+        }
+    }
+
+    public bool flipVertical
+    {
+        get { return m_FlipVertical; }
+        set
+        {
+            m_FlipVertical = value;
+            graphic.SetVerticesDirty();
+        }
+    }
+
+    public override void ModifyMesh(VertexHelper vh)
+    {
+        if (!IsActive() || vh.currentVertCount == 0)
+        {
+            return;
+        }
+        var vertexs = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexs);
+        if (flipHorizontal || flipVertical)
+        {
+            Flip(vertexs);
+        }
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(vertexs);
+    }
+
+    void Flip(List<UIVertex> vertexs)
+    {
+        var rect = graphic.GetPixelAdjustedRect();
+        var count = vertexs.Count;
+        for (int i = 0; i < count; i++)
+        {
+            var vertex = vertexs[i];
+            var position = vertex.position;
+            if (flipHorizontal)
+            {
+                position.x = -position.x + rect.max.x + rect.min.x;
+            }
+            if (flipVertical)
+            {
+                position.y = -position.y + rect.max.y + rect.min.y;
+            }
+            vertex.position = position;
+            vertexs[i] = vertex;
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Decorate/Graph/FlipImage.cs.meta b/Main/Component/UI/Decorate/Graph/FlipImage.cs.meta
new file mode 100644
index 0000000..b6bf73b
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/FlipImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d01ab0c7706729e48ac25411506e3a18
+timeCreated: 1541129037
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/Hexagon.cs b/Main/Component/UI/Decorate/Graph/Hexagon.cs
new file mode 100644
index 0000000..4211b86
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/Hexagon.cs
@@ -0,0 +1,69 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, August 23, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    [RequireComponent(typeof(RectTransform))]
+    public class Hexagon:BaseMeshEffect {
+
+        const float SQUARE_ROOT_THREE = 1.732f;
+        Vector3[] positions = new Vector3[3];
+
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform {
+            get {
+                return m_RectTransform ?? (m_RectTransform = this.transform as RectTransform);
+            }
+        }
+
+        Image m_Image;
+        public Image image {
+            get {
+                return m_Image ?? (m_Image = this.GetComponent<Image>());
+            }
+        }
+
+        public override void ModifyMesh(VertexHelper vh) {
+            vh.Clear();
+
+            var uv = this.image != null ? DataUtility.GetOuterUV(this.image.overrideSprite) : Vector4.zero;
+
+            var uvCenterX = (uv.x + uv.z) * 0.5f;
+            var uvCenterY = (uv.y + uv.w) * 0.5f;
+            var uvScaleX = (uv.z - uv.x) / this.rectTransform.rect.width;
+            var uvScaleY = (uv.w - uv.y) / this.rectTransform.rect.height;
+
+            var xoffset = this.rectTransform.rect.width * 0.5f;
+            var yoffset = this.rectTransform.rect.height * 0.5f;
+
+            this.positions[0] = new Vector3(0,yoffset);
+            this.positions[1] = new Vector3(-xoffset,yoffset * (1f - SQUARE_ROOT_THREE));
+            this.positions[2] = new Vector3(xoffset,yoffset * (1f - SQUARE_ROOT_THREE));
+
+            for(var i = 0;i < 3;i++) {
+                var position = this.positions[i];
+                var uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+                var vertex = UIUtility.PackageUIVertex(position,uv0,this.image.color);
+                vh.AddVert(vertex);
+
+                position = this.positions[i] * -1f;
+                uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+                vertex = UIUtility.PackageUIVertex(position,uv0,this.image.color);
+                vh.AddVert(vertex);
+            }
+
+            vh.AddTriangle(0,2,4);
+            vh.AddTriangle(1,3,5);
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/Hexagon.cs.meta b/Main/Component/UI/Decorate/Graph/Hexagon.cs.meta
new file mode 100644
index 0000000..10b19a7
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/Hexagon.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a6a9049b9f3f2a845bfc9ff79040c162
+timeCreated: 1503454052
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs b/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs
new file mode 100644
index 0000000..73c63b3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs
@@ -0,0 +1,52 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HorizontalReversalImage : Image
+{
+
+    protected override void OnPopulateMesh(VertexHelper vh)
+    {
+        base.OnPopulateMesh(vh);
+
+        if (!IsActive() || vh.currentVertCount == 0)
+        {
+            return;
+        }
+
+        var vertexs = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexs);
+
+        var uv05 = vertexs[4].uv0;
+        var uv1 = vertexs[2].uv0;
+        var uv23 = vertexs[1].uv0;
+        var uv4 = vertexs[0].uv0;
+
+        var reveralVertexs = new List<UIVertex>();
+        reveralVertexs.Add(AmendUV0(vertexs[0], uv05));
+        reveralVertexs.Add(AmendUV0(vertexs[1], uv1));
+        reveralVertexs.Add(AmendUV0(vertexs[2], uv23));
+        reveralVertexs.Add(AmendUV0(vertexs[3], uv23));
+        reveralVertexs.Add(AmendUV0(vertexs[4], uv4));
+        reveralVertexs.Add(AmendUV0(vertexs[5], uv05));
+
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(reveralVertexs);
+    }
+
+    public UIVertex AmendUV0(UIVertex _vertex, Vector2 _uv0)
+    {
+        _vertex.uv0 = _uv0;
+        return _vertex;
+    }
+
+    public enum Align
+    {
+        Left,
+        Right,
+        Bottom,
+        Top,
+        Orthogon,
+    }
+}
diff --git a/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs.meta b/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs.meta
new file mode 100644
index 0000000..97cfbc2
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/HorizontalReversalImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 93439e000618ad24fa5ac9ff775fcab4
+timeCreated: 1515640524
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/MirrorImage.cs b/Main/Component/UI/Decorate/Graph/MirrorImage.cs
new file mode 100644
index 0000000..361bc46
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/MirrorImage.cs
@@ -0,0 +1,103 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+using System.Collections.Generic;
+
+[DisallowMultipleComponent]
+public class MirrorImage:BaseMeshEffect {
+
+    [SerializeField]
+    Align m_Align = Align.Right;
+    public Align align { get { return m_Align; } }
+
+    public override void ModifyMesh(VertexHelper vh) {
+        if(!IsActive() || vh.currentVertCount == 0) {
+            return;
+        }
+
+        var vertexs = new List<UIVertex>();
+        vh.GetUIVertexStream(vertexs);
+        var min = CalculateMin(vertexs);
+        var max = CalculateMax(vertexs);
+
+        if(align == Align.Orthogon) {
+            vertexs.AddRange(Copy(Align.Right,min,max,vertexs));
+            vertexs.AddRange(Copy(Align.Bottom,min,max,vertexs));
+        }
+        else {
+            vertexs.AddRange(Copy(align,min,max,vertexs));
+        }
+
+        vh.Clear();
+        vh.AddUIVertexTriangleStream(vertexs);
+    }
+
+    private List<UIVertex> Copy(Align _align,Vector2 _min,Vector2 _max,List<UIVertex> _originalVertexs) {
+        var copyVertexs = new List<UIVertex>();
+
+        var reversal = _align == Align.Top || _align == Align.Right;
+        var axis = _align == Align.Left || _align == Align.Right ? 0 : 1;
+        var count = _originalVertexs.Count;
+        for(int i = 0;i < count;i++) {
+            var vertex = _originalVertexs[i];
+            vertex = _originalVertexs[i];
+            var position = vertex.position;
+            if(reversal) {
+                position[axis] = _max[axis] - position[axis] + _max[axis];
+            }
+            else {
+                position[axis] = _min[axis] - position[axis] + _min[axis];
+            }
+
+            vertex.position = position;
+            copyVertexs.Add(vertex);
+        }
+
+        return copyVertexs;
+    }
+
+
+    Vector2 CalculateMin(List<UIVertex> _vertexs) {
+        var count = _vertexs.Count;
+        var min = _vertexs[0].position;
+
+        for(int i = 1;i < count;i++) {
+            var vertex = _vertexs[i];
+            if(vertex.position[0] < min[0]) {
+                min[0] = vertex.position[0];
+            }
+            else if(vertex.position[1] < min[1]) {
+                min[1] = vertex.position[1];
+            }
+        }
+
+        return min;
+    }
+
+    Vector2 CalculateMax(List<UIVertex> _vertexs) {
+        var count = _vertexs.Count;
+        var max = _vertexs[0].position;
+
+        for(int i = 1;i < count;i++) {
+            var vertex = _vertexs[i];
+            if(vertex.position[0] > max[0]) {
+                max[0] = vertex.position[0];
+            }
+            else if(vertex.position[1] > max[1]) {
+                max[1] = vertex.position[1];
+            }
+        }
+
+        return max;
+    }
+
+    public enum Align {
+        Left,
+        Right,
+        Bottom,
+        Top,
+        Orthogon,
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Decorate/Graph/MirrorImage.cs.meta b/Main/Component/UI/Decorate/Graph/MirrorImage.cs.meta
new file mode 100644
index 0000000..019c4f1
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/MirrorImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6c14a3c32cb51de49b41d8d3916874ba
+timeCreated: 1498269248
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/OffsetImage.cs b/Main/Component/UI/Decorate/Graph/OffsetImage.cs
new file mode 100644
index 0000000..623b32d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/OffsetImage.cs
@@ -0,0 +1,97 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, August 23, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI {
+
+    public class OffsetImage:BaseMeshEffect {
+
+        [SerializeField]
+        Vector2 m_Offset;
+        public Vector2 offset {
+            get {
+                return m_Offset;
+            }
+            set {
+                m_Offset = value;
+
+            }
+        }
+
+        public override void ModifyMesh(VertexHelper vh) {
+            List<UIVertex> vertexs = new List<UIVertex>();
+            vh.GetUIVertexStream(vertexs);
+
+            if(vertexs == null || vertexs.Count == 0) {
+                return;
+            }
+            vh.Clear();
+
+            var positions = new Vector3[3];
+            var uv0s = new Vector2[3];
+
+            var firstQuard = new UIVertex[6] {
+                vertexs[0],
+                vertexs[1],
+                vertexs[2],
+                vertexs[3],
+                vertexs[4],
+                vertexs[5]
+            };
+
+            for(var i = 0;i < firstQuard.Length;i++) {
+                var vertex = firstQuard[i];
+                var position = vertex.position + new Vector3(offset.x,offset.y,0);
+                vertex.position = position;
+                firstQuard[i] = vertex;
+
+                if((i % 3) == 2) {
+                    positions[0] = firstQuard[i - 2].position;
+                    uv0s[0] = firstQuard[i - 2].uv0;
+                    positions[1] = firstQuard[i - 1].position;
+                    uv0s[1] = firstQuard[i - 1].uv0;
+                    positions[2] = firstQuard[i].position;
+                    uv0s[2] = firstQuard[i].uv0;
+
+                    UIUtility.AddTriangle(vh,positions,Color.white,uv0s);
+                }
+            }
+
+
+
+            var index = 5 * 6;
+            for(int i = 0;i < vertexs.Count;i++) {
+
+                if(i > index) {
+
+                }
+
+                if((i % 3) == 2) {
+                    positions[0] = vertexs[i - 2].position;
+                    uv0s[0] = vertexs[i - 2].uv0;
+                    positions[1] = vertexs[i - 1].position;
+                    uv0s[1] = vertexs[i - 1].uv0;
+                    positions[2] = vertexs[i].position;
+                    uv0s[2] = vertexs[i].uv0;
+
+                    UIUtility.AddTriangle(vh,positions,Color.white,uv0s);
+                }
+            }
+
+
+
+
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/OffsetImage.cs.meta b/Main/Component/UI/Decorate/Graph/OffsetImage.cs.meta
new file mode 100644
index 0000000..f0aa0ff
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/OffsetImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 62595dedecb4d2843b2913a1a285644a
+timeCreated: 1503466779
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/OffsetImage2.cs b/Main/Component/UI/Decorate/Graph/OffsetImage2.cs
new file mode 100644
index 0000000..2860c18
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/OffsetImage2.cs
@@ -0,0 +1,79 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, August 23, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI {
+
+    public class OffsetImage2:Text {
+
+        [SerializeField]
+        Vector2 m_Offset;
+        public Vector2 offset {
+            get {
+                return m_Offset;
+            }
+            set {
+                m_Offset = value;
+
+            }
+        }
+
+        protected override void OnPopulateMesh(VertexHelper toFill) {
+            base.OnPopulateMesh(toFill);
+            List<UIVertex> vertexs = new List<UIVertex>();
+            toFill.GetUIVertexStream(vertexs);
+
+            if(vertexs == null || vertexs.Count == 0) {
+                return;
+            }
+
+            toFill.Clear();
+            var newVertexs = new List<UIVertex>();
+            var index = 1 * 6 - 1;
+            for(int i = 0;i < vertexs.Count;i++) {
+
+                var vertex = vertexs[i];
+                if(i == index) {
+                    newVertexs.AddRange(AddHexgon(vertexs[i - 5].position,new Vector2(offset.x,font.fontSize),Color.white));
+                }
+                if(i > index) {
+                    var position = vertex.position + new Vector3(offset.x,offset.y,0);
+                    vertex.position = position;
+                }
+                newVertexs.Add(vertex);
+            }
+
+
+         var aaa=   this.cachedTextGenerator.verts;
+            toFill.AddUIVertexTriangleStream(newVertexs);
+            LayoutRebuilder.MarkLayoutForRebuild(this.rectTransform);
+        }
+
+        private UIVertex[] AddHexgon(Vector3 _startPosition,Vector2 _offset,Color _color) {
+
+            var hexgon = new UIVertex[4];
+            var positions = new Vector3[4];
+            positions[0] = _startPosition;
+            positions[1] = _startPosition + new Vector3(_offset.x,0,0);
+            positions[2] = _startPosition + new Vector3(_offset.x,-_offset.y,0);
+            positions[3] = _startPosition + new Vector3(0,-_offset.y,0);
+
+            for(int i = 0;i < 4;i++) {
+                hexgon[i] = UIUtility.PackageUIVertexUV1(positions[i],Vector2.zero,_color);
+            }
+
+            return hexgon;
+
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/OffsetImage2.cs.meta b/Main/Component/UI/Decorate/Graph/OffsetImage2.cs.meta
new file mode 100644
index 0000000..6485028
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/OffsetImage2.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 81deca47485d84642b99375cb9739ba7
+timeCreated: 1503476440
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/PolylineImage.cs b/Main/Component/UI/Decorate/Graph/PolylineImage.cs
new file mode 100644
index 0000000..8aaddb2
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/PolylineImage.cs
@@ -0,0 +1,71 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, August 10, 2017
+//--------------------------------------------------------
+
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    /// <summary>
+    /// 杩欎釜缁勪欢鎺ユ敹涓�浜涢《鐐癸紝缁樺埗鍑烘按骞冲拰鍨傜洿鐨勭嚎銆�
+    /// </summary>
+    public class PolylineImage:Graphic {
+
+        [SerializeField]
+        float m_Width;
+        public float width {
+            get {
+                return this.m_Width;
+            }
+            set {
+                this.m_Width = value;
+                base.SetVerticesDirty();
+            }
+        }
+
+        [SerializeField]
+        Vector2[] m_Points;
+        public Vector2[] points {
+            get {
+                return this.m_Points;
+            }
+            set {
+                this.m_Points = value;
+                base.SetVerticesDirty();
+            }
+        }
+
+        protected override void OnPopulateMesh(VertexHelper vh) {
+            vh.Clear();
+            if(this.points == null || this.points.Length < 2) {
+                return;
+            }
+
+            var hw = this.width * 0.5f;
+
+            for(var i = 0;i < this.points.Length - 1;i++) {
+                var point = this.points[i];
+                var nextPoint = this.points[i + 1];
+
+                var xReversal = point.x > nextPoint.x;
+                var yReversal = point.y > nextPoint.y;
+
+                var positions = new Vector3[4];
+                positions[0] = new Vector2(xReversal ? point.x + hw : point.x - hw,yReversal ? point.y + hw : point.y - hw);
+                positions[1] = new Vector2(xReversal ? nextPoint.x - hw : nextPoint.x + hw,yReversal ? point.y + hw : point.y - hw);
+                positions[2] = new Vector2(xReversal ? nextPoint.x - hw : nextPoint.x + hw,yReversal ? nextPoint.y - hw : nextPoint.y + hw);
+                positions[3] = new Vector2(xReversal ? point.x + hw : point.x - hw,yReversal ? nextPoint.y - hw : nextPoint.y + hw);
+
+                UIUtility.AddQuad(vh,positions,color,new Vector2[4] { Vector2.one,Vector2.one,Vector2.one,Vector2.one });
+            }
+
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/PolylineImage.cs.meta b/Main/Component/UI/Decorate/Graph/PolylineImage.cs.meta
new file mode 100644
index 0000000..ad19f9a
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/PolylineImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6ac489af12c96b440953af843ae42881
+timeCreated: 1502337050
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/RayAccepter.cs b/Main/Component/UI/Decorate/Graph/RayAccepter.cs
new file mode 100644
index 0000000..1ee7a1d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/RayAccepter.cs
@@ -0,0 +1,21 @@
+锘�//--------------------------------------------------------------
+//      [    Author   ]:                 Leonard.wu
+//      [ CopyRight ]:                  
+//--------------------------------------------------------------
+
+using UnityEngine;
+using UnityEngine.UI;
+using System.Collections.Generic;
+
+/// <summary>
+/// 绌虹櫧鐨勫浘褰㈢粍浠�,杩欎釜缁勪欢鍙互褰卞搷UI浜嬩欢,浣嗘槸涓嶄細鍙備笌缁樺埗
+/// 鍗冲畠涓嶄細褰卞搷DrawCall,涔熶笉浼氬鍔犻《鐐�
+/// </summary>
+[DisallowMultipleComponent]
+public class RayAccepter:MaskableGraphic {
+
+    protected override void OnPopulateMesh(VertexHelper vh) {
+        base.OnPopulateMesh(vh);
+        vh.Clear();
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Decorate/Graph/RayAccepter.cs.meta b/Main/Component/UI/Decorate/Graph/RayAccepter.cs.meta
new file mode 100644
index 0000000..bedb1cf
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/RayAccepter.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 289d1d8afe251bb41b641723d355c134
+timeCreated: 1498127664
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/Rhombus.cs b/Main/Component/UI/Decorate/Graph/Rhombus.cs
new file mode 100644
index 0000000..61f67c6
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/Rhombus.cs
@@ -0,0 +1,73 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Wednesday, August 23, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    [RequireComponent(typeof(RectTransform))]
+    public class Rhombus : BaseMeshEffect
+    {
+        const float SQUARE_ROOT_THREE = 1f;
+        Vector3[] positions = new Vector3[3];
+
+        RectTransform m_RectTransform;
+        public RectTransform rectTransform {
+            get {
+                return m_RectTransform ?? (m_RectTransform = this.transform as RectTransform);
+            }
+        }
+
+        Image m_Image;
+        public Image image {
+            get {
+                return m_Image ?? (m_Image = this.GetComponent<Image>());
+            }
+        }
+
+        public override void ModifyMesh(VertexHelper vh)
+        {
+            vh.Clear();
+
+            var uv = this.image != null ? DataUtility.GetOuterUV(this.image.overrideSprite) : Vector4.zero;
+
+            var uvCenterX = (uv.x + uv.z) * 0.5f;
+            var uvCenterY = (uv.y + uv.w) * 0.5f;
+            var uvScaleX = (uv.z - uv.x) / this.rectTransform.rect.width;
+            var uvScaleY = (uv.w - uv.y) / this.rectTransform.rect.height;
+
+            var xoffset = this.rectTransform.rect.width * 0.5f;
+            var yoffset = this.rectTransform.rect.height * 0.5f;
+
+            this.positions[0] = new Vector3(0, yoffset);
+            this.positions[1] = new Vector3(-xoffset, yoffset * (1f - SQUARE_ROOT_THREE));
+            this.positions[2] = new Vector3(xoffset, yoffset * (1f - SQUARE_ROOT_THREE));
+
+            for (var i = 0; i < 3; i++)
+            {
+                var position = this.positions[i];
+                var uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+                var vertex = UIUtility.PackageUIVertex(position, uv0, this.image.color);
+                vh.AddVert(vertex);
+
+                position = this.positions[i] * -1f;
+                uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+                vertex = UIUtility.PackageUIVertex(position, uv0, this.image.color);
+                vh.AddVert(vertex);
+            }
+
+            vh.AddTriangle(0, 2, 4);
+            vh.AddTriangle(1, 3, 5);
+        }
+
+    }
+
+}
+
+
+
+
diff --git a/Main/Component/UI/Decorate/Graph/Rhombus.cs.meta b/Main/Component/UI/Decorate/Graph/Rhombus.cs.meta
new file mode 100644
index 0000000..e4152a2
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/Rhombus.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4d59649450cace24bb3e7f39f466179f
+timeCreated: 1516328467
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs b/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs
new file mode 100644
index 0000000..05040f3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs
@@ -0,0 +1,122 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Sprites;
+using UnityEngine.UI;
+
+[DisallowMultipleComponent]
+[AddComponentMenu("UI/Custom/Circle Image")]
+[RequireComponent(typeof(Image))]
+public class RoundedRectangleImage:BaseMeshEffect,ICanvasRaycastFilter {
+
+    [SerializeField]
+    float m_Radius = 10f;
+    public float radius { get { return m_Radius; } }
+
+    [SerializeField]
+    [Range(16,128)]
+    int m_Segements = 16;
+    public int segements { get { return m_Segements; } }
+
+    [SerializeField]
+    Vector2 m_RealArea = Vector2.one * 100;
+    public Vector2 realArea { get { return m_RealArea; } }
+
+    private Image m_Image;
+    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } }
+
+    List<Vector3> vertexPosition = new List<Vector3>();
+    public override void ModifyMesh(VertexHelper vh) {
+        vh.Clear();
+        vertexPosition.Clear();
+
+        var tw = image.rectTransform.rect.width;
+        var th = image.rectTransform.rect.height;
+        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero;
+
+        var uvCenterX = (uv.x + uv.z) * 0.5f;
+        var uvCenterY = (uv.y + uv.w) * 0.5f;
+        var uvScaleX = (uv.z - uv.x) / tw;
+        var uvScaleY = (uv.w - uv.y) / th;
+
+        var interval = radius / (segements - 1);
+
+        var center = new Vector2(realArea.x * 0.5f - radius,realArea.y * 0.5f - radius);
+        for(int i = 0;i < segements;i++) {
+            var position = new Vector2();
+            var offsetX = interval * i;
+            position.x = center.x + offsetX;
+            position.y = center.y + Mathf.Sqrt(radius * radius - offsetX * offsetX);
+            vertexPosition.Add(position);
+            var vertex = new UIVertex();
+            vertex.position = position;
+            vertex.color = image.color;
+            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            vh.AddVert(vertex);
+        }
+
+        center = new Vector2(realArea.x * 0.5f - radius,-realArea.y * 0.5f + radius);
+        for(int i = 0;i < segements;i++) {
+            var position = new Vector2();
+            var offsetX = interval * i;
+            position.x = center.x + radius - offsetX;
+            position.y = center.y - Mathf.Sqrt(radius * radius - (radius - offsetX) * (radius - offsetX));
+            vertexPosition.Add(position);
+            var vertex = new UIVertex();
+            vertex.position = position;
+            vertex.color = image.color;
+            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            vh.AddVert(vertex);
+        }
+
+        center = new Vector2(-realArea.x * 0.5f + radius,-realArea.y * 0.5f + radius);
+        for(int i = 0;i < segements;i++) {
+            var position = new Vector2();
+            var offsetX = interval * i;
+            position.x = center.x - offsetX;
+            position.y = center.y - Mathf.Sqrt(radius * radius - offsetX * offsetX);
+            vertexPosition.Add(position);
+            var vertex = new UIVertex();
+            vertex.position = position;
+            vertex.color = image.color;
+            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            vh.AddVert(vertex);
+        }
+
+        center = new Vector2(-realArea.x * 0.5f + radius,realArea.y * 0.5f - radius);
+        for(int i = 0;i < segements;i++) {
+            var position = new Vector2();
+            var offsetX = interval * i;
+            position.x = center.x - radius + offsetX;
+            position.y = center.y + Mathf.Sqrt(radius * radius - (radius - offsetX) * (radius - offsetX));
+            vertexPosition.Add(position);
+            var vertex = new UIVertex();
+            vertex.position = position;
+            vertex.color = image.color;
+            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY);
+            vh.AddVert(vertex);
+        }
+
+        var triangleCount = segements * 12 - 3;
+        for(int i = 0,vIdx = 1;i < triangleCount - 3;i += 3,vIdx++) {
+            vh.AddTriangle(vIdx,0,vIdx + 1);
+        }
+    }
+
+    public virtual bool IsRaycastLocationValid(Vector2 screenPoint,Camera eventCamera) {
+        var sprite = image.overrideSprite;
+        if(sprite == null) {
+            return true;
+        }
+
+        Vector2 local;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform,screenPoint,eventCamera,out local);
+        return Contains(local,vertexPosition);
+    }
+
+    private bool Contains(Vector2 _p,List<Vector3> _vertexPositions) {
+        var crossNumber = 0;
+        crossNumber += UIUtility.RayCrossingCount(_p,_vertexPositions);
+        return (crossNumber & 1) == 1;
+    }
+
+}
diff --git a/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs.meta b/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs.meta
new file mode 100644
index 0000000..40aaa33
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/RoundedRectangleImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 88a0b5bc64155d94f988c049c64a6101
+timeCreated: 1498189099
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/SectionImage.cs b/Main/Component/UI/Decorate/Graph/SectionImage.cs
new file mode 100644
index 0000000..8994e3e
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/SectionImage.cs
@@ -0,0 +1,51 @@
+锘縰sing UnityEngine;
+using UnityEngine.UI;
+
+[DisallowMultipleComponent]
+[RequireComponent(typeof(RectTransform))]
+public class SectionImage:Graphic {
+
+    [SerializeField]
+    [Range(2,100)]
+    int m_Section = 3;
+    public int section {
+        get {
+            return m_Section;
+        }
+    }
+
+    [SerializeField]
+    [Range(1,200)]
+    float m_Width = 2f;
+    public float width {
+        get {
+            return m_Width;
+        }
+    }
+
+    Vector2[] uv0s= new Vector2[4] { Vector2.one,Vector2.one,Vector2.one,Vector2.one };
+
+    protected override void OnPopulateMesh(VertexHelper vh) {
+        vh.Clear();
+
+        var size = new Vector2(rectTransform.rect.width,rectTransform.rect.height);
+
+        var squareCount = section - 1;
+        var deltaX = (size.x - (section - 1) * width) / section + width;
+        var startX = -size.x * 0.5f + deltaX - width;
+
+        for(var i = 0;i < squareCount;i++) {
+
+            var positions = new Vector3[4];
+
+            positions[0] = new Vector2(startX,-size.y * 0.5f);
+            positions[1] = new Vector2(startX + width,-size.y * 0.5f);
+            positions[2] = new Vector2(startX + width,size.y * 0.5f);
+            positions[3] = new Vector2(startX,size.y * 0.5f);
+
+            UIUtility.AddQuad(vh,positions,color,uv0s);
+            startX += deltaX;
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Decorate/Graph/SectionImage.cs.meta b/Main/Component/UI/Decorate/Graph/SectionImage.cs.meta
new file mode 100644
index 0000000..c9cc4a6
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/SectionImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b9778a2f8ec1c114eafb2e9878889f4f
+timeCreated: 1500551194
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs b/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs
new file mode 100644
index 0000000..24d51a1
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs
@@ -0,0 +1,136 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.Sprites;
+
+[AddComponentMenu("UI/Custom/SquareHollow Image")]
+[DisallowMultipleComponent]
+[RequireComponent(typeof(Image))]
+public class SquareHollowImage : BaseMeshEffect, ICanvasRaycastFilter
+{
+    [SerializeField]
+    Vector2 m_Center;
+    public Vector2 center {
+        get { return m_Center; }
+        set {
+            m_Center = value;
+            base.graphic.SetVerticesDirty();
+        }
+    }
+
+    [SerializeField]
+    Vector2 m_Cell;
+    public Vector2 cell {
+        get {
+            return m_Cell;
+        }
+        set {
+            m_Cell = value;
+            base.graphic.SetVerticesDirty();
+        }
+    }
+
+    public RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+    private List<Vector3> innerVertices = new List<Vector3>();
+    private List<Vector3> outterVertices = new List<Vector3>();
+
+    private Image m_Image;
+    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } }
+
+    public override void ModifyMesh(VertexHelper vh)
+    {
+        vh.Clear();
+        innerVertices.Clear();
+        outterVertices.Clear();
+
+        var width = image.rectTransform.rect.width;
+        var height = image.rectTransform.rect.height;
+        var outerArea = new Vector2(0.5f * width, 0.5f * height);
+
+        var leftBottom = new Vector2(outerArea.x * -1f, outerArea.y * -1f);
+        var innerArea = new Vector2(Mathf.Clamp(cell.x, 0, width), Mathf.Clamp(cell.y, 0, height));
+        var innerCenter = new Vector2(Mathf.Clamp(center.x, (innerArea.x - width) * 0.5f, (width - innerArea.x) * 0.5f), Mathf.Clamp(center.y, (innerArea.y - height) * 0.5f, (height - innerArea.y) * 0.5f));
+
+        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero;
+
+        var uvCenterX = (uv.x + uv.z) * 0.5f;
+        var uvCenterY = (uv.y + uv.w) * 0.5f;
+        var uvScaleX = (uv.z - uv.x) / width;
+        var uvScaleY = (uv.w - uv.y) / height;
+
+        var positions = new List<Vector3>();
+        var position = Vector3.zero;
+        position = new Vector3(innerCenter.x + innerArea.x * -0.5f, innerCenter.y + innerArea.y * -0.5f);
+        positions.Add(position);
+        innerVertices.Add(position);
+
+        position = new Vector3(outerArea.x * -1f, outerArea.y * -1f);
+        positions.Add(position);
+        outterVertices.Add(position);
+
+        position = new Vector3(innerCenter.x + innerArea.x * 0.5f, innerCenter.y + innerArea.y * -0.5f);
+        positions.Add(position);
+        innerVertices.Add(position);
+
+        position = new Vector3(outerArea.x * 1f, outerArea.y * -1f);
+        positions.Add(position);
+        outterVertices.Add(position);
+
+        position = new Vector3(innerCenter.x + innerArea.x * 0.5f, innerCenter.y + innerArea.y * 0.5f);
+        positions.Add(position);
+        innerVertices.Add(position);
+
+        position = new Vector3(outerArea.x * 1f, outerArea.y * 1f);
+        positions.Add(position);
+        outterVertices.Add(position);
+
+        position = new Vector3(innerCenter.x + innerArea.x * -0.5f, innerCenter.y + innerArea.y * 0.5f);
+        positions.Add(position);
+        innerVertices.Add(position);
+
+        position = new Vector3(outerArea.x * -1f, outerArea.y * 1f);
+        positions.Add(position);
+        outterVertices.Add(position);
+
+        for (int i = 0; i < positions.Count; i++)
+        {
+            position = positions[i];
+            var uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY);
+            var uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color);
+            vh.AddVert(uiVertex);
+        }
+
+        var triangleCount = 8 * 3;
+        for (int i = 0, vIdx = 0; i < triangleCount - 6; i += 6, vIdx += 2)
+        {
+            vh.AddTriangle(vIdx + 1, vIdx, vIdx + 3);
+            vh.AddTriangle(vIdx, vIdx + 2, vIdx + 3);
+        }
+        vh.AddTriangle(8 - 1, 8 - 2, 1);
+        vh.AddTriangle(8 - 2, 0, 1);
+
+    }
+
+    public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
+    {
+        var sprite = image.overrideSprite;
+        if (sprite == null)
+        {
+            return true;
+        }
+
+        Vector2 local;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, screenPoint, eventCamera, out local);
+        return Contains(local, outterVertices, innerVertices);
+    }
+
+    private bool Contains(Vector2 p, List<Vector3> outterVertices, List<Vector3> innerVertices)
+    {
+        var crossNumber = 0;
+        crossNumber += UIUtility.RayCrossingCount(p, innerVertices);
+        crossNumber += UIUtility.RayCrossingCount(p, outterVertices);
+        return (crossNumber & 1) == 1;
+    }
+}
diff --git a/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs.meta b/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs.meta
new file mode 100644
index 0000000..6f6be30
--- /dev/null
+++ b/Main/Component/UI/Decorate/Graph/SquareHollowImage.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 22d2d80174c2e3c4fad3f44f0b6f4418
+timeCreated: 1499135699
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Move.meta b/Main/Component/UI/Decorate/Move.meta
new file mode 100644
index 0000000..92f173d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Move.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: fa95052e40dd80a41804f17de32be64d
+folderAsset: yes
+timeCreated: 1523241570
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Move/UILinerMove.cs b/Main/Component/UI/Decorate/Move/UILinerMove.cs
new file mode 100644
index 0000000..29cf4d3
--- /dev/null
+++ b/Main/Component/UI/Decorate/Move/UILinerMove.cs
@@ -0,0 +1,82 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, April 09, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(RectTransform))]
+    public class UILinerMove : MonoBehaviour
+    {
+        [SerializeField] float m_Duration;
+        public float duration {
+            get { return m_Duration; }
+            set { m_Duration = value; }
+        }
+
+        [SerializeField] Vector2 m_From;
+        public Vector2 from {
+            get { return m_From; }
+            set { m_From = value; }
+        }
+
+        [SerializeField] Vector2 m_To;
+        public Vector2 to {
+            get { return m_To; }
+            set { m_To = value; }
+        }
+
+        float timer = float.MaxValue;
+        RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+        public void Begin()
+        {
+            if (duration < 0f)
+            {
+                return;
+            }
+
+            if (!this.gameObject.activeInHierarchy)
+            {
+                Stop();
+            }
+            else
+            {
+                timer = 0f;
+                rectTransform.anchoredPosition = from;
+            }
+        }
+
+        public void Stop()
+        {
+            timer = float.MaxValue;
+            rectTransform.anchoredPosition = to;
+        }
+
+        private void OnDisable()
+        {
+            if (timer < duration)
+            {
+                Stop();
+            }
+        }
+
+        private void LateUpdate()
+        {
+            if (timer < duration)
+            {
+                timer += Time.deltaTime;
+                var t = Mathf.Clamp01(timer / duration);
+                rectTransform.anchoredPosition = Vector2.Lerp(from, to, t);
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Move/UILinerMove.cs.meta b/Main/Component/UI/Decorate/Move/UILinerMove.cs.meta
new file mode 100644
index 0000000..bae0ce7
--- /dev/null
+++ b/Main/Component/UI/Decorate/Move/UILinerMove.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6ef2edd2389d5f943aef376a8c967a63
+timeCreated: 1523241553
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Move/UISmoothMove.cs b/Main/Component/UI/Decorate/Move/UISmoothMove.cs
new file mode 100644
index 0000000..255b4ac
--- /dev/null
+++ b/Main/Component/UI/Decorate/Move/UISmoothMove.cs
@@ -0,0 +1,60 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, April 09, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class UISmoothMove : MonoBehaviour
+    {
+        [SerializeField] Vector2 m_To;
+        public Vector2 to {
+            get { return m_To; }
+            set { m_To = value; }
+        }
+
+        [SerializeField] float m_Smooth = 0.2f;
+
+        Vector2 refPosition = Vector2.zero;
+        RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+        bool show = false;
+
+        public void Begin()
+        {
+            refPosition = Vector2.zero;
+            show = true;
+        }
+
+        public void Stop()
+        {
+            show = false;
+        }
+
+        private void LateUpdate()
+        {
+            if (Vector2.Distance(rectTransform.anchoredPosition, to) > 1f)
+            {
+                if (show)
+                {
+                    var newPosition = Vector2.SmoothDamp(rectTransform.anchoredPosition, to, ref refPosition, m_Smooth, 1000, Time.deltaTime);
+                    rectTransform.anchoredPosition = newPosition;
+                }
+            }
+            else
+            {
+                show = false;
+            }
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Move/UISmoothMove.cs.meta b/Main/Component/UI/Decorate/Move/UISmoothMove.cs.meta
new file mode 100644
index 0000000..e750cdc
--- /dev/null
+++ b/Main/Component/UI/Decorate/Move/UISmoothMove.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d8eabc4994acf834db3ed3d601fe354e
+timeCreated: 1523273875
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/PingPong.meta b/Main/Component/UI/Decorate/PingPong.meta
new file mode 100644
index 0000000..a6c2752
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: a7a6138753b56fd47b811a23bcefeccf
+folderAsset: yes
+timeCreated: 1459987228
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongMove.cs b/Main/Component/UI/Decorate/PingPong/PingPongMove.cs
new file mode 100644
index 0000000..024af32
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongMove.cs
@@ -0,0 +1,47 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI {
+    public class PingPongMove:MonoBehaviour {
+
+        public Transform reference;
+        public Vector3 amplitue;
+        public float speed;
+
+        Vector3 referencePos = Vector3.zero;
+
+        void OnEnable() {
+            referencePos = reference == null ? this.transform.localPosition : reference.localPosition;
+        }
+
+        float x = 0f;
+        float y = 0f;
+        float z = 0f;
+        void LateUpdate() {
+
+            if(Mathf.Abs(amplitue.x) > 0.001f) {
+                x = referencePos.x - amplitue.x * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.x);
+            }
+            else {
+                x = referencePos.x;
+            }
+
+            if(Mathf.Abs(amplitue.y) > 0.001f) {
+                y = referencePos.y - amplitue.y * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.y);
+            }
+            else {
+                y = referencePos.y;
+            }
+
+            if(Mathf.Abs(amplitue.z) > 0.001f) {
+                z = referencePos.z - amplitue.z * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.z);
+            }
+            else {
+                z = referencePos.z;
+            }
+
+            this.transform.localPosition = new Vector3(x,y,z);
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongMove.cs.meta b/Main/Component/UI/Decorate/PingPong/PingPongMove.cs.meta
new file mode 100644
index 0000000..f337b9d
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongMove.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7129b6935a9972f4fbae071275cda92d
+timeCreated: 1458475023
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs b/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs
new file mode 100644
index 0000000..fdf6859
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs
@@ -0,0 +1,47 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI {
+    public class PingPongRotation:MonoBehaviour {
+
+        public Transform reference;
+        public Vector3 amplitue;
+        public float speed;
+
+        Vector3 referenceEuler = Vector3.zero;
+
+        void OnEnable() {
+            referenceEuler = reference == null ? this.transform.localEulerAngles : reference.localEulerAngles;
+        }
+
+        float x = 0f;
+        float y = 0f;
+        float z = 0f;
+        void LateUpdate() {
+
+            if(Mathf.Abs(amplitue.x) > 0.001f) {
+                x = referenceEuler.x - amplitue.x * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.x);
+            }
+            else {
+                x = referenceEuler.x;
+            }
+
+            if(Mathf.Abs(amplitue.y) > 0.001f) {
+                y = referenceEuler.y - amplitue.y * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.y);
+            }
+            else {
+                y = referenceEuler.y;
+            }
+
+            if(Mathf.Abs(amplitue.z) > 0.001f) {
+                z = referenceEuler.z - amplitue.z * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.z);
+            }
+            else {
+                z = referenceEuler.z;
+            }
+
+            this.transform.localEulerAngles = new Vector3(x,y,z);
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs.meta b/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs.meta
new file mode 100644
index 0000000..0c6207a
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongRotation.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a46b1422dda61f848adab91bcaea1e52
+timeCreated: 1458475900
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongScale.cs b/Main/Component/UI/Decorate/PingPong/PingPongScale.cs
new file mode 100644
index 0000000..ce2c45e
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongScale.cs
@@ -0,0 +1,48 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI {
+    public class PingPongScale:MonoBehaviour {
+
+        public Transform reference;
+        public Vector3 amplitue;
+        public float speed;
+
+        Vector3 referenceScale = Vector3.zero;
+
+        void OnEnable() {
+            referenceScale = reference == null ? this.transform.localScale : reference.localScale;
+        }
+
+        float x = 0f;
+        float y = 0f;
+        float z = 0f;
+        void LateUpdate() {
+
+            if(Mathf.Abs(amplitue.x) > 0.001f) {
+                x = referenceScale.x - amplitue.x * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.x);
+            }
+            else {
+                x = referenceScale.x;
+            }
+
+            if(Mathf.Abs(amplitue.y) > 0.001f) {
+                y = referenceScale.y - amplitue.y * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.y);
+            }
+            else {
+                y = referenceScale.y;
+            }
+
+            if(Mathf.Abs(amplitue.z) > 0.001f) {
+                z = referenceScale.z - amplitue.z * 0.5f + Mathf.PingPong(Time.time * speed,amplitue.z);
+            }
+            else {
+                z = referenceScale.z;
+            }
+
+            this.transform.localScale = new Vector3(x,y,z);
+        }
+    }
+
+}
+
diff --git a/Main/Component/UI/Decorate/PingPong/PingPongScale.cs.meta b/Main/Component/UI/Decorate/PingPong/PingPongScale.cs.meta
new file mode 100644
index 0000000..985ac16
--- /dev/null
+++ b/Main/Component/UI/Decorate/PingPong/PingPongScale.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2c5c714c997cf534b90f154cb7f107e1
+timeCreated: 1458476246
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Smooth.meta b/Main/Component/UI/Decorate/Smooth.meta
new file mode 100644
index 0000000..8a16e87
--- /dev/null
+++ b/Main/Component/UI/Decorate/Smooth.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 127ebe8785ff4624cb4c8bea33441875
+folderAsset: yes
+timeCreated: 1460123930
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Smooth/SmoothMove.cs b/Main/Component/UI/Decorate/Smooth/SmoothMove.cs
new file mode 100644
index 0000000..d236779
--- /dev/null
+++ b/Main/Component/UI/Decorate/Smooth/SmoothMove.cs
@@ -0,0 +1,91 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using System;
+
+public class SmoothMove : MonoBehaviour
+{
+
+    Vector3 targetPosition = Vector3.zero;
+    float smoothTime = 0f;
+    bool isLocal = false;
+    Action callBack = null;
+
+    Vector3 refPosition = Vector3.zero;
+    bool startSmooth = false;
+
+    public static float checkDistance = 0.01f;
+
+    public static void MoveTo(GameObject _gameObject, Vector3 _targetPosition, float _smoothTime, bool _isLocal, Action _callBack)
+    {
+        SmoothMove smove = _gameObject.AddMissingComponent<SmoothMove>();
+        smove.MoveTo(_targetPosition, _smoothTime, _isLocal, _callBack);
+    }
+
+    public void MoveTo(Vector3 _targetPosition, float _smoothTime, bool _isLocal, Action _callBack)
+    {
+
+        targetPosition = _targetPosition;
+        smoothTime = _smoothTime;
+        isLocal = _isLocal;
+        callBack = _callBack;
+
+        startSmooth = true;
+    }
+
+    private void LateUpdate()
+    {
+        if (!startSmooth)
+        {
+            return;
+        }
+
+        if (isLocal)
+        {
+            if (Vector3.Distance(this.transform.localPosition, targetPosition) > checkDistance)
+            {
+                Vector3 newPosition = Vector3.SmoothDamp(this.transform.localPosition, targetPosition, ref refPosition, smoothTime);
+                this.transform.localPosition = newPosition;
+            }
+            else
+            {
+                this.transform.localPosition = targetPosition;
+                if (callBack != null)
+                {
+                    callBack();
+                    callBack = null;
+                }
+                Destroy(this);
+            }
+        }
+        else
+        {
+            if (Vector3.Distance(this.transform.position, targetPosition) > 0.01f)
+            {
+                Vector3 newPosition = Vector3.SmoothDamp(this.transform.position, targetPosition, ref refPosition, smoothTime);
+                this.transform.position = newPosition;
+            }
+            else
+            {
+                this.transform.position = targetPosition;
+                if (callBack != null)
+                {
+                    callBack();
+                    callBack = null;
+                }
+                Destroy(this);
+            }
+        }
+
+    }
+
+
+    void OnDisable()
+    {
+        if (callBack != null)
+        {
+            callBack();
+            callBack = null;
+        }
+        startSmooth = false;
+    }
+}
diff --git a/Main/Component/UI/Decorate/Smooth/SmoothMove.cs.meta b/Main/Component/UI/Decorate/Smooth/SmoothMove.cs.meta
new file mode 100644
index 0000000..4f43941
--- /dev/null
+++ b/Main/Component/UI/Decorate/Smooth/SmoothMove.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8535aee34ca68f541b7e6fd918dae1a0
+timeCreated: 1460123992
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens.meta b/Main/Component/UI/Decorate/Tweens.meta
new file mode 100644
index 0000000..50d7c22
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 061bfec616ca3414fbdc7b8916fbb6da
+folderAsset: yes
+timeCreated: 1459743819
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/PositionTween.cs b/Main/Component/UI/Decorate/Tweens/PositionTween.cs
new file mode 100644
index 0000000..20c9db1
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/PositionTween.cs
@@ -0,0 +1,48 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+    public class PositionTween : Tween
+    {
+
+        public override void SetStartState()
+        {
+            base.SetStartState();
+            this.rectTransform.anchoredPosition = from;
+        }
+
+        public override void SetEndState()
+        {
+            base.SetEndState();
+            this.rectTransform.anchoredPosition = to;
+        }
+
+        protected override void OnPrepare()
+        {
+            base.OnPrepare();
+            this.rectTransform.anchoredPosition = reversal ? to : from;
+        }
+
+        protected override void OnOnceEnd()
+        {
+            if (wrapMode == WrapMode.PingPongOnce)
+            {
+                SetStartState();
+            }
+            else
+            { 
+                this.rectTransform.anchoredPosition = reversal ? from : to;
+            }
+
+            base.OnOnceEnd();
+        }
+
+        protected override void UpdateVector3()
+        {
+            base.UpdateVector3();
+            this.rectTransform.anchoredPosition = CalculateVector3();
+        }
+
+    }
+}
diff --git a/Main/Component/UI/Decorate/Tweens/PositionTween.cs.meta b/Main/Component/UI/Decorate/Tweens/PositionTween.cs.meta
new file mode 100644
index 0000000..444157c
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/PositionTween.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2167023bbd4b8be4ca9957d338e191e7
+timeCreated: 1459743845
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/RotationTween.cs b/Main/Component/UI/Decorate/Tweens/RotationTween.cs
new file mode 100644
index 0000000..c5aa8dd
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/RotationTween.cs
@@ -0,0 +1,41 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+
+    public class RotationTween : Tween
+    {
+
+        public override void SetStartState()
+        {
+            base.SetStartState();
+            this.transform.localEulerAngles = from;
+        }
+
+        public override void SetEndState()
+        {
+            base.SetEndState();
+            this.transform.localEulerAngles = to;
+        }
+
+        protected override void OnPrepare()
+        {
+            base.OnPrepare();
+            this.transform.localEulerAngles = reversal ? to : from;
+        }
+
+        protected override void OnOnceEnd()
+        {
+
+            this.transform.localEulerAngles = reversal ? from : to;
+            base.OnOnceEnd();
+        }
+
+        protected override void UpdateVector3()
+        {
+            base.UpdateVector3();
+            this.transform.localEulerAngles = CalculateVector3();
+        }
+    }
+}
diff --git a/Main/Component/UI/Decorate/Tweens/RotationTween.cs.meta b/Main/Component/UI/Decorate/Tweens/RotationTween.cs.meta
new file mode 100644
index 0000000..0413764
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/RotationTween.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c79d7a9b820a4fb4391f05c98bb51c51
+timeCreated: 1459750870
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/ScaleTween.cs b/Main/Component/UI/Decorate/Tweens/ScaleTween.cs
new file mode 100644
index 0000000..257050d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/ScaleTween.cs
@@ -0,0 +1,40 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+    public class ScaleTween : Tween
+    {
+        public override void SetStartState()
+        {
+            base.SetStartState();
+            this.transform.localScale = from;
+        }
+
+        public override void SetEndState()
+        {
+            base.SetEndState();
+            this.transform.localScale = to;
+        }
+
+        protected override void OnPrepare()
+        {
+            base.OnPrepare();
+            this.transform.localScale = reversal ? to : from;
+        }
+
+        protected override void OnOnceEnd()
+        {
+            this.transform.localScale = reversal ? from : to;
+            base.OnOnceEnd();
+        }
+
+        protected override void UpdateVector3()
+        {
+            base.UpdateVector3();
+            this.transform.localScale = CalculateVector3();
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Decorate/Tweens/ScaleTween.cs.meta b/Main/Component/UI/Decorate/Tweens/ScaleTween.cs.meta
new file mode 100644
index 0000000..94ffd07
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/ScaleTween.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1d62b0928b057af4c955488a048ad8e7
+timeCreated: 1459750871
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/Tween.cs b/Main/Component/UI/Decorate/Tweens/Tween.cs
new file mode 100644
index 0000000..0036f84
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/Tween.cs
@@ -0,0 +1,236 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using System;
+
+namespace vnxbqy.UI
+{
+    [RequireComponent(typeof(RectTransform))]
+    public class Tween : MonoBehaviour
+    {
+        public TweenCurve curve;
+        public Vector3 from;
+        public Vector3 to;
+
+        public DelayMode delayMode = DelayMode.Time;
+        public float delay = 0f;
+
+        public float duration = 1f;
+        public Trigger trigger = Trigger.Manual;
+        public WrapMode wrapMode;
+        public bool reversal;
+
+        protected RectTransform rectTransform { get { return this.transform as RectTransform; } }
+
+        protected float accumulatedTime;
+        protected float curveLength;
+        protected bool doTween = false;
+
+        Action onPlayEndCallBack;
+
+        public virtual void SetStartState()
+        {
+
+        }
+
+        public virtual void SetEndState()
+        {
+
+        }
+
+        public void Play()
+        {
+            onPlayEndCallBack = null;
+            reversal = false;
+            StopAllCoroutines();
+            StartCoroutine(Co_StartTween());
+        }
+
+        public void Play(bool _reversal)
+        {
+            onPlayEndCallBack = null;
+            reversal = _reversal;
+            StopAllCoroutines();
+            StartCoroutine(Co_StartTween());
+        }
+
+        public void Play(Action _callBack)
+        {
+            reversal = false;
+            onPlayEndCallBack = _callBack;
+            StopAllCoroutines();
+            StartCoroutine(Co_StartTween());
+        }
+
+        public void Play(bool _reversal, Action _callBack)
+        {
+            reversal = _reversal;
+            onPlayEndCallBack = _callBack;
+            StopAllCoroutines();
+            StartCoroutine(Co_StartTween());
+        }
+
+        void Start()
+        {
+            if (trigger == Trigger.Start)
+            {
+                StartCoroutine(Co_StartTween());
+            }
+        }
+
+        protected virtual void OnEnable()
+        {
+            if (trigger == Trigger.Enable)
+            {
+                StartCoroutine(Co_StartTween());
+            }
+        }
+
+        protected virtual void OnDisable()
+        {
+            onPlayEndCallBack = null;
+            StopAllCoroutines();
+        }
+
+        void LateUpdate()
+        {
+            if (doTween && duration > 0.001f)
+            {
+                accumulatedTime += Time.deltaTime;
+                UpdateVector3();
+
+                switch (wrapMode)
+                {
+                    case WrapMode.Once:
+                        if (accumulatedTime > duration)
+                        {
+                            OnOnceEnd();
+                            doTween = false;
+                        }
+                        break;
+                    case WrapMode.PingPongOnce:
+                        if (accumulatedTime > duration*2)
+                        {
+                            OnOnceEnd();
+                            doTween = false;
+                        }
+                        break;
+                }
+            }
+        }
+
+        IEnumerator Co_StartTween()
+        {
+            if (delay < 0f)
+            {
+                DebugEx.LogError("Delaytime should not be less than zero!");
+                yield break;
+            }
+            if (duration < 0.001f)
+            {
+                DebugEx.LogError("Duration should not be less than zero!");
+                yield break;
+            }
+
+            if (curve.keys.Length < 2)
+            {
+                DebugEx.LogError("涓嶆纭殑鏇茬嚎!");
+                yield break;
+            }
+
+            accumulatedTime = 0f;
+            doTween = false;
+            OnPrepare();
+            switch (delayMode)
+            {
+                case DelayMode.OneFrame:
+                    yield return null;
+                    break;
+                case DelayMode.TwiceFrame:
+                    yield return null;
+                    yield return null;
+                    break;
+                case DelayMode.Time:
+                    if (delay > 0.001f)
+                    {
+                        yield return new WaitForSeconds(delay);
+                    }
+                    break;
+            }
+
+            curveLength = curve.keys[curve.keys.Length - 1].time - curve.keys[0].time;
+            doTween = true;
+
+        }
+
+        protected Vector3 CalculateVector3()
+        {
+            Vector3 newVector3 = Vector3.zero;
+            float t = 0f;
+            switch (wrapMode)
+            {
+                case WrapMode.Once:
+                    t = (accumulatedTime / duration) * curveLength;
+                    break;
+                case WrapMode.Loop:
+                    t = Mathf.Repeat((accumulatedTime / duration) * curveLength, 1);
+                    break;
+                case WrapMode.PingPong:
+                case WrapMode.PingPongOnce:
+                    t = Mathf.PingPong((accumulatedTime / duration) * curveLength, 1);
+                    break;
+            }
+
+            var value = curve.Evaluate(reversal ? curveLength - t : t);
+            newVector3 = Vector3.LerpUnclamped(from, to, value);
+
+            return newVector3;
+        }
+
+        protected virtual void OnPrepare()
+        {
+
+        }
+
+        protected virtual void OnOnceEnd()
+        {
+            if (onPlayEndCallBack != null)
+            {
+                onPlayEndCallBack();
+                onPlayEndCallBack = null;
+            }
+        }
+
+        protected virtual void UpdateVector3()
+        {
+
+        }
+
+        public void Stop()
+        {
+            doTween = false;
+        }
+
+        public enum DelayMode
+        {
+            OneFrame,
+            TwiceFrame,
+            Time,
+        }
+
+        public enum Trigger
+        {
+            Manual,
+            Start,
+            Enable,
+        }
+
+        public enum WrapMode
+        {
+            Once,
+            Loop,
+            PingPong,
+            PingPongOnce,
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Decorate/Tweens/Tween.cs.meta b/Main/Component/UI/Decorate/Tweens/Tween.cs.meta
new file mode 100644
index 0000000..48807a1
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/Tween.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b0240d64a059ba74e91c47c10cf98bb2
+timeCreated: 1459751786
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/TweenCurve.cs b/Main/Component/UI/Decorate/Tweens/TweenCurve.cs
new file mode 100644
index 0000000..e32f5a2
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/TweenCurve.cs
@@ -0,0 +1,43 @@
+锘縰sing UnityEngine;
+
+public class TweenCurve : ScriptableObject
+{
+    public AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
+
+    Keyframe[] m_Keys;
+    public Keyframe[] keys {
+        get {
+            return m_Keys ?? (m_Keys = curve.keys);
+        }
+    }
+
+    public int length {
+        get {
+            return curve.length;
+        }
+    }
+
+    float m_TotalTime = -1f;
+    public float totalTime {
+        get {
+            if (m_TotalTime < 0f)
+            {
+                m_TotalTime = curve.keys[curve.keys.Length - 1].time - curve.keys[0].time;
+            }
+            return m_TotalTime;
+        }
+    }
+
+    public Keyframe this[int index] {
+        get {
+            return curve[index];
+        }
+    }
+
+    public float Evaluate(float time)
+    {
+        float aaa = curve.Evaluate(time);
+        return aaa;
+    }
+
+}
diff --git a/Main/Component/UI/Decorate/Tweens/TweenCurve.cs.meta b/Main/Component/UI/Decorate/Tweens/TweenCurve.cs.meta
new file mode 100644
index 0000000..3cd82f7
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/TweenCurve.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5e8751910f36c154898b3bca27c09d8b
+timeCreated: 1504310132
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs b/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs
new file mode 100644
index 0000000..22bf92d
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs
@@ -0,0 +1,233 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System;
+
+namespace vnxbqy.UI
+{
+    
+    [RequireComponent(typeof(CanvasGroup))]
+    public class UIAlphaTween : MonoBehaviour
+    {
+        public TweenCurve curve;
+        [Range(0, 1)]
+        public float from;
+        [Range(0, 1)]
+        public float to;
+        public float delay = 0f;
+        public float duration = 1f;
+        public Trigger trigger = Trigger.Manual;
+        public WrapMode wrapMode;
+        public bool reversal;
+
+        CanvasGroup m_CanvasGroup;
+        public CanvasGroup canvasGroup {
+            get {
+                return m_CanvasGroup ?? (m_CanvasGroup = this.GetComponent<CanvasGroup>());
+            }
+        }
+
+        protected float accumulatedTime;
+        protected float curveLength;
+        protected bool doTween = false;
+
+        Action onPlayEndCallBack;
+
+        public void SetStartState()
+        {
+            canvasGroup.alpha = from;
+        }
+
+        public void SetEndState()
+        {
+            canvasGroup.alpha = to;
+        }
+
+        public void Play()
+        {
+            onPlayEndCallBack = null;
+            reversal = false;
+            StopAllCoroutines();
+            if (this.gameObject.activeInHierarchy)
+            {
+                SetStartState();
+                StartCoroutine("Co_StartTween");
+            }
+        }
+
+        public void Play(bool _reversal)
+        {
+            onPlayEndCallBack = null;
+            reversal = _reversal;
+            StopAllCoroutines();
+            if (this.gameObject.activeInHierarchy)
+            {
+                if (_reversal)
+                {
+                    SetEndState();
+                }
+                else
+                {
+                    SetStartState();
+                }
+
+                StartCoroutine("Co_StartTween");
+            }
+        }
+
+        public void Play(Action _callBack)
+        {
+            onPlayEndCallBack = _callBack;
+            reversal = false;
+            StopAllCoroutines();
+            if (this.gameObject.activeInHierarchy)
+            {
+                SetStartState();
+                StartCoroutine("Co_StartTween");
+            }
+        }
+
+        public void Stop()
+        {
+            doTween = false;
+            accumulatedTime = 0f;
+            StopAllCoroutines();
+            SetStartState();
+        }
+
+
+        void Start()
+        {
+            if (trigger == Trigger.Start)
+            {
+                SetStartState();
+                StartCoroutine("Co_StartTween");
+            }
+        }
+
+        protected virtual void OnEnable()
+        {
+            if (trigger == Trigger.Enable)
+            {
+                SetStartState();
+                StartCoroutine("Co_StartTween");
+            }
+        }
+
+        protected virtual void OnDisable()
+        {
+            doTween = false;
+            accumulatedTime = 0f;
+            StopAllCoroutines();
+        }
+
+        void LateUpdate()
+        {
+            if (doTween && duration > 0.001f)
+            {
+                accumulatedTime += Time.deltaTime;
+                UpdateAlpha();
+            }
+        }
+
+        IEnumerator Co_StartTween()
+        {
+            if (delay < 0f)
+            {
+                DebugEx.LogError("Delaytime should not be less than zero!");
+                yield break;
+            }
+            if (duration < 0.001f)
+            {
+                DebugEx.LogError("Duration should not be less than zero!");
+                yield break;
+            }
+
+            if (curve.keys.Length < 2)
+            {
+                DebugEx.LogError("涓嶆纭殑鏇茬嚎!");
+                yield break;
+            }
+
+            doTween = false;
+            OnPrepare();
+            yield return new WaitForSeconds(delay);
+            curveLength = curve.keys[curve.keys.Length - 1].time - curve.keys[0].time;
+            doTween = true;
+            accumulatedTime = 0f;
+        }
+
+        protected void UpdateAlpha()
+        {
+            float t = 0f;
+            switch (wrapMode)
+            {
+                case WrapMode.Once:
+                    t = (accumulatedTime / duration) * curveLength;
+                    break;
+                case WrapMode.Loop:
+                    t = Mathf.Repeat((accumulatedTime / duration) * curveLength, 1);
+                    break;
+                case WrapMode.PingPong:
+                    t = Mathf.PingPong((accumulatedTime / duration) * curveLength, 1);
+                    break;
+            }
+
+            var value = curve.Evaluate(reversal ? curveLength - t : t);
+            canvasGroup.alpha = Mathf.LerpUnclamped(from, to, value);
+
+            switch (wrapMode)
+            {
+                case WrapMode.Once:
+                    if (t > curveLength && doTween)
+                    {
+                        OnOnceEnd();
+                        doTween = false;
+                    }
+                    break;
+            }
+        }
+
+        protected virtual void OnPrepare()
+        {
+
+        }
+
+        protected virtual void OnOnceEnd()
+        {
+            if (onPlayEndCallBack != null)
+            {
+                onPlayEndCallBack();
+                onPlayEndCallBack = null;
+            }
+        }
+
+        protected virtual void UpdateVector3()
+        {
+
+        }
+
+        public enum Trigger
+        {
+            Manual,
+            Start,
+            Enable,
+        }
+
+        public enum WrapMode
+        {
+            Once,
+            Loop,
+            PingPong,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs.meta b/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs.meta
new file mode 100644
index 0000000..b29cda5
--- /dev/null
+++ b/Main/Component/UI/Decorate/Tweens/UIAlphaTween.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e374e11920c66d44f8600c893b3d2df1
+timeCreated: 1505356878
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect.meta b/Main/Component/UI/Effect.meta
new file mode 100644
index 0000000..422f61f
--- /dev/null
+++ b/Main/Component/UI/Effect.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: cb02efd82b1cfc142a02dae9fcd9b40c
+folderAsset: yes
+timeCreated: 1504508766
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/ActorEffectEvent.cs b/Main/Component/UI/Effect/ActorEffectEvent.cs
new file mode 100644
index 0000000..5139a51
--- /dev/null
+++ b/Main/Component/UI/Effect/ActorEffectEvent.cs
@@ -0,0 +1,14 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ActorEffectEvent : MonoBehaviour
+{
+
+    public void PlayEffect(int _effectId)
+    {
+        SFXPlayUtility.Instance.Play(_effectId, this.transform);
+    }
+
+
+}
diff --git a/Main/Component/UI/Effect/ActorEffectEvent.cs.meta b/Main/Component/UI/Effect/ActorEffectEvent.cs.meta
new file mode 100644
index 0000000..1a731fd
--- /dev/null
+++ b/Main/Component/UI/Effect/ActorEffectEvent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7923f721c33fe1247b0ec0a309b68355
+timeCreated: 1508464348
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/ColorCorrectionCurves.cs b/Main/Component/UI/Effect/ColorCorrectionCurves.cs
new file mode 100644
index 0000000..41237fa
--- /dev/null
+++ b/Main/Component/UI/Effect/ColorCorrectionCurves.cs
@@ -0,0 +1,181 @@
+using System;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects
+{
+    [ExecuteAlways]
+    [AddComponentMenu ("Image Effects/Color Adjustments/Color Correction (Curves, Saturation)")]
+    public class ColorCorrectionCurves : PostEffectsBase
+	{
+        public enum ColorCorrectionMode
+		{
+            Simple = 0,
+            Advanced = 1
+        }
+
+        public AnimationCurve redChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+        public AnimationCurve greenChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+        public AnimationCurve blueChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+
+        public bool  useDepthCorrection = false;
+
+        public AnimationCurve zCurve = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+        public AnimationCurve depthRedChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+        public AnimationCurve depthGreenChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+        public AnimationCurve depthBlueChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
+
+        private Material ccMaterial;
+        private Material ccDepthMaterial;
+        private Material selectiveCcMaterial;
+
+        private Texture2D rgbChannelTex;
+        private Texture2D rgbDepthChannelTex;
+        private Texture2D zCurveTex;
+
+        public float saturation = 1.0f;
+
+        public bool  selectiveCc = false;
+
+        public Color selectiveFromColor = Color.white;
+        public Color selectiveToColor = Color.white;
+
+        public ColorCorrectionMode mode;
+
+        public bool  updateTextures = true;
+
+        public Shader colorCorrectionCurvesShader = null;
+        public Shader simpleColorCorrectionCurvesShader = null;
+        public Shader colorCorrectionSelectiveShader = null;
+
+        private bool  updateTexturesOnStartup = true;
+
+
+        new void Start ()
+		{
+            base.Start ();
+            updateTexturesOnStartup = true;
+        }
+
+        void Awake () {	}
+
+
+        public override bool CheckResources ()
+		{
+            CheckSupport (mode == ColorCorrectionMode.Advanced);
+
+            ccMaterial = CheckShaderAndCreateMaterial (simpleColorCorrectionCurvesShader, ccMaterial);
+            ccDepthMaterial = CheckShaderAndCreateMaterial (colorCorrectionCurvesShader, ccDepthMaterial);
+            selectiveCcMaterial = CheckShaderAndCreateMaterial (colorCorrectionSelectiveShader, selectiveCcMaterial);
+
+            if (!rgbChannelTex)
+                rgbChannelTex = new Texture2D (256, 4, TextureFormat.ARGB32, false, true);
+            if (!rgbDepthChannelTex)
+                rgbDepthChannelTex = new Texture2D (256, 4, TextureFormat.ARGB32, false, true);
+            if (!zCurveTex)
+                zCurveTex = new Texture2D (256, 1, TextureFormat.ARGB32, false, true);
+
+            rgbChannelTex.hideFlags = HideFlags.DontSave;
+            rgbDepthChannelTex.hideFlags = HideFlags.DontSave;
+            zCurveTex.hideFlags = HideFlags.DontSave;
+
+            rgbChannelTex.wrapMode = TextureWrapMode.Clamp;
+            rgbDepthChannelTex.wrapMode = TextureWrapMode.Clamp;
+            zCurveTex.wrapMode = TextureWrapMode.Clamp;
+
+            if (!isSupported)
+                ReportAutoDisable ();
+            return isSupported;
+        }
+
+        public void UpdateParameters ()
+		{
+            CheckResources(); // textures might not be created if we're tweaking UI while disabled
+
+            if (redChannel != null && greenChannel != null && blueChannel != null)
+			{
+                for (float i = 0.0f; i <= 1.0f; i += 1.0f / 255.0f)
+				{
+                    float rCh = Mathf.Clamp (redChannel.Evaluate(i), 0.0f, 1.0f);
+                    float gCh = Mathf.Clamp (greenChannel.Evaluate(i), 0.0f, 1.0f);
+                    float bCh = Mathf.Clamp (blueChannel.Evaluate(i), 0.0f, 1.0f);
+
+                    rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(rCh,rCh,rCh) );
+                    rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 1, new Color(gCh,gCh,gCh) );
+                    rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 2, new Color(bCh,bCh,bCh) );
+
+                    float zC = Mathf.Clamp (zCurve.Evaluate(i), 0.0f,1.0f);
+
+                    zCurveTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(zC,zC,zC) );
+
+                    rCh = Mathf.Clamp (depthRedChannel.Evaluate(i), 0.0f,1.0f);
+                    gCh = Mathf.Clamp (depthGreenChannel.Evaluate(i), 0.0f,1.0f);
+                    bCh = Mathf.Clamp (depthBlueChannel.Evaluate(i), 0.0f,1.0f);
+
+                    rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(rCh,rCh,rCh) );
+                    rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 1, new Color(gCh,gCh,gCh) );
+                    rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 2, new Color(bCh,bCh,bCh) );
+                }
+
+                rgbChannelTex.Apply ();
+                rgbDepthChannelTex.Apply ();
+                zCurveTex.Apply ();
+            }
+        }
+
+        void UpdateTextures ()
+		{
+            UpdateParameters ();
+        }
+
+        void OnRenderImage (RenderTexture source, RenderTexture destination)
+		{
+            if (CheckResources()==false)
+			{
+                Graphics.Blit (source, destination);
+                return;
+            }
+
+            if (updateTexturesOnStartup)
+			{
+                UpdateParameters ();
+                updateTexturesOnStartup = false;
+            }
+
+            if (useDepthCorrection)
+                GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+
+            RenderTexture renderTarget2Use = destination;
+
+            if (selectiveCc)
+			{
+                renderTarget2Use = RenderTexture.GetTemporary (source.width, source.height);
+            }
+
+            if (useDepthCorrection)
+			{
+                ccDepthMaterial.SetTexture ("_RgbTex", rgbChannelTex);
+                ccDepthMaterial.SetTexture ("_ZCurve", zCurveTex);
+                ccDepthMaterial.SetTexture ("_RgbDepthTex", rgbDepthChannelTex);
+                ccDepthMaterial.SetFloat ("_Saturation", saturation);
+
+                Graphics.Blit (source, renderTarget2Use, ccDepthMaterial);
+            }
+            else
+			{
+                ccMaterial.SetTexture ("_RgbTex", rgbChannelTex);
+                ccMaterial.SetFloat ("_Saturation", saturation);
+
+                Graphics.Blit (source, renderTarget2Use, ccMaterial);
+            }
+
+            if (selectiveCc)
+			{
+                selectiveCcMaterial.SetColor ("selColor", selectiveFromColor);
+                selectiveCcMaterial.SetColor ("targetColor", selectiveToColor);
+                Graphics.Blit (renderTarget2Use, destination, selectiveCcMaterial);
+
+                RenderTexture.ReleaseTemporary (renderTarget2Use);
+            }
+        }
+    }
+}
diff --git a/Main/Component/UI/Effect/ColorCorrectionCurves.cs.meta b/Main/Component/UI/Effect/ColorCorrectionCurves.cs.meta
new file mode 100644
index 0000000..e60e166
--- /dev/null
+++ b/Main/Component/UI/Effect/ColorCorrectionCurves.cs.meta
@@ -0,0 +1,15 @@
+fileFormatVersion: 2
+guid: 1fd999d1b2cf94a45a5b0a47ce074bef
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences:
+  - colorCorrectionCurvesShader: {fileID: 4800000, guid: 62bcade1028c24ca1a39760ed84b9487,
+      type: 3}
+  - simpleColorCorrectionCurvesShader: {fileID: 4800000, guid: 438ddd58d82c84d9eb1fdc56111702e1,
+      type: 3}
+  - colorCorrectionSelectiveShader: {fileID: 4800000, guid: e515e0f94cefc4c0db54b45cba621544,
+      type: 3}
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
diff --git a/Main/Component/UI/Effect/EffectMgr.cs b/Main/Component/UI/Effect/EffectMgr.cs
new file mode 100644
index 0000000..d64e7ba
--- /dev/null
+++ b/Main/Component/UI/Effect/EffectMgr.cs
@@ -0,0 +1,121 @@
+锘縰sing vnxbqy.UI;
+using UnityEngine;
+
+public class EffectMgr : SingletonMonobehaviour<EffectMgr>
+
+{
+    public UIEffectBehaviour GetUIEffect(int id, bool _destroy = false)
+    {
+        var _prefab = InstanceResourcesLoader.LoadEffect(id);
+        if (_prefab == null)
+        {
+            return null;
+        }
+        GameObjectPoolManager.GameObjectPool _pool = GameObjectPoolManager.Instance.RequestPool(_prefab);
+        _prefab = _pool.Request();
+        var _effect = _prefab.GetComponent<UIEffect>();
+        if (_effect != null && _destroy)
+        {
+            Destroy(_effect);
+        }
+        var _behaviour = _prefab.AddMissingComponent<UIEffectBehaviour>();
+        return _behaviour;
+    }
+
+    //鐜╁鏄惁涓诲姩灞忚斀浜嗙壒鏁�
+    public bool IsNotShowBySetting(int id)
+    {
+        var config = EffectConfig.Get(id);
+        if (config == null)
+        {
+#if UNITY_EDITOR
+            Debug.LogError("鐗规晥閰嶇疆琛ㄤ腑娌℃湁鎵惧埌id涓�" + id + "鐨勭壒鏁�");
+#endif
+            return true;
+        }
+        bool isNotShow = LocalSave.GetBool("IsNotShowBroadEffect", false);
+        if (config.notShow == 1 && isNotShow)
+            return true;
+
+        return false;
+    }
+
+    public UIEffect PlayUIEffect(int id, int renderQueue, Transform parent, bool loop)
+    {
+        if (IsNotShowBySetting(id))
+            return null;
+        UIEffectBehaviour _behaviour = GetUIEffect(id);
+        UIEffect uieffect = null;
+        if (_behaviour != null)
+        {
+            _behaviour.SetActive(false);
+            _behaviour.transform.SetParent(parent);
+            uieffect = _behaviour.AddMissingComponent<UIEffect>();
+            uieffect.target = _behaviour;
+            SetUIEffect(uieffect, id, renderQueue, loop, Vector3.zero, Vector3.zero);
+            uieffect.Active();
+        }
+        return uieffect;
+    }
+
+    public UIEffect PlayUIEffect(int id, int renderQueue, Transform parent, Vector3 _localPos, Vector3 _localRot, bool loop)
+    {
+        if (IsNotShowBySetting(id))
+            return null;
+        UIEffectBehaviour _behaviour = GetUIEffect(id);
+        UIEffect uieffect = null;
+        if (_behaviour != null)
+        {
+            _behaviour.SetActive(false);
+            _behaviour.transform.SetParent(parent);
+            uieffect = _behaviour.AddMissingComponent<UIEffect>();
+            uieffect.target = _behaviour;
+            SetUIEffect(uieffect, id, renderQueue, loop, _localPos, _localRot);
+            uieffect.Active();
+        }
+        return uieffect;
+    }
+
+    public UIEffect PlayUIEffect(int id, int renderQueue, Vector3 _localPos, bool loop = false)
+    {
+        if (IsNotShowBySetting(id))
+            return null;
+        UIEffectBehaviour _behaviour = GetUIEffect(id);
+        UIEffect uieffect = null;
+        if (_behaviour != null)
+        {
+            _behaviour.SetActive(false);
+            _behaviour.transform.SetParent(WindowCenter.Instance.uiRoot.baseCanvas);
+            uieffect = _behaviour.AddMissingComponent<UIEffect>();
+            uieffect.target = _behaviour;
+            SetUIEffect(uieffect, id, renderQueue, loop, _localPos, Vector3.zero);
+            uieffect.Active();
+        }
+        return uieffect;
+    }
+
+    private void SetUIEffect(UIEffect effect, int id, int renderQueue, bool loop, Vector3 _localPos, Vector3 _localRot)
+    {
+        effect.effect = id;
+        effect.renderQueue = renderQueue;
+        effect.loop = loop;
+        effect.effectPos = _localPos;
+        effect.effectRot = _localRot;
+    }
+
+    public void RecyleUIEffect(int id, GameObject _effectObj)
+    {
+        var _prefab = InstanceResourcesLoader.LoadEffect(id);
+        _effectObj.SetActive(false);
+        if (_prefab == null)
+        {
+            return;
+        }
+        GameObjectPoolManager.GameObjectPool _pool = GameObjectPoolManager.Instance.RequestPool(_prefab);
+        if (_pool != null)
+        {
+            _pool.Release(_effectObj);
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Effect/EffectMgr.cs.meta b/Main/Component/UI/Effect/EffectMgr.cs.meta
new file mode 100644
index 0000000..52f69e9
--- /dev/null
+++ b/Main/Component/UI/Effect/EffectMgr.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 27852eca2c3ec374684e63e4ba079b20
+timeCreated: 1501502579
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/PostEffectsBase.cs b/Main/Component/UI/Effect/PostEffectsBase.cs
new file mode 100644
index 0000000..72294cd
--- /dev/null
+++ b/Main/Component/UI/Effect/PostEffectsBase.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects
+{
+    [ExecuteAlways]
+    [RequireComponent (typeof(Camera))]
+    public class PostEffectsBase : MonoBehaviour
+	{
+        protected bool  supportHDRTextures = true;
+        protected bool  supportDX11 = false;
+        protected bool  isSupported = true;
+
+        private List<Material> createdMaterials = new List<Material> ();
+
+        protected Material CheckShaderAndCreateMaterial ( Shader s, Material m2Create)
+		{
+            if (!s)
+			{
+                Debug.Log("Missing shader in " + ToString ());
+                enabled = false;
+                return null;
+            }
+
+            if (s.isSupported && m2Create && m2Create.shader == s)
+                return m2Create;
+
+            if (!s.isSupported)
+			{
+                NotSupported ();
+                Debug.Log("The shader " + s.ToString() + " on effect "+ToString()+" is not supported on this platform!");
+                return null;
+            }
+
+            m2Create = new Material (s);
+            createdMaterials.Add (m2Create);
+            m2Create.hideFlags = HideFlags.DontSave;
+
+            return m2Create;
+		}
+
+
+        protected Material CreateMaterial (Shader s, Material m2Create)
+		{
+            if (!s)
+			{
+                Debug.Log ("Missing shader in " + ToString ());
+                return null;
+            }
+
+            if (m2Create && (m2Create.shader == s) && (s.isSupported))
+                return m2Create;
+
+            if (!s.isSupported)
+			{
+                return null;
+            }
+
+            m2Create = new Material (s);
+            createdMaterials.Add (m2Create);
+            m2Create.hideFlags = HideFlags.DontSave;
+                
+            return m2Create;
+		}
+
+        void OnEnable ()
+		{
+            isSupported = true;
+        }
+
+        void OnDestroy ()
+        {
+            RemoveCreatedMaterials ();    
+        }
+
+        private void RemoveCreatedMaterials ()
+        {
+            while (createdMaterials.Count > 0)
+            {
+                Material mat = createdMaterials[0];
+                createdMaterials.RemoveAt (0);
+#if UNITY_EDITOR
+                DestroyImmediate (mat);
+#else
+                Destroy(mat);
+#endif
+            }
+        }
+
+        protected bool CheckSupport ()
+		{
+            return CheckSupport (false);
+        }
+
+
+        public virtual bool CheckResources ()
+		{
+            Debug.LogWarning ("CheckResources () for " + ToString() + " should be overwritten.");
+            return isSupported;
+        }
+
+
+        protected void Start ()
+		{
+            CheckResources ();
+        }
+
+        protected bool CheckSupport (bool needDepth)
+		{
+            isSupported = true;
+            supportHDRTextures = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf);
+            supportDX11 = SystemInfo.graphicsShaderLevel >= 50 && SystemInfo.supportsComputeShaders;
+
+   //         if (!SystemInfo.supportsImageEffects)
+			//{
+   //             NotSupported ();
+   //             return false;
+   //         }
+
+            if (needDepth && !SystemInfo.SupportsRenderTextureFormat (RenderTextureFormat.Depth))
+			{
+                NotSupported ();
+                return false;
+            }
+
+            if (needDepth)
+                GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+
+            return true;
+        }
+
+        protected bool CheckSupport (bool needDepth,  bool needHdr)
+		{
+            if (!CheckSupport(needDepth))
+                return false;
+
+            if (needHdr && !supportHDRTextures)
+			{
+                NotSupported ();
+                return false;
+            }
+
+            return true;
+        }
+
+
+        public bool Dx11Support ()
+		{
+            return supportDX11;
+        }
+
+
+        protected void ReportAutoDisable ()
+		{
+            Debug.LogWarning ("The image effect " + ToString() + " has been disabled as it's not supported on the current platform.");
+        }
+
+        // deprecated but needed for old effects to survive upgrading
+        bool CheckShader (Shader s)
+		{
+            Debug.Log("The shader " + s.ToString () + " on effect "+ ToString () + " is not part of the Unity 3.2+ effects suite anymore. For best performance and quality, please ensure you are using the latest Standard Assets Image Effects (Pro only) package.");
+            if (!s.isSupported)
+			{
+                NotSupported ();
+                return false;
+            }
+            else
+			{
+                return false;
+            }
+        }
+
+
+        protected void NotSupported ()
+		{
+            enabled = false;
+            isSupported = false;
+            return;
+        }
+
+
+        protected void DrawBorder (RenderTexture dest, Material material)
+		{
+            float x1;
+            float x2;
+            float y1;
+            float y2;
+
+            RenderTexture.active = dest;
+            bool  invertY = true; // source.texelSize.y < 0.0ff;
+            // Set up the simple Matrix
+            GL.PushMatrix();
+            GL.LoadOrtho();
+
+            for (int i = 0; i < material.passCount; i++)
+            {
+                material.SetPass(i);
+
+                float y1_; float y2_;
+                if (invertY)
+                {
+                    y1_ = 1.0f; y2_ = 0.0f;
+                }
+                else
+                {
+                    y1_ = 0.0f; y2_ = 1.0f;
+                }
+
+                // left
+                x1 = 0.0f;
+                x2 = 0.0f + 1.0f/(dest.width*1.0f);
+                y1 = 0.0f;
+                y2 = 1.0f;
+                GL.Begin(GL.QUADS);
+
+                GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
+                GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
+                GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
+                GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
+
+                // right
+                x1 = 1.0f - 1.0f/(dest.width*1.0f);
+                x2 = 1.0f;
+                y1 = 0.0f;
+                y2 = 1.0f;
+
+                GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
+                GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
+                GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
+                GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
+
+                // top
+                x1 = 0.0f;
+                x2 = 1.0f;
+                y1 = 0.0f;
+                y2 = 0.0f + 1.0f/(dest.height*1.0f);
+
+                GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
+                GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
+                GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
+                GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
+
+                // bottom
+                x1 = 0.0f;
+                x2 = 1.0f;
+                y1 = 1.0f - 1.0f/(dest.height*1.0f);
+                y2 = 1.0f;
+
+                GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
+                GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
+                GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
+                GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
+
+                GL.End();
+            }
+
+            GL.PopMatrix();
+        }
+    }
+}
diff --git a/Main/Component/UI/Effect/PostEffectsBase.cs.meta b/Main/Component/UI/Effect/PostEffectsBase.cs.meta
new file mode 100644
index 0000000..a310534
--- /dev/null
+++ b/Main/Component/UI/Effect/PostEffectsBase.cs.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: b6f4318ec6c2bf643a0f9edfeeaba0ec
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
diff --git a/Main/Component/UI/Effect/SpringDecorate.cs b/Main/Component/UI/Effect/SpringDecorate.cs
new file mode 100644
index 0000000..0fed5e7
--- /dev/null
+++ b/Main/Component/UI/Effect/SpringDecorate.cs
@@ -0,0 +1,49 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+[RequireComponent(typeof(RectTransform))]
+public class SpringDecorate : MonoBehaviour
+{
+    [SerializeField] int m_SortOrder = 0;
+
+    GameObject springDecorate = null;
+
+    private void Start()
+    {
+        if (GeneralDefine.UISpringDecorate != 0)
+        {
+            if (springDecorate == null)
+            {
+                springDecorate = UIUtility.CreateWidget("Container_SpringDecorate", "SpringDecorate");
+            }
+            var rectTransform = springDecorate.transform as RectTransform;
+            rectTransform.MatchWhith(this.transform as RectTransform);
+
+            if (m_SortOrder != 0)
+            {
+                var canvas = this.AddMissingComponent<Canvas>();
+                canvas.overrideSorting = true;
+                canvas.sortingLayerName = "UI";
+                canvas.sortingOrder = m_SortOrder;
+            }
+            else
+            {
+                var canvas = this.GetComponent<Canvas>();
+                if (canvas != null)
+                {
+                    DestroyImmediate(canvas);
+                }
+            }
+        }
+        else
+        {
+            if (springDecorate != null)
+            {
+                GameObject.DestroyImmediate(springDecorate);
+            }
+        }
+    }
+
+
+}
diff --git a/Main/Component/UI/Effect/SpringDecorate.cs.meta b/Main/Component/UI/Effect/SpringDecorate.cs.meta
new file mode 100644
index 0000000..253d0f1
--- /dev/null
+++ b/Main/Component/UI/Effect/SpringDecorate.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2f22490435e43864f8b21928175f09be
+timeCreated: 1548641856
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/TimeItem.cs b/Main/Component/UI/Effect/TimeItem.cs
new file mode 100644
index 0000000..32e670e
--- /dev/null
+++ b/Main/Component/UI/Effect/TimeItem.cs
@@ -0,0 +1,52 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class TimeItem
+{
+
+    public float time = 0.0f;
+
+    public Action<Component> func;
+
+    private Component m_Comp;
+
+    private int loopCnt = 0;
+
+    private int m_NowCnt = 0;
+
+    private float m_NowTime = 0.0f;
+
+    public TimeItem(float t, Component comp, int loopCnt, Action<Component> func)
+    {
+        time = t;
+        m_Comp = comp;
+        this.loopCnt = loopCnt;
+        this.func = func;
+    }
+
+    public void Update()
+    {
+        m_NowTime += Time.deltaTime;
+        if (m_NowTime >= time)
+        {
+            if (loopCnt != 0)
+            {
+                m_NowCnt++;
+            }
+            if (m_NowCnt >= loopCnt && loopCnt != 0)
+            {
+                m_NowCnt = 0;
+                m_NowTime = 0.0f;
+                TimeMgr.Instance.UnRegister(m_Comp);
+                func(m_Comp);
+            }
+            else
+            {
+                func(m_Comp);
+                m_NowTime = 0.0f;
+            }
+        }
+    }
+}
diff --git a/Main/Component/UI/Effect/TimeItem.cs.meta b/Main/Component/UI/Effect/TimeItem.cs.meta
new file mode 100644
index 0000000..b7cc322
--- /dev/null
+++ b/Main/Component/UI/Effect/TimeItem.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 12072f9fa6cc5664e8e8113352bfa28a
+timeCreated: 1503584117
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/TimeMgr.cs b/Main/Component/UI/Effect/TimeMgr.cs
new file mode 100644
index 0000000..212af32
--- /dev/null
+++ b/Main/Component/UI/Effect/TimeMgr.cs
@@ -0,0 +1,265 @@
+锘縰sing System;
+using System.Collections.Generic;
+using UnityEngine;
+
+
+public class TimeMgr : SingletonMonobehaviour<TimeMgr>
+
+{
+    private Dictionary<Component, TimeItem> timeItems = new Dictionary<Component, TimeItem>();
+    private List<TimeItem> timeItemList = new List<TimeItem>();
+    private int hourBuff = -1;
+    private int minuteBuff = -1;
+    public int dayBuff = -1;
+    public int monthBuff { get { return LocalSave.GetInt("month"); } private set { LocalSave.SetInt("month", value); } }
+    public int weekBuff { get { return LocalSave.GetInt("week"); } private set { LocalSave.SetInt("week", value); } }
+    public event Action OnDayEvent;
+    public event Action OnHourEvent;
+    public event Action OnMinuteEvent;
+    public event Action OnMonthAfterPlayerDataInitializeEvent;
+    public event Action OnWeekAfterPlayerDataInitializeEvent;
+
+    private void LateUpdate()
+    {
+        try
+        {
+            if (weekBuff != GetWeekOfYear(TimeUtility.ServerNow))
+            {
+                if (OnWeekAfterPlayerDataInitializeEvent != null && DTC0102_tagCDBPlayer.isAfterPlayerDataInitialize)
+                {
+
+                    OnWeekAfterPlayerDataInitializeEvent();
+                    weekBuff = GetWeekOfYear(TimeUtility.ServerNow);
+                }
+            }
+            if (monthBuff != TimeUtility.ServerNow.Month)
+            {
+                if (OnMonthAfterPlayerDataInitializeEvent != null && DTC0102_tagCDBPlayer.isAfterPlayerDataInitialize)
+                {
+                    OnMonthAfterPlayerDataInitializeEvent();
+                    monthBuff = TimeUtility.ServerNow.Month;
+                }
+            }
+            if (dayBuff != TimeUtility.ServerNow.Day)
+            {
+                if (OnDayEvent != null)
+                {
+                    OnDayEvent();
+                }
+                dayBuff = TimeUtility.ServerNow.Day;
+            }
+            if (hourBuff != TimeUtility.ServerNow.Hour)
+            {
+                if (OnHourEvent != null)
+                {
+                    OnHourEvent();
+                }
+                hourBuff = TimeUtility.ServerNow.Hour;
+            }
+            if (minuteBuff != TimeUtility.ServerNow.Minute)
+            {
+                if (OnMinuteEvent != null)
+                {
+                    OnMinuteEvent();
+                }
+                minuteBuff = TimeUtility.ServerNow.Minute;
+            }
+        }
+        catch (Exception e)
+        {
+            DebugEx.Log(e.StackTrace);
+        }
+        for (int i = 0; i < syntonyList.Count; i++)
+        {
+            if ((TimeUtility.ServerNow - syntonyList[i].endTime).TotalSeconds > 0)
+            {
+                if (syntonyList[i].callback != null)
+                {
+                    syntonyList[i].callback();
+                }
+                var _type = syntonyList[i].type;
+                syntonyList.RemoveAt(i);
+                if (OnSyntonyEvent != null)
+                {
+                    OnSyntonyEvent(_type);
+                }
+                i--;
+            }
+        }
+        if (timeItems.Count > 0)
+        {
+            timeItemList.RemoveRange(0, timeItemList.Count);
+            foreach (Component item in timeItems.Keys)
+            {
+                if (item == null) continue;
+                timeItemList.Add(timeItems[item]);
+            }
+            for (int i = 0; i < timeItemList.Count; i++)
+            {
+                timeItemList[i].Update();
+            }
+        }
+    }
+
+    //鑾峰彇褰撳墠datatime鏄粖骞寸殑绗嚑鍛�
+    int GetWeekOfYear(DateTime date)
+    {
+        // 鑾峰彇璇ュ勾绗竴澶�
+        DateTime firstDayOfYear = new DateTime(date.Year, 1, 1);
+
+        // 璁$畻绗竴鍛ㄧ殑寮�濮嬫棩鏈燂紙濡傛灉1鏈�1鏃ヤ笉鏄懆涓�锛屽垯鍚戝墠鎺ㄥ埌鏈�杩戠殑鍛ㄤ竴锛�
+        int daysOffset = DayOfWeek.Thursday - firstDayOfYear.DayOfWeek;
+
+        // 濡傛灉鏄懆浜斻�佸懆鍏�佸懆鏃ワ紝鎴戜滑闇�瑕佸悜鍚庢帹
+        if (daysOffset < 0)
+            daysOffset += 7;
+
+        // 璁$畻璇ュ勾绗竴涓懆鍥涚殑鏃ユ湡
+        DateTime firstThursday = firstDayOfYear.AddDays(daysOffset);
+
+        // 璁$畻缁欏畾鏃ユ湡涓庣涓�涓懆鍥涗箣闂寸殑澶╂暟宸�
+        int daysSinceFirstThursday = (date - firstThursday).Days;
+
+        // 璁$畻鍛ㄦ暟
+        int weekNumber = (daysSinceFirstThursday / 7) + 1;
+
+        // 澶勭悊骞村垵鍜屽勾鏈殑鐗规畩鎯呭喌
+        if (weekNumber < 1)
+        {
+            // 濡傛灉鍛ㄦ暟灏忎簬1锛岃鏄庢槸涓婁竴骞寸殑鏈�鍚庝竴鍛�
+            return GetWeekOfYear(new DateTime(date.Year - 1, 12, 31));
+        }
+        else if (weekNumber > 52)
+        {
+            // 璁$畻涓嬩竴骞寸殑绗竴涓懆鍥�
+            DateTime nextYearFirstDay = new DateTime(date.Year + 1, 1, 1);
+            int nextYearDaysOffset = DayOfWeek.Thursday - nextYearFirstDay.DayOfWeek;
+            if (nextYearDaysOffset < 0)
+                nextYearDaysOffset += 7;
+            DateTime nextYearFirstThursday = nextYearFirstDay.AddDays(nextYearDaysOffset);
+
+            // 濡傛灉缁欏畾鏃ユ湡鍦ㄤ笅涓�骞寸殑绗竴涓懆鍥涗箣鍓嶏紝閭d箞瀹冨睘浜庢湰骞寸殑鏈�鍚庝竴鍛�
+            if (date < nextYearFirstThursday)
+            {
+                return weekNumber;
+            }
+            else
+            {
+                // 鍚﹀垯锛岃繖鏄笅涓�骞寸殑绗竴鍛�
+                return 1;
+            }
+        }
+
+        return weekNumber;
+    }
+
+    public void Register(Component comp, Action<Component> func, float t, int loopCnt = 1)
+    {
+        if (comp == null) return;
+        if (!timeItems.ContainsKey(comp))
+        {
+            TimeItem item = new TimeItem(t, comp, loopCnt, func);
+            timeItems.Add(comp, item);
+        }
+    }
+
+    public void SetInterval(Component comp, float t)
+    {
+        if (timeItems.ContainsKey(comp))
+        {
+            TimeItem item = timeItems[comp];
+            item.time = t;
+        }
+    }
+
+    public void UnRegister(Component comp)
+    {
+        if (comp == null) return;
+        if (timeItems.ContainsKey(comp))
+        {
+            TimeItem item = timeItems[comp];
+            timeItems.Remove(comp);
+            item = null;
+        }
+    }
+
+    public bool IsRegister(Component comp)
+    {
+        return timeItems.ContainsKey(comp);
+    }
+
+    public void Register(SyntonyType type, float _totalTime, Action _func = null)
+    {
+        int index;
+        if (ContainsSyntony(type, out index))
+        {
+            syntonyList[index].SetTime(_totalTime, _func);
+        }
+        else
+        {
+            Syntony syntony = new Syntony();
+            syntony.type = type;
+            syntony.SetTime(_totalTime, _func);
+            syntonyList.Add(syntony);
+        }
+    }
+
+    public void UnRegister(SyntonyType type)
+    {
+        int index;
+        if (ContainsSyntony(type, out index))
+        {
+            syntonyList.RemoveAt(index);
+        }
+    }
+
+    public struct Syntony
+    {
+        public SyntonyType type;
+        public DateTime endTime { get; private set; }
+        public Action callback;
+        public void SetTime(float _totalTime, Action _func = null)
+        {
+            endTime = TimeUtility.ServerNow.AddSeconds(_totalTime);
+            callback = _func;
+            DebugEx.LogFormat("{0}{1}", type, endTime);
+        }
+    }
+
+    private List<Syntony> syntonyList = new List<Syntony>();
+
+    public event Action<SyntonyType> OnSyntonyEvent;
+
+    private bool ContainsSyntony(SyntonyType type, out int index)
+    {
+        index = 0;
+        for (int i = 0; i < syntonyList.Count; i++)
+        {
+            if (syntonyList[i].type == type)
+            {
+                index = i;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public enum SyntonyType
+    {
+        PrayerRedpoint,
+        BossShow,
+        BossShowName,
+        BossShowDialogue,
+        BossShowSound,
+        FairyLeaugeStage,
+        VipExperirnceOverdue,
+        HeavenBattleState,
+        Realm,
+        RealmSit,
+        GuardHurtEffect,
+        GetFairyInfo,
+        Audio,
+        OSRedEnvelope,
+        AutoPlayVoice,
+    }
+}
diff --git a/Main/Component/UI/Effect/TimeMgr.cs.meta b/Main/Component/UI/Effect/TimeMgr.cs.meta
new file mode 100644
index 0000000..a5b5895
--- /dev/null
+++ b/Main/Component/UI/Effect/TimeMgr.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 63bade02b606f5848aa390ce20062b08
+timeCreated: 1503584100
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/UIEffect.cs b/Main/Component/UI/Effect/UIEffect.cs
new file mode 100644
index 0000000..bf8bdbb
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffect.cs
@@ -0,0 +1,298 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using UnityEngine.Rendering;
+using vnxbqy.UI;
+using UnityEngine.UI;
+
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+
+public class UIEffect : MonoBehaviour
+{
+    public int renderQueue = 3000;
+    public int effect = 0;
+    public UIEffectBehaviour target;
+    public Vector3 effectPos = Vector3.zero;
+    public Vector3 effectRot = Vector3.zero;
+    public Vector3 effectScl = Vector3.one;
+    public bool playOnAwake = false;
+    public bool loop = false;
+    public bool keep = false;
+    public float duration { get; private set; }
+    public bool IsPlaying { get; protected set; }
+    public Action OnComplete;
+    [SerializeField] RectTransform m_MaskArea;
+    public RectTransform maskArea
+    {
+        get { return m_MaskArea; }
+        set { m_MaskArea = value; }
+    }
+    private Window retrospectWindow;
+    private Coroutine stopCoroutine = null;
+    public void Play()
+    {
+        if (EffectMgr.Instance.IsNotShowBySetting(effect))
+            return;
+        if (target != null)
+        {
+            StopImediatly();
+        }
+        if (stopCoroutine != null)
+        {
+            SnxxzGame.Instance.StopCoroutine(stopCoroutine);
+        }
+        target = EffectMgr.Instance.GetUIEffect(effect, true);
+        if (target != null)
+        {
+            Active();
+        }
+    }
+
+    public void Active()
+    {
+        target.SetActive(true);
+        target.transform.SetParent(this.transform);
+        retrospectWindow = RetrospectWindow(transform);
+        duration = target.duration;
+        target.SetOrder(renderQueue);
+        target.transform.localPosition = effectPos;
+        target.transform.localEulerAngles = effectRot;
+        target.transform.localScale = effectScl;
+        target.SetParticlesScale(effectScl);
+        RockonEffect();
+        IsPlaying = true;
+        var _effectCfg = EffectConfig.Get(effect);
+        if (_effectCfg != null)
+        {
+            SoundPlayer.Instance.PlayUIAudio(_effectCfg.audio);
+        }
+        SetMask();
+    }
+
+    public void ResetOrder(int _order)
+    {
+        renderQueue = _order;
+        if (target != null)
+        {
+            target.SetOrder(renderQueue);
+        }
+    }
+
+    public void SetMask()
+    {
+        if (target == null)
+        {
+            return;
+        }
+        if (maskArea != null)
+        {
+            target.PerformMask(maskArea);
+            return;
+        }
+        var _masks = GetComponentsInParent<RectMask2D>(true);
+        if (_masks != null && _masks.Length > 0)
+        {
+            target.PerformMask(_masks);
+        }
+        else
+        {
+            var _smoothMask = GetComponentsInParent<SmoothMask>(true);
+            if (_smoothMask != null && _smoothMask.Length > 0)
+            {
+                target.PerformMask(_smoothMask[0].rectTransform);
+                return;
+            }
+            target.PerformMask(GetComponentsInParent<Mask>(true));
+        }
+    }
+
+    private void OnWinPreClose(Window _window)
+    {
+        if (retrospectWindow != null)
+        {
+            if (retrospectWindow == _window)
+            {
+                StopImediatly();
+            }
+        }
+    }
+    private void RockonEffect()
+    {
+        if (!loop)
+        {
+            this.SetWait(duration);
+            this.DoWaitRestart();
+            this.OnWaitCompelete(OnEffectComplete);
+        }
+    }
+    private void OnEffectComplete(Component comp)
+    {
+        this.DoWaitStop();
+        if (target != null)
+        {
+            if (!keep)
+            {
+                EffectMgr.Instance.RecyleUIEffect(effect, target.gameObject);
+                target = null;
+            }
+            if (OnComplete != null)
+            {
+                OnComplete();
+            }
+        }
+        IsPlaying = false;
+    }
+
+    private void OnEnable()
+    {
+        WindowCenter.Instance.windowBeforeCloseEvent += OnWinPreClose;
+        if (playOnAwake)
+        {
+            Play();
+        }
+    }
+
+    private void OnDisable()
+    {
+        WindowCenter.Instance.windowBeforeCloseEvent -= OnWinPreClose;
+        if (target != null && !playOnAwake)
+        {
+            stopCoroutine = SnxxzGame.Instance.StartCoroutine(Co_StopEffect());
+        }
+    }
+
+    public void Stop()
+    {
+        OnEffectComplete(this);
+    }
+    public void StopImediatly()
+    {
+        this.DoWaitStop();
+        if (target != null)
+        {
+            EffectMgr.Instance.RecyleUIEffect(effect, target.gameObject);
+            target = null;
+        }
+        IsPlaying = false;
+    }
+    public void SetLayer(int _layer)
+    {
+        if (target != null)
+        {
+            target.gameObject.SetLayer(_layer, true);
+        }
+    }
+    IEnumerator Co_StopEffect()
+    {
+        yield return null;
+        StopImediatly();
+    }
+    private Window RetrospectWindow(Transform parent)
+    {
+        if (parent == null)
+        {
+            return null;
+        }
+        Window window = null;
+        window = parent.GetComponent<Window>();
+        if (window != null)
+        {
+            return window;
+        }
+        else
+        {
+            return RetrospectWindow(parent.parent);
+        }
+    }
+
+    private const string EDITOR_EFFECT_PATH = "Assets/ResourcesOut/Effect/UI/";
+    private const string EFFECT_EXTENAL = ".prefab";
+    public void Preview(string _name)
+    {
+#if UNITY_EDITOR
+        if (target != null)
+        {
+            DestroyImmediate(target);
+        }
+        var _prefab = AssetDatabase.LoadAssetAtPath<GameObject>(StringUtility.Contact(EDITOR_EFFECT_PATH, _name, EFFECT_EXTENAL));
+        if (_prefab != null)
+        {
+            _prefab = Instantiate(_prefab);
+        }
+        target = _prefab.AddComponent<UIEffectBehaviour>();
+        target.SetActive(true);
+        target.transform.SetParent(this.transform);
+        target.SetOrder(renderQueue);
+        //target.PerformMask(GetComponentsInParent<RectMask2D>(true));
+        target.transform.localPosition = Vector3.zero;
+        target.transform.localEulerAngles = Vector3.zero;
+        target.transform.localScale = Vector3.one;
+        Selection.activeGameObject = target.gameObject;
+#endif
+    }
+
+}
+#if UNITY_EDITOR
+[CustomEditor(typeof(UIEffect))]
+[CanEditMultipleObjects]
+public class UIEffectEditor : Editor
+{
+    public UIEffect uieffect;
+    private string effectPath = string.Empty;
+
+    private void OnEnable()
+    {
+        if (target != null)
+        {
+            uieffect = target as UIEffect;
+        }
+    }
+
+    public override void OnInspectorGUI()
+    {
+        if (uieffect == null)
+        {
+            return;
+        }
+        EditorGUILayout.BeginHorizontal();
+        effectPath = EditorGUILayout.TextField("Effect Path", effectPath);
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        if (GUILayout.Button("Preview"))
+        {
+            uieffect.Preview(effectPath);
+        }
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        uieffect.playOnAwake = EditorGUILayout.Toggle("OnEnable", uieffect.playOnAwake);
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        uieffect.effect = EditorGUILayout.IntField("Effect ID", uieffect.effect);
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        uieffect.renderQueue = EditorGUILayout.IntField("RenderQueue", uieffect.renderQueue);
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        uieffect.loop = EditorGUILayout.Toggle("Loop", uieffect.loop);
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        uieffect.maskArea = EditorGUILayout.ObjectField("Mask", uieffect.maskArea, typeof(RectTransform), true) as RectTransform;
+        EditorGUILayout.EndHorizontal();
+        EditorGUILayout.BeginHorizontal();
+        if (GUILayout.Button("ResetOrder"))
+        {
+            uieffect.target.SetOrder(uieffect.renderQueue);
+        }
+        EditorGUILayout.EndHorizontal();
+
+        EditorGUILayout.BeginHorizontal();
+        uieffect.effectScl = EditorGUILayout.Vector3Field("Scale", uieffect.effectScl);
+        EditorGUILayout.EndHorizontal();
+    }
+}
+#endif
+
diff --git a/Main/Component/UI/Effect/UIEffect.cs.meta b/Main/Component/UI/Effect/UIEffect.cs.meta
new file mode 100644
index 0000000..6e586b5
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 39dcca0c219ff5543b682ac83ebbbe74
+timeCreated: 1503409144
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/UIEffectBehaviour.cs b/Main/Component/UI/Effect/UIEffectBehaviour.cs
new file mode 100644
index 0000000..729a241
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffectBehaviour.cs
@@ -0,0 +1,158 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+namespace vnxbqy.UI
+{
+    public class UIEffectBehaviour : MonoBehaviour
+    {
+        private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
+        private List<Animator> m_Animators = new List<Animator>();
+        private List<Renderer> m_Renderers = new List<Renderer>();
+
+        public float duration { get; private set; }
+        private Vector3 m_RectMaskPosition;
+        private bool m_RectMaskEnable;
+        private RectTransform m_RectMask;
+
+        public bool IsAnimatorControl { get; private set; }
+
+        private void Awake()
+        {
+            GetComponent();
+            this.gameObject.SetLayer(LayerUtility.UIEffectLayer, true);
+        }
+
+        public void SetParticlesScale(Vector3 _scale)
+        {
+            if (_scale != Vector3.one)
+            foreach (var par in m_Particles)
+            {
+                par.transform.localScale = _scale;
+            }
+        }
+
+
+        public void SetOrder(int _order)
+        {
+            foreach (var _renderer in m_Renderers)
+            {
+                _renderer.sortingOrder = _order;
+                _renderer.sortingLayerName = "UI";
+            }
+        }
+
+        public void PerformMask(RectMask2D[] _masks)
+        {
+            RectTransform _rect = null;
+            var _mask = _masks == null || _masks.Length == 0 ? null : _masks[0];
+            if (_mask == null)
+            {
+                 _rect = null;
+            }
+            else
+            {
+                _rect = _mask.rectTransform;
+            }
+            PerformMask(_rect);
+        }
+
+        public void PerformMask(Mask[] _masks)
+        {
+            RectTransform _rect = null;
+            var _mask = _masks == null || _masks.Length == 0 ? null : _masks[0];
+            if (_mask == null)
+            {
+                _rect = null;
+            }
+            else
+            {
+                _rect = _mask.rectTransform;
+            }
+            PerformMask(_rect);
+        }
+
+        public void PerformMask(RectTransform _mask)
+        {
+            m_RectMask = _mask;
+            m_RectMaskEnable = _mask != null;
+            if (_mask != null)
+            {
+                m_RectMaskPosition = _mask.position;
+                _mask.GetWorldCorners(s_RectMask);
+                s_ClipRect.x = s_RectMask[0].x; s_ClipRect.y = s_RectMask[0].y;
+                s_ClipRect.z = s_RectMask[2].x; s_ClipRect.w = s_RectMask[2].y;
+            }
+            foreach (var _renderer in m_Renderers)
+            {
+                var _mat = _renderer.material;
+                SetClipRect(_mat, s_ClipRect, m_RectMaskEnable);
+            }
+        }
+
+        private void GetComponent()
+        {
+            transform.GetComponentsInChildren(true, m_Renderers);
+            IsAnimatorControl = false;
+            TraverseChild(transform);
+        }
+
+        private void TraverseChild(Transform parent)
+        {
+            ParticleSystem particle = parent.GetComponent<ParticleSystem>();
+            if (particle != null)
+            {
+                if (particle.main.duration > duration && !IsAnimatorControl)
+                {
+                    duration = particle.main.duration;
+                }
+                m_Particles.Add(particle);
+            }
+            Animator animator = parent.GetComponent<Animator>();
+            if (animator != null)
+            {
+                m_Animators.Add(animator);
+                AnimatorStateInfo state = animator.GetCurrentAnimatorStateInfo(0);
+                duration = state.length > duration ? state.length : duration;
+                IsAnimatorControl = true;
+            }
+            foreach (Transform child in parent)
+            {
+                TraverseChild(child);
+            }
+        }
+
+        private Vector4 s_ClipRect = Vector4.zero;
+        private Vector3[] s_RectMask = new Vector3[4];
+
+        private void SetClipRect(Material _mat, Vector4 _clipRect, bool _mask)
+        {
+            _mat.SetVector("_ClipRect", _clipRect);
+            _mat.SetFloat("_UseClipRect", _mask ? 1 : 0);
+        }
+
+        public Animator GetAnimator()
+        {
+            if (IsAnimatorControl && m_Animators.Count > 0)
+            {
+                return m_Animators[0];
+            }
+            return null;
+        }
+
+        private void LateUpdate()
+        {
+            if (m_RectMask != null && (m_RectMaskPosition != m_RectMask.position))
+            {
+                m_RectMaskPosition = m_RectMask.position;
+                PerformMask(m_RectMask);
+            }
+        }
+
+        private void OnDisable()
+        {
+            m_RectMask = null;
+        }
+    }
+}
+
diff --git a/Main/Component/UI/Effect/UIEffectBehaviour.cs.meta b/Main/Component/UI/Effect/UIEffectBehaviour.cs.meta
new file mode 100644
index 0000000..bcdc61b
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffectBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8876d172a02c7e84e93a167132081f51
+timeCreated: 1517986550
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Effect/UIEffectTransmitController.cs b/Main/Component/UI/Effect/UIEffectTransmitController.cs
new file mode 100644
index 0000000..ba4b672
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffectTransmitController.cs
@@ -0,0 +1,48 @@
+锘縰sing UnityEngine;
+
+public class UIEffectTransmitController : MonoBehaviour
+{
+    public Transform start;
+    public Transform end;
+    public UIEffect transmit;
+    public int scale = 1; //鏍规嵁鐣岄潰鑷璋冩暣姣斾緥
+
+    private void Update()
+    {
+
+        if (transform == null)
+        {
+            return;
+        }
+
+        if (transmit == null)
+        {
+            return;
+        }
+
+        if (start == null)
+        {
+            return;
+        }
+
+        if (end == null)
+        {
+            return;
+        }
+
+        transmit.transform.position = start.position;
+        transmit.transform.localScale = new Vector3(Vector3.Distance(end.position, start.position) * scale, 1, 1);
+        //transmit.transform.localRotation.z 鍊兼牴鎹� end鍜宻tart鐨勪綅缃绠�, end鍦╯tart鐨勫彸杈规椂,localRotation.z = 0, end鍦╯tart鐨勫乏杈规椂,localRotation.z = 180
+        float angle = Mathf.Atan2(end.position.y - start.position.y, end.position.x - start.position.x) * Mathf.Rad2Deg;
+        transmit.transform.localRotation = Quaternion.Euler(0, 0, angle);
+
+    }
+
+    private void OnDisable()
+    {
+        start = null;
+        end = null;
+        transmit = null;
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Component/UI/Effect/UIEffectTransmitController.cs.meta b/Main/Component/UI/Effect/UIEffectTransmitController.cs.meta
new file mode 100644
index 0000000..47e7eef
--- /dev/null
+++ b/Main/Component/UI/Effect/UIEffectTransmitController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ef9791258cf62d544871c2a0c053d930
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/EnhancedScroller.meta b/Main/Component/UI/EnhancedScroller.meta
new file mode 100644
index 0000000..09c81b0
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 4cecc386fc2f1b74687c451b5c18dc00
+folderAsset: yes
+timeCreated: 1504508766
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs b/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs
new file mode 100644
index 0000000..8a2ace4
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs
@@ -0,0 +1,2260 @@
+锘縰sing UnityEngine;
+using UnityEngine.UI;
+using System.Collections;
+using System;
+using System.Collections.Generic;
+
+namespace EnhancedUI.EnhancedScroller
+{
+    /// <summary>
+    /// This delegate handles the visibility changes of cell views
+    /// </summary>
+    /// <param name="cellView">The cell view that changed visibility</param>
+    public delegate void CellViewVisibilityChangedDelegate(EnhancedScrollerCellView cellView);
+    //濮旀墭 褰撳彲瑙佹�ф敼鍙樻椂锛屼紶鍏ョ殑鏄綋鍓嶆敼鍙樼殑CellView瀵硅薄锛堝璞$户鎵胯嚜EnhancedScrollerCellView) 浜嬩欢鍦� AddCellView鍜宊RecycleCell涓Е鍙�
+
+    /// <summary>
+    /// This delegate handles the scrolling callback of the ScrollRect.
+    /// </summary>
+    /// <param name="scroller">The scroller that called the delegate</param>
+    /// <param name="val">The scroll value of the scroll rect</param>
+    /// <param name="scrollPosition">The scroll position in pixels from the start of the scroller</param>
+    public delegate void ScrollerScrolledDelegate(EnhancedScroller scroller, Vector2 val, float scrollPosition);
+    //濮旀墭 褰搒croll valuechange 鏃讹紝鍦╫nvaluechange浜嬩欢涓Е鍙�
+
+    /// <summary>
+    /// This delegate handles the snapping of the scroller.
+    /// </summary>
+    /// <param name="scroller">The scroller that called the delegate</param>
+    /// <param name="cellIndex">The index of the cell view snapped on (this may be different than the data index in case of looping)</param>
+    /// <param name="dataIndex">The index of the data the view snapped on</param>
+    public delegate void ScrollerSnappedDelegate(EnhancedScroller scroller, int cellIndex, int dataIndex);
+    //濮旀墭 褰搒nap瀹屾垚鏃讹紝 鍦⊿napJumpComplete鏃惰Е鍙�(褰撳紑鍚痵nap鏃讹紝姣忔婊戝姩鍚庨兘浼氬幓杩涜瀹氫綅锛屽綋瀹氫綅鍚庡氨浼氳皟鐢⊿napJumpComplete锛�
+
+    /// <summary>
+    /// This delegate handles the change in state of the scroller (scrolling or not scrolling)
+    /// </summary>
+    /// <param name="scroller">The scroller that changed state</param>
+    /// <param name="scrolling">Whether or not the scroller is scrolling</param>
+    public delegate void ScrollerScrollingChangedDelegate(EnhancedScroller scroller, bool scrolling);
+    //濮旀墭 褰搒croll.velocity寮�濮嬩笉涓�0 鎴栦负0 鏃� 锛屽湪Update涓Е鍙戯紙鍗冲綋寮�濮嬫粦鍔ㄦ椂鎴栧綋鍋滄婊戝姩鏃惰Е鍙戯紝浠elocity涓哄熀鍑嗭紝涓�0鍜屼笉涓�0鏃跺垎鍒Е鍙戜竴娆★級
+
+    /// <summary>
+    /// This delegate handles the change in state of the scroller (jumping or not jumping)
+    /// </summary>
+    /// <param name="scroller">The scroller that changed state</param>
+    /// <param name="tweening">Whether or not the scroller is tweening</param>
+    public delegate void ScrollerTweeningChangedDelegate(EnhancedScroller scroller, bool tweening);
+    //濮旀墭 褰撳紑濮嬫挱鏀綯ween鍜屽仠姝ween鏃惰皟鐢� 锛屽湪JumpToDataIndex涓鏋滀娇鐢═ween杩涜杩囨浮瀹氫綅鏃讹紝浼氬湪寮�濮嬫挱鏀炬椂鍜岀粨鏉熸椂鍚勮Е鍙戜竴娆�
+
+    /// <summary>
+    /// The EnhancedScroller allows you to easily set up a dynamic scroller that will recycle views for you. This means
+    /// that using only a handful of views, you can display thousands of rows. This will save memory and processing
+    /// power in your application.
+    /// </summary>
+    [RequireComponent(typeof(ScrollRect))]
+    public class EnhancedScroller : MonoBehaviour
+    {
+        #region Public
+
+        /// <summary>
+        /// The direction this scroller is handling
+        /// </summary>
+        public enum ScrollDirectionEnum//婊戝姩鏂瑰紡
+        {
+            Vertical,
+            Horizontal
+        }
+
+        /// <summary>
+        /// Which side of a cell to reference.
+        /// For vertical scrollers, before means above, after means below.
+        /// For horizontal scrollers, before means to left of, after means to the right of.
+        /// </summary>
+        public enum CellViewPositionEnum//褰撳墠CellViewPrefab鐨勪笂鏂硅繕鏄笅鏂�
+        {
+            Before,
+            After
+        }
+
+        /// <summary>
+        /// This will set how the scroll bar should be shown based on the data. If no scrollbar
+        /// is attached, then this is ignored. OnlyIfNeeded will hide the scrollbar based on whether
+        /// the scroller is looping or there aren't enough items to scroll.
+        /// </summary>
+        public enum ScrollbarVisibilityEnum//鏄惁鏈夋粦鍔ㄦ潯锛屽湪looping妯″紡涓嬫槸涓嶄細鏄剧ず鐨�
+        {
+            OnlyIfNeeded,
+            Always,
+            Never
+        }
+
+        /// <summary>
+        /// The direction the scroller is handling
+        /// </summary>
+        public ScrollDirectionEnum scrollDirection;
+
+        /// <summary>
+        /// The number of pixels between cell views, starting after the first cell view
+        /// </summary>
+        public float spacing;
+
+        /// <summary>
+        /// The padding inside of the scroller: top, bottom, left, right.
+        /// </summary>
+        public RectOffset padding;
+
+        /// <summary>
+        /// Whether the scroller should loop the cell views
+        /// </summary>
+        [SerializeField]
+        private bool loop;
+
+        /// <summary>
+        /// Whether the scollbar should be shown
+        /// </summary>
+        [SerializeField]
+        private ScrollbarVisibilityEnum scrollbarVisibility;
+
+        /// <summary>
+        /// Whether snapping is turned on
+        /// </summary>
+        public bool snapping;//鏄惁寮�鍚畾浣�
+
+        /// <summary>
+        /// This is the speed that will initiate the snap. When the
+        /// scroller slows down to this speed it will snap to the location
+        /// specified.
+        /// </summary>
+        public float snapVelocityThreshold;//妫�娴嬪畾浣嶇殑闃�鍊硷紝褰撲綆浜庤繖涓�肩殑鏃跺�欏氨浼氳Е鍙戝畾浣�
+
+        /// <summary>
+        /// The snap offset to watch for. When the snap occurs, this
+        /// location in the scroller will be how which cell to snap to 
+        /// is determined.
+        /// Typically, the offset is in the range 0..1, with 0 being
+        /// the top / left of the scroller and 1 being the bottom / right.
+        /// In most situations the watch offset and the jump offset 
+        /// will be the same, they are just separated in case you need
+        /// that added functionality.
+        /// </summary>
+        public float snapWatchOffset;//瀹氫綅鍚庡綋鍓岰ellVeiw鍦ㄥ彲瑙嗗尯鍩熷唴鍋忕Щ锛屽綋涓�0鏃跺畾浣嶅湪鏈�涓婃柟锛屼负1鏃跺畾浣嶅湪鏈�涓嬫柟
+
+        /// <summary>
+        /// The snap location to move the cell to. When the snap occurs,
+        /// this location in the scroller will be where the snapped cell
+        /// is moved to.
+        /// Typically, the offset is in the range 0..1, with 0 being
+        /// the top / left of the scroller and 1 being the bottom / right.
+        /// In most situations the watch offset and the jump offset 
+        /// will be the same, they are just separated in case you need
+        /// that added functionality.
+        /// </summary>
+        public float snapJumpToOffset;//璁剧疆瀹氫綅鐨勫亸绉伙紝瀹炶川涓婄粨鏋滃拰snapWatchOffset涓�鏍凤紝涔熸槸鍦�0~1涔嬮棿锛屽鍔犺繖涓睘鎬т富瑕佹槸鑰冭檻鍒板彲鑳戒細鍑虹幇涓�浜涚壒娈婃儏鍐佃浣跨敤鍒板畠
+
+        /// <summary>
+        /// Once the cell has been snapped to the scroller location, this
+        /// value will determine how the cell is centered on that scroller
+        /// location. 
+        /// Typically, the offset is in the range 0..1, with 0 being
+        /// the top / left of the cell and 1 being the bottom / right.
+        /// </summary>
+        public float snapCellCenterOffset;//璁剧疆琚畾浣嶇殑CellVeiw瀹氫綅鍚庣殑涓績鍋忕Щ锛�0~1涔嬮棿鍙栧�硷紝濡傛灉榛樿鐨勮瘽浼氫互瀹冪殑涓婇儴涓哄熀鍑嗭紝涓嶈埇鏉ヨ搴旇璁剧疆涓�0.5锛屽畾浣嶅埌姝d腑蹇�
+
+        /// <summary>
+        /// Whether to include the spacing between cells when determining the
+        /// cell offset centering.
+        /// </summary>
+        public bool snapUseCellSpacing;//寮�鍚繖涓睘鎬х殑鏃跺�欙紝璁$畻瀹氫綅鍚庣殑鍋忕Щ灏嗗寘鎷畠鐨勪笂涓嬩袱涓棿璺濓紝鍚﹀垯鍗充娇鏈夐棿璺濅篃涓嶄細绾冲叆璁$畻鑼冨洿鍐�
+
+        /// <summary>
+        /// What function to use when interpolating between the current 
+        /// scroll position and the snap location. This is also known as easing. 
+        /// If you want to go immediately to the snap location you can either 
+        /// set the snapTweenType to immediate or set the snapTweenTime to zero.
+        /// </summary>
+        public TweenType snapTweenType;//瀹氫綅鏃舵挱鏀惧姩鐢荤殑绫诲瀷
+
+        /// <summary>
+        /// The time it takes to interpolate between the current scroll 
+        /// position and the snap location.
+        /// If you want to go immediately to the snap location you can either 
+        /// set the snapTweenType to immediate or set the snapTweenTime to zero.
+        /// </summary>
+        public float snapTweenTime;//鎾斁鍔ㄧ敾鐨勬�绘椂闀�
+
+        public Action OnCompLoad;
+
+        /// <summary>
+        /// This delegate is called when a cell view is hidden or shown
+        /// </summary>
+        public CellViewVisibilityChangedDelegate cellViewVisibilityChanged;
+
+        /// <summary>
+        /// This delegate is called when the scroll rect scrolls
+        /// </summary>
+        public ScrollerScrolledDelegate scrollerScrolled;
+
+        /// <summary>
+        /// This delegate is called when the scroller has snapped to a position
+        /// </summary>
+        public ScrollerSnappedDelegate scrollerSnapped;
+
+        /// <summary>
+        /// This delegate is called when the scroller has started or stopped scrolling
+        /// </summary>
+        public ScrollerScrollingChangedDelegate scrollerScrollingChanged;
+
+        /// <summary>
+        /// This delegate is called when the scroller has started or stopped tweening
+        /// </summary>
+        public ScrollerTweeningChangedDelegate scrollerTweeningChanged;
+
+        /// <summary>
+        /// The Delegate is what the scroller will call when it needs to know information about
+        /// the underlying data or views. This allows a true MVC process.
+        /// </summary>
+        public IEnhancedScrollerDelegate Delegate { get { return _delegate; } set { _delegate = value; _reloadData = true; } }
+        /*杩欓噷瑕佸皢涓�涓疄鐜颁簡IEnhancedScrollerDelegate鎺ュ彛鐨勭被鐨勫璞¤祴鍊艰繃鏉ワ紝杩欎釜瀵硅薄鐢ㄤ簬鎺у埗鏁翠釜Scroll,閫氳繃瀹炵幇杩欎釜鎺ュ彛鐨勫嚑涓柟娉�
+         * 鍙互瀹氫箟锛� 1. 褰撳墠CellVeiw鐨勬�绘暟鐩� 
+         * 
+         * 2. 鏌恉ataIndex瀵瑰簲鐨凜ellView鍏冪礌鐨剆ize 
+         * 
+         * 3.濡備綍鑾峰彇锛堜粠寰幆姹犻噷鍙栵紝鎴栧疄渚嬪寲锛変竴涓狢ellView
+         * 骞跺緱鍒板叾CellView瀵硅薄锛岃�岃繖涓璞″張缁ф壙鑷狤nhancedScrollerCellView锛�
+         * 鎵�浠ュ疄闄呬笂鑾峰彇浜嗚繖涓狢ellView鐨� 锛�
+         * 1.cellIdentifier锛坰croll瀛樺湪涓嶅悓Prefab鏃剁敤浜庡尯鍒嗙殑瀛楃涓诧級
+         * 2.cellIndex  dataIndex 锛坉ataIndex浠h〃鐨勬槸瑕佸惊鐜殑cellview鍏冪礌绱㈠紩锛岃�宑ellIndex浠h〃鐨勬槸闆嗗悎鍐呭厓绱犵殑绱㈠紩
+         *                          褰撴病鏈夊紑鍚惊鐜ā寮忕殑鏃跺�欙紝闆嗗悎鍜屽厓绱犳槸涓�鑷寸殑锛屽畠浠苟娌℃湁浠�涔堜笉鍚岋紝閮借兘瀵瑰簲涓婄浉搴旂殑cellview鍏冪礌
+         *                          锛屼絾褰撳紑鍚惊鐜悗锛岄泦鍚堜細琚墿鍏咃紙姣斿鎵╁厖3鍊嶏級锛屾鏃禿ataIndex鐨勬暣涓懆鏈熸墠鏄湡姝e搴攃ellview鍏冪礌鐨勬暣涓懆鏈燂級
+         * 3. active 鏄惁鏄縺娲荤姸鎬�
+         * 4.鎻愪緵涓�涓櫄鏂规硶渚涘瓙绫婚噸鍐欑敤鏉ュ疄鐜颁竴浜涘叿浣撶殑鍔熻兘
+         * 5.閫氬父杩欎釜瀵硅薄鏈韩涔熶細鎻愪緵涓�涓柟娉曠敤浜庡鍏惰繘琛屽垵濮嬪寲(姣斿Start()鎴栬�呯洿鎺ユ彁渚涗竴涓叕鏈夋柟娉曚緵澶栭儴涓诲姩璋冪敤锛�
+         *
+         *杩欎釜瀵硅薄鏄暣涓猻croll鐨勬牳蹇冿紝閫氳繃瀹炵幇瀹冪户鎵跨殑鎺ュ彛锛屽畾涔変簡scroll涓婥ellView鐨勬�绘暟鐩紝姣忎釜CellView鐨剆ize锛�
+         * 閫氳繃璋冪敤 EnhancedScroller 涓殑 ReloadData()鏂规硶鏉ュ垵濮嬪寲鏁翠釜Scroll
+         * 閫氳繃瀹炵幇GetCellView鏂规硶锛屽彲浠ヨ皟鐢‥nhancedScrolelr绫讳笅鐨凣etCellView锛堬級鏂规硶锛屼紶鍏ョ浉搴旂殑CellView Prefab锛岄�氳繃瀹氫箟鐨刢ellIdentifier
+         * 鏉ヤ粠寰幆姹犻噷鍙栧搴旂殑CellVeiw锛屽鏋滄病鎵惧埌鍒欏疄渚嬪寲涓�涓紝鑰屽緱鍒扮殑杩欎釜瀵硅薄鍙堝寘鍚叾鐩稿叧鐨勫睘鎬э紝绱㈠紩鍜屽垵濮嬪寲鐨勬柟娉�
+         * 閫氳繃澹版槑涓�绯诲垪鐨勪簨浠跺彲浠ョ粦瀹欵nhancedScroller涓殑濮旀墭鐢ㄤ簬鍚勭被浜嬩欢鐨勮Е鍙�
+         * */
+
+
+        /// <summary>
+        /// The absolute position in pixels from the start of the scroller
+        /// </summary>
+        public float ScrollPosition
+        {
+            get
+            {
+                return _scrollPosition;
+            }
+            set
+            {
+                // make sure the position is in the bounds of the current set of views
+                value = Mathf.Clamp(value, 0, GetScrollPositionForCellViewIndex(_cellViewSizeArray.Count - 1, CellViewPositionEnum.Before));
+                //灏嗕紶鍏ョ殑Value鐨勫ぇ灏忛檺鍒跺湪鏁翠釜_cellViewSizeArray闆嗗悎鍐咃紙娉ㄦ剰鏄渶鍚庝竴涓厓绱犵殑涓婃柟锛屼絾鏄繖涓泦鍚堢殑闀垮害涔熷彲鑳芥槸澶嶅埗杩囧悗鐨勶級
+                // only if the value has changed
+                if (_scrollPosition != value)
+                {
+                    _scrollPosition = value;
+                    if (scrollDirection == ScrollDirectionEnum.Vertical)
+                    {
+                        // set the vertical position
+                        scrollRect.verticalNormalizedPosition = 1f - (_scrollPosition / _ScrollSize);
+                        //杩欓噷瑕佹敞鎰忥紝濡傛灉闆嗗悎杩涜杩囧鍒讹紝閭d箞杩欓噷鐨刜scrollSize涔熶竴鏍蜂細姣斿師鏉ョ殑澧炲姞锛屽洜涓篲ScrollSize姘歌繙姣攃ontent鐨勬�诲ぇ灏忓皬涓�涓彲瑙嗗尯澶у皬
+                        
+                    }
+                    else
+                    {
+                        // set the horizontal position
+                        scrollRect.horizontalNormalizedPosition = (_scrollPosition / _ScrollSize);
+                    }
+
+                    // flag that we need to refresh
+                    _refreshActive = true;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Whether the scroller should loop the resulting cell views.
+        /// Looping creates three sets of internal size data, attempting
+        /// to keep the scroller in the middle set. If the scroller goes
+        /// outside of this set, it will jump back into the middle set,
+        /// giving the illusion of an infinite set of data.
+        /// </summary>
+        public bool Loop
+        {
+            get
+            {
+                return loop;
+            }
+            set
+            {
+                // only if the value has changed
+                if (loop != value)//濡傛灉鐩稿叧灞炴�у彂鐢熶簡鍙樺寲
+                {
+                    // get the original position so that when we turn looping on
+                    // we can jump back to this position
+                    var originalScrollPosition = _scrollPosition;
+
+                    loop = value;
+
+                    // call resize to generate more internal elements if loop is on,
+                    // remove the elements if loop is off
+                    _Resize(false);
+
+                    if (loop)
+                    {
+                        // set the new scroll position based on the middle set of data + the original position
+                        ScrollPosition = _loopFirstScrollPosition + originalScrollPosition;
+                    }
+                    else
+                    {
+                        // set the new scroll position based on the original position and the first loop position
+                        ScrollPosition = originalScrollPosition - _loopFirstScrollPosition;
+                    }
+
+                    // update the scrollbars
+                    ScrollbarVisibility = scrollbarVisibility;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sets how the visibility of the scrollbars should be handled
+        /// </summary>
+        public ScrollbarVisibilityEnum ScrollbarVisibility
+        {
+            get
+            {
+                return scrollbarVisibility;
+            }
+            set
+            {
+                scrollbarVisibility = value;
+
+                // only if the scrollbar exists
+                if (_scrollbar != null)
+                {
+                    // make sure we actually have some cell views
+                    if (_cellViewOffsetArray != null && _cellViewOffsetArray.Count > 0)
+                    {
+                        if (_cellViewOffsetArray.Last() < ScrollRectSize || loop)
+                        {
+                            // if the size of the scrollable area is smaller than the scroller
+                            // or if we have looping on, hide the scrollbar unless the visibility
+                            // is set to Always.
+                            _scrollbar.SetActive(scrollbarVisibility == ScrollbarVisibilityEnum.Always);
+                        }
+                        else
+                        {
+                            // if the size of the scrollable areas is larger than the scroller
+                            // or looping is off, then show the scrollbars unless visibility
+                            // is set to Never.
+                            _scrollbar.SetActive(scrollbarVisibility != ScrollbarVisibilityEnum.Never);
+                        }
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// This is the velocity of the scroller.
+        /// </summary>
+        public Vector2 Velocity
+        {
+            get
+            {
+                return scrollRect.velocity;
+            }
+            set
+            {
+                scrollRect.velocity = value;
+            }
+        }
+
+        /// <summary>
+        /// The linear velocity is the velocity on one axis.
+        /// The scroller should only be moving one one axix.
+        /// </summary>
+        public float LinearVelocity //瀹炶川涓婃槸鎿嶄綔ScrollRect.velocity
+                       //Get : 灏嗗悜閲忚浆涓篺loat绫诲瀷
+                       //Set锛氱敤涓�涓猣loat绫诲瀷鏋勯�犱竴涓浉搴旂殑鍚戦噺
+        //澶栭儴鏂规硶鍙互閫氳繃璁块棶杩欎釜灞炴�ф潵浣縮croll杩愬姩璧锋潵
+        {
+            get
+            {
+                // return the velocity component depending on which direction this is scrolling
+                return (scrollDirection == ScrollDirectionEnum.Vertical ? scrollRect.velocity.y : scrollRect.velocity.x);
+            }
+            set
+            {
+                // set the appropriate component of the velocity
+                if (scrollDirection == ScrollDirectionEnum.Vertical)
+                {
+                    scrollRect.velocity = new Vector2(0, value);
+                }
+                else
+                {
+                    scrollRect.velocity = new Vector2(value, 0);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Whether the scroller is scrolling or not
+        /// </summary>
+        public bool IsScrolling
+        {
+            get; private set;
+        }
+
+        /// <summary>
+        /// Whether the scroller is tweening or not
+        /// </summary>
+        public bool IsTweening
+        {
+            get; private set;
+        }
+
+        /// <summary>
+        /// This is the first cell view index showing in the scroller's visible area
+        /// </summary>
+        public int StartCellViewIndex//鍙鍖哄唴绗竴涓兘鐪嬪埌鐨勫厓绱犵储寮曪紙鍙鑳界湅鍒板氨琛岋紝涓嶄竴瀹氳瀹屽叏鑳界湅鍒帮級
+        {
+            get
+            {
+                return _activeCellViewsStartIndex;
+            }
+        }
+
+        /// <summary>
+        /// This is the last cell view index showing in the scroller's visible area
+        /// </summary>
+        public int EndCellViewIndex
+        {
+            get
+            {
+                return _activeCellViewsEndIndex;
+            }
+        }
+
+        /// <summary>
+        /// This is the first data index showing in the scroller's visible area
+        /// </summary>
+        public int StartDataIndex//褰撳惊鐜紑鍚椂dataIndex浠h〃寰幆鍐呯殑绱㈠紩锛屽綋寮�鍚柊涓�杞惊鐜椂锛宒ataIndex涔熶細閲嶆柊璁℃暟
+        {
+            get
+            {
+                return _activeCellViewsStartIndex % NumberOfCells;
+            }
+        }
+        
+        /// <summary>
+        /// This is the last data index showing in the scroller's visible area
+        /// </summary>
+        public int EndDataIndex
+        {
+            get
+            {
+                return _activeCellViewsEndIndex % NumberOfCells;
+            }
+        }
+
+        public int ActiveCellCnt {
+            get {
+                return _activeCellViews.Count;
+            }
+        }
+
+        /// <summary>
+        /// This is the number of cells in the scroller
+        /// </summary>
+        public int NumberOfCells//CellView鐨勬�讳釜鏁帮紝浠庢渶涓婃柟婊戝姩鍒版渶涓嬫柟鎬诲叡鏄剧ず鐨勬暟鐩�
+        {
+            get
+            {
+                return (_delegate != null ? _delegate.GetNumberOfCells(this) : 0);
+            }
+        }
+
+        /// <summary>
+        /// The size of the visible portion of the scroller
+        /// </summary>
+        public float ScrollRectSize//寰楀埌Scroll鐨勯珮鎴栧
+        {
+            get
+            {
+                if (scrollDirection == ScrollDirectionEnum.Vertical)
+                    return _scrollRectTransform.rect.height;
+                else
+                    return _scrollRectTransform.rect.width;
+            }
+        }
+
+        public event Action OnFirstLoadAllEvent;
+        private bool m_IsLoadAll = false;
+
+        /// <summary>
+        /// Create a cell view, or recycle one if it already exists
+        /// </summary>
+        /// <param name="cellPrefab">The prefab to use to create the cell view</param>
+        /// <returns></returns>
+        public EnhancedScrollerCellView GetCellView(EnhancedScrollerCellView cellPrefab)
+        {
+            // see if there is a view to recycle
+            var cellView = _GetRecycledCellView(cellPrefab);
+            if (cellView == null)
+            {
+                // no recyleable cell found, so we create a new view
+                // and attach it to our container
+                var go = Instantiate(cellPrefab.gameObject);
+                cellView = go.GetComponent<EnhancedScrollerCellView>();
+                cellView.transform.SetParent(_container);
+                
+            }
+            Vector3 pos = cellView.transform.localPosition;
+            if (pos.x == float.NaN || pos.y == float.NaN)
+            {
+                pos = Vector3.zero;
+            }
+            pos.z = 0;
+            cellView.transform.localPosition = pos;
+            return cellView;
+            /*杩欎釜鏂规硶浼氶�氳繃涓�涓猚ellPrefab鏉ュ彇鍑轰竴涓猚ellView瀵硅薄锛岄鍏堜細鍏堜粠缂撳啿姹犻噷鍙栵紝濡傛灉鏈夌浉鍚宑ellIdentifier灞炴�х殑鐗╀綋
+             * 灏辨妸杩欎釜瀵硅薄浠庣紦鍐叉睜鍙栧嚭鏉ワ紝濡傛灉娌℃湁鐨勮瘽灏卞疄渚嬪寲涓�涓�
+             */
+        }
+
+        /// <summary>
+        /// This resets the internal size list and refreshes the cell views
+        /// </summary>
+        public void ReloadData()
+        {
+            _reloadData = false;
+
+            _scrollPosition = 0;
+
+            // recycle all the active cells so
+            // that we are sure to get fresh views
+            _RecycleAllCells();
+
+            // if we have a delegate handling our data, then
+            // call the resize
+            if (_delegate != null)
+                _Resize(false);
+            //杩欎釜鏂规硶鐢ㄤ簬鍒濆鍖栬繖涓粍浠舵垨閲嶆柊鍔犺浇杩欎釜缁勪欢
+            /*1.灏哶reloadData缃负false锛岀敤浜庢爣璁版缁勪欢宸茬粡鍒濆鍖栵紝Update()鏂规硶涓嶇敤鍐嶉噸鏂版墽琛�
+             *2.灏哶scrollPosition 璧嬪�间负 0锛屽綋瀹冧负0鏃讹紝鍚庣画鐨勫彲瑙嗗尯鍩熶細浠ュ畠涓哄熀鍑嗭紝婊戝姩鏉″皢绉诲姩鍒版渶涓婅竟鎴栨渶宸﹁竟
+             *3.濡傛灉鏈夊彲瑙佺殑鍏冪礌锛屽叏閮ㄧЩ鍔ㄥ埌缂撳啿姹�
+             *4.鎵цResize
+             *  1锛夊惊鐜ā寮忎笅锛屾墿鍏呭惊鐜泦鍚堝埌3鍊嶇殑澶у皬锛堝疄闄呬笂鍦ㄥ惊鐜ā寮忎笅锛屼笉绠℃�庝箞婊戝姩閮藉彧浼氬湪涓棿閭d釜寰幆鍐咃級
+             *  2锛夊鏋滀紶鍏alse鍒欏畾浣嶅埌璧峰鐐癸紝濡傛灉浼犲叆true鍒欏畾浣嶅埌褰撳墠_position锛堝惊鐜ā寮忎笅瀹氫綅鍒颁腑闂撮偅涓惊鐜殑瀵瑰簲鐐癸級
+             */
+        }
+
+        /// <summary>
+        /// This calls the RefreshCellView method on each active cell.
+        /// If you override the RefreshCellView method in your cells
+        /// then you can update the UI without having to reload the data.
+        /// Note: this will not change the cell sizes, you will need
+        /// to call ReloadData for that to work.
+        /// </summary>
+        public void RefreshActiveCellViews() //杩欐槸鎻愪緵缁欏鐣岀殑涓�涓柟娉曪紝鐢ㄤ簬鍘讳富鍔ㄦ搷浣滃綋鍓峉croll鍙鍖哄唴鎵�鏈夌殑鍙鍏冪礌
+        {
+            for (var i = 0; i < _activeCellViews.Count; i++)
+            {
+                _activeCellViews[i].RefreshCellView();//姣忎竴涓彲瑙佸厓绱犻兘鍙互閲嶅啓杩欎釜鏂规硶鏉ュ叿浣撴墽琛屾煇娈甸�昏緫
+            }
+            if (this.Delegate != null)
+            {
+                this.Delegate.OnRebuildComplete();
+            }
+        }
+
+        public EnhancedScrollerCellView GetActiveCellView(int _index)
+        {
+            for (int i = 0; i < _activeCellViews.Count; i++)
+            {
+                if (_activeCellViews[i].index == _index)
+                {
+                    return _activeCellViews[i];
+                }
+            }
+            return null;
+        }
+
+        public SmallList<EnhancedScrollerCellView> GetActiveCellViews()
+        {
+            return _activeCellViews;
+        }
+
+        internal float GetCellSize(int _dataIndex)
+        {
+            if (_dataIndex >= 0 && _dataIndex < _cellViewSizeArray.Count)
+            {
+                return _cellViewSizeArray[_dataIndex];
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Removes all the recycled cell views. This should only be used after you
+        /// load in a completely different set of cell views that will not use the 
+        /// recycled views. This will call garbage collection.
+        /// </summary>
+        public void ClearRecycled()//涓诲姩璋冪敤杩欎釜鏂规硶浼氱珛鍗虫竻绌虹紦瀛樻睜骞堕噴鏀炬帀瀹冨崰鐢ㄧ殑鍐呭瓨锛屽彲浠ラ厤鍚堜笂闈㈢殑鏂规硶鍔ㄦ�佹洿鏂皊croll
+        {
+            for (var i = 0; i < _recycledCellViews.Count; i++)
+            {
+                DestroyImmediate(_recycledCellViews[i].gameObject);
+            }
+            _recycledCellViews.Clear();
+        }
+
+        /// <summary>
+        /// Turn looping on or off. This is just a helper function so 
+        /// you don't have to keep track of the state of the looping
+        /// in your own scripts.
+        /// </summary>
+        public void ToggleLoop()//涓诲姩璋冪敤浼氬垏鎹㈠綋鍓嶇殑寰幆妯″紡
+        {
+            Loop = !loop;
+        }
+
+        /// <summary>
+        /// Jump to a position in the scroller based on a dataIndex. This overload allows you
+        /// to specify a specific offset within a cell as well.
+        /// </summary>
+        /// <param name="dataIndex">he data index to jump to</param>
+        /// <param name="scrollerOffset">The offset from the start (top / left) of the scroller in the range 0..1.
+        /// Outside this range will jump to the location before or after the scroller's viewable area</param>
+        /// <param name="cellOffset">The offset from the start (top / left) of the cell in the range 0..1</param>
+        /// <param name="useSpacing">Whether to calculate in the spacing of the scroller in the jump</param>
+        /// <param name="tweenType">What easing to use for the jump</param>
+        /// <param name="tweenTime">How long to interpolate to the jump point</param>
+        /// <param name="jumpComplete">This delegate is fired when the jump completes</param>
+        /// 璺宠浆鍒癲ataIndex瀵瑰簲鐨刢ellview鍏冪礌锛屽彲浠ラ�夋嫨鐩稿簲鐨則ween鍔ㄧ敾
+        public void JumpToDataIndex(int dataIndex,
+            float scrollerOffset = 0,
+            float cellOffset = 0,
+            bool useSpacing = true,
+            TweenType tweenType = TweenType.immediate,
+            float tweenTime = 0f,
+            Action jumpComplete = null
+            )
+        {
+            var cellOffsetPosition = 0f;
+
+            if (cellOffset != 0)
+            {
+                // calculate the cell offset position
+
+                // get the cell's size
+                var cellSize = (_delegate != null ? _delegate.GetCellViewSize(this, dataIndex) : 0);
+
+                if (useSpacing)
+                {
+                    // if using spacing add spacing from one side
+                    cellSize += spacing;
+
+                    // if this is not a bounday cell, then add spacing from the other side
+                    if (dataIndex > 0 && dataIndex < (NumberOfCells - 1)) cellSize += spacing;
+                }
+
+                // calculate the position based on the size of the cell and the offset within that cell
+                cellOffsetPosition = cellSize * cellOffset;
+            }
+
+            var newScrollPosition = 0f;
+
+            // cache the offset for quicker calculation
+            var offset = -(scrollerOffset * ScrollRectSize) + cellOffsetPosition;
+
+            if (loop)
+            {
+                // if looping, then we need to determine the closest jump position.
+                // we do that by checking all three sets of data locations, and returning the closest one
+
+                // get the scroll positions for each data set.
+                // Note: we are calculating the position based on the cell view index, not the data index here
+                var set1Position = GetScrollPositionForCellViewIndex(dataIndex, CellViewPositionEnum.Before) + offset;
+                var set2Position = GetScrollPositionForCellViewIndex(dataIndex + NumberOfCells, CellViewPositionEnum.Before) + offset;
+                var set3Position = GetScrollPositionForCellViewIndex(dataIndex + (NumberOfCells * 2), CellViewPositionEnum.Before) + offset;
+
+                // get the offsets of each scroll position from the current scroll position
+                var set1Diff = (Mathf.Abs(_scrollPosition - set1Position));
+                var set2Diff = (Mathf.Abs(_scrollPosition - set2Position));
+                var set3Diff = (Mathf.Abs(_scrollPosition - set3Position));
+
+                // choose the smallest offset from the current position (the closest position)
+                if (set1Diff < set2Diff)
+                {
+                    if (set1Diff < set3Diff)
+                    {
+                        newScrollPosition = set1Position;
+                    }
+                    else
+                    {
+                        newScrollPosition = set3Position;
+                    }
+                }
+                else
+                {
+                    if (set2Diff < set3Diff)
+                    {
+                        newScrollPosition = set2Position;
+                    }
+                    else
+                    {
+                        newScrollPosition = set3Position;
+                    }
+                }
+            }
+            else
+            {
+                // not looping, so just get the scroll position from the dataIndex
+                newScrollPosition = GetScrollPositionForDataIndex(dataIndex, CellViewPositionEnum.Before) + offset;
+            }
+
+            // clamp the scroll position to a valid location
+            newScrollPosition = Mathf.Clamp(newScrollPosition, 0, GetScrollPositionForCellViewIndex(_cellViewSizeArray.Count - 1, CellViewPositionEnum.Before));
+
+            // if spacing is used, adjust the final position
+            if (useSpacing)
+            {
+                // move back by the spacing if necessary
+                newScrollPosition = Mathf.Clamp(newScrollPosition - spacing, 0, GetScrollPositionForCellViewIndex(_cellViewSizeArray.Count - 1, CellViewPositionEnum.Before));
+            }
+
+            // start tweening
+            if (tweenType == TweenType.immediate || tweenTime == 0)
+            {
+                // if the easing is immediate or the time is zero, just jump to the end position
+                ScrollPosition = newScrollPosition;
+                return;
+            }
+            StartCoroutine(TweenPosition(tweenType, tweenTime, ScrollPosition, newScrollPosition, jumpComplete));
+        }
+
+        public void Tween(TweenType tweenType, float tweenTime, float newPosition, Action jumpComplete = null)
+        {
+            StartCoroutine(TweenPosition(tweenType, tweenTime, ScrollPosition, newPosition, jumpComplete));
+        }
+
+        /// <summary>
+        /// Jump to a position in the scroller based on a dataIndex.
+        /// </summary>
+        /// <param name="dataIndex">The data index to jump to</param>
+        /// <param name="position">Whether you should jump before or after the cell view</param>
+        [System.Obsolete("This is an obsolete method, please use the version of this function with a cell offset.")]
+        //杩囨椂鐨勬柟娉曪紝鍙互閫夋嫨瀹氫綅鍒板厓绱犱笂鏂规垨涓嬫柟锛堝乏鍙冲悓鐞�)锛屽彲浠ラ�氳繃涓婇潰鐨勬柟娉曡皟鏁村亸绉昏揪鍒板悓鏍风殑鏁堟灉
+        public void JumpToDataIndex(int dataIndex,
+            CellViewPositionEnum position = CellViewPositionEnum.Before,
+            bool useSpacing = true)
+        {
+            // if looping is on, we need to jump to the middle set of data, otherwise just use the dataIndex for the cellIndex
+            ScrollPosition = GetScrollPositionForDataIndex(dataIndex, position);
+
+            // if spacing is used, adjust the final position
+            if (useSpacing)
+            {
+                if (position == CellViewPositionEnum.Before)
+                    ScrollPosition = _scrollPosition - spacing;
+                else
+                    ScrollPosition = _scrollPosition + spacing;
+            }
+        }
+
+        /// <summary>
+        /// Snaps the scroller on command. This is called internally when snapping is set to true and the velocity
+        /// has dropped below the threshold. You can use this to manually snap whenever you like.
+        /// </summary>
+        /// 褰撳紑鍚攣瀹氫綅缃姛鑳芥椂锛屽湪婊戝姩鏉℃粦鍔ㄥ悗鍏冪礌浼氳繘琛岀浉搴旂殑瀹氫綅锛堝畾浣嶇殑绾︽潫鍦ㄩ潰鏉夸腑鍙互杩涜璁剧疆锛�
+        public void Snap()
+        {
+            if (NumberOfCells == 0) return;
+
+            // set snap jumping to true so other events won't process while tweening
+            _snapJumping = true;
+
+            // stop the scroller
+            LinearVelocity = 0;
+
+            // cache the current inertia state and turn off inertia
+            _snapInertia = scrollRect.inertia;
+            scrollRect.inertia = false;
+
+            // calculate the snap position
+            var snapPosition = ScrollPosition + (ScrollRectSize * Mathf.Clamp01(snapWatchOffset));
+
+            // get the cell view index of cell at the watch location
+            _snapCellViewIndex = GetCellViewIndexAtPosition(snapPosition);
+
+            // get the data index of the cell at the watch location
+            _snapDataIndex = _snapCellViewIndex % NumberOfCells;
+
+            // jump the snapped cell to the jump offset location and center it on the cell offset
+            JumpToDataIndex(_snapDataIndex, snapJumpToOffset, snapCellCenterOffset, snapUseCellSpacing, snapTweenType, snapTweenTime, SnapJumpComplete);
+        }
+
+        /// <summary>
+        /// Gets the scroll position in pixels from the start of the scroller based on the cellViewIndex
+        /// </summary>
+        /// <param name="cellViewIndex">The cell index to look for. This is used instead of dataIndex in case of looping</param>
+        /// <param name="insertPosition">Do we want the start or end of the cell view's position</param>
+        /// <returns></returns>
+        public float GetScrollPositionForCellViewIndex(int cellViewIndex, CellViewPositionEnum insertPosition)//鏍规嵁鐩稿叧鐨勭储寮曚粠_cellViewOffsetArray閲屽彇瀵瑰簲鐨刾osition
+        {
+            /*杩欎釜鏂规硶鐨勪富瑕佷綔鐢ㄦ槸閫氳繃涓�涓储寮曟潵杩斿洖position锛岃�岃繖涓猵osition瀹為檯涓婂彲浠ヨ涓烘槸鍙粦鍔ㄧ殑content鍚戜笂鎴栧悜宸︽粦鍔ㄤ簡澶氬皯
+             * 鍥犱负涔嬪墠閫氳繃_cellViewOffsetArray鏉ュ瓨鍌ㄤ簡姣忎釜cellView涓嬫柟鐩稿浜庡乏涓婄殑鍋忕Щ(TextAnchor.UpperLeft)鎵�浠ラ�氳繃绱㈠紩瀹為檯涓婂氨鑳藉彇鍑鸿繖涓亸绉婚噺
+             * 鍐嶉�氳繃Before(鍙栦笂鎴栧乏) After(鍙栦笅鎴栧彸)鏉ュ垽鏂渶缁坧osition鐨勫��
+             * -----scrollRect鐨凬ormallizedPosition瀹為檯涓婃槸鍙粦鍔ㄥ尯鍩熺殑澶у皬鍚戝彟涓�鏂规粦鍔ㄤ腑鍋忕Щ閲忕殑姣斾緥--------------
+             * 鎵�浠ュ彲浠ラ�氳繃postion鍜屽彲婊戝姩鍖哄煙澶у皬鐨勬瘮鍊兼潵瀹氫箟婊戝姩鏉℃粦鍔ㄥ埌浜嗗摢涓綅缃�
+             */
+
+            if (NumberOfCells == 0 || _cellViewOffsetArray.Count == 0) return 0;//濡傛灉scroll娌℃湁瀛愮墿浣撶洿鎺ヨ繑鍥�
+
+            if (cellViewIndex <= 0 && insertPosition == CellViewPositionEnum.Before)
+            {
+                return 0;//濡傛灉鏄涓�涓瓙鐗╀綋涓旇寰楀埌瀹冪殑涓婃柟浣嶇疆锛岀洿鎺ヨ繑鍥�0
+            }
+            else
+            {
+                if (cellViewIndex < _cellViewOffsetArray.Count)
+                {
+                    // the index is in the range of cell view offsets
+
+                    if (insertPosition == CellViewPositionEnum.Before)
+                    {
+                        // return the previous cell view's offset + the spacing between cell views
+                        return _cellViewOffsetArray[cellViewIndex - 1] + spacing + (scrollDirection == ScrollDirectionEnum.Vertical ? padding.top : padding.left);
+                        //杩斿洖褰撳墠绱㈠紩涓婃柟鐨勫��
+                        //杩欓噷瑕佹敞鎰忎竴鐐瑰氨鏄竴鑸潵璇磋皟鐢ㄨ繖涓柟娉曠殑鏃跺�欏氨鏄鍦╨oop妯″紡涔嬩笅锛岃繖閲岀殑_cellViewOffsetArray鏄粡杩囧鍒跺悗鐨勯泦鍚�
+                    }
+                    else
+                    {
+                        // return the offset of the cell view (offset is after the cell)
+                        return _cellViewOffsetArray[cellViewIndex] + (scrollDirection == ScrollDirectionEnum.Vertical ? padding.top : padding.left);
+                        //杩斿洖褰撳墠绱㈠紩涓嬫柟鐨勫��
+                    }
+                }
+                else
+                {
+                    // get the start position of the last cell (the offset of the second to last cell)
+                    return _cellViewOffsetArray[_cellViewOffsetArray.Count - 2];
+                    //杩斿洖鏈�鍚庝竴涓储寮曠殑涓婃柟鍊�
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the scroll position in pixels from the start of the scroller based on the dataIndex
+        /// </summary>
+        /// <param name="dataIndex">The data index to look for</param>
+        /// <param name="insertPosition">Do we want the start or end of the cell view's position</param>
+        /// <returns></returns>
+        public float GetScrollPositionForDataIndex(int dataIndex, CellViewPositionEnum insertPosition)
+        {
+            return GetScrollPositionForCellViewIndex(loop ? _delegate.GetNumberOfCells(this) + dataIndex : dataIndex, insertPosition);
+            //閫氳繃dataIndex鏉ョ‘瀹歋crollPosition锛岃娉ㄦ剰鐨勬槸GetScrollPositionForCellViewIndex闇�瑕佺殑鏄痗ellIndex鑰屼笉鏄痙ataIndex
+            //鎵�浠ュ湪寰幆妯″紡涓嬶紝dataIndex瑕佸姞涓婃墍鏈夊厓绱犵殑鏁伴噺锛堝洜涓哄湪寰幆妯″紡涓嬶紝dataIndex瀵瑰簲鐨勫厓绱犳案杩滈兘鏄湪闆嗗悎涓殑绗簩缁勶級
+        }
+
+        /// <summary>
+        /// Gets the index of a cell view at a given position
+        /// </summary>
+        /// <param name="position">The pixel offset from the start of the scroller</param>
+        /// <returns></returns>
+        public int GetCellViewIndexAtPosition(float position)
+        {
+            // call the overrloaded method on the entire range of the list
+            return _GetCellIndexAtPosition(position, 0, _cellViewOffsetArray.Count - 1);
+        }
+
+        #endregion
+
+        #region Private
+
+        /// <summary>
+        /// Cached reference to the scrollRect
+        /// </summary>
+        private ScrollRect m_ScrollRect;
+        public ScrollRect scrollRect {
+            get {
+                if (m_ScrollRect == null) {
+                    m_ScrollRect = this.GetComponent<ScrollRect>();
+                }
+                return m_ScrollRect;
+            }
+        }
+
+        /// <summary>
+        /// Cached reference to the scrollRect's transform
+        /// </summary>
+        private RectTransform _scrollRectTransform;
+
+        /// <summary>
+        /// Cached reference to the scrollbar if it exists
+        /// </summary>
+        private Scrollbar _scrollbar;
+
+        /// <summary>
+        /// Cached reference to the active cell view container
+        /// </summary>
+        private RectTransform _container;
+
+        /// <summary>
+        /// Cached reference to the layout group that handles view positioning
+        /// </summary>
+        private HorizontalOrVerticalLayoutGroup _layoutGroup;
+        public HorizontalOrVerticalLayoutGroup LayoutGroup
+        {
+            get
+            {
+                return _layoutGroup;
+            }
+        }
+        /// <summary>
+        /// Reference to the delegate that will tell this scroller information
+        /// about the underlying data
+        /// </summary>
+        private IEnhancedScrollerDelegate _delegate;
+
+        /// <summary>
+        /// Flag to tell the scroller to reload the data
+        /// </summary>
+        private bool _reloadData;
+
+        /// <summary>
+        /// Flag to tell the scroller to refresh the active list of cell views
+        /// </summary>
+        private bool _refreshActive;
+
+        /// <summary>
+        /// List of views that have been recycled
+        /// </summary>
+        private SmallList<EnhancedScrollerCellView> _recycledCellViews = new SmallList<EnhancedScrollerCellView>();
+
+        /// <summary>
+        /// Cached reference to the element used to offset the first visible cell view
+        /// </summary>
+        private LayoutElement _firstPadder;
+
+        /// <summary>
+        /// Cached reference to the element used to keep the cell views at the correct size
+        /// </summary>
+        private LayoutElement _lastPadder;
+
+        /// <summary>
+        /// Cached reference to the container that holds the recycled cell views
+        /// </summary>
+        private RectTransform _recycledCellViewContainer;
+
+        /// <summary>
+        /// Internal list of cell view sizes. This is created when the data is reloaded 
+        /// to speed up processing.
+        /// </summary>
+        private SmallList<float> _cellViewSizeArray = new SmallList<float>();
+
+        /// <summary>
+        /// Internal list of cell view offsets. Each cell view offset is an accumulation 
+        /// of the offsets previous to it.
+        /// This is created when the data is reloaded to speed up processing.
+        /// </summary>
+        private SmallList<float> _cellViewOffsetArray = new SmallList<float>();
+
+        /// <summary>
+        /// The scrollers position
+        /// </summary>
+        private float _scrollPosition;
+
+        /// <summary>
+        /// The list of cell views that are currently being displayed
+        /// </summary>
+        private SmallList<EnhancedScrollerCellView> _activeCellViews = new SmallList<EnhancedScrollerCellView>();
+
+        /// <summary>
+        /// The index of the first cell view that is being displayed
+        /// </summary>
+        private int _activeCellViewsStartIndex;
+
+        /// <summary>
+        /// The index of the last cell view that is being displayed
+        /// </summary>
+        private int _activeCellViewsEndIndex;
+
+        /// <summary>
+        /// The index of the first element of the middle section of cell view sizes.
+        /// Used only when looping
+        /// </summary>
+        private int _loopFirstCellIndex;
+
+        /// <summary>
+        /// The index of the last element of the middle seciton of cell view sizes.
+        /// used only when looping
+        /// </summary>
+        private int _loopLastCellIndex;
+
+        /// <summary>
+        /// The scroll position of the first element of the middle seciotn of cell views.
+        /// Used only when looping
+        /// </summary>
+        private float _loopFirstScrollPosition;
+
+        /// <summary>
+        /// The scroll position of the last element of the middle section of cell views.
+        /// Used only when looping
+        /// </summary>
+        private float _loopLastScrollPosition;
+
+        /// <summary>
+        /// The position that triggers the scroller to jump to the end of the middle section
+        /// of cell views. This keeps the scroller in the middle section as much as possible.
+        /// </summary>
+        private float _loopFirstJumpTrigger;
+
+        /// <summary>
+        /// The position that triggers the scroller to jump to the start of the middle section
+        /// of cell views. This keeps the scroller in the middle section as much as possible.
+        /// </summary>
+        private float _loopLastJumpTrigger;
+
+        /// <summary>
+        /// The cached value of the last scroll rect size. This is checked every frame to see
+        /// if the scroll rect has resized. If so, it will refresh.
+        /// </summary>
+        private float _lastScrollRectSize;
+
+        /// <summary>
+        /// The cached value of the last loop setting. This is checked every frame to see
+        /// if looping was toggled. If so, it will refresh.
+        /// </summary>
+        private bool _lastLoop;
+
+        /// <summary>
+        /// The cell view index we are snapping to
+        /// </summary>
+        private int _snapCellViewIndex;
+
+        /// <summary>
+        /// The data index we are snapping to
+        /// </summary>
+        private int _snapDataIndex;
+
+        /// <summary>
+        /// Whether we are currently jumping due to a snap
+        /// </summary>
+        private bool _snapJumping;
+
+        /// <summary>
+        /// What the previous inertia setting was before the snap jump.
+        /// We cache it here because we need to turn off inertia while
+        /// manually tweeing.
+        /// </summary>
+        private bool _snapInertia;
+
+        /// <summary>
+        /// The cached value of the last scrollbar visibility setting. This is checked every
+        /// frame to see if the scrollbar visibility needs to be changed.
+        /// </summary>
+        private ScrollbarVisibilityEnum _lastScrollbarVisibility;
+
+        /// <summary>
+        /// Where in the list we are
+        /// </summary>
+        private enum ListPositionEnum
+        {
+            First,
+            Last
+        }
+
+        /// <summary>
+        /// The size of the active cell view container minus the visibile portion
+        /// of the scroller
+        /// </summary>
+        public float _ScrollSize//杩欓噷骞朵笉鏄寚scrllrect鐨勫ぇ灏忥紝鑰屾槸鎸囩湡姝e湪婊戝姩鐨勫尯鍩熺殑澶у皬
+                                /*scrollrect鐨刵ormallizePosition瀹為檯涓婂氨鏄繖涓湡姝h兘婊戝姩鐨勫尯鍩熺殑澶у皬
+                                 * 鍦ㄦ粦鍔ㄨ繃绋嬩腑褰掍竴鍖栫殑鍊硷紝鑰岃繖涓ぇ灏忓氨鏄墍鏈夊瓙鐗╀綋鐨勫ぇ灏忎笌鍙鍖栧尯鍩熺殑宸�
+                                 * 褰揷ontent鐨勫ぇ灏忕瓑浜庢墍鏈夊瓙鐗╀綋鐨勫ぇ灏忔椂锛屽氨鍙互绠�鍖栨搷浣滅洿鎺ョ敤content鐨勫ぇ灏忔潵浠f浛
+                                 */
+        {
+            get
+            {
+                if (scrollDirection == ScrollDirectionEnum.Vertical)
+                {
+                    if (_container != null && _scrollRectTransform != null)
+                        return _container.rect.height - _scrollRectTransform.rect.height;
+                    else
+                        return 0;
+
+                }
+                  
+                else
+                {
+                    if (_container != null && _scrollRectTransform != null)
+                        return _container.rect.width - _scrollRectTransform.rect.width;
+                    else
+                        return 0;
+                }
+                   
+            }
+        }
+
+        /// <summary>
+        /// This function will create an internal list of sizes and offsets to be used in all calculations.
+        /// It also sets up the loop triggers and positions and initializes the cell views.
+        /// </summary>
+        /// <param name="keepPosition">If true, then the scroller will try to go back to the position it was at before the resize</param>
+        private void _Resize(bool keepPosition)
+        {
+            // cache the original position
+            var originalScrollPosition = _scrollPosition;
+
+            // clear out the list of cell view sizes and create a new list
+            _cellViewSizeArray.Clear();
+            var offset = _AddCellViewSizes();//姣忔娓呯┖鍚庨噸鏂版坊鍔犱竴娆★紝骞惰繑鍥炶繖涓泦鍚堢殑鍊肩殑鍜�
+
+            // if looping, we need to create three sets of size data
+            if (loop)
+            {
+                // if the cells don't entirely fill up the scroll area, 
+                // make some more size entries to fill it up
+                if (offset < ScrollRectSize)//鎵�鏈夊瓙鐗╀綋鐩稿姞娌℃湁杩欏潡鍙鍖哄煙澶�
+                {
+                    int additionalRounds = Mathf.CeilToInt(ScrollRectSize / offset);
+                    _DuplicateCellViewSizes(additionalRounds, _cellViewSizeArray.Count);//濡傛灉瀛愮墿浣撶殑涓暟涓嶈冻浠ュ~鍏呭彲瑙嗗尯鍩燂紝瑕佽繘琛屽鍒�
+                }
+
+                // set up the loop indices
+                _loopFirstCellIndex = _cellViewSizeArray.Count;
+                _loopLastCellIndex = _loopFirstCellIndex + _cellViewSizeArray.Count - 1;
+                //杩欓噷鐨勪袱涓�兼槸鍦ㄩ泦鍚堟病鏈夎繘琛屼换浣曞鍒舵椂璧嬪�肩殑锛宊loopFirstCellIndex鏄浜屾寰幆鐨勭涓�涓厓绱犵储寮曪紝_loopLastCellIndex鏄浜屾寰幆鐨勬渶鍚庝竴涓储寮�
+
+                // create two more copies of the cell sizes
+                _DuplicateCellViewSizes(2, _cellViewSizeArray.Count);
+                /*褰撲娇鐢ㄥ惊鐜ā寮忕殑鏃跺�欙紝濡傛灉瀛愮墿浣撲笉瓒充互濉厖鍙鍖哄氨杩涜涓�娆″鍒讹紝浣垮厓绱犺兘澶熸粦鍔�
+                 *褰撳厓绱犺冻澶熷锛岃兘澶熷湪鍙鍖烘粦鍔ㄧ殑鏃跺�欙紝鍐嶈繘琛屼袱娆″鍒讹紙鏈�缁堢粨鏋滄槸涓変釜寰幆锛�
+                 * firstCellIndex涓虹涓�涓惊鐜殑绗竴涓墿浣撶储寮曪紝姣斿10涓厓绱狅紝绗竴涓惊鐜殑绗竴涓储寮曞氨鏄�10锛屽洜涓烘槸浠庯紙0~9锛�
+                 * lastCellIndex涓虹涓�涓惊鐜殑鏈�鍚庝竴涓墿浣撶储寮曪紝姣斿10鍏冪礌锛�0~9锛�+ 10 = 19
+                 * 瑕佹敞鎰忥細 涓婇潰璇寸殑澶嶅埗鍦ㄨ繖閲屽苟娌℃湁澶嶅埗娓告垙瀵硅薄锛屽彧鏄闆嗗悎杩涜浜嗕竴浜涙墿鍏咃紝杩欏彧鏄负浜嗘柟渚跨悊瑙�
+                */
+            }
+
+            // calculate the offsets of each cell view
+            _CalculateCellViewOffsets();//璁$畻浜嗙涓�涓厓绱犱笅鏂圭浉瀵瑰師鐐圭殑鍋忕Щ锛堝叾涓篃鍖呮嫭浜嗛棿璺濓級
+
+            // set the size of the active cell view container based on the number of cell views there are and each of their sizes
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+                _container.sizeDelta = new Vector2(_container.sizeDelta.x, _cellViewOffsetArray.Last() + padding.top + padding.bottom);
+            else
+                _container.sizeDelta = new Vector2(_cellViewOffsetArray.Last() + padding.left + padding.right, _container.sizeDelta.y);
+            //璁剧疆content鐨勫ぇ灏忥紝鏍规嵁_cellViewOffsetArray鐨勬渶鍚庝竴涓�煎氨鍙互寰楀埌鎵�鏈夊厓绱犲拰瀹冧滑鐨勯棿璺濈殑鎬诲拰锛屽啀鍔犱笂padding鐨勫�煎氨鍙互璁ヽontent鍜屾墍鏈夊瓙鐗╀綋瀹岀編鍖归厤
+            //涓斿洜涓轰箣鍓嶈缃簡pivot鐨勫師鍥狅紝鐩存帴璁剧疆content鐨勫ぇ灏忓苟涓嶄細璁╁畠寰�涓よ竟缂╂斁锛岃�屾槸椤虹潃鎴戜滑闇�瑕佺殑鏂瑰悜杩涜缂╂斁
+            // if looping, set up the loop positions and triggers
+            if (loop)
+            {
+                _loopFirstScrollPosition = GetScrollPositionForCellViewIndex(_loopFirstCellIndex, CellViewPositionEnum.Before) + (spacing * 0.5f);
+                _loopLastScrollPosition = GetScrollPositionForCellViewIndex(_loopLastCellIndex, CellViewPositionEnum.After) - ScrollRectSize + (spacing * 0.5f);
+               
+
+                _loopFirstJumpTrigger = _loopFirstScrollPosition - ScrollRectSize;
+                _loopLastJumpTrigger = _loopLastScrollPosition + ScrollRectSize;
+                //firstJumpTrigger鏄涓�涓惊鐜殑鏈�鍚庝竴涓储寮曠殑涓嬫柟 - 鍙鍖哄ぇ灏忥紝lastJumpTrigger鏄浜屾寰幆鐨勬渶鍚庝竴涓储寮曠殑涓嬫柟
+            }
+
+            // create the visibile cells
+            _ResetVisibleCellViews();//鏍规嵁鍙鍖轰袱绔储寮曪紙閫氳繃_scrollPosition鏉ヨ绠楃储寮�)鏉ラ噸寤哄彲瑙嗗尯鍩熷唴鐨勫瓙鐗╀綋
+            if (this.Delegate != null)
+            {
+                this.Delegate.OnRebuildComplete();
+            }
+            // if we need to maintain our original position
+            if (keepPosition)//濡傛灉涓簍rue鍒欎繚鎸佽皟鐢ㄨ繖涓柟娉曟椂瀵瑰簲鐨勪綅缃�
+            {
+                ScrollPosition = originalScrollPosition;
+            }
+            else
+            {
+                if (loop)
+                {
+                    ScrollPosition = _loopFirstScrollPosition;//寰幆妯″紡鏃跺畾涔夌殑鏄浜屾寰幆鐨勮捣濮嬬偣锛堢浉褰撲簬涓よ竟閮藉瓨鍦ㄤ竴涓惊鐜紝瀹氫綅鍦ㄤ腑闂撮偅涓惊鐜殑璧峰鐐癸級
+                }
+                else
+                {
+                    ScrollPosition = 0;
+                }
+            }
+
+            // set up the visibility of the scrollbar
+            ScrollbarVisibility = scrollbarVisibility;
+
+            if (!m_IsLoadAll)
+            {
+                m_IsLoadAll = true;
+                if (OnFirstLoadAllEvent != null)
+                {
+                    OnFirstLoadAllEvent();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Creates a list of cell view sizes for faster access
+        /// </summary>
+        /// <returns></returns>
+        private float _AddCellViewSizes()//鍒涘缓涓�涓敤浜庡瓨鏀炬墍鏈夊瓙鐗╀綋鐨勫ぇ灏忕殑闆嗗悎锛屽苟杩斿洖鎵�鏈夊瓙鐗╀綋鐩稿姞鍚庣殑鎬诲昂瀵�
+        {
+            var offset = 0f;
+            // add a size for each row in our data based on how many the delegate tells us to create
+            for (var i = 0; i < NumberOfCells; i++)
+            {
+                // add the size of this cell based on what the delegate tells us to use. Also add spacing if this cell isn't the first one
+                _cellViewSizeArray.Add(_delegate.GetCellViewSize(this, i) + (i == 0 ? 0 : _layoutGroup.spacing));
+                offset += _cellViewSizeArray[_cellViewSizeArray.Count - 1];
+            }
+
+            return offset;
+        }
+
+        /// <summary>
+        /// Create a copy of the cell view sizes. This is only used in looping
+        /// </summary>
+        /// <param name="numberOfTimes">How many times the copy should be made</param>
+        /// <param name="cellCount">How many cells to copy</param>
+        private void _DuplicateCellViewSizes(int numberOfTimes, int cellCount)//褰撲娇鐢ㄥ惊鐜ā寮忔椂锛屽鏋滃瓙鐗╀綋涓嶈冻浠ュ~鍏呭彲瑙嗗尯鍩燂紝灏辫繘琛屽鍒�
+        {
+            for (var i = 0; i < numberOfTimes; i++)             //娉ㄦ剰姝ゅ鐨勫鍒跺苟涓嶆槸澶嶅埗娓告垙瀵硅薄锛岃�屽彧鏄泦鍚堢殑鎵╁厖
+            {
+                for (var j = 0; j < cellCount; j++)
+                {
+                    _cellViewSizeArray.Add(_cellViewSizeArray[j] + (j == 0 ? _layoutGroup.spacing : 0));//瀛樺偍瀛愮墿浣搒ize鐨勯泦鍚堜篃瑕佽窡鐫�鍙�
+                    /*j == 0 ? _layoutGroup.spacing : 0  娉ㄦ剰杩欎釜涓夊厓琛ㄨ揪寮忥紝鍦ㄨ繘琛屽鍒舵椂锛屽鏋滄槸澶嶅埗闆嗗悎鐨勭涓�涓厓绱犺澶氬姞涓�涓猻pacing
+                     * 鍥犱负婊戝姩鏉′腑鍙湁绗竴涓厓绱犲墠鏂规垨宸︽柟鏄病鏈塻pacing鐨勶紝鎵�浠ュ綋澶嶅埗n浠芥椂锛屽氨瑕佸鍔爊涓猻pacing
+                     */
+                }
+            }
+        }
+
+        /// <summary>
+        /// Calculates the offset of each cell, accumulating the values from previous cells
+        /// </summary>
+        private void _CalculateCellViewOffsets()//姝ゅ鐨勫亸绉婚泦鍚堝瓨鍌ㄧ殑鏄綋鍓嶇储寮曚笅鐨勭墿浣撲笅鏂圭浉瀵瑰師鐐圭殑鍋忕Щ閲忥紝涔熷氨鏄鏈�鍚庝竴涓厓绱犵殑澶у皬灏辨槸鎵�鏈夊瓙鐗╀綋澶у皬鍔犻棿璺濈殑鎬诲拰
+        {
+            _cellViewOffsetArray.Clear();
+            var offset = 0f;
+            for (var i = 0; i < _cellViewSizeArray.Count; i++)
+            {
+                offset += _cellViewSizeArray[i];
+                _cellViewOffsetArray.Add(offset);
+            }
+        }
+
+        /// <summary>
+        /// Get a recycled cell with a given identifier if available
+        /// </summary>
+        /// <param name="cellPrefab">The prefab to check for</param>
+        /// <returns></returns>
+        private EnhancedScrollerCellView _GetRecycledCellView(EnhancedScrollerCellView cellPrefab)//浠庣紦瀛樻睜涓彇涓�涓猚ellPrefab
+        {
+            for (var i = 0; i < _recycledCellViews.Count; i++)
+            {
+                if (_recycledCellViews[i].cellIdentifier == cellPrefab.cellIdentifier)
+                {
+                    // the cell view was found, so we use this recycled one.
+                    // we also remove it from the recycled list
+                    var cellView = _recycledCellViews.RemoveAt(i);
+                    return cellView;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// This sets up the visible cells, adding and recycling as necessary
+        /// </summary>
+        private void _ResetVisibleCellViews()//閫氳繃鏌愪釜_scrollPosition鏉ュ垽鏂彲瑙嗗尯涓ょ鑳界湅鍒扮殑绱㈠紩锛屽啀閫氳繃杩欎袱涓储寮曟潵閲嶅缓鍙鍖哄唴鐨勫瓙鐗╀綋锛屽苟鏇存柊鐩稿簲鐨勯泦鍚�
+        {
+            int startIndex;
+            int endIndex;
+
+            // calculate the range of the visible cells
+            _CalculateCurrentActiveCellRange(out startIndex, out endIndex);//杩欎釜鏂规硶杩斿洖褰撳墠_scrollPosition瀵瑰簲鐨勫彲瑙嗗尯涓ょ鑳界湅鍒扮殑瀛愮墿浣撶储寮曪紙骞朵笉涓�瀹氳瀹屽叏鍦ㄥ彲瑙嗗尯鍐咃級
+            // go through each previous active cell and recycle it if it no longer falls in the range
+            var i = 0;
+            SmallList<int> remainingCellIndices = new SmallList<int>();
+            while (i < _activeCellViews.Count)
+            {
+                if (_activeCellViews[i].cellIndex < startIndex || _activeCellViews[i].cellIndex > endIndex)
+                {
+                    _RecycleCell(_activeCellViews[i]);//濡傛灉鍘熸湰鍙鐨勫厓绱犱笉鍦ㄥ彲瑙嗗尯鍩熷唴灏嗗叾绉诲姩鍒癬RecycleCell鑺傜偣涓�
+                }
+                else
+                {
+                    // this cell index falls in the new range, so we add its
+                    // index to the reusable list
+                    remainingCellIndices.Add(_activeCellViews[i].cellIndex);
+                    //鍓╀笅鐨勮偗瀹氭槸鍙鍏冪礌锛屾斁鍏emainingCellIndices闆嗗悎涓紝杩欓噷瑕佹敞鎰忕殑鏄紝杩欎竴闆嗗悎骞朵笉涓�瀹氳兘澶熷~鍏呮暣涓彲瑙嗗尯鍩燂紝
+                    //startIndex鍜宔ndIndex鍐呯殑閮ㄥ垎绱㈠紩鍙兘骞舵病鏈夊搴旂殑鍙瀛愮墿浣�
+                    i++;
+                }
+            }
+
+            if (remainingCellIndices.Count == 0)//鍦ㄨ烦杞嚦杈冭繙浣嶇疆鏃讹紝浼氬鑷村師鏉ュ彲瑙佸厓绱犲叏閮ㄩ兘涓嶅彲瑙佷簡锛屽張鎴栬�呮缁勪欢鍒氳繘琛屽垵濮嬪寲鏃讹紝骞舵病鏈変换浣曞彲瑙佸厓绱�
+            {
+                // there were no previous active cells remaining, 
+                // this list is either brand new, or we jumped to 
+                // an entirely different part of the list.
+                // just add all the new cell views
+
+                for (i = startIndex; i <= endIndex; i++)
+                {
+                    _AddCellView(i, ListPositionEnum.Last);
+                    /*姝e簭娣诲姞锛屽綋remainingCellIndices闆嗗悎娌℃湁鍏冪礌鏃讹紝鐩存帴鎸夐『搴忔坊鍔犲氨鍙互浜嗭紝鍏堟坊鍔犵殑鍦ㄥ墠闈紝鍚庢坊鍔犵殑鍦ㄥ悗闈�
+                     * 鍦ㄥ綋鍓峗scrollPosition涓嬭兘鐪嬪埌鐨勫氨鍙湁浠巗tartIndex鍒癳ndIndex杩欏嚑涓厓绱狅紝鍙渶瑕佸疄渚嬪寲锛堜粠缂撳啿姹犲彇锛夎繖鍑犱釜鍏冪礌灏辫浜�*/
+                }
+            }
+            else
+            {
+                // we are able to reuse some of the previous
+                // cell views
+
+                // first add the views that come before the 
+                // previous list, going backward so that the
+                // new views get added to the front
+                for (i = endIndex; i >= startIndex; i--)
+                {
+                    if (i < remainingCellIndices.First())
+                    {
+                        _AddCellView(i, ListPositionEnum.First);//鍊掑簭娣诲姞锛屽嵆褰撳墠娣诲姞鐨勫厓绱犱竴瀹氬湪绗竴涓紝瀹屾垚寰幆鍚庣涓�涓娣诲姞鐨勫厓绱犲氨鏀惧埌浜嗘渶鍚庝竴涓�
+                    }
+                    /*褰搑emainingCellIndices闆嗗悎涓瓨鍦ㄥ厓绱犳椂锛岃鏄庨泦鍚堜腑鐨勫厓绱犳槸鍙鐨勶紝浣嗘槸涓嶄竴瀹氳兘澶熷畬鍏ㄥ~鍏呭彲瑙嗗尯锛屾墍浠ヨ繕闇�瑕佹牴鎹儏鍐垫潵娣诲姞鏂扮殑鍙鍏冪礌
+                     * 濡傛灉姝ら泦鍚堢殑鏈�灏忓厓绱犵储寮曞ぇ浜巗tartIndex鍜宔ndIndex涔嬪唴鐨勬煇涓�绱㈠紩锛岃鏄庤繖涓�绱㈠紩瀵瑰簲鐨勫瓙鐗╀綋瑕佽繘琛屽疄渚嬪寲锛堜粠缂撳啿姹犲彇锛夛紝涓斾竴瀹氭帓鍦ㄨ繖涓泦鍚堢殑绗竴涓厓绱犱箣鍓�
+                     * 杩欓噷瑕佹敞鎰忕殑鏄惊鐜腑i鏄�掑噺鐨勶紝褰撶储寮昳姣旈泦鍚堜腑鏈�灏忕殑鍏冪礌绱㈠紩閮借灏忔椂璇存槑浜唅绱㈠紩姝ゆ椂骞舵病鏈夊彲瀵瑰簲鐨勫彲瑙佸瓙鐗╀綋锛屽疄渚嬪寲瀛愮墿浣撴椂瑕�
+                     * 灏嗗畠璁剧疆鍦ㄦ渶鍓嶉潰锛屼互姝ょ被鎺紝寰幆瀹屾垚鍚庯紝鍚庢坊鍔犵殑浼氭瘮鍏堟坊鍔犵殑鎺掑湪鍓嶉潰
+                     */
+                }
+
+                // next add teh views that come after the
+                // previous list, going forward and adding
+                // at the end of the list
+                for (i = startIndex; i <= endIndex; i++)
+                {
+                    if (i > remainingCellIndices.Last())
+                    {
+                        _AddCellView(i, ListPositionEnum.Last);
+                    }
+                    /*褰撴闆嗗悎鏈�澶х殑鍏冪礌绱㈠紩灏忎簬startIndex鍒癳ndIndex涓煇涓�绱㈠紩鏃讹紝璇存槑杩欎竴绱㈠紩涓�鏍锋病鏈夊搴旂殑鍙瀛愮墿浣擄紝
+                     * 鍙堝洜涓烘寰幆鏄�掑鐨勶紝鎵�浠ュ厛杩涜瀹炰緥鍖栵紙缂撳啿姹犲彇锛夌殑瀛愮墿浣撲竴瀹氭槸瑕佹瘮鍚庢坊鍔犵殑瀛愮墿浣撴帓鍦ㄥ墠闈�
+                     */
+                }
+            }
+
+            // update the start and end indices
+            _activeCellViewsStartIndex = startIndex;
+            _activeCellViewsEndIndex = endIndex;
+
+            // adjust the padding elements to offset the cell views correctly
+            _SetPadders();//褰撳彲瑙佸尯鍩熻濉厖婊″悗锛屽氨鍙互灏嗗叾瀹冨尯鍩熻缃负padding
+        }
+
+        /// <summary>
+        /// Recycles all the active cells
+        /// </summary>
+        private void _RecycleAllCells()//绉婚櫎鍏ㄩ儴鍙鍏冪礌鍒扮紦鍐叉睜
+        {
+            while (_activeCellViews.Count > 0) _RecycleCell(_activeCellViews[0]);
+            _activeCellViewsStartIndex = 0;
+            _activeCellViewsEndIndex = 0;
+        }
+
+        /// <summary>
+        /// Recycles one cell view
+        /// </summary>
+        /// <param name="cellView"></param>
+        public void _RecycleCell(EnhancedScrollerCellView cellView)//浠巁activeCellVeiws闆嗗悎涓Щ闄ゅ厓绱犲埌_RecycleCell闆嗗悎涓�
+        {
+            // remove the cell view from the active list
+            _activeCellViews.Remove(cellView);
+
+            // add the cell view to the recycled list
+            _recycledCellViews.Add(cellView);
+
+            // move the GameObject to the recycled container
+            cellView.transform.SetParent(_recycledCellViewContainer);
+
+            // reset the cellView's properties
+            cellView.dataIndex = 0;
+            cellView.cellIndex = 0;
+            cellView.active = false;
+
+            if (cellViewVisibilityChanged != null) cellViewVisibilityChanged(cellView);
+        }
+
+        /// <summary>
+        /// Creates a cell view, or recycles if it can
+        /// </summary>
+        /// <param name="cellIndex">The index of the cell view</param>
+        /// <param name="listPosition">Whether to add the cell to the beginning or the end</param>
+        private void _AddCellView(int cellIndex, ListPositionEnum listPosition)
+        {   
+            //閫氳繃鏌愪釜绱㈠紩娣诲姞锛堜粠缂撳啿姹犱腑鍙栵級瀛愮墿浣撳埌_activeCellViews闆嗗悎涓紝骞惰Е鍙戠浉鍏充簨浠�
+            //杩欎釜鏂规硶鏈韩涔熶細鏍规嵁浼犺繃鏉ョ殑绱㈠紩鏉ュ垵濮嬪寲CellView
+             
+            if (NumberOfCells == 0) return;
+
+            // get the dataIndex. Modulus is used in case of looping so that the first set of cells are ignored
+            var dataIndex = cellIndex % NumberOfCells;
+            // request a cell view from the delegate
+            var cellView = _delegate.GetCellView(this, dataIndex, cellIndex);
+
+            // set the cell's properties
+            cellView.cellIndex = cellIndex;
+            cellView.dataIndex = dataIndex;
+            cellView.active = true;
+
+            // add the cell view to the active container
+            cellView.transform.SetParent(_container, false);
+            cellView.transform.localScale = Vector3.one;
+
+            // add a layout element to the cellView
+            LayoutElement layoutElement = cellView.GetComponent<LayoutElement>();
+            if (layoutElement == null) layoutElement = cellView.gameObject.AddComponent<LayoutElement>();
+
+            // set the size of the layout element
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+                layoutElement.minHeight = _cellViewSizeArray[cellIndex] - (cellIndex > 0 ? _layoutGroup.spacing : 0);
+            else
+                layoutElement.minWidth = _cellViewSizeArray[cellIndex] - (cellIndex > 0 ? _layoutGroup.spacing : 0);
+
+            // add the cell to the active list
+            if (listPosition == ListPositionEnum.First)
+                _activeCellViews.AddStart(cellView);
+            else
+                _activeCellViews.Add(cellView);
+
+            // set the hierarchy position of the cell view in the container
+            if (listPosition == ListPositionEnum.Last)
+                cellView.transform.SetSiblingIndex(_container.childCount - 2);//杩欓噷鐨勬坊鍔犳柟寮忓喅瀹氫簡涓や釜padder鐨勪綅缃槸澶圭潃鎵�鏈夌殑cellView鐨�
+            else if (listPosition == ListPositionEnum.First)
+                cellView.transform.SetSiblingIndex(1);
+
+            // call the visibility change delegate if available
+            if (cellViewVisibilityChanged != null) cellViewVisibilityChanged(cellView);
+        }
+
+        /// <summary>
+        /// This function adjusts the two padders that control the first cell view's
+        /// offset and the overall size of each cell.
+        /// </summary>
+        private void _SetPadders()//褰撳鐞嗗畬鍙鍖哄煙鍚庯紝Padder灏卞彲浠ヨ绠楀嚭鏉ワ紝padder鐨勪綔鐢ㄥ氨鏄敤鏉ユ敮鎾戞暣涓猻croll鍐呯殑鍏冪礌锛屼繚璇佸畠浠殑浣嶇疆
+        {
+            if (NumberOfCells == 0) return;
+
+            // calculate the size of each padder
+            var firstSize = _cellViewOffsetArray[_activeCellViewsStartIndex] - _cellViewSizeArray[_activeCellViewsStartIndex];
+            var lastSize = _cellViewOffsetArray.Last() - _cellViewOffsetArray[_activeCellViewsEndIndex];
+
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+            {
+                // set the first padder and toggle its visibility
+                _firstPadder.minHeight = firstSize;
+                _firstPadder.SetActive(_firstPadder.minHeight > 0);
+
+                // set the last padder and toggle its visibility
+                _lastPadder.minHeight = lastSize;
+                _lastPadder.SetActive(_lastPadder.minHeight > 0);
+            }
+            else
+            {
+                // set the first padder and toggle its visibility
+                _firstPadder.minWidth = firstSize;
+                _firstPadder.SetActive(_firstPadder.minWidth > 0);
+
+                // set the last padder and toggle its visibility
+                _lastPadder.minWidth = lastSize;
+                _lastPadder.SetActive(_lastPadder.minWidth > 0);
+            }
+        }
+
+        /// <summary>
+        /// This function is called if the scroller is scrolled, updating the active list of cells
+        /// </summary>
+        private void _RefreshActive()
+        {
+            _refreshActive = false;
+
+            int startIndex;
+            int endIndex;
+            var velocity = Vector2.zero;
+
+            // if looping, check to see if we scrolled past a trigger
+            if (loop)
+            {
+                if (_scrollPosition < _loopFirstJumpTrigger)
+                {
+                    velocity = scrollRect.velocity;
+                    ScrollPosition = _loopLastScrollPosition - (_loopFirstJumpTrigger - _scrollPosition);
+                    scrollRect.velocity = velocity;
+                }
+                else if (_scrollPosition > _loopLastJumpTrigger)
+                {
+                    velocity = scrollRect.velocity;
+                    ScrollPosition = _loopFirstScrollPosition + (_scrollPosition - _loopLastJumpTrigger);
+                    scrollRect.velocity = velocity;
+                }
+                //寰幆妯″紡涓嬭灏哠crollPosition闄愬埗鍦ㄧ浜屼釜寰幆鍐咃紝杩欓噷鐨勫嚑涓彉閲忛兘鏄敤浜庢帶鍒惰繖涓�灞炴�х殑
+                /*娉ㄦ剰杩欓噷鐨凷crollPosition鐨勮祴鍊兼搷浣滐紝鍙湁褰撳湪寰幆妯″紡涓嬶紝涓旀粦鍔ㄧ殑鍋忕Щ宸茬粡杈惧埌浜嗚Е鍙慱loopJumpTrigger鐨勬椂鍊�
+                 * 瀹冩墠浼氬彂鐢熻祴鍊兼搷浣滐紝褰撳畠琚祴鍊间互鍚庯紝鍗虫鏃剁殑content鐨勪綅缃彂鐢熶簡鏀瑰彉锛岀劧鍚庝細鍐嶆璋冪敤姝ゆ柟娉曞埛鏂板彲瑙嗗尯锛岀洿鍒板啀娆¤Е鍙憀oopJumpTirgger
+                 * 涔嬪墠锛孲crollPosition閮戒笉浼氬啀娆¤璧嬪�间簡
+                 */
+            }
+
+            // get the range of visibile cells
+            _CalculateCurrentActiveCellRange(out startIndex, out endIndex);
+
+            // if the index hasn't changed, ignore and return
+            if (startIndex == _activeCellViewsStartIndex && endIndex == _activeCellViewsEndIndex) return;
+
+            // recreate the visibile cells
+            _ResetVisibleCellViews();
+
+            if (this.Delegate != null)
+            {
+                this.Delegate.OnRebuildComplete();
+            }
+        }
+
+        /// <summary>
+        /// Determines which cells can be seen
+        /// </summary>
+        /// <param name="startIndex">The index of the first cell visible</param>
+        /// <param name="endIndex">The index of the last cell visible</param>
+        private void _CalculateCurrentActiveCellRange(out int startIndex, out int endIndex)//杩欎釜鏂规硶杩斿洖鐨勬槸鍩轰簬_scrollPosition寰楀埌鐨勫彲瑙嗗尯鍩熶袱绔储寮�
+        {
+            startIndex = 0;
+            endIndex = 0;
+
+            // get the positions of the scroller
+            var startPosition = _scrollPosition;
+            var endPosition = _scrollPosition + (scrollDirection == ScrollDirectionEnum.Vertical ? _scrollRectTransform.rect.height : _scrollRectTransform.rect.width);
+
+            // calculate each index based on the positions
+            startIndex = GetCellViewIndexAtPosition(startPosition);
+            endIndex = GetCellViewIndexAtPosition(endPosition);
+        }
+
+        /// <summary>
+        /// Gets the index of a cell at a given position based on a subset range.
+        /// This function uses a recursive binary sort to find the index faster.
+        /// </summary>
+        /// <param name="position">The pixel offset from the start of the scroller</param>
+        /// <param name="startIndex">The first index of the range</param>
+        /// <param name="endIndex">The last index of the rnage</param>
+        /// <returns></returns>
+        private int _GetCellIndexAtPosition(float position, int startIndex, int endIndex)//杩欎釜鏂规硶鐨剆tartIndex涓�0 锛宔ndIndex涓篲cellViewOffsetArray鐨勫厓绱犳暟閲�(浣嗕細鏍规嵁璁$畻鐨勫�艰繘琛岃皟鏁达級
+        {
+            // if the range is invalid, then we found our index, return the start index
+            if (startIndex >= endIndex) return startIndex;
+            // determine the middle point of our binary search
+            var middleIndex = (startIndex + endIndex) / 2;
+            // if the middle index is greater than the position, then search the last
+            // half of the binary tree, else search the first half
+            if ((_cellViewOffsetArray[middleIndex] + (scrollDirection == ScrollDirectionEnum.Vertical ? padding.top : padding.left)) >= position)
+                return _GetCellIndexAtPosition(position, startIndex, middleIndex);
+            else
+                return _GetCellIndexAtPosition(position, middleIndex + 1, endIndex);
+        }
+
+        /// <summary>
+        /// Caches and initializes the scroller
+        /// </summary>
+        void Awake()
+        {
+            GameObject go;
+
+            // cache some components
+            //_scrollRect = this.GetComponent<ScrollRect>();
+            _scrollRectTransform = scrollRect.GetComponent<RectTransform>();
+
+            // destroy any content objects if they exist. Likely there will be
+            // one at design time because Unity gives errors if it can't find one.
+            if (scrollRect.content != null)
+            {
+                DestroyImmediate(scrollRect.content.gameObject);//濡傛灉瀛樺湪content鍒欓攢姣�
+            }
+
+            // Create a new active cell view container with a layout group
+            go = new GameObject("Container", typeof(RectTransform));
+            go.transform.SetParent(_scrollRectTransform);
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+                go.AddComponent<VerticalLayoutGroup>();
+            else
+                go.AddComponent<HorizontalLayoutGroup>();
+            _container = go.GetComponent<RectTransform>();
+            // set the containers anchor and pivot
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+            {
+                _container.anchorMin = new Vector2(0, 1);
+                _container.anchorMax = Vector2.one;
+                _container.pivot = new Vector2(0.5f, 1f);
+                //璁剧疆浜哻ontent鐨勯敋鐐瑰拰杞村績锛屼富瑕佷綔鐢ㄦ槸渚夸簬璁$畻,浠ュ畠涓婃柟涓績鐨勭偣鍒皊croll涓婃柟鐨勮窛绂讳负瀹冪殑y杞村�硷紝瀹冪殑闀垮害鍗充负瀹冪殑Height灞炴��
+                //褰撹缃畠鐨勯珮鐨勬椂鍊欏氨鏄缃簡浠栫殑澶у皬
+            }
+            else
+            {
+                _container.anchorMin = Vector2.zero;
+                _container.anchorMax = new Vector2(0, 1f);
+                _container.pivot = new Vector2(0, 0.5f);//鍚屼笂
+            }
+            _container.offsetMax = Vector2.zero;
+            _container.offsetMin = Vector2.zero;
+            _container.localScale = Vector3.one;
+            Vector3 pos = _container.transform.localPosition;
+            pos.z = 0;
+            _container.transform.localPosition = pos;
+            //灏嗗畠鐨勪綅缃浐瀹氬湪scrol涓婃柟鎴栧乏鏂癸紝閫氳繃杩欎釜浣嶇疆鍜屼笂闈㈣缃殑閿氱偣鏉ヤ繚璇佽缃ぇ灏忕殑鏃跺�欎笉浼氳窇鍋�
+            scrollRect.content = _container;
+
+            // cache the scrollbar if it exists
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+            {
+                _scrollbar = scrollRect.verticalScrollbar;
+            }
+            else
+            {
+                _scrollbar = scrollRect.horizontalScrollbar;
+            }
+
+            // cache the layout group and set up its spacing and padding
+            _layoutGroup = _container.GetComponent<HorizontalOrVerticalLayoutGroup>();
+            _layoutGroup.spacing = spacing;
+            _layoutGroup.padding = padding;
+            _layoutGroup.childAlignment = TextAnchor.UpperLeft;//娣诲姞閿氱偣
+            _layoutGroup.childForceExpandHeight = true;
+            _layoutGroup.childForceExpandWidth = true;
+
+            // force the scroller to scroll in the direction we want
+            //_scrollRect.horizontal = scrollDirection == ScrollDirectionEnum.Horizontal;
+            //_scrollRect.vertical = scrollDirection == ScrollDirectionEnum.Vertical;
+
+            // create the padder objects
+
+            go = new GameObject("First Padder", typeof(RectTransform), typeof(LayoutElement));
+            go.transform.SetParent(_container, false);
+            _firstPadder = go.GetComponent<LayoutElement>();
+
+            go = new GameObject("Last Padder", typeof(RectTransform), typeof(LayoutElement));
+            go.transform.SetParent(_container, false);
+            _lastPadder = go.GetComponent<LayoutElement>();
+
+            // create the recycled cell view container
+            go = new GameObject("Recycled Cells", typeof(RectTransform));
+            go.transform.SetParent(scrollRect.transform, false);
+            _recycledCellViewContainer = go.GetComponent<RectTransform>();
+            _recycledCellViewContainer.SetActive(false);
+            //瀹炰緥鍖栦簡涓や釜padder鍜屼竴涓紦鍐叉睜
+            // set up the last values for updates
+            _lastScrollRectSize = ScrollRectSize;
+            _lastLoop = loop;
+            _lastScrollbarVisibility = scrollbarVisibility;
+            //涓�浜涘彉閲忚繘琛屼簡鍒濆鍖�
+
+            if(OnCompLoad!=null) OnCompLoad();
+            inited = true;
+        }
+
+        void Update()
+        {
+            if (_reloadData)//褰撳閮ㄨ剼鏈缃瓺elegate鐨勬椂鍊欏氨浼氬皢_reloadData缃负true
+            {
+                // if the reload flag is true, then reload the data
+                ReloadData();//鐞嗚涓婁笉鐢ㄥ湪澶栭儴璋冪敤ReloadData()鍥犱负褰撴垚鍔熻祴鍊糄elegate鍚庤繖涓柟娉曞氨浼氭墽琛屼竴娆�
+                               //浣嗗鏋滄兂鍦╱pdate涔嬪墠鎵ц灏变富鍔ㄨ皟鐢≧eloadData()
+            }
+
+            // if the scroll rect size has changed and looping is on,
+            // or the loop setting has changed, then we need to resize
+            if (
+                    (loop && _lastScrollRectSize != ScrollRectSize)//褰揝croll鐨勫ぇ灏忓彂鐢熸敼鍙樺苟涓斿紑鍚惊鐜椂
+                    ||
+                    (loop != _lastLoop)//褰撳惊鐜紑鍏冲彂鐢熶簡鏀瑰彉
+                )
+            {
+                _Resize(true);
+                _lastScrollRectSize = ScrollRectSize;
+
+                _lastLoop = loop;
+            }
+
+            // update the scroll bar visibility if it has changed
+            if (_lastScrollbarVisibility != scrollbarVisibility)//濡傛灉婊戝姩鏉$殑鍙鎬у彂鐢熸敼鍙樹篃闇�瑕佹洿鏂颁竴涓嬬浉鍏冲彉閲�
+            {
+                ScrollbarVisibility = scrollbarVisibility;
+                _lastScrollbarVisibility = scrollbarVisibility;
+            }
+
+            // determine if the scroller has started or stopped scrolling
+            // and call the delegate if so.
+            if (LinearVelocity != 0 && !IsScrolling)//褰揝croll.velocity涓嶄负0鏃惰鏄庡湪婊戝姩锛屾鏃跺鏋淚sScrolling涓篺alse(鏍囪涓烘病鏈夋粦鍔�)
+            {                                       //瑙﹀彂褰撴粦鍔ㄥ紑濮嬫椂鐨勪簨浠�
+                IsScrolling = true;
+                if (scrollerScrollingChanged != null) scrollerScrollingChanged(this, true);
+            }
+            else if (LinearVelocity == 0 && IsScrolling)//鍚岀悊瑙﹀彂褰撴粦鍔ㄧ粨鏉熸椂鐨勪簨浠讹紝杩欓噷鐨勪袱涓簨浠堕兘鍙細鍦ㄤ竴涓粦鍔ㄥ懆鏈熸椂鍚勬墽琛屼竴娆�
+            {
+                IsScrolling = false;
+                if (scrollerScrollingChanged != null) scrollerScrollingChanged(this, false);
+            }
+        }
+
+        void LateUpdate()
+        {
+            if (_refreshActive)//褰撹缃甋crollPosition鏃跺氨浼氬皢_refreshActive缃负true,姝ゆ椂灏变細璋冪敤_RefreshActive()鏂规硶
+            {
+                // if the refresh toggle is on, then
+                // refresh the list
+                _RefreshActive();
+            }
+        }
+
+        void OnEnable()
+        {
+            // when the scroller is enabled, add a listener to the onValueChanged handler
+            scrollRect.onValueChanged.AddListener(_ScrollRect_OnValueChanged);//褰撴樉绀烘椂娉ㄥ唽
+        }
+
+        void OnDisable()
+        {
+            // when the scroller is disabled, remove the listener
+            scrollRect.onValueChanged.RemoveListener(_ScrollRect_OnValueChanged);//褰撻殣钘忔椂绉婚櫎娉ㄥ唽
+        }
+
+        /// <summary>
+        /// Handler for when the scroller changes value
+        /// </summary>
+        /// <param name="val">The scroll rect's value</param>
+        private void _ScrollRect_OnValueChanged(Vector2 val)
+        {
+            // set the internal scroll position
+            if (scrollDirection == ScrollDirectionEnum.Vertical)
+            {
+                _scrollPosition = (1f - val.y) * _ScrollSize;//娉ㄦ剰杩欓噷鍙槸缁欑鏈夊瓧娈佃祴鍊硷紝骞朵笉浼氳皟鐢ㄧ浉鍏冲睘鎬х殑Set鏂规硶锛堝鏋滆皟鐢ㄤ簡Set鏂规硶浼氬鑷存棤闄愬惊鐜紝Set鏂规硶浼氳Е鍙憊aluechange锛寁aluechange鍙堣Е鍙慡et)
+            }
+            else
+            {
+                _scrollPosition = val.x * _ScrollSize;
+            }
+            _refreshActive = true;//鏍囪瑕佽繘琛屽埛鏂�
+
+            // call the handler if it exists
+            if (scrollerScrolled != null) scrollerScrolled(this, val, _scrollPosition);//婊戝姩杩囩▼涓Е鍙戠殑鐩稿叧浜嬩欢
+
+            // if the snapping is turned on, handle it
+            if (snapping && !_snapJumping)//濡傛灉寮�鍚攣瀹氫綅缃紝浣嗘鏃舵病鏈夊畾浣�
+            {
+                // if the speed has dropped below the threshhold velocity
+                if (Mathf.Abs(LinearVelocity) <= snapVelocityThreshold)
+                {
+                    // Call the snap function
+                    Snap();//杩涜瀹氫綅
+                }
+            }
+
+            _RefreshActive();//鍒锋柊
+            /*鍦ㄦ粦鍔ㄧ殑杩囩▼涓紝閫氳繃NormalizePosition鏉ユ眰寰梍scrollPosition
+             * 濡傛灉婊¤冻瀹氫綅鏉′欢灏辫繘琛屽畾浣�
+             * 浠ヤ笂浠g爜鎵ц瀹屾垚鍚庡氨浼氬幓鍒锋柊鏁翠釜Scroll
+             */
+
+        }
+        
+        /// <summary>
+        /// This is fired by the tweener when the snap tween is completed
+        /// </summary>
+        private void SnapJumpComplete()//褰撳畾浣嶅畬鎴愭椂
+        {
+            // reset the snap jump to false and restore the inertia state
+            _snapJumping = false;
+            scrollRect.inertia = _snapInertia;
+
+            // fire the scroller snapped delegate
+            if (scrollerSnapped != null) scrollerSnapped(this, _snapCellViewIndex, _snapDataIndex);
+        }
+
+        #endregion
+
+        #region Tweening
+
+        /// <summary>
+        /// The easing type
+        /// </summary>
+        public enum TweenType
+        {
+            immediate,
+            linear,
+            spring,
+            easeInQuad,
+            easeOutQuad,
+            easeInOutQuad,
+            easeInCubic,
+            easeOutCubic,
+            easeInOutCubic,
+            easeInQuart,
+            easeOutQuart,
+            easeInOutQuart,
+            easeInQuint,
+            easeOutQuint,
+            easeInOutQuint,
+            easeInSine,
+            easeOutSine,
+            easeInOutSine,
+            easeInExpo,
+            easeOutExpo,
+            easeInOutExpo,
+            easeInCirc,
+            easeOutCirc,
+            easeInOutCirc,
+            easeInBounce,
+            easeOutBounce,
+            easeInOutBounce,
+            easeInBack,
+            easeOutBack,
+            easeInOutBack,
+            easeInElastic,
+            easeOutElastic,
+            easeInOutElastic
+        }
+
+        private float _tweenTimeLeft;
+        public bool inited;
+
+        /// <summary>
+        /// Moves the scroll position over time between two points given an easing function. When the
+        /// tween is complete it will fire the jumpComplete delegate.
+        /// </summary>
+        /// <param name="tweenType">The type of easing to use</param>
+        /// <param name="time">The amount of time to interpolate</param>
+        /// <param name="start">The starting scroll position</param>
+        /// <param name="end">The ending scroll position</param>
+        /// <param name="jumpComplete">The action to fire when the tween is complete</param>
+        /// <returns></returns>
+        IEnumerator TweenPosition(TweenType tweenType, float time, float start, float end, Action tweenComplete)
+        {
+            if (tweenType == TweenType.immediate || time == 0)
+            {
+                // if the easing is immediate or the time is zero, just jump to the end position
+                ScrollPosition = end;
+            }
+            else
+            {
+                // zero out the velocity
+                scrollRect.velocity = Vector2.zero;
+
+                // fire the delegate for the tween start
+                IsTweening = true;
+                if (scrollerTweeningChanged != null) scrollerTweeningChanged(this, true);
+
+                _tweenTimeLeft = 0;
+                var newPosition = 0f;
+
+                // while the tween has time left, use an easing function
+                while (_tweenTimeLeft < time)
+                {
+                    switch (tweenType)
+                    {
+                        case TweenType.linear: newPosition = linear(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.spring: newPosition = spring(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInQuad: newPosition = easeInQuad(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutQuad: newPosition = easeOutQuad(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutQuad: newPosition = easeInOutQuad(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInCubic: newPosition = easeInCubic(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutCubic: newPosition = easeOutCubic(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutCubic: newPosition = easeInOutCubic(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInQuart: newPosition = easeInQuart(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutQuart: newPosition = easeOutQuart(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutQuart: newPosition = easeInOutQuart(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInQuint: newPosition = easeInQuint(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutQuint: newPosition = easeOutQuint(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutQuint: newPosition = easeInOutQuint(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInSine: newPosition = easeInSine(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutSine: newPosition = easeOutSine(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutSine: newPosition = easeInOutSine(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInExpo: newPosition = easeInExpo(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutExpo: newPosition = easeOutExpo(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutExpo: newPosition = easeInOutExpo(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInCirc: newPosition = easeInCirc(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutCirc: newPosition = easeOutCirc(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutCirc: newPosition = easeInOutCirc(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInBounce: newPosition = easeInBounce(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutBounce: newPosition = easeOutBounce(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutBounce: newPosition = easeInOutBounce(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInBack: newPosition = easeInBack(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutBack: newPosition = easeOutBack(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutBack: newPosition = easeInOutBack(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInElastic: newPosition = easeInElastic(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeOutElastic: newPosition = easeOutElastic(start, end, (_tweenTimeLeft / time)); break;
+                        case TweenType.easeInOutElastic: newPosition = easeInOutElastic(start, end, (_tweenTimeLeft / time)); break;
+                    }
+
+                    if (loop)
+                    {
+                        // if we are looping, we need to make sure the new position isn't past the jump trigger.
+                        // if it is we need to reset back to the jump position on the other side of the area.
+
+                        if (end > start && newPosition > _loopLastJumpTrigger)
+                        {
+                            //DesignDebug.Log("name: " + name + " went past the last jump trigger, looping back around");
+                            newPosition = _loopFirstScrollPosition + (newPosition - _loopLastJumpTrigger);
+                        }
+                        else if (start > end && newPosition < _loopFirstJumpTrigger)
+                        {
+                            //DesignDebug.Log("name: " + name + " went past the first jump trigger, looping back around");
+                            newPosition = _loopLastScrollPosition - (_loopFirstJumpTrigger - newPosition);
+                        }
+                    }
+
+                    // set the scroll position to the tweened position
+                    ScrollPosition = newPosition;
+
+                    // increase the time elapsed
+                    _tweenTimeLeft += Time.unscaledDeltaTime;
+
+                    yield return null;
+                }
+
+                // the time has expired, so we make sure the final scroll position
+                // is the actual end position.
+                ScrollPosition = end;
+            }
+
+            // the tween jump is complete, so we fire the delegate
+            if (tweenComplete != null) tweenComplete();
+
+            // fire the delegate for the tween ending
+            IsTweening = false;
+            if (scrollerTweeningChanged != null) scrollerTweeningChanged(this, false);
+        }
+
+        private float linear(float start, float end, float val)
+        {
+            return Mathf.Lerp(start, end, val);
+        }
+
+        private static float spring(float start, float end, float val)
+        {
+            val = Mathf.Clamp01(val);
+            val = (Mathf.Sin(val * Mathf.PI * (0.2f + 2.5f * val * val * val)) * Mathf.Pow(1f - val, 2.2f) + val) * (1f + (1.2f * (1f - val)));
+            return start + (end - start) * val;
+        }
+
+        private static float easeInQuad(float start, float end, float val)
+        {
+            end -= start;
+            return end * val * val + start;
+        }
+
+        private static float easeOutQuad(float start, float end, float val)
+        {
+            end -= start;
+            return -end * val * (val - 2) + start;
+        }
+
+        private static float easeInOutQuad(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return end / 2 * val * val + start;
+            val--;
+            return -end / 2 * (val * (val - 2) - 1) + start;
+        }
+
+        private static float easeInCubic(float start, float end, float val)
+        {
+            end -= start;
+            return end * val * val * val + start;
+        }
+
+        private static float easeOutCubic(float start, float end, float val)
+        {
+            val--;
+            end -= start;
+            return end * (val * val * val + 1) + start;
+        }
+
+        private static float easeInOutCubic(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return end / 2 * val * val * val + start;
+            val -= 2;
+            return end / 2 * (val * val * val + 2) + start;
+        }
+
+        private static float easeInQuart(float start, float end, float val)
+        {
+            end -= start;
+            return end * val * val * val * val + start;
+        }
+
+        private static float easeOutQuart(float start, float end, float val)
+        {
+            val--;
+            end -= start;
+            return -end * (val * val * val * val - 1) + start;
+        }
+
+        private static float easeInOutQuart(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return end / 2 * val * val * val * val + start;
+            val -= 2;
+            return -end / 2 * (val * val * val * val - 2) + start;
+        }
+
+        private static float easeInQuint(float start, float end, float val)
+        {
+            end -= start;
+            return end * val * val * val * val * val + start;
+        }
+
+        private static float easeOutQuint(float start, float end, float val)
+        {
+            val--;
+            end -= start;
+            return end * (val * val * val * val * val + 1) + start;
+        }
+
+        private static float easeInOutQuint(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return end / 2 * val * val * val * val * val + start;
+            val -= 2;
+            return end / 2 * (val * val * val * val * val + 2) + start;
+        }
+
+        private static float easeInSine(float start, float end, float val)
+        {
+            end -= start;
+            return -end * Mathf.Cos(val / 1 * (Mathf.PI / 2)) + end + start;
+        }
+
+        private static float easeOutSine(float start, float end, float val)
+        {
+            end -= start;
+            return end * Mathf.Sin(val / 1 * (Mathf.PI / 2)) + start;
+        }
+
+        private static float easeInOutSine(float start, float end, float val)
+        {
+            end -= start;
+            return -end / 2 * (Mathf.Cos(Mathf.PI * val / 1) - 1) + start;
+        }
+
+        private static float easeInExpo(float start, float end, float val)
+        {
+            end -= start;
+            return end * Mathf.Pow(2, 10 * (val / 1 - 1)) + start;
+        }
+
+        private static float easeOutExpo(float start, float end, float val)
+        {
+            end -= start;
+            return end * (-Mathf.Pow(2, -10 * val / 1) + 1) + start;
+        }
+
+        private static float easeInOutExpo(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return end / 2 * Mathf.Pow(2, 10 * (val - 1)) + start;
+            val--;
+            return end / 2 * (-Mathf.Pow(2, -10 * val) + 2) + start;
+        }
+
+        private static float easeInCirc(float start, float end, float val)
+        {
+            end -= start;
+            return -end * (Mathf.Sqrt(1 - val * val) - 1) + start;
+        }
+
+        private static float easeOutCirc(float start, float end, float val)
+        {
+            val--;
+            end -= start;
+            return end * Mathf.Sqrt(1 - val * val) + start;
+        }
+
+        private static float easeInOutCirc(float start, float end, float val)
+        {
+            val /= .5f;
+            end -= start;
+            if (val < 1) return -end / 2 * (Mathf.Sqrt(1 - val * val) - 1) + start;
+            val -= 2;
+            return end / 2 * (Mathf.Sqrt(1 - val * val) + 1) + start;
+        }
+
+        private static float easeInBounce(float start, float end, float val)
+        {
+            end -= start;
+            float d = 1f;
+            return end - easeOutBounce(0, end, d - val) + start;
+        }
+
+        private static float easeOutBounce(float start, float end, float val)
+        {
+            val /= 1f;
+            end -= start;
+            if (val < (1 / 2.75f))
+            {
+                return end * (7.5625f * val * val) + start;
+            }
+            else if (val < (2 / 2.75f))
+            {
+                val -= (1.5f / 2.75f);
+                return end * (7.5625f * (val) * val + .75f) + start;
+            }
+            else if (val < (2.5 / 2.75))
+            {
+                val -= (2.25f / 2.75f);
+                return end * (7.5625f * (val) * val + .9375f) + start;
+            }
+            else
+            {
+                val -= (2.625f / 2.75f);
+                return end * (7.5625f * (val) * val + .984375f) + start;
+            }
+        }
+
+        private static float easeInOutBounce(float start, float end, float val)
+        {
+            end -= start;
+            float d = 1f;
+            if (val < d / 2) return easeInBounce(0, end, val * 2) * 0.5f + start;
+            else return easeOutBounce(0, end, val * 2 - d) * 0.5f + end * 0.5f + start;
+        }
+
+        private static float easeInBack(float start, float end, float val)
+        {
+            end -= start;
+            val /= 1;
+            float s = 1.70158f;
+            return end * (val) * val * ((s + 1) * val - s) + start;
+        }
+
+        private static float easeOutBack(float start, float end, float val)
+        {
+            float s = 1.70158f;
+            end -= start;
+            val = (val / 1) - 1;
+            return end * ((val) * val * ((s + 1) * val + s) + 1) + start;
+        }
+
+        private static float easeInOutBack(float start, float end, float val)
+        {
+            float s = 1.70158f;
+            end -= start;
+            val /= .5f;
+            if ((val) < 1)
+            {
+                s *= (1.525f);
+                return end / 2 * (val * val * (((s) + 1) * val - s)) + start;
+            }
+            val -= 2;
+            s *= (1.525f);
+            return end / 2 * ((val) * val * (((s) + 1) * val + s) + 2) + start;
+        }
+
+        private static float easeInElastic(float start, float end, float val)
+        {
+            end -= start;
+
+            float d = 1f;
+            float p = d * .3f;
+            float s = 0;
+            float a = 0;
+
+            if (val == 0) return start;
+            val = val / d;
+            if (val == 1) return start + end;
+
+            if (a == 0f || a < Mathf.Abs(end))
+            {
+                a = end;
+                s = p / 4;
+            }
+            else
+            {
+                s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
+            }
+            val = val - 1;
+            return -(a * Mathf.Pow(2, 10 * val) * Mathf.Sin((val * d - s) * (2 * Mathf.PI) / p)) + start;
+        }
+
+        private static float easeOutElastic(float start, float end, float val)
+        {
+            end -= start;
+
+            float d = 1f;
+            float p = d * .3f;
+            float s = 0;
+            float a = 0;
+
+            if (val == 0) return start;
+
+            val = val / d;
+            if (val == 1) return start + end;
+
+            if (a == 0f || a < Mathf.Abs(end))
+            {
+                a = end;
+                s = p / 4;
+            }
+            else
+            {
+                s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
+            }
+
+            return (a * Mathf.Pow(2, -10 * val) * Mathf.Sin((val * d - s) * (2 * Mathf.PI) / p) + end + start);
+        }
+
+        private static float easeInOutElastic(float start, float end, float val)
+        {
+            end -= start;
+
+            float d = 1f;
+            float p = d * .3f;
+            float s = 0;
+            float a = 0;
+
+            if (val == 0) return start;
+
+            val = val / (d / 2);
+            if (val == 2) return start + end;
+
+            if (a == 0f || a < Mathf.Abs(end))
+            {
+                a = end;
+                s = p / 4;
+            }
+            else
+            {
+                s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
+            }
+
+            if (val < 1)
+            {
+                val = val - 1;
+                return -0.5f * (a * Mathf.Pow(2, 10 * val) * Mathf.Sin((val * d - s) * (2 * Mathf.PI) / p)) + start;
+            }
+            val = val - 1;
+            return a * Mathf.Pow(2, -10 * val) * Mathf.Sin((val * d - s) * (2 * Mathf.PI) / p) * 0.5f + end + start;
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs.meta b/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs.meta
new file mode 100644
index 0000000..f0884b6
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/EnhancedScroller.cs.meta
@@ -0,0 +1,25 @@
+fileFormatVersion: 2
+guid: 9c1b74f910281224a8cae6d8e4fc1f43
+labels:
+- Data
+- Inventory
+- Cells
+- Cell
+- Reuse
+- UI
+- ScrollRect
+- Scroller
+- Virtualize
+- Recycle
+- Scroll
+- List
+timeCreated: 1435585470
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs b/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs
new file mode 100644
index 0000000..2e99af9
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs
@@ -0,0 +1,53 @@
+锘縰sing UnityEngine;
+using System;
+using System.Collections;
+
+namespace EnhancedUI.EnhancedScroller
+{
+    /// <summary>
+    /// This is the base class that all cell views should derive from
+    /// </summary>
+    public class EnhancedScrollerCellView : WidgetBehavior
+    {
+        /// <summary>
+        /// The cellIdentifier is a unique string that allows the scroller
+        /// to handle different types of cells in a single list. Each type
+        /// of cell should have its own identifier
+        /// </summary>
+        public string cellIdentifier; //褰撳瓨鍦ㄤ笉鍚宲refab鐨勬椂鍊欙紝灏卞彲浠ョ敤杩欎釜identifier鏉ュ尯鍒�
+
+        /// <summary>
+        /// The cell index of the cell view
+        /// This will differ from the dataIndex if the list is looping
+        /// </summary>
+        [NonSerialized]
+        public int cellIndex;//_activeCellViews涓殑绱㈠紩
+
+        [NonSerialized]
+        public int index = -1;//_activeCellViews涓殑绱㈠紩
+
+        /// <summary>
+        /// The data index of the cell view
+        /// </summary>
+        [NonSerialized]
+        public int dataIndex;//闈炲惊鐜ā寮忎笅鍜宑ellIndex鐩稿悓锛屽惊鐜ā寮忎笅涓哄綋鍓嶅惊鐜殑瀛愮墿浣撶殑绱㈠紩
+
+        /// <summary>
+        /// Whether the cell is active or recycled
+        /// </summary>
+        [NonSerialized]
+        public bool active;
+
+        /// <summary>
+        /// This method is called by the scroller when the RefreshActiveCellViews is called on the scroller
+        /// You can override it to update your cell's view UID
+        /// </summary>
+        public virtual void RefreshCellView() { }//褰撲富鍔ㄨ皟鐢‥nhancedScrller绫讳腑RefreshActiveCellViews()鏂规硶鏃讹紝浼氶亶鍘嗗綋鍓嶅浜嶢ctive鐘舵�佺殑CellVeiw锛屽苟璋冪敤瀹冧滑閲嶅啓鐨勮繖涓柟娉�
+                                                 //杩欎釜鏂规硶鍙互鐢ㄤ簬涓诲姩鍒锋柊褰撳墠澶勪簬Active鐘舵�佺殑CellVeiw
+
+        protected virtual void Awake()
+        {
+            InitWidgts();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs.meta b/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs.meta
new file mode 100644
index 0000000..323996a
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/EnhancedScrollerCellView.cs.meta
@@ -0,0 +1,25 @@
+fileFormatVersion: 2
+guid: 1f75717e94199704f82f26fcf6953e84
+labels:
+- Data
+- Inventory
+- Cells
+- Cell
+- Reuse
+- UI
+- ScrollRect
+- Scroller
+- Virtualize
+- Recycle
+- Scroll
+- List
+timeCreated: 1435585579
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs b/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs
new file mode 100644
index 0000000..b82ac3f
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs
@@ -0,0 +1,53 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace EnhancedUI.EnhancedScroller
+{
+    /// <summary>
+    /// All scripts that handle the scroller's callbacks should inherit from this interface
+    /// </summary>
+    public interface IEnhancedScrollerDelegate
+    {
+        /// <summary>
+        /// Gets the number of cells in a list of data
+        /// </summary>
+        /// <param name="scroller"></param>
+        /// <returns></returns>
+        int GetNumberOfCells(EnhancedScroller scroller);//寰楀埌Scroll閲岄潰CellVeiw鐨勬�绘暟鐩�
+
+        /// <summary>
+        /// Gets the size of a cell view given the index of the data set.
+        /// This allows you to have different sized cells
+        /// </summary>
+        /// <param name="scroller"></param>
+        /// <param name="dataIndex"></param>
+        /// <returns></returns>
+        float GetCellViewSize(EnhancedScroller scroller, int dataIndex);//寰楀埌鏌愪釜dataIndex鐨剆ize锛堝洜涓烘湁鍙兘浼氬瓨鍦ㄤ笉鍚岀殑CellVeiw锛�
+
+        /// <summary>
+        /// Gets the cell view that should be used for the data index. Your implementation
+        /// of this function should request a new cell from the scroller so that it can
+        /// properly recycle old cells.
+        /// </summary>
+        /// <param name="scroller"></param>
+        /// <param name="dataIndex"></param>
+        /// <param name="cellIndex"></param>
+        /// <returns></returns>
+        EnhancedScrollerCellView GetCellView(EnhancedScroller scroller, int dataIndex, int cellIndex);
+        /*
+         * 鐢ㄤ簬寰楀埌锛堟垨浠庡惊鐜泦鍚堜腑鍙栵紝鎴栧疄渚嬪寲锛変竴涓狢ellView骞跺彇鍏禖ellView瀵硅薄
+           娉ㄦ剰杩欓噷杩斿洖鐨勬槸CellView鐨勭埗绫诲瀷锛孋ellVeiw鏄鑷繁鏉ュ啓鐨�,杩欐牱灏卞彲浠ラ�氳繃閲嶅啓鐖剁被鐨勮櫄鏂规硶瀹炵幇澶氭��
+           */
+
+
+        /*瑕佹兂浣跨敤杩欎釜鎻掍欢锛岄渶瑕佹垜浠坊鍔犱袱涓被锛�
+         * 1锛変竴涓被缁ф壙鑷狤nHancedScrollerCellView锛岀敤浜庝繚瀛樺崟涓狢ellView鐨勭浉鍏充俊鎭�
+         * 2锛夊彟涓�涓被瀹炵幇杩欎釜鎺ュ彛锛岀敤浜庢帶鍒舵暣涓猄croll锛屽苟鎻愪緵缁欏鐣屼竴浜涚浉鍏充俊鎭紙鎬荤殑CellView鏁扮洰锛屾瘡涓狢ellView鐨剆ize绛夛級
+         *      鍏朵腑锛孏etCellView()鏂规硶鍦ㄥ疄鐜扮殑鏃跺�欑洿鎺ヨ皟鐢� EnhancedScroller绫讳腑鐨凣etCellView锛堬級鏂规硶鏉ヨ繘琛屽疄鐜板氨鍙互浜�
+         * 杩欎袱涓被涔熷彲鏍规嵁鑷繁鐨勯渶瑕佽繘琛屾墿灞�
+         */
+
+
+        void OnRebuildComplete();
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs.meta b/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs.meta
new file mode 100644
index 0000000..d8b3d83
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/IEnhancedScrollerDelegate.cs.meta
@@ -0,0 +1,25 @@
+fileFormatVersion: 2
+guid: 7701b31137fe72d47b256054738fd57d
+labels:
+- Data
+- Inventory
+- Cells
+- Cell
+- Reuse
+- UI
+- ScrollRect
+- Scroller
+- Virtualize
+- Recycle
+- Scroll
+- List
+timeCreated: 1435585741
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/EnhancedScroller/SmallList.cs b/Main/Component/UI/EnhancedScroller/SmallList.cs
new file mode 100644
index 0000000..b681c5b
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/SmallList.cs
@@ -0,0 +1,219 @@
+锘縰sing UnityEngine;
+using System.Collections.Generic;
+
+namespace EnhancedUI
+{
+    /// <summary>
+    /// This is a super light implementation of an array that 
+    /// behaves like a list, automatically allocating new memory
+    /// when needed, but not releasing it to garbage collection.
+    /// </summary>
+    /// <typeparam name="T">The type of the list</typeparam>
+    public class SmallList<T>
+    {
+        /// <summary>
+        /// internal storage of list data
+        /// </summary>
+        public T[] data;
+
+        /// <summary>
+        /// The number of elements in the list
+        /// </summary>
+        public int Count = 0;
+
+        /// <summary>
+        /// Indexed access to the list items
+        /// </summary>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public T this[int i]
+        {
+            get { return data[i]; }
+            set { data[i] = value; }
+        }
+
+        /// <summary>
+        /// Resizes the array when more memory is needed.
+        /// </summary>
+        private void ResizeArray()
+        {
+            T[] newData;
+
+            if (data != null)
+                newData = new T[Mathf.Max(data.Length << 1, 64)];
+            else
+                newData = new T[64];
+
+            if (data != null && Count > 0)
+                data.CopyTo(newData, 0);
+
+            data = newData;
+        }
+
+        /// <summary>
+        /// Instead of releasing the memory to garbage collection, 
+        /// the list size is set back to zero
+        /// </summary>
+        public void Clear()
+        {
+            Count = 0;
+        }
+
+        /// <summary>
+        /// Returns the first element of the list
+        /// </summary>
+        /// <returns></returns>
+        public T First()
+        {
+            if (data == null || Count == 0) return default(T);
+            return data[0];
+        }
+
+        /// <summary>
+        /// Returns the last element of the list
+        /// </summary>
+        /// <returns></returns>
+        public T Last()
+        {
+            if (data == null || Count == 0) return default(T);
+            return data[Count - 1];
+        }
+
+        /// <summary>
+        /// Adds a new element to the array, creating more
+        /// memory if necessary
+        /// </summary>
+        /// <param name="item"></param>
+        public void Add(T item)
+        {
+            if (data == null || Count == data.Length)
+                ResizeArray();
+
+            data[Count] = item;
+            Count++;
+        }
+
+        /// <summary>
+        /// Adds a new element to the start of the array, creating more
+        /// memory if necessary
+        /// </summary>
+        /// <param name="item"></param>
+        public void AddStart(T item)
+        {
+            Insert(item, 0);
+        }
+
+        /// <summary>
+        /// Inserts a new element to the array at the index specified, creating more
+        /// memory if necessary
+        /// </summary>
+        /// <param name="item"></param>
+        public void Insert(T item, int index)
+        {
+            if (data == null || Count == data.Length)
+                ResizeArray();
+
+            for (var i = Count; i > index; i--)
+            {
+                data[i] = data[i - 1];
+            }
+
+            data[index] = item;
+            Count++;
+        }
+
+        /// <summary>
+        /// Removes an item from the start of the data
+        /// </summary>
+        /// <returns></returns>
+        public T RemoveStart()
+        {
+            return RemoveAt(0);
+        }
+
+        /// <summary>
+        /// Removes an item from the index of the data
+        /// </summary>
+        /// <returns></returns>
+        public T RemoveAt(int index)
+        {
+            if (data != null && Count != 0)
+            {
+                T val = data[index];
+
+                for (var i = index; i < Count - 1; i++)
+                {
+                    data[i] = data[i + 1];
+                }
+
+                Count--;
+                data[Count] = default(T);
+                return val;
+            }
+            else
+            {
+                return default(T);
+            }
+        }
+
+        /// <summary>
+        /// Removes an item from the data
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public T Remove(T item)
+        {
+            if (data != null && Count != 0)
+            {
+                for (var i = 0; i < Count; i++)
+                {
+                    if (data[i].Equals(item))
+                    {
+                        return RemoveAt(i);
+                    }
+                }
+            }
+
+            return default(T);
+        }
+
+        /// <summary>
+        /// Removes an item from the end of the data
+        /// </summary>
+        /// <returns></returns>
+        public T RemoveEnd()
+        {
+            if (data != null && Count != 0)
+            {
+                Count--;
+                T val = data[Count];
+                data[Count] = default(T);
+
+                return val;
+            }
+            else
+            {
+                return default(T);
+            }
+        }
+
+        /// <summary>
+        /// Determines if the data contains the item
+        /// </summary>
+        /// <param name="item">The item to compare</param>
+        /// <returns>True if the item exists in teh data</returns>
+        public bool Contains(T item)
+        {
+            if (data == null)
+                return false;
+
+            for (var i = 0; i < Count; i++)
+            {
+                if (data[i].Equals(item))
+                    return true;
+            }
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/Component/UI/EnhancedScroller/SmallList.cs.meta b/Main/Component/UI/EnhancedScroller/SmallList.cs.meta
new file mode 100644
index 0000000..05a4a0f
--- /dev/null
+++ b/Main/Component/UI/EnhancedScroller/SmallList.cs.meta
@@ -0,0 +1,25 @@
+fileFormatVersion: 2
+guid: aab29d68fb4a95d49bca25f359d8f076
+labels:
+- Data
+- Inventory
+- Cells
+- Cell
+- Reuse
+- UI
+- ScrollRect
+- Scroller
+- Virtualize
+- Recycle
+- Scroll
+- List
+timeCreated: 1435585634
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD.meta b/Main/Component/UI/HUD.meta
new file mode 100644
index 0000000..a585204
--- /dev/null
+++ b/Main/Component/UI/HUD.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 3dea1f2e58b7e4d4ea5465f0d68856e1
+folderAsset: yes
+timeCreated: 1458660429
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/DialogueBubble.cs b/Main/Component/UI/HUD/DialogueBubble.cs
new file mode 100644
index 0000000..5382e8a
--- /dev/null
+++ b/Main/Component/UI/HUD/DialogueBubble.cs
@@ -0,0 +1,72 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, December 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class DialogueBubble : HUDBehaviour
+    {
+        [SerializeField] Text m_Content;
+        [SerializeField] protected float m_Duration = 2f;
+        public float duration {
+            get { return m_Duration; }
+            set { m_Duration = value; }
+        }
+
+        public Pattern pattern { get; set; }
+        protected bool showing = false;
+        float endTime = 0f;
+        GameObject tempTarget;
+
+        public virtual void Show(string _content, Transform _target, Camera _camera)
+        {
+            base.target = _target;
+            base.offset = Vector3.zero;
+            base.camera = _camera;
+            endTime = Time.time + m_Duration;
+            m_Content.text = _content;
+            this.SetActive(true);
+            SyncPosition(true);
+
+            showing = true;
+        }
+
+        public void Show(string _content, Vector3 _position, Camera _camera)
+        {
+            if (tempTarget == null)
+            {
+                tempTarget = new GameObject("Temp_MountPoint");
+            }
+            tempTarget.transform.position = _position;
+
+            Show(_content, tempTarget.transform, _camera);
+        }
+
+        protected override void LateUpdate()
+        {
+            base.LateUpdate();
+
+            if (showing && Time.time > endTime)
+            {
+                showing = false;
+                DialogueBubblePool.Recycle(this);
+            }
+        }
+
+        public enum Pattern
+        {
+            NPC,
+            Story,
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/DialogueBubble.cs.meta b/Main/Component/UI/HUD/DialogueBubble.cs.meta
new file mode 100644
index 0000000..32a283a
--- /dev/null
+++ b/Main/Component/UI/HUD/DialogueBubble.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6fd0c99bc20b9b0489fbbe92c1e8a836
+timeCreated: 1512783340
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/DialogueBubblePool.cs b/Main/Component/UI/HUD/DialogueBubblePool.cs
new file mode 100644
index 0000000..522c120
--- /dev/null
+++ b/Main/Component/UI/HUD/DialogueBubblePool.cs
@@ -0,0 +1,75 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, December 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI
+{
+
+    public class DialogueBubblePool
+    {
+        static Dictionary<int, GameObjectPoolManager.GameObjectPool> pools = new Dictionary<int, GameObjectPoolManager.GameObjectPool>();
+
+        public static DialogueBubble Require(DialogueBubble.Pattern _pattern)
+        {
+            var intPattern = (int)_pattern;
+            GameObjectPoolManager.GameObjectPool pool = null;
+            if (!pools.ContainsKey(intPattern))
+            {
+                var prefab = UILoader.LoadPrefab(StringUtility.Contact("DialogueBubble_", _pattern));
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pools[intPattern] = pool;
+                }
+            }
+            else
+            {
+                pool = pools[intPattern];
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                var dialogueBubble = instance.GetComponent<DialogueBubble>();
+                dialogueBubble.pattern = _pattern;
+                return dialogueBubble;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(DialogueBubble _dialogueBubble)
+        {
+            var intPattern = (int)_dialogueBubble.pattern;
+            if (pools.ContainsKey(intPattern))
+            {
+                var pool = pools[intPattern];
+                pool.Release(_dialogueBubble.gameObject);
+                _dialogueBubble.transform.SetParent(null);
+                _dialogueBubble.SetActive(false);
+            }
+        }
+
+        public static void Clear()
+        {
+            foreach (var pool in pools.Values)
+            {
+                pool.Clear();
+            }
+
+            pools.Clear();
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/DialogueBubblePool.cs.meta b/Main/Component/UI/HUD/DialogueBubblePool.cs.meta
new file mode 100644
index 0000000..c824483
--- /dev/null
+++ b/Main/Component/UI/HUD/DialogueBubblePool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2d972d1175ddaf545ae61e2490fcd6d5
+timeCreated: 1512783431
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/FacingCamera.cs b/Main/Component/UI/HUD/FacingCamera.cs
new file mode 100644
index 0000000..40d3b8c
--- /dev/null
+++ b/Main/Component/UI/HUD/FacingCamera.cs
@@ -0,0 +1,33 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+    public class FacingCamera : MonoBehaviour
+    {
+
+        [SerializeField]
+        Camera m_Camera;
+        public new Camera camera
+        {
+            get
+            {
+                return m_Camera;
+            }
+            set
+            {
+                m_Camera = value;
+            }
+        }
+
+        private void LateUpdate()
+        {
+            if (camera == null)
+            {
+                return;
+            }
+            this.transform.rotation = camera.transform.rotation;
+        }
+    }
+}
+
diff --git a/Main/Component/UI/HUD/FacingCamera.cs.meta b/Main/Component/UI/HUD/FacingCamera.cs.meta
new file mode 100644
index 0000000..e60ed17
--- /dev/null
+++ b/Main/Component/UI/HUD/FacingCamera.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4bb158512c2eb734099b658a57884f20
+timeCreated: 1500865165
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/FollowTargetIgnoreY.cs b/Main/Component/UI/HUD/FollowTargetIgnoreY.cs
new file mode 100644
index 0000000..fda4598
--- /dev/null
+++ b/Main/Component/UI/HUD/FollowTargetIgnoreY.cs
@@ -0,0 +1,44 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Monday, February 05, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class FollowTargetIgnoreY : MonoBehaviour
+    {
+        Transform m_Target;
+        Camera m_Camera;
+        float yRecord = 0f;
+
+        public void Follow(Transform _target, Camera _camera)
+        {
+            m_Target = _target;
+            m_Camera = _camera;
+
+            if (m_Target != null)
+            {
+                yRecord = m_Target.position.y;
+            }
+        }
+
+        private void LateUpdate()
+        {
+            if (m_Target != null && m_Camera != null)
+            {
+                var uiPosition = CameraUtility.ConvertToUIPosition(m_Camera, m_Target.position.SetY(yRecord));
+                this.transform.position = uiPosition.SetZ(WindowCenter.Instance.uiRoot.transform.position.z);
+            }
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/FollowTargetIgnoreY.cs.meta b/Main/Component/UI/HUD/FollowTargetIgnoreY.cs.meta
new file mode 100644
index 0000000..24180c3
--- /dev/null
+++ b/Main/Component/UI/HUD/FollowTargetIgnoreY.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d563f6c3f3d0fd84f8b551cbe80518aa
+timeCreated: 1517797800
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HUDBehaviour.cs b/Main/Component/UI/HUD/HUDBehaviour.cs
new file mode 100644
index 0000000..64d14aa
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDBehaviour.cs
@@ -0,0 +1,94 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+namespace vnxbqy.UI
+{
+    public class HUDBehaviour : MonoBehaviour
+    {
+        [Header("HUD Base")]
+        [SerializeField]
+        FacingCamera m_FacingCamera;
+        public FacingCamera facingCamera {
+            get {
+                return this.m_FacingCamera;
+            }
+        }
+
+        [SerializeField]
+        Transform m_Target;
+        public Transform target {
+            get {
+                return this.m_Target;
+            }
+            set {
+                this.m_Target = value;
+            }
+        }
+
+        [SerializeField]
+        Vector3 m_Offset;
+        public Vector3 offset {
+            get { return m_Offset; }
+            set { m_Offset = value; }
+        }
+
+        [SerializeField]
+        bool m_IsLocal = false;
+        public bool isLocal {
+            get { return m_IsLocal; }
+        }
+
+        Camera m_Camera;
+        new public Camera camera {
+            get {
+                return this.m_Camera;
+            }
+            set {
+                this.m_Camera = value;
+                if (this.m_Camera != null && this.facingCamera != null)
+                {
+                    this.facingCamera.camera = this.m_Camera;
+                }
+            }
+        }
+
+        Vector2 prePosition = new Vector2(-10000, 0);
+
+        protected virtual void OnEnable()
+        {
+            SyncPosition(false);
+        }
+
+        protected virtual void LateUpdate()
+        {
+            SyncPosition(false);
+        }
+
+        public void SyncPosition(bool _force)
+        {
+            if (target == null || camera == null)
+            {
+                return;
+            }
+
+            if (isLocal)
+            {
+                var uiposition = CameraUtility.ConvertToUIPosition(camera, target.position + offset);
+                if (_force || Vector3.Distance(this.prePosition, uiposition) > 0.0001f)
+                {
+                    prePosition = this.transform.position = uiposition;
+                    this.transform.localPosition = this.transform.localPosition.SetZ(0);
+                }
+            }
+            else
+            {
+                if (_force || Vector3.Distance(this.prePosition, target.position + offset) > 0.001f)
+                {
+                    prePosition = this.transform.position = target.position + offset;
+                }
+            }
+        }
+
+    }
+}
+
diff --git a/Main/Component/UI/HUD/HUDBehaviour.cs.meta b/Main/Component/UI/HUD/HUDBehaviour.cs.meta
new file mode 100644
index 0000000..79cb92a
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDBehaviour.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 20878c4daf9944f4a8acd2cd8689df0b
+timeCreated: 1458660444
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HUDCenter.cs b/Main/Component/UI/HUD/HUDCenter.cs
new file mode 100644
index 0000000..50259b9
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDCenter.cs
@@ -0,0 +1,30 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace vnxbqy.UI
+{
+    public class HUDCenter
+    {
+        public static HUDRoot hudRoot {
+            get; set;
+        }
+
+        public static HUDRoot CreateHUDRoot()
+        {
+            if (hudRoot == null)
+            {
+                var prefab = BuiltInLoader.LoadPrefab("HUDRoot");
+                var instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity);
+                instance.name = "HUDRoot";
+                hudRoot = instance.GetComponent<HUDRoot>();
+
+                GameObject.DontDestroyOnLoad(instance);
+            }
+
+            return hudRoot;
+        }
+
+    }
+}
+
diff --git a/Main/Component/UI/HUD/HUDCenter.cs.meta b/Main/Component/UI/HUD/HUDCenter.cs.meta
new file mode 100644
index 0000000..95dfeac
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDCenter.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f58f024207fa9b445b7b6732b246506f
+timeCreated: 1504839059
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HUDRoot.cs b/Main/Component/UI/HUD/HUDRoot.cs
new file mode 100644
index 0000000..8c9ff04
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDRoot.cs
@@ -0,0 +1,54 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+    public class HUDRoot : MonoBehaviour
+    {
+        [SerializeField]
+        private Canvas m_LifeBarCanvas;
+        public Canvas lifeBarCanvas {
+            get {
+                return this.m_LifeBarCanvas;
+            }
+        }
+
+        [SerializeField]
+        private Canvas m_HeadUpNameCanvas;
+        public Canvas headUpNameCanvas {
+            get {
+                return this.m_HeadUpNameCanvas;
+            }
+        }
+
+        [SerializeField]
+        private Canvas m_DropItemCanvas;
+        public Canvas dropItemCanvas {
+            get {
+                return this.m_DropItemCanvas;
+            }
+        }
+
+        public void SetCamera(Camera _camera)
+        {
+            m_LifeBarCanvas.worldCamera = _camera;
+            m_HeadUpNameCanvas.worldCamera = _camera;
+            dropItemCanvas.worldCamera = _camera;
+        }
+
+        float nextPopupAbleTime = 0f;
+        float popupInterval = 0.1f;
+
+        private void LateUpdate()
+        {
+            if (Time.time > nextPopupAbleTime && PopUpNum.popupInfoQueue.Count > 0)
+            {
+                PopUpNum.Popup(PopUpNum.popupInfoQueue.Dequeue());
+                nextPopupAbleTime = Time.time + popupInterval;
+            }
+
+        }
+    }
+}
+
diff --git a/Main/Component/UI/HUD/HUDRoot.cs.meta b/Main/Component/UI/HUD/HUDRoot.cs.meta
new file mode 100644
index 0000000..2098063
--- /dev/null
+++ b/Main/Component/UI/HUD/HUDRoot.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 041e8c86b8df3f647ab35f4463e7f562
+timeCreated: 1458743900
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpName.cs b/Main/Component/UI/HUD/HeadUpName.cs
new file mode 100644
index 0000000..7139299
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpName.cs
@@ -0,0 +1,522 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpName : HUDBehaviour
+    {
+
+
+        [Header("HeadUpName")]
+        [SerializeField]
+        Transform m_TitleName;
+        [SerializeField] TextImage m_Realm;
+        [SerializeField] Image m_PlayerTitle;
+        [SerializeField] TextImage m_PlayerName;
+        [SerializeField] TextImage m_HangHint;
+        [SerializeField] Transform m_Alliance;
+        [SerializeField] TextImage m_AllianceName;
+        [SerializeField] TextImage m_FairyTitle;
+        [SerializeField] TextImage m_FairyFlag;
+        [SerializeField] TextImage m_AncientKing;
+        [SerializeField] TextImage m_AncientEnemy;
+        [SerializeField] ElderGodAngerBehaviour m_ElderAnger;
+        [SerializeField] IceCrystalScoreBehaviour m_IceCrystalScore;
+        [SerializeField] Transform m_BossDropout;
+        [SerializeField] TimerBehaviour m_TimeBehaviour;
+        [SerializeField] Text m_RebornTime;
+        [SerializeField] Text m_NpcAppearTxt;
+        [SerializeField] RebornRightNowBossInfoQuery m_BossInfoQuery;
+        [SerializeField] Text m_FuncTxt;
+        [SerializeField] InputField m_ChatInput;
+        [SerializeField] TextImage m_CrossKing;
+
+        bool secondTextInited = false;
+
+        uint titleId = 0;
+        int npcId = 0;
+        int faction = 0;
+
+        int monsterLevel = 0;
+        E_MonsterType monsterType = E_MonsterType.Normal;
+
+        public Pattern pattern { get; set; }
+
+        FindPreciousModel findPreciousModel { get { return ModelCenter.Instance.GetModel<FindPreciousModel>(); } }
+        SkyTowerModel skyTowerModel { get { return ModelCenter.Instance.GetModel<SkyTowerModel>(); } }
+        DungeonModel dungeonModel { get { return ModelCenter.Instance.GetModel<DungeonModel>(); } }
+
+        public static HeadUpName RequireHeadUpName(Pattern _pattern, Transform _target, float _offsetY, Camera _camera)
+        {
+            var headUpName = HeadUpNamePool.Require(_pattern);
+            headUpName.pattern = _pattern;
+            headUpName.camera = _camera;
+            headUpName.target = _target;
+            headUpName.offset = new Vector3(0, _offsetY, 0);
+            headUpName.transform.SetParentEx(WindowCenter.Instance.uiRoot.nameCanvas.transform, Vector3.zero, Quaternion.identity, Vector3.one);
+            headUpName.SyncPosition(true);
+            return headUpName;
+        }
+
+        public static void Recycle(HeadUpName _headUpName)
+        {
+            if (_headUpName != null)
+            {
+                _headUpName.Dispose();
+                HeadUpNamePool.Recycle(_headUpName);
+            }
+        }
+
+        /// <summary>
+        /// 鐜╁鏈韩鍜屽埆鐨勭帺瀹堕兘鐢ㄨ繖涓�
+        /// </summary>
+        /// <param name="_titleId"></param>
+        /// <param name="_name"></param>
+        /// <param name="_alliance"></param>
+        public void SetPlayerInfo(PlayerInfo info)
+        {
+            faction = info.faction;
+            m_PlayerName.text = info.name;
+            m_HangHint.SetActive(info.isHang);
+            SetPlayerRealm((int)info.realm);
+            SetTitle(info.title);
+            SetAlliance(info.alliance);
+            SyncPosition(true);
+        }
+
+        public void SetPlayerRealm(int realm)
+        {
+            if (m_Realm)
+            {
+                if (realm > 0 && RealmConfig.Has(realm))
+                {
+                    m_Realm.SetActive(true);
+                    m_PlayerName.alignment = TextAnchor.MiddleLeft;
+                    var realmConfig = RealmConfig.Get(realm);
+                    m_Realm.SetSprite(realmConfig.Img);
+                    SetImageMaterialTexture(realmConfig.Img);
+                }
+                else
+                {
+                    m_Realm.SetActive(false);
+                    m_PlayerName.alignment = TextAnchor.MiddleCenter;
+                }
+            }
+        }
+
+        public void SetNpcRealm(int _realm)
+        {
+            if (m_Realm != null)
+            {
+                if (_realm > 0 && RealmConfig.Has(_realm))
+                {
+                    m_Realm.SetActive(true);
+                    m_PlayerName.alignment = TextAnchor.MiddleLeft;
+                    var realmConfig = RealmConfig.Get(_realm);
+                    m_Realm.SetSprite(realmConfig.Img);
+                    SetImageMaterialTexture(realmConfig.Img);
+                }
+                else
+                {
+                    m_PlayerName.alignment = TextAnchor.MiddleCenter;
+                    m_Realm.SetActive(false);
+                }
+            }
+        }
+
+
+        public void SetTitle(uint _titleId)
+        {
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) == GeneralDefine.CrossBattleFieldMapID)
+            {
+                titleId = 0;
+            }
+            titleId = _titleId;
+            if (_titleId == 0)
+            {
+                if (m_PlayerTitle != null)
+                    m_PlayerTitle.SetActive(false);
+            }
+            else
+            {
+                var config = DienstgradConfig.Get((int)titleId);
+                if (config == null)
+                {
+                    m_PlayerTitle.SetActive(false);
+                    return;
+                }
+
+                m_PlayerTitle.SetActive(true);
+                UIFrame frame = m_PlayerTitle.GetComponent<UIFrame>();
+                if (UIFrameMgr.Inst.ContainsDynamicImage(config.Image))
+                {
+                    if (frame == null) frame = m_PlayerTitle.gameObject.AddComponent<UIFrame>();
+                    m_PlayerTitle.raycastTarget = false;
+                    frame.ResetFrame(config.Image);
+                    frame.enabled = true;
+                }
+                else
+                {
+                    if (frame != null) frame.enabled = false;
+                    m_PlayerTitle.SetSprite(config.Image);
+                }
+                //SetImageMaterialTexture(config.Image);
+            }
+        }
+
+        public void SetAncientKing(bool isAncientKing)
+        {
+            if (m_AncientKing == null)
+            {
+                return;
+            }
+            m_AncientKing.SetActive(isAncientKing);
+
+            if (!isAncientKing) return;
+
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) == GeneralDefine.CrossFamilyBattleMapID)
+            {
+                m_AncientKing.SetSprite("ZLWJ3");
+            }
+            else
+            {
+                m_AncientKing.SetSprite("IntegralKing");
+            }
+        }
+
+
+        public void SetAncientEnemy(bool isAncientEnemy)
+        {
+            if (m_AncientEnemy == null)
+            {
+                return;
+            }
+            m_AncientEnemy.SetActive(isAncientEnemy);
+
+            if (!isAncientEnemy) return;
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) == GeneralDefine.CrossFamilyBattleMapID)
+            {
+                m_AncientEnemy.SetSprite("ZLWJ2");
+            }
+            else
+            {
+                m_AncientEnemy.SetSprite("Enemy");
+            }
+        }
+
+        public void SetCrossKing(bool isKing)
+        {
+            if (m_CrossKing == null)
+            {
+                return;
+            }
+            m_CrossKing.SetActive(isKing);
+
+            if (!isKing) return;
+
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) == GeneralDefine.CrossFamilyBattleMapID)
+            {
+                m_CrossKing.SetSprite("ZLWJ1");
+            }
+            else
+            {
+                m_CrossKing.SetSprite("IntegralKing");
+            }
+        }
+
+        public void SetAlliance(string _alliance)
+        {
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) != GeneralDefine.CrossBattleFieldMapID)
+            {
+                if (string.IsNullOrEmpty(_alliance) || _alliance.Length == 0 || _alliance == "")
+                {
+                    m_Alliance.SetActive(false);
+                }
+                else
+                {
+                    m_Alliance.SetActive(true);
+                    m_AllianceName.text = _alliance;
+                }
+            }
+            else
+            {
+                if (pattern == Pattern.Hero)
+                {
+                    faction = (int)PlayerDatas.Instance.baseData.faction;
+                }
+                m_Alliance.SetActive(true);
+                m_AllianceName.text = string.Empty;
+                m_FairyTitle.text = Language.Get("CrossBattleField63_" + faction);
+                m_FairyFlag.SetActive(false);
+                m_PlayerName.color = UIHelper.GetUIColor(faction == 1 ? TextColType.Blue : TextColType.Orange);
+            }
+        }
+
+        public void SetRedName(bool _isRed)
+        {
+            m_PlayerName.color = _isRed ? UIHelper.GetUIColor(TextColType.Red) : UIHelper.GetUIColor(pattern == Pattern.Hero ? TextColType.Green : TextColType.White);
+        }
+
+        public void SetYellowName(bool _isYellow)
+        {
+            m_PlayerName.color = _isYellow ? UIHelper.GetUIColor(TextColType.NavyYellow) : UIHelper.GetUIColor(pattern == Pattern.Hero ? TextColType.Green : TextColType.White);
+        }
+
+        public void SetGrayName(bool _isGray)
+        {
+            m_PlayerName.color = _isGray ? Color.gray : UIHelper.GetUIColor(pattern == Pattern.Hero ? TextColType.Green : TextColType.White);
+        }
+
+        public void SetFairyLeague(bool on, int _faction)
+        {
+            if (dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID) != GeneralDefine.CrossBattleFieldMapID)
+            {
+                _faction = pattern == Pattern.Hero ? (int)PlayerDatas.Instance.baseData.faction : _faction;
+                m_FairyFlag.SetActive(on);
+                m_FairyTitle.text = on ? (_faction == PlayerDatas.Instance.baseData.faction ?
+                    Language.Get("UnionMatch_Ourself") : Language.Get("UnionMatch_Enemy")) : Language.Get("UnionMatch_Ourself");
+                m_FairyTitle.color = on ? UIHelper.GetUIColor((FairyCampType)_faction == FairyCampType.Blue ?
+                        TextColType.Blue : TextColType.Red) : UIHelper.GetUIColor(TextColType.Blue);
+                m_AllianceName.color = on ? UIHelper.GetUIColor((FairyCampType)_faction == FairyCampType.Blue ?
+                        TextColType.Blue : TextColType.Red) : UIHelper.GetUIColor(TextColType.Blue);
+                if (on)
+                {
+                    m_FairyFlag.SetSprite((FairyCampType)_faction == FairyCampType.Blue ? "FlagBlue" : "FlagRed");
+                    m_PlayerName.color = UIHelper.GetUIColor(pattern == Pattern.Hero ?
+                        TextColType.Green : (FairyCampType)_faction == FairyCampType.Blue ? TextColType.Blue : TextColType.Red);
+                }
+            }
+            else
+            {
+                if (pattern == Pattern.Hero)
+                {
+                    faction = (int)PlayerDatas.Instance.baseData.faction;
+                }
+                m_FairyTitle.text = Language.Get("CrossBattleField63_" + faction);
+                m_AllianceName.text = string.Empty;
+                m_FairyFlag.SetActive(false);
+                m_PlayerName.color = UIHelper.GetUIColor(faction == 1 ? TextColType.Blue : TextColType.Orange);
+            }
+        }
+
+        public void SetNameColor(TextColType _type)
+        {
+            m_PlayerName.color = UIHelper.GetUIColor(_type);
+        }
+
+        public void SetBossDropout(bool _isOwner)
+        {
+            if (m_BossDropout != null)
+            {
+                m_BossDropout.SetActive(_isOwner);
+            }
+        }
+
+        public void SetNPCName(string _name)
+        {
+            SetNpcRealm(999);
+            m_PlayerName.text = _name;
+            SyncPosition(true);
+        }
+
+        public void SetNPCName(int _id)
+        {
+            var config = NPCConfig.Get(_id);
+            if (config != null)
+            {
+                SetNpcRealm(config.Realm);
+                m_PlayerName.text = config.charName;
+            }
+
+            SyncPosition(true);
+        }
+
+        public void SetNpcReborn(int _npcId)
+        {
+            NPCInteractProcessor.s_NpcInteractEvent -= OnClickNpcReborn;
+            NPCInteractProcessor.s_NpcInteractEvent += OnClickNpcReborn;
+            findPreciousModel.bossInfoUpdateEvent -= UpdateNpcRebornTime;
+            findPreciousModel.bossInfoUpdateEvent += UpdateNpcRebornTime;
+            npcId = _npcId;
+
+            var config = NPCConfig.Get(_npcId);
+            if (config != null)
+            {
+                SetNpcRealm(config.Realm);
+                m_PlayerName.text = config.charName;
+            }
+
+            UpdateNpcRebornTime(_npcId);
+            m_FuncTxt.SetActive(!CrossServerUtility.IsCrossServer() && PlayerDatas.Instance.baseData.FBID != 0);
+            m_FuncTxt.text = Language.Get("BossReborn_Transfer");
+        }
+
+        private void OnClickNpcReborn(E_NpcType _npcType, int _npcId, uint arg3)
+        {
+            if (CrossServerUtility.IsCrossServer())
+            {
+                return;
+            }
+
+            if (_npcType != E_NpcType.Func)
+            {
+                return;
+            }
+
+            var _cfg = BossInfoConfig.GetBossInfoByStoneId(_npcId);
+            if (_cfg != null)
+            {
+                if (PlayerDatas.Instance.baseData.FBID != 0 && !BossJiaLineUtility.Instance.showJiaLine)
+                {
+                    ConfirmCancel.ShowPopConfirm(Language.Get("Mail101"), Language.Get("Supplement1001"), (bool _isOk) =>
+                    {
+                        if (_isOk)
+                        {
+                            MapTransferUtility.Instance.MoveToNPC(_cfg.NPCID);
+                        }
+                    });
+                }
+            }
+        }
+
+        private void UpdateNpcRebornTime(int _id)
+        {
+            if (_id != npcId)
+            {
+                return;
+            }
+
+            m_BossInfoQuery.bossId = npcId;
+            FindPreciousModel.BossInfo _bossInfo;
+            if (findPreciousModel.TryGetBossInfo(npcId, out _bossInfo))
+            {
+                m_RebornTime.SetActive(true);
+                (m_TimeBehaviour as TimerToChsBehaviour).addtionInfo = Language.Get("BossReborn_RefreshTime");
+                m_TimeBehaviour.Begin((int)(_bossInfo.refreshTime - TimeUtility.ServerNow).TotalSeconds, () =>
+                {
+                    m_NpcAppearTxt.SetActive(true);
+                });
+            }
+            else
+            {
+                m_RebornTime.SetActive(false);
+            }
+
+            m_NpcAppearTxt.SetActive(!m_RebornTime.gameObject.activeSelf);
+        }
+
+        public void SetMonsterInfo(int _npcId, int _level)
+        {
+            var config = NPCConfig.Get(_npcId);
+            if (config != null)
+            {
+                SetNpcRealm(config.Realm);
+                m_PlayerName.text = StringUtility.Contact(config.charName, Language.Get("HeadUpName_Monster", _level));
+                monsterLevel = _level;
+                monsterType = (E_MonsterType)config.IsBoss;
+
+                //if (m_ElderAnger != null)
+                //{
+                //    m_ElderAnger.Display(_npcId);
+                //}
+
+                if (m_IceCrystalScore != null)
+                {
+                    m_IceCrystalScore.Display(_npcId);
+                }
+            }
+
+            UpdateMonsterNameColor(PlayerDatas.Instance.baseData.LV);
+            SyncPosition(true);
+            PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerInfoRefresh;
+            PlayerDatas.Instance.playerDataRefreshEvent += OnPlayerInfoRefresh;
+        }
+
+        public void Dispose()
+        {
+            SetAncientKing(false);
+            SetAncientEnemy(false);
+            SetCrossKing(false);
+
+            NPCInteractProcessor.s_NpcInteractEvent -= OnClickNpcReborn;
+            findPreciousModel.bossInfoUpdateEvent -= UpdateNpcRebornTime;
+            PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerInfoRefresh;
+        }
+
+        private void OnPlayerInfoRefresh(PlayerDataType _refreshType)
+        {
+            switch (_refreshType)
+            {
+                case PlayerDataType.LV:
+                    UpdateMonsterNameColor((int)PlayerDatas.Instance.baseData.LV);
+                    break;
+            }
+        }
+
+        private void UpdateMonsterNameColor(int _playerLevel)
+        {
+            switch (pattern)
+            {
+                case Pattern.Monster:
+                    m_PlayerName.color = MonsterNameColor.GetColor(monsterType, _playerLevel, monsterLevel);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        private void SetImageMaterialTexture(string _iconKey)
+        {
+            if (!secondTextInited)
+            {
+                var sprite = UILoader.LoadSprite(_iconKey);
+                if (sprite != null)
+                {
+                    if (m_Realm != null)
+                    {
+                        m_Realm.material.SetTexture("_Tex2", sprite.texture);
+                    }
+
+                    if (m_PlayerTitle != null)
+                    {
+                        m_PlayerTitle.material.SetTexture("_Tex2", sprite.texture);
+                    }
+
+                    secondTextInited = true;
+                }
+            }
+        }
+
+        public enum Pattern
+        {
+            Hero,
+            Player,
+            Monster,
+            FunctionNPC,
+            NpcReborn,
+        }
+
+        public struct PlayerInfo
+        {
+            public uint realm;
+            public uint title;
+            public string name;
+            public string alliance;
+            public bool isHang;
+            public int faction;
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpName.cs.meta b/Main/Component/UI/HUD/HeadUpName.cs.meta
new file mode 100644
index 0000000..70958fa
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpName.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 18a0978e677b72649ba2c87bf3edd95a
+timeCreated: 1505370200
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpNamePool.cs b/Main/Component/UI/HUD/HeadUpNamePool.cs
new file mode 100644
index 0000000..45f6c5f
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpNamePool.cs
@@ -0,0 +1,81 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 14, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpNamePool
+    {
+        static Dictionary<int, GameObjectPoolManager.GameObjectPool> pools = new Dictionary<int, GameObjectPoolManager.GameObjectPool>();
+
+        public static HeadUpName Require(HeadUpName.Pattern _pattern)
+        {
+            GameObjectPoolManager.GameObjectPool pool = null;
+            var poolKey = (int)_pattern;
+            if (!pools.ContainsKey(poolKey))
+            {
+                var prefab = UILoader.LoadPrefab(StringUtility.Contact("HeadUpName_", _pattern));
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pools[poolKey] = pool;
+                }
+            }
+            else
+            {
+                pool = pools[poolKey];
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                var headUpName= instance.GetComponent<HeadUpName>();
+                headUpName.enabled = true;
+                headUpName.SetActive(true);
+                return headUpName;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(HeadUpName _headUpName)
+        {
+            var pattern = _headUpName.pattern;
+            GameObjectPoolManager.GameObjectPool pool;
+            if (pools.TryGetValue((int)pattern, out pool))
+            {
+                _headUpName.enabled = false;
+                _headUpName.SetActive(false);
+                pool.Release(_headUpName.gameObject);
+            }
+
+        }
+
+        public static void Clear()
+        {
+            foreach (var key in pools.Keys)
+            {
+                var pool = pools[key];
+                if (pool != null)
+                {
+                    pool.Clear();
+                }
+            }
+            pools.Clear();
+        }
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpNamePool.cs.meta b/Main/Component/UI/HUD/HeadUpNamePool.cs.meta
new file mode 100644
index 0000000..a03e601
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpNamePool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1d2b4c38036b62247ac024544072d4c3
+timeCreated: 1505380391
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpQuestSign.cs b/Main/Component/UI/HUD/HeadUpQuestSign.cs
new file mode 100644
index 0000000..b762fe6
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpQuestSign.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 28, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpQuestSign : HUDBehaviour
+    {
+
+        public static HeadUpQuestSign RequireHeadUpQuestSign(Pattern _pattern, Transform _target, float _offsetY, Camera _camera)
+        {
+            var questSign = HeadUpQuestSignPool.Require(_pattern);
+            questSign.camera = _camera;
+            questSign.target = _target;
+            questSign.offset = new Vector3(0, _offsetY, 0);
+            questSign.pattern = _pattern;
+            questSign.transform.SetParentEx(WindowCenter.Instance.uiRoot.nameCanvas.transform, Vector3.zero, Quaternion.identity, Vector3.one);
+            questSign.SyncPosition(true);
+            return questSign;
+        }
+
+        public static void Recycle(HeadUpQuestSign _sign)
+        {
+            HeadUpQuestSignPool.Recycle(_sign);
+        }
+
+        public Pattern pattern {
+            get; set;
+        }
+
+        public enum Pattern
+        {
+            Exclamation = 0,//鎰熷徆鍙�
+            DeQuestion = 1,//鐏拌壊闂彿
+            Question = 2,//闂彿
+        }
+
+
+    }
+
+}
+
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpQuestSign.cs.meta b/Main/Component/UI/HUD/HeadUpQuestSign.cs.meta
new file mode 100644
index 0000000..1d4e3a2
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpQuestSign.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 482f608b786b8664386f9c2df18dddb2
+timeCreated: 1506567091
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpQuestSignPool.cs b/Main/Component/UI/HUD/HeadUpQuestSignPool.cs
new file mode 100644
index 0000000..6371cb0
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpQuestSignPool.cs
@@ -0,0 +1,76 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, September 28, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpQuestSignPool
+    {
+
+        static Dictionary<int, GameObjectPoolManager.GameObjectPool> pools = new Dictionary<int, GameObjectPoolManager.GameObjectPool>();
+
+        public static HeadUpQuestSign Require(HeadUpQuestSign.Pattern _pattern)
+        {
+            GameObjectPoolManager.GameObjectPool pool = null;
+            var poolKey = (int)_pattern;
+            if (!pools.ContainsKey(poolKey))
+            {
+                var prefab = UILoader.LoadPrefab(StringUtility.Contact("HeadUpQuestSign_", _pattern));
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pools[poolKey] = pool;
+                }
+            }
+            else
+            {
+                pool = pools[poolKey];
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                instance.SetActive(true);
+                return instance.GetComponent<HeadUpQuestSign>();
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(HeadUpQuestSign _questSign)
+        {
+            var pattern = _questSign.pattern;
+            GameObjectPoolManager.GameObjectPool pool;
+            if (pools.TryGetValue((int)pattern, out pool))
+            {
+                pool.Release(_questSign.gameObject);
+                _questSign.transform.SetParent(null);
+                _questSign.SetActive(false);
+            }
+
+        }
+
+        public static void Clear()
+        {
+            foreach (var key in pools.Keys)
+            {
+                var pool = pools[key];
+                if (pool != null)
+                {
+                    pool.Clear();
+                }
+            }
+            pools.Clear();
+        }
+    }
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpQuestSignPool.cs.meta b/Main/Component/UI/HUD/HeadUpQuestSignPool.cs.meta
new file mode 100644
index 0000000..53802be
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpQuestSignPool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 19b100e182361e2429b3a3d6d5da2bac
+timeCreated: 1506567802
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpSkillName.cs b/Main/Component/UI/HUD/HeadUpSkillName.cs
new file mode 100644
index 0000000..e211250
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpSkillName.cs
@@ -0,0 +1,68 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, November 21, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpSkillName : HUDBehaviour
+    {
+
+        [SerializeField] Animation m_Animation;
+        [SerializeField] Text m_SkillName;
+        float recycleTime = 0f;
+
+        public static void Popup(int _skillId, Vector3 _position, Camera _camera)
+        {
+            var canvas = WindowCenter.Instance.uiRoot.nameCanvas;
+            var skillName = HeadUpSkillNamePool.Require();
+            if (skillName == null)
+            {
+                return;
+            }
+
+            var uiPosition = CameraUtility.ConvertToUIPosition(_camera, _position);
+            skillName.transform.SetParent(canvas.transform);
+            skillName.transform.position = uiPosition;
+            skillName.transform.localPosition = skillName.transform.localPosition.SetZ(0);
+            skillName.transform.localScale = Vector3.one;
+
+            var skillConfig = SkillConfig.Get(_skillId);
+            skillName.PopUp(skillConfig.SkillName);
+        }
+
+        public void PopUp(string _skillName)
+        {
+            this.SetActive(true);
+            if (m_Animation.clip != null)
+            {
+                recycleTime = Time.time + m_Animation.clip.length;
+            }
+            else
+            {
+                recycleTime = Time.time;
+            }
+
+            m_SkillName.text = _skillName;
+            SyncPosition(true);
+            m_Animation.Play();
+        }
+
+        protected override  void LateUpdate()
+        {
+            if (Time.time > recycleTime)
+            {
+                HeadUpSkillNamePool.Recycle(this.gameObject);
+            }
+        }
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpSkillName.cs.meta b/Main/Component/UI/HUD/HeadUpSkillName.cs.meta
new file mode 100644
index 0000000..5e7756f
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpSkillName.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ce841210d5f4cab4a95590a6808d4492
+timeCreated: 1511245993
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpSkillNamePool.cs b/Main/Component/UI/HUD/HeadUpSkillNamePool.cs
new file mode 100644
index 0000000..d09bf1a
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpSkillNamePool.cs
@@ -0,0 +1,61 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Tuesday, November 21, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI {
+
+    public class HeadUpSkillNamePool:MonoBehaviour {
+
+        static GameObjectPoolManager.GameObjectPool pool = null;
+
+        public static HeadUpSkillName Require()
+        {
+            if (pool == null)
+            {
+                var prefab = UILoader.LoadPrefab("HeadUpSkillName");
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                }
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                return instance.GetComponent<HeadUpSkillName>();
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(GameObject _gameObject)
+        {
+            if (pool != null)
+            {
+                pool.Release(_gameObject);
+                _gameObject.transform.SetParent(null);
+                _gameObject.SetActive(false);
+            }
+        }
+
+        public static void Clear()
+        {
+            if (pool != null)
+            {
+                pool.Clear();
+                pool = null;
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpSkillNamePool.cs.meta b/Main/Component/UI/HUD/HeadUpSkillNamePool.cs.meta
new file mode 100644
index 0000000..4652095
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpSkillNamePool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f71b0db9f771d554fa58488406601626
+timeCreated: 1511246015
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpStorySign.cs b/Main/Component/UI/HUD/HeadUpStorySign.cs
new file mode 100644
index 0000000..7661d22
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpStorySign.cs
@@ -0,0 +1,99 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, December 28, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class HeadUpStorySign : HUDBehaviour
+    {
+        [SerializeField] float m_Duration = 1f;
+        float endTime = 0f;
+
+        public static void Display(Transform _target, Camera _camera)
+        {
+            var bubble = HeadUpStorySignPool.Require();
+            bubble.transform.SetParentEx(WindowCenter.Instance.uiRoot.bossShowCanvas.transform, Vector3.zero, Vector3.zero, Vector3.one);
+            bubble.SetActive(true);
+
+            bubble.Show(_target, _camera);
+        }
+
+        public virtual void Show(Transform _target, Camera _camera)
+        {
+            base.target = _target;
+            base.offset = Vector3.zero;
+            base.camera = _camera;
+
+            endTime = Time.time + m_Duration;
+            this.SetActive(true);
+            SyncPosition(true);
+        }
+
+        protected override void LateUpdate()
+        {
+            base.LateUpdate();
+
+            if (Time.time > endTime)
+            {
+                HeadUpStorySignPool.Recycle(this.gameObject);
+            }
+        }
+
+    }
+
+    public class HeadUpStorySignPool
+    {
+        static GameObjectPoolManager.GameObjectPool pool = null;
+
+        public static HeadUpStorySign Require()
+        {
+            if (pool == null)
+            {
+                var prefab = UILoader.LoadPrefab("HeadUpStorySign");
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                }
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                return instance.GetComponent<HeadUpStorySign>();
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(GameObject _gameObject)
+        {
+            if (pool != null)
+            {
+                pool.Release(_gameObject);
+                _gameObject.transform.SetParent(null);
+                _gameObject.SetActive(false);
+            }
+        }
+
+        public static void Clear()
+        {
+            if (pool != null)
+            {
+                pool.Clear();
+                pool = null;
+            }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/HeadUpStorySign.cs.meta b/Main/Component/UI/HUD/HeadUpStorySign.cs.meta
new file mode 100644
index 0000000..09ac708
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpStorySign.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 02d81e5d4611e67429e3f39a448e163c
+timeCreated: 1514449180
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpTreasure.cs b/Main/Component/UI/HUD/HeadUpTreasure.cs
new file mode 100644
index 0000000..b7e1e28
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpTreasure.cs
@@ -0,0 +1,45 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.EventSystems;
+
+using System;
+
+namespace vnxbqy.UI
+{
+    public class HeadUpTreasure : HUDBehaviour
+    {
+        [SerializeField] Image m_TreasureName;
+
+        private int treasureId = 0;
+
+        public static HeadUpTreasure RequireHeadUpTreasure(Transform _target, float _offsetY, Camera _camera)
+        {
+            var headUpName = HeadUpTreasurePool.Require();
+            headUpName.camera = _camera;
+            headUpName.target = _target;
+            headUpName.offset = new Vector3(0, _offsetY, 0);
+            headUpName.transform.SetParentEx(WindowCenter.Instance.uiRoot.modalCanvas, Vector3.zero, Quaternion.identity, Vector3.one);
+            headUpName.SyncPosition(true);
+            return headUpName;
+        }
+
+        public void SetTreasure(int _treasure)
+        {
+            treasureId = _treasure;
+            m_TreasureName.SetSprite("Money_Type_1");
+            m_TreasureName.SetNativeSize();
+            m_TreasureName.SetActive(false);
+        }
+
+        public static void Recycle(HeadUpTreasure _headUpTreasure)
+        {
+            if (_headUpTreasure != null)
+            {
+                HeadUpTreasurePool.Recycle(_headUpTreasure);
+            }
+        }
+    }
+}
+
diff --git a/Main/Component/UI/HUD/HeadUpTreasure.cs.meta b/Main/Component/UI/HUD/HeadUpTreasure.cs.meta
new file mode 100644
index 0000000..1d09920
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpTreasure.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 48c2e6eff8236a549b4fa68a7aa4184c
+timeCreated: 1524837780
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/HeadUpTreasurePool.cs b/Main/Component/UI/HUD/HeadUpTreasurePool.cs
new file mode 100644
index 0000000..5e74f89
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpTreasurePool.cs
@@ -0,0 +1,40 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using vnxbqy.UI;
+public class HeadUpTreasurePool
+{
+    static GameObjectPoolManager.GameObjectPool pool;
+
+    public static HeadUpTreasure Require()
+    {
+        var prefab = UILoader.LoadPrefab("HeadUp_Treasure");
+        pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+        if (pool != null)
+        {
+            var instance = pool.Request();
+            var headUpName = instance.GetComponent<HeadUpTreasure>();
+            headUpName.enabled = true;
+            return headUpName;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static void Recycle(HeadUpTreasure _headUpName)
+    {
+        if (pool != null)
+        {
+            _headUpName.enabled = false;
+            pool.Release(_headUpName.gameObject);
+        }
+    }
+
+    public static void Clear()
+    {
+        pool.Clear();
+    }
+
+}
diff --git a/Main/Component/UI/HUD/HeadUpTreasurePool.cs.meta b/Main/Component/UI/HUD/HeadUpTreasurePool.cs.meta
new file mode 100644
index 0000000..9dadee5
--- /dev/null
+++ b/Main/Component/UI/HUD/HeadUpTreasurePool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 76a37a89cc402b244860f74e3330be16
+timeCreated: 1524837819
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/LifeBar.cs b/Main/Component/UI/HUD/LifeBar.cs
new file mode 100644
index 0000000..cb50f33
--- /dev/null
+++ b/Main/Component/UI/HUD/LifeBar.cs
@@ -0,0 +1,198 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace vnxbqy.UI
+{
+
+    [DisallowMultipleComponent]
+    public class LifeBar : HUDBehaviour
+    {
+
+        [Header("LifeBar")]
+        [SerializeField]
+        MultipleSmoothSlider m_MultipleSlider;
+        public MultipleSmoothSlider multipleSlider
+        {
+            get
+            {
+                return m_MultipleSlider;
+            }
+        }
+
+        [SerializeField]
+        [Range(0, 10)]
+        float m_Delay;
+        public float delay
+        {
+            get
+            {
+                return m_Delay;
+            }
+        }
+
+        [SerializeField]
+        bool m_NeverHide;
+        public bool neverHide
+        {
+            get
+            {
+                return m_NeverHide;
+            }
+            set
+            {
+                m_NeverHide = value;
+            }
+        }
+
+        [SerializeField]
+        [Range(0, 100)]
+        float m_HideInterval;
+        public float hideInterval
+        {
+            get
+            {
+                return m_HideInterval;
+            }
+            set
+            {
+                m_HideInterval = Mathf.Clamp(value, 0, 100);
+            }
+        }
+
+        float m_Value;
+        public float value
+        {
+            get
+            {
+                return m_Value;
+            }
+            set
+            {
+                m_Value = Mathf.Clamp01(value);
+                if (multipleSlider != null)
+                {
+                    multipleSlider.value = m_Value;
+                }
+            }
+        }
+
+        Camera m_TargetCamera;
+        public Camera targetCamera
+        {
+            get
+            {
+                return m_TargetCamera;
+            }
+            set
+            {
+                m_TargetCamera = value;
+                if (m_TargetCamera != null && facingCamera != null)
+                {
+                    facingCamera.camera = m_TargetCamera;
+                }
+            }
+        }
+
+        float[] reduceHpDelay = new float[2];
+        float[] addHpDelay = new float[2];
+
+        float hideTime = 0f;
+        Pattern m_Pattern = Pattern.Enemy;
+        public Pattern pattern
+        {
+            get { return m_Pattern; }
+            set { m_Pattern = value; }
+        }
+
+        public static LifeBar RequireLifeBar(Transform _target, float _offsetY, Camera _camera)
+        {
+            var lifeBar = LifeBarPool.Require(Pattern.Enemy);
+            lifeBar.camera = _camera;
+            lifeBar.target = _target;
+            lifeBar.offset = new Vector3(0, _offsetY, 0);
+            lifeBar.transform.SetParentEx(WindowCenter.Instance.uiRoot.lifeBarCanvas.transform, Vector3.zero, Quaternion.identity, Vector3.one);
+            if (lifeBar.multipleSlider != null)
+            {
+                lifeBar.multipleSlider.ResetValue(1f);
+            }
+            lifeBar.value = 1f;
+            lifeBar.pattern = Pattern.Enemy;
+            return lifeBar;
+        }
+
+        public static void Recycle(LifeBar _lifeBar)
+        {
+            LifeBarPool.Recycle(_lifeBar.gameObject, _lifeBar.pattern);
+        }
+
+        public void Set(ulong _hp, ulong _maxHp)
+        {
+            var targetValue = _hp / (float)_maxHp;
+            value = targetValue;
+            this.transform.localScale = Vector3.one;
+            hideTime = Time.time + hideInterval;
+            multipleSlider.ResetValue(value);
+            SyncPosition(true);
+        }
+
+        public void Show(ulong _hp, ulong _maxHp)
+        {
+            var targetValue = _hp / (float)_maxHp;
+            if (targetValue < this.value)
+            {
+                multipleSlider.UpdateDelayTimes(reduceHpDelay);
+            }
+            else
+            {
+                multipleSlider.UpdateDelayTimes(addHpDelay);
+            }
+
+            value = targetValue;
+            this.transform.localScale = Vector3.one;
+            hideTime = Time.time + hideInterval;
+            SyncPosition(true);
+        }
+
+        public void Hide()
+        {
+            this.transform.localScale = Vector3.zero;
+        }
+
+        void Awake()
+        {
+            reduceHpDelay[0] = 0f;
+            reduceHpDelay[1] = delay;
+
+            addHpDelay[0] = delay;
+            addHpDelay[1] = 0f;
+        }
+
+        protected override void OnEnable()
+        {
+            base.OnEnable();
+            multipleSlider.ResetValue(value);
+        }
+
+        protected override void LateUpdate()
+        {
+            base.LateUpdate();
+
+            if (Time.time > hideTime && !neverHide)
+            {
+                this.transform.localScale = Vector3.zero;
+            }
+        }
+
+
+        public enum Pattern
+        {
+            Friendly = 1,
+            Pet = 2,
+            Enemy = 3,
+        }
+
+    }
+
+}
+
diff --git a/Main/Component/UI/HUD/LifeBar.cs.meta b/Main/Component/UI/HUD/LifeBar.cs.meta
new file mode 100644
index 0000000..ca9ad08
--- /dev/null
+++ b/Main/Component/UI/HUD/LifeBar.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 592817f991018364793738b8383db151
+timeCreated: 1500883963
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/LifeBarPool.cs b/Main/Component/UI/HUD/LifeBarPool.cs
new file mode 100644
index 0000000..af78433
--- /dev/null
+++ b/Main/Component/UI/HUD/LifeBarPool.cs
@@ -0,0 +1,64 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace vnxbqy.UI
+{
+    public static class LifeBarPool
+    {
+        const int poolSize = 10;
+        static GameObjectPoolManager.GameObjectPool pools = null;
+
+        public static LifeBar Require(LifeBar.Pattern _pattern)
+        {
+            var patternToInt = (int)_pattern;
+            if (pools == null)
+            {
+                var prefab = UILoader.LoadPrefab(ParsePrefabName(_pattern));
+                if (prefab != null)
+                {
+                    pools = GameObjectPoolManager.Instance.RequestPool(prefab);
+                }
+            }
+
+            if (pools != null)
+            {
+                var instance = pools.Request();
+                return instance.GetComponent<LifeBar>();
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(GameObject _gameObject, LifeBar.Pattern _pattern)
+        {
+            var patternToInt = (int)_pattern;
+
+            if (pools != null)
+            {
+                pools.Release(_gameObject);
+            }
+        }
+
+        public static void Clear()
+        {
+            if (pools!=null)
+            {
+                pools.Clear();
+                pools = null;
+            }
+        }
+
+        static string ParsePrefabName(LifeBar.Pattern _pattern)
+        {
+            return StringUtility.Contact("LifeBar_", _pattern);
+        }
+
+
+    }
+
+
+}
+
diff --git a/Main/Component/UI/HUD/LifeBarPool.cs.meta b/Main/Component/UI/HUD/LifeBarPool.cs.meta
new file mode 100644
index 0000000..e65f2f0
--- /dev/null
+++ b/Main/Component/UI/HUD/LifeBarPool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 36430806a73f52a439c5a27fc413ffc7
+timeCreated: 1500886420
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/MonsterNameColor.cs b/Main/Component/UI/HUD/MonsterNameColor.cs
new file mode 100644
index 0000000..c44db6e
--- /dev/null
+++ b/Main/Component/UI/HUD/MonsterNameColor.cs
@@ -0,0 +1,86 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Friday, September 29, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+
+namespace vnxbqy.UI
+{
+
+    public class MonsterNameColor
+    {
+
+        static Dictionary<E_MonsterType, List<MonsterNameColorConfig>> monsterNameColors = null;
+
+        public static Color GetColor(E_MonsterType _monsterType, int _heroLevel, int _monsterLevel)
+        {
+            if (monsterNameColors == null)
+            {
+                monsterNameColors = new Dictionary<E_MonsterType, List<MonsterNameColorConfig>>();
+                var allConfig = MonsterNameColorConfig.GetValues();
+                foreach (var config in allConfig)
+                {
+                    var monsterType = (E_MonsterType)config.MonsterType;
+                    List<MonsterNameColorConfig> colors = null;
+                    if (!monsterNameColors.ContainsKey(monsterType))
+                    {
+                        colors = new List<MonsterNameColorConfig>();
+                        monsterNameColors[monsterType] = colors;
+                    }
+                    else
+                    {
+                        colors = monsterNameColors[monsterType];
+                    }
+
+                    colors.Add(config);
+                }
+
+                foreach (var key in monsterNameColors.Keys)
+                {
+                    var colors = monsterNameColors[key];
+                    colors.Sort(
+                        (MonsterNameColorConfig a, MonsterNameColorConfig b) =>
+                        {
+                            return a.LevelDelta < b.LevelDelta ? -1 : 1;
+                        }
+                        );
+                }
+
+            }
+
+            int levelDelta = _monsterLevel - _heroLevel;
+            List<MonsterNameColorConfig> nameColors = null;
+            if (monsterNameColors.TryGetValue(_monsterType, out nameColors))
+            {
+                for (int i = 0; i < nameColors.Count; i++)
+                {
+                    var config = nameColors[i];
+                    if (levelDelta < config.LevelDelta || i == nameColors.Count - 1)
+                    {
+                        return new Color(config.Color.x, config.Color.y, config.Color.z, 1);
+                    }
+                }
+
+                return Color.white;
+            }
+            else
+            {
+                return Color.white;
+            }
+
+        }
+
+
+
+
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/MonsterNameColor.cs.meta b/Main/Component/UI/HUD/MonsterNameColor.cs.meta
new file mode 100644
index 0000000..22e35a0
--- /dev/null
+++ b/Main/Component/UI/HUD/MonsterNameColor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 99c09dfdb9fedee4ebacfbf67c40f128
+timeCreated: 1506688637
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/NPCDialogueBubble.cs b/Main/Component/UI/HUD/NPCDialogueBubble.cs
new file mode 100644
index 0000000..1e8e299
--- /dev/null
+++ b/Main/Component/UI/HUD/NPCDialogueBubble.cs
@@ -0,0 +1,197 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Saturday, December 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+
+namespace vnxbqy.UI
+{
+
+    public class NPCDialogueBubble : DialogueBubble
+    {
+        static Dictionary<int, Dictionary<int, NpcDialogue>> npcDialogues = new Dictionary<int, Dictionary<int, NpcDialogue>>();
+
+        static DungeonModel m_DungeonModel;
+        static DungeonModel dungeonModel {
+            get { return m_DungeonModel ?? (m_DungeonModel = ModelCenter.Instance.GetModel<DungeonModel>()); }
+        }
+
+        public static DialogueBubble TimingShow(int _npcId, Transform _target, Camera _camera)
+        {
+            var dataMapId = dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID);
+            var dialogue = GetDialogue(_npcId, dataMapId);
+            if (dialogue == null)
+            {
+                dialogue = GetDialogue(_npcId, 0);
+            }
+
+            if (dialogue == null)
+            {
+                return null;
+            }
+
+            if (!dialogue.hasDialogue)
+            {
+                return null;
+            }
+
+            DialogueBubble bubble = null;
+            if (dialogue.timeAble && Random.Range(0, dialogue.countInterval) == 0)
+            {
+                bubble = PackageDialogue(_npcId);
+                bubble.Show(dialogue.config.Dialogues[dialogue.index], _target, _camera);
+                dialogue.index++;
+                dialogue.lastDialogueTime = Time.time;
+            }
+
+            dialogue.intervalBuf++;
+            return bubble;
+        }
+
+        static NpcDialogue GetDialogue(int _npcId, int _dataMapId)
+        {
+            if (FindConfig(_npcId, _dataMapId) == null)
+            {
+                return null;
+            }
+
+            NpcDialogue dialogue = null;
+            if (npcDialogues.ContainsKey(_npcId))
+            {
+                var dataMapDialogues = npcDialogues[_npcId];
+                if (dataMapDialogues.ContainsKey(_dataMapId))
+                {
+                    dialogue = dataMapDialogues[_dataMapId];
+                }
+                else
+                {
+                    dialogue = dataMapDialogues[_dataMapId] = new NpcDialogue(_npcId, _dataMapId);
+                }
+            }
+            else
+            {
+                var dataMapDialogues = npcDialogues[_npcId] = new Dictionary<int, NpcDialogue>();
+                dialogue = dataMapDialogues[_dataMapId] = new NpcDialogue(_npcId, _dataMapId);
+            }
+
+            return dialogue;
+        }
+
+        static DialogueBubble PackageDialogue(int _npcId)
+        {
+            DialogueBubble bubble = null;
+            bubble = DialogueBubblePool.Require(Pattern.NPC);
+            bubble.transform.SetParentEx(WindowCenter.Instance.uiRoot.nameCanvas, Vector3.zero, Vector3.zero, Vector3.one);
+            bubble.SetActive(true);
+
+            return bubble;
+        }
+
+        public static void Recyle(DialogueBubble _bubble)
+        {
+            DialogueBubblePool.Recycle(_bubble);
+        }
+
+        static List<NPCDialogueConfig> m_NpcDialogueConfigs;
+        static List<NPCDialogueConfig> npcDialogueConfigs { get { return m_NpcDialogueConfigs ?? (m_NpcDialogueConfigs = NPCDialogueConfig.GetValues()); } }
+
+        public static NPCDialogueConfig FindConfig(int _npcId, int _dataMapId)
+        {
+            foreach (var config in npcDialogueConfigs)
+            {
+                if (config.NPCID == _npcId && config.DataMapId == _dataMapId)
+                {
+                    return config;
+                }
+            }
+
+            return null;
+        }
+
+    }
+
+    class NpcDialogue
+    {
+        public readonly bool hasDialogue = false;
+
+        int dialogueContentLength;
+        public int countInterval;
+        float timeInterval = 5f;
+
+        int m_Index = 0;
+        public int index {
+            get { return m_Index; }
+            set {
+                if (value >= dialogueContentLength)
+                {
+                    m_Index = 0;
+                }
+                else
+                {
+                    m_Index = value;
+                }
+            }
+        }
+
+        int m_IntervalBuf = 0;
+        public int intervalBuf {
+            get { return m_IntervalBuf; }
+            set {
+                if (value >= countInterval)
+                {
+                    m_IntervalBuf = 0;
+                }
+                else
+                {
+                    m_IntervalBuf = value;
+                }
+            }
+        }
+
+        float m_LastDialogueTime = 0f;
+        public float lastDialogueTime {
+            get { return m_LastDialogueTime; }
+            set { m_LastDialogueTime = value; }
+        }
+
+        public NPCDialogueConfig config { get; private set; }
+
+        public NpcDialogue(int _npcId, int _dataMapId)
+        {
+            config = NPCDialogueBubble.FindConfig(_npcId, _dataMapId);
+            hasDialogue = config != null && config.Interval != 0;
+            if (config != null)
+            {
+                timeInterval = config.NextTime;
+                countInterval = config.Interval;
+                dialogueContentLength = config.Dialogues.Length;
+            }
+            else
+            {
+                timeInterval = 5f;
+                countInterval = 10;
+                dialogueContentLength = 0;
+            }
+
+            index = 0;
+            m_IntervalBuf = 0;
+        }
+
+        public bool countAble {
+            get { return m_IntervalBuf == 0; }
+        }
+
+        public bool timeAble {
+            get { return Time.time > lastDialogueTime + timeInterval; }
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/NPCDialogueBubble.cs.meta b/Main/Component/UI/HUD/NPCDialogueBubble.cs.meta
new file mode 100644
index 0000000..e19b88a
--- /dev/null
+++ b/Main/Component/UI/HUD/NPCDialogueBubble.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 19438d220e178a040aadb2edd731f9da
+timeCreated: 1512784022
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/PopUpNum.cs b/Main/Component/UI/HUD/PopUpNum.cs
new file mode 100644
index 0000000..5390150
--- /dev/null
+++ b/Main/Component/UI/HUD/PopUpNum.cs
@@ -0,0 +1,416 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+using System.Text;
+
+namespace vnxbqy.UI
+{
+    [DisallowMultipleComponent]
+    public class PopUpNum : MonoBehaviour
+    {
+
+        [SerializeField] Text m_Text;
+        [SerializeField] TweenCurve m_AlphaCurve;
+        [SerializeField] Animation m_Animation;
+        new public Animation animation { get { return m_Animation; } }
+        [SerializeField] FollowTargetIgnoreY m_FollowTarget;
+        [SerializeField] ScreenDiffuseMove m_DiffuseMove;
+
+        Pattern m_Pattern = Pattern.EnemyAttack;
+        public Pattern pattern {
+            get { return m_Pattern; }
+            set { m_Pattern = value; }
+        }
+
+        float hideTime = 0f;
+        float startTimeStep2 = 0f;
+        float durationStep1 = 0f;
+        float durationStep2 = 0f;
+
+        static StringBuilder stringBuild = new StringBuilder();
+        static int popupQueueMax = 20;
+        static Queue<PopupInfo> m_PopupInfoQueue = new Queue<PopupInfo>();
+        public static Queue<PopupInfo> popupInfoQueue {
+            get { return m_PopupInfoQueue; }
+        }
+
+        public static void RecordPopup(PopupInfo _popupInfo)
+        {
+            if (_popupInfo.isPlayer)
+            {
+                while (popupInfoQueue.Count >= popupQueueMax)
+                {
+                    popupInfoQueue.Dequeue();
+                }
+
+                popupInfoQueue.Enqueue(
+                    new PopupInfo()
+                    {
+                        pattern = _popupInfo.pattern,
+                        num = _popupInfo.num,
+                        camera = _popupInfo.camera,
+                        target = _popupInfo.target,
+                        direction = _popupInfo.direction,
+                        isPlayer = _popupInfo.isPlayer,
+                        realmSuppress = _popupInfo.realmSuppress,
+                    }
+                    );
+            }
+            else
+            {
+                Popup(_popupInfo);
+            }
+        }
+
+        public static void Popup(PopupInfo _popupInfo)
+        {
+            var groups = WindowCenter.Instance.uiRoot.fightCanvasGroup.damageNumGroups;
+            if (groups == null || groups.Length == 0)
+            {
+                return;
+            }
+
+            if (_popupInfo.target==null || _popupInfo.camera==null)
+            {
+                return;
+            }
+
+            var popupNum = PopUpNumPool.Require(_popupInfo.pattern);
+            if (popupNum == null)
+            {
+                return;
+            }
+
+            var uiPosition = CameraUtility.ConvertToUIPosition(_popupInfo.camera, _popupInfo.target.position);
+            var targetGroup = groups[groups.Length - 1];
+            for (int i = 0; i < groups.Length; i++)
+            {
+                var group = groups[i];
+                if (group.childCount < 20)
+                {
+                    targetGroup = group;
+                    break;
+                }
+            }
+
+            popupNum.transform.SetParent(targetGroup);
+            popupNum.transform.position = uiPosition;
+            popupNum.transform.localPosition = popupNum.transform.localPosition.SetZ(0);
+            popupNum.transform.localScale = Vector3.one;
+            popupNum.PopUp(_popupInfo);
+        }
+
+        public void PopUp(PopupInfo _popupInfo)
+        {
+            stringBuild.Remove(0, stringBuild.Length);
+
+            if (_popupInfo.realmSuppress)
+            {
+                var realmSuppressKey = GetRealmSuppressKey(_popupInfo.pattern);
+                if (realmSuppressKey > 0)
+                {
+                    stringBuild.Append((char)realmSuppressKey);
+                }
+            }
+
+            var prefixKey = GetPrefiexKey(_popupInfo.pattern);
+            if (prefixKey > 0)
+            {
+                stringBuild.Append((char)prefixKey);
+            }
+
+            var symbolKey = GetSymbolKey(_popupInfo.pattern);
+            if (symbolKey > 0)
+            {
+                stringBuild.Append((char)symbolKey);
+            }
+
+            switch (_popupInfo.pattern)
+            {
+                case Pattern.PlayerMiss:
+                case Pattern.PetMiss:
+                case Pattern.EnemyMiss:
+                case Pattern.PlayerImmune:
+                case Pattern.PetImmune:
+                case Pattern.EnemyImmune:
+                case Pattern.EnemyZhanSha:
+                case Pattern.PetZhanSha:
+                case Pattern.PlayerZhanSha:
+                    break;
+                default:
+                    var chars = UIHelper.ReplaceLargeArtNum(_popupInfo.num);
+                    for (var i = 0; i < chars.Length; i++)
+                    {
+                        var numChar = GetNumKey(_popupInfo.pattern, chars[i]);
+                        if (numChar > 0)
+                        {
+                            stringBuild.Append((char)numChar);
+                        }
+                    }
+                    break;
+            }
+
+            m_Text.text = stringBuild.ToString();
+            m_Text.color = m_Text.color.SetA(1f);
+            this.SetActive(true);
+
+            if (m_FollowTarget != null)
+            {
+                if (m_DiffuseMove != null)
+                {
+                    switch (m_DiffuseMove.moveType)
+                    {
+                        case ScreenDiffuseMove.DiffuseType.RelativePosition:
+                        case ScreenDiffuseMove.DiffuseType.ReversalRelativePosition:
+                            m_FollowTarget.enabled = false;
+                            break;
+                        default:
+                            m_FollowTarget.Follow(_popupInfo.target, _popupInfo.camera);
+                            m_FollowTarget.enabled = true;
+                            break;
+                    }
+                }
+                else
+                {
+                    m_FollowTarget.Follow(_popupInfo.target, _popupInfo.camera);
+                    m_FollowTarget.enabled = true;
+                }
+            }
+
+            if (animation != null)
+            {
+                animation.enabled = true;
+                animation.Play();
+                var clip = animation.clip;
+                if (clip != null)
+                {
+                    durationStep1 = clip.length;
+                }
+            }
+            else
+            {
+                durationStep1 = 0f;
+            }
+
+            if (m_DiffuseMove != null)
+            {
+                m_DiffuseMove.delay = 0f;
+                durationStep2 = m_DiffuseMove.duration;
+                m_DiffuseMove.Begin(_popupInfo.direction, true);
+                m_DiffuseMove.transform.localPosition = Vector3.zero;
+            }
+
+            durationStep1 = 0f;
+            startTimeStep2 = Time.time + durationStep1;
+            hideTime = Time.time + durationStep1 + durationStep2;
+
+            PopUpNumPool.recycleAllEvent -= OnReycleAll;
+            PopUpNumPool.recycleAllEvent += OnReycleAll;
+        }
+
+        public void SetEnable(bool _enable)
+        {
+            m_Animation.enabled = _enable;
+            m_FollowTarget.enabled = _enable;
+            m_DiffuseMove.enabled = _enable;
+            this.enabled = _enable;
+        }
+
+        int GetRealmSuppressKey(Pattern _pattern)
+        {
+            var config = DamageNumConfig.Get(_pattern.ToString());
+            return config.realm;
+        }
+
+        int GetPrefiexKey(Pattern _pattern)
+        {
+            var config = DamageNumConfig.Get(_pattern.ToString());
+            return config.prefix;
+        }
+
+        int GetSymbolKey(Pattern _pattern)
+        {
+            var config = DamageNumConfig.Get(_pattern.ToString());
+            switch (_pattern)
+            {
+                case Pattern.EnemyRecovery:
+                case Pattern.PlayerRecovery:
+                case Pattern.PetRecovery:
+                case Pattern.BuffAddDefense:
+                case Pattern.BuffAddAttack:
+                case Pattern.BuffAddAttackSpeed:
+                case Pattern.BuffAddAccurate:
+                case Pattern.BuffAddDodge:
+                case Pattern.BuffAddMaxHp:
+                case Pattern.BuffAddMoveSpeed:
+                    return config.plus;
+                default:
+                    return config.minus;
+            }
+        }
+
+        int GetNumKey(Pattern _pattern, int _num)
+        {
+            var key = string.Empty;
+            var config = DamageNumConfig.Get(_pattern.ToString());
+
+            //.鐨凙SCII鐮佹槸46
+            if (_num == 46)
+            {
+                return config.nums[10];
+            }
+            //k鐨凙SCII鐮佹槸107
+            else if (_num == 107)
+            {
+                return config.nums[11];
+            }
+            //m鐨凙SCII鐮佹槸109
+            else if (_num == 109)
+            {
+                return config.nums[12];
+            }
+            //b鐨凙SCII鐮佹槸98
+            else if (_num == 98)
+            {
+                return config.nums[13];
+            }
+            //t鐨凙SCII鐮佹槸116
+            else if (_num == 116)
+            {
+                return config.nums[14];
+            }
+            return config.nums[_num - 48];
+        }
+
+        void LateUpdate()
+        {
+            if (Time.time > hideTime)
+            {
+                PopUpNumPool.Recycle(this);
+            }
+            else if (Time.time > startTimeStep2)
+            {
+                if (m_AlphaCurve != null)
+                {
+                    var t = (Time.time - startTimeStep2) / durationStep2 * m_AlphaCurve.totalTime;
+                    m_Text.color = m_Text.color.SetA(1 - m_AlphaCurve.Evaluate(t));
+                }
+            }
+        }
+
+        private void OnReycleAll()
+        {
+            PopUpNumPool.recycleAllEvent -= OnReycleAll;
+            PopUpNumPool.Recycle(this);
+        }
+
+        public enum Pattern
+        {
+            PlayerAttack = 1,                 //鐜╁鏀诲嚮锛屽彈鍑诲璞′负鏁屽鎬墿鎴栫帺瀹�
+            PetAttack = 2,                       //瀹犵墿鏀诲嚮锛屽彈鍑诲璞′负鏁屽鎬墿鎴栫帺瀹�
+            EnemyAttack = 3,                 //鏁屽鎬墿鎴栫帺瀹舵敾鍑伙紝鍙楀嚮瀵硅薄涓虹帺瀹跺強鍙嬫柟鍗曚綅
+
+            PlayerRecovery = 4,               //鐜╁鍥炲
+            PetRecovery = 5,                   //瀹犵墿鍥炲
+            EnemyRecovery = 6,              //鏁屼汉鍥炲
+
+            PlayerTurnTheBlade = 7,        //鐜╁鍙嶅脊锛屽彈鍑诲璞′负鏁屽鎬墿鎴栫帺瀹�
+            PetTurnTheBlade = 8,             //瀹犵墿鍙嶅脊锛屽彈鍑诲璞′负鏁屽鎬墿鎴栫帺瀹�
+            EnemyTurnTheBlade = 9,       //鏁屼汉鍙嶅脊锛屽彈鍑诲璞′负鐜╁鍙婂弸鏂瑰崟浣�
+
+            PlayerBleed = 10,                    //鐜╁娴佽
+            PetBleed = 11,                          //瀹犵墿娴佽
+            EnemyBleed = 12,                    //鏁屼汉娴佽
+
+            PlayerParry = 13,                     //鐜╁鏍兼尅
+            PetParry = 14,                         //瀹犵墿鏍兼尅
+            EnemyParry = 15,                    //鏁屼汉鏍兼尅
+
+            PlayerDoubleHit = 16,             //鐜╁杩炲嚮
+            PetDoubleHit = 17,                  //瀹犵墿杩炲嚮                          
+            EnemyDoubleHit = 18,             //鏁屼汉杩炲嚮             
+
+            PlayerCrit = 19,                         //鐜╁鏆村嚮             
+            PetCrit = 20,                             //瀹犵墿鏆村嚮               
+            EnemyCrit = 21,                        //鏁屼汉鏆村嚮
+
+            PlayerHuiXin = 22,                    //鐜╁浼氬績涓�鍑�
+            PetHuiXin = 23,                        //瀹犵墿浼氬績涓�鍑�                          
+            EnemyHuiXin = 24,                   //鏁屼汉浼氬績涓�鍑�
+
+            PlayerMiss = 25,                    //鐜╁Miss
+            PetMiss = 26,                        //瀹犵墿Miss                      
+            EnemyMiss = 27,                   //鏁屼汉Miss
+
+            PlayerImmune = 28,                    //鐜╁鍏嶇柅
+            PetImmune = 29,                        //瀹犵墿鍏嶇柅                      
+            EnemyImmune = 30,                   //鏁屼汉鍏嶇柅
+
+            PlayerZhanSha = 34,                    //鐜╁鏂╂潃
+            PetZhanSha = 35,                        //瀹犵墿鏂╂潃                      
+            EnemyZhanSha = 36,                   //鏁屼汉鏂╂潃
+
+            PlayerZhuXian = 37,                    //鐜╁璇涗粰
+            PetZhuXian = 38,                        //瀹犵墿璇涗粰                      
+            EnemyZhuXian = 39,                   //鏁屼汉璇涗粰
+
+            PlayerDeadlyHit = 43,                    //鐜╁鑷存涓�鍑�
+            PetDeadlyHit = 44,                        //瀹犵墿鑷存涓�鍑�                      
+            EnemyDeadlyHit = 45,                   //鏁屼汉鑷存涓�鍑�
+
+            PlayerThumpHit = 46,                    //鐜╁閲嶅嚮
+            PetThumpHit = 47,                        //瀹犵墿閲嶅嚮                      
+            EnemyThumpHit = 48,                   //鏁屼汉閲嶅嚮
+
+            PlayerYinji = 49,                    //鐜╁鍗拌
+            PetYinji = 50,                        //瀹犵墿鍗拌                      
+            EnemyYinji = 51,                   //鏁屼汉鍗拌
+
+            PlayerBurning = 52,                    //鐜╁鐏肩儳
+            PetBurning = 53,                        //瀹犵墿鐏肩儳                      
+            EnemyBurning = 54,                   //鏁屼汉鐏肩儳
+
+            BuffAddDefense = 101,//+闃插尽buff
+            BuffAddAttack = 102,//+鏀诲嚮buff
+            BuffAddAttackSpeed = 103,//+鏀婚�焍uff
+            BuffAddAccurate = 104,//+鍛戒腑buff
+            BuffAddDodge = 105,//+闂伩Buff
+            BuffAddMaxHp = 106,//+琛�閲忎笂闄恇uff
+            BuffAddMoveSpeed = 107,//+绉诲姩閫熷害buff
+
+            BuffReduceDefense = 201,//-闃插尽buff
+            BuffReduceAttack = 202,//-鏀诲嚮buff
+            BuffReduceAttackSpeed = 203,//-鏀婚�焍uff
+            BuffReduceAccurate = 204,//-鍛戒腑buff
+            BuffReduceDodge = 205,//-闂伩Buff
+            BuffReduceMaxHp = 206,//-琛�閲忎笂闄恇uff
+            BuffReduceMoveSpeed = 207,//-绉诲姩閫熷害buff
+
+        }
+
+        public enum AttackObject
+        {
+            Player,
+            Pet,
+            Enemy,
+        }
+
+        public struct PopupInfo
+        {
+            public Pattern pattern;
+            public ulong num;
+            public Camera camera;
+            public Transform target;
+            public Vector3 direction;
+            public bool realmSuppress;
+            public bool isPlayer;
+        }
+
+
+
+    }
+
+}
+
diff --git a/Main/Component/UI/HUD/PopUpNum.cs.meta b/Main/Component/UI/HUD/PopUpNum.cs.meta
new file mode 100644
index 0000000..d1839ab
--- /dev/null
+++ b/Main/Component/UI/HUD/PopUpNum.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1646861b0b8ac8e4096e18603df2c996
+timeCreated: 1500889651
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/PopUpNumPool.cs b/Main/Component/UI/HUD/PopUpNumPool.cs
new file mode 100644
index 0000000..3e8b69e
--- /dev/null
+++ b/Main/Component/UI/HUD/PopUpNumPool.cs
@@ -0,0 +1,82 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+namespace vnxbqy.UI
+{
+
+    public class PopUpNumPool
+    {
+
+        public static event Action recycleAllEvent;
+        static Dictionary<int, GameObjectPoolManager.GameObjectPool> pools = new Dictionary<int, GameObjectPoolManager.GameObjectPool>();
+
+        public static PopUpNum Require(PopUpNum.Pattern _pattern)
+        {
+            GameObjectPoolManager.GameObjectPool pool = null;
+            var poolKey = (int)_pattern;
+            if (!pools.ContainsKey(poolKey))
+            {
+                var prefab = UILoader.LoadPrefab(StringUtility.Contact("PopUpNum_", _pattern));
+                if (prefab != null)
+                {
+                    pool = GameObjectPoolManager.Instance.RequestPool(prefab);
+                    pools[poolKey] = pool;
+                }
+            }
+            else
+            {
+                pool = pools[poolKey];
+            }
+
+            if (pool != null)
+            {
+                var instance = pool.Request();
+                var popupNum = instance.GetComponent<PopUpNum>();
+                popupNum.pattern = _pattern;
+                popupNum.enabled = true;
+                return popupNum;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public static void Recycle(PopUpNum _popupNum)
+        {
+            var pattern = _popupNum.pattern;
+            GameObjectPoolManager.GameObjectPool pool;
+            if (pools.TryGetValue((int)pattern, out pool))
+            {
+                pool.Release(_popupNum.gameObject);
+                _popupNum.SetEnable(false);
+            }
+
+        }
+
+        public static void RecycleAll()
+        {
+            if (recycleAllEvent != null)
+            {
+                recycleAllEvent();
+            }
+        }
+
+        public static void Clear()
+        {
+            foreach (var key in pools.Keys)
+            {
+                var pool = pools[key];
+                if (pool != null)
+                {
+                    pool.Clear();
+                }
+            }
+            pools.Clear();
+        }
+    }
+
+}
+
diff --git a/Main/Component/UI/HUD/PopUpNumPool.cs.meta b/Main/Component/UI/HUD/PopUpNumPool.cs.meta
new file mode 100644
index 0000000..0237b89
--- /dev/null
+++ b/Main/Component/UI/HUD/PopUpNumPool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 00bad1c54ede5684fa28e5298f093a44
+timeCreated: 1500896369
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/HUD/StoryDialogueBubble.cs b/Main/Component/UI/HUD/StoryDialogueBubble.cs
new file mode 100644
index 0000000..f382574
--- /dev/null
+++ b/Main/Component/UI/HUD/StoryDialogueBubble.cs
@@ -0,0 +1,68 @@
+锘�//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, December 28, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+namespace vnxbqy.UI
+{
+
+    public class StoryDialogueBubble : DialogueBubble
+    {
+        float m_Delay = 0f;
+        bool delayOver = false;
+
+        string content = string.Empty;
+        new Transform target;
+        new Camera camera;
+
+        public static void StoryShow(string _content, Transform _target, Camera _camera, float _delay = 0f)
+        {
+            var bubble = DialogueBubblePool.Require(Pattern.Story);
+            bubble.transform.SetParentEx(WindowCenter.Instance.uiRoot.bossShowCanvas.transform, Vector3.zero, Vector3.zero, Vector3.one);
+            bubble.SetActive(true);
+
+            var storyBubble = bubble as StoryDialogueBubble;
+            if (storyBubble)
+            {
+                storyBubble.DelayShow(_content, _target, _camera, _delay);
+            }
+        }
+
+        public void DelayShow(string _content, Transform _target, Camera _camera, float _delay)
+        {
+            content = _content;
+            target = _target;
+            camera = _camera;
+
+            delayOver = false;
+
+            m_Delay = Time.time + _delay;
+            if (m_Delay > 0f)
+            {
+                this.transform.localScale = Vector3.zero;
+            }
+        }
+
+        protected override void LateUpdate()
+        {
+            base.LateUpdate();
+
+            if (!delayOver && Time.time > m_Delay)
+            {
+                delayOver = true;
+                this.transform.localScale = Vector3.one;
+
+                base.Show(content, target, camera);
+            }
+
+        }
+
+    }
+
+}
+
+
+
diff --git a/Main/Component/UI/HUD/StoryDialogueBubble.cs.meta b/Main/Component/UI/HUD/StoryDialogueBubble.cs.meta
new file mode 100644
index 0000000..77b6a89
--- /dev/null
+++ b/Main/Component/UI/HUD/StoryDialogueBubble.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 61918c8deafbcf647b83914954629e58
+timeCreated: 1514440008
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Manager.meta b/Main/Component/UI/Manager.meta
new file mode 100644
index 0000000..5453201
--- /dev/null
+++ b/Main/Component/UI/Manager.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: e9892f39d363922408fd397155f817b7
+folderAsset: yes
+timeCreated: 1504507815
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Component/UI/Manager/UIEventTrigger.cs b/Main/Component/UI/Manager/UIEventTrigger.cs
new file mode 100644
index 0000000..e9abe30
--- /dev/null
+++ b/Main/Component/UI/Manager/UIEventTrigger.cs
@@ -0,0 +1,191 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System;
+
+public class UIEventTrigger : EventTrigger {
+    public delegate void ObjectDelegate(GameObject go,PointerEventData eventData);
+    public delegate void OneParamDelegate(GameObject go);
+    public delegate void PointerEvtDataDelegate(PointerEventData eventData);
+    public delegate void NoParamDelegate();
+    public ObjectDelegate OnClick;
+    public OneParamDelegate OneParaClick;
+
+    private bool doubleClick = false;
+    private bool m_DoubleClick = false;
+    private bool continueClick = true;
+    private NoParamDelegate m_OnDoubleClick;
+
+    private bool m_OnScroll = false;
+
+    public NoParamDelegate OnDoubleClick {
+        get { return m_OnDoubleClick; }
+        set {
+              doubleClick = value!=null;
+              m_OnDoubleClick = value;
+        }
+    }
+    /// <summary>
+    /// 鐢ㄤ簬澶勭悊ScrollRect涓偣鍑讳簨浠跺拰鎷栧姩浜嬩欢鐨勫啿绐�
+    /// </summary>
+    public PointerEvtDataDelegate OnScrollBeginDrag;
+    /// <summary>
+    /// 鐢ㄤ簬澶勭悊ScrollRect涓偣鍑讳簨浠跺拰鎷栧姩浜嬩欢鐨勫啿绐�
+    /// </summary>
+    private PointerEvtDataDelegate m_OnScrollDrag;
+    public PointerEvtDataDelegate OnScrollDrag {
+        get { return m_OnScrollDrag; }
+        set {
+            //m_OnScroll= value != null;
+            m_OnScrollDrag = value;
+        }
+    }
+    /// <summary>
+    /// 鐢ㄤ簬澶勭悊ScrollRect涓偣鍑讳簨浠跺拰鎷栧姩浜嬩欢鐨勫啿绐�
+    /// </summary>
+    public PointerEvtDataDelegate OnScrollEndDrag;
+    /// <summary>
+    /// 榧犳爣鎸変笅浜嬩欢
+    /// </summary>
+    public OneParamDelegate OnDown;
+    /// <summary>
+    /// 榧犳爣鏀惧紑浜嬩欢
+    /// </summary>
+    public OneParamDelegate OnUp;
+
+    public NoParamDelegate OnNoParamsClick;
+
+
+    public static PointerEventData EventData;
+    private void Awake()
+    {
+        if (EventData == null) EventData =new PointerEventData(EventSystem.current);
+    }
+
+    public static UIEventTrigger Get(GameObject go)
+    {
+        UIEventTrigger listener = null;
+        listener = go.GetComponent<UIEventTrigger>();
+        if(listener==null) {
+            listener = go.AddComponent<UIEventTrigger>();
+        }
+        listener.enabled = true;
+        return listener;
+    }
+    /// <summary>
+    /// 閲嶈浇鐐瑰嚮UI鐐瑰嚮鐨勪簨浠讹紝鍖呭惈鎵�鏈夌殑UI缁勪欢锛屽苟浼犻�掕鐐瑰嚮鐨勭墿浣�
+    /// </summary>
+    /// <param name="eventData"></param>
+    public override void OnPointerClick(PointerEventData eventData)
+    {
+        if (CheckDouble()) return;
+        if (CheckScroll()) return;
+        if (null != OnClick && enabled) OnClick(gameObject, eventData);
+        if (null != OneParaClick && enabled) OneParaClick(gameObject);
+        if (null != OnNoParamsClick && enabled) OnNoParamsClick();
+    }
+
+    private bool CheckDouble()
+    {
+        if (!doubleClick) return doubleClick;
+        if (!continueClick) return doubleClick;
+        if (m_DoubleClick) {
+            OnDoubleClick();
+            continueClick = false;
+            m_DoubleClick = false;
+        }
+        else {
+            this.OnWaitCompelete(OnDoubleWait);
+            this.SetWait(0.3f);
+            this.DoWaitRestart();
+            m_DoubleClick = true;
+        }
+        return doubleClick;
+    }
+
+    private bool CheckScroll()
+    {
+        return m_OnScroll;
+    }
+
+    private void OnDoubleWait(Component comp)
+    {
+        if (m_DoubleClick) {
+            if (null != OneParaClick && enabled) OneParaClick(gameObject);
+            if (null != OnNoParamsClick && enabled) OnNoParamsClick();
+        }
+        continueClick = true;
+        m_DoubleClick = false;
+    }
+
+    /// <summary>
+    /// 寮�濮嬫嫋鍔�
+    /// </summary>
+    /// <param name="eventData"></param>
+    private Vector2 m_BeginSrPos = Vector2.zero;
+    public override void OnBeginDrag(PointerEventData eventData)
+    {
+        if (null != OnScrollBeginDrag && enabled) 
+        {
+            m_BeginSrPos = eventData.position;
+            OnScrollBeginDrag(eventData);
+        }
+
+    }
+    /// <summary>
+    /// 鎷栧姩涓�
+    /// </summary>
+    /// <param name="eventData"></param>
+    public override void OnDrag(PointerEventData eventData)
+    {
+        if (null != OnScrollDrag && enabled) 
+        {
+            if (Vector2.Distance(m_BeginSrPos, eventData.position) < 10.0f) {
+                return;
+            }
+            m_OnScroll = true;
+            OnScrollDrag(eventData);
+        }
+    }
+    /// <summary>
+    /// 缁撴潫鎷栧姩
+    /// </summary>
+    /// <param name="eventData"></param>
+    public override void OnEndDrag(PointerEventData eventData)
+    {
+        if (null != OnScrollEndDrag && enabled) 
+        {
+            m_OnScroll = false;
+            OnScrollEndDrag(eventData);
+        } 
+    }
+    /// <summary>
+    /// 榧犳爣鎸変笅
+    /// </summary>
+    /// <param name="eventData"></param>
+    public override void OnPointerDown(PointerEventData eventData)
+    {
+        if (null != OnDown && enabled) OnDown(gameObject);
+    }
+    /// <summary>
+    /// 榧犳爣鏀惧紑
+    /// </summary>
+    /// <param name="eventData"></param>
+    public override void OnPointerUp(PointerEventData eventData)
+    {
+        if (null != OnUp && enabled) OnUp(gameObject);
+    }
+
+    public static UIEventTrigger Contains(GameObject go)
+    {
+        return go.GetComponent<UIEventTrigger>();
+    }
+
+    private void OnDisable()
+    {
+        m_DoubleClick = false;
+        continueClick = true;
+        m_OnScroll = false;
+    }
+}
diff --git a/Main/Component/UI/Manager/UIEventTrigger.cs.meta b/Main/Component/UI/Manager/UIEventTrigger.cs.meta
new file mode 100644
index 0000000..415cb28
--- /dev/null
+++ b/Main/Component/UI/Manager/UIEventTrigger.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5469ebca9453da147b534601d95d0990
+timeCreated: 1504507824
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/ConfigBase.cs b/Main/Config/ConfigBase.cs
index ea87401..cd5373e 100644
--- a/Main/Config/ConfigBase.cs
+++ b/Main/Config/ConfigBase.cs
@@ -1,5 +1,8 @@
 using System.Collections.Generic;
 using UnityEngine;
+using Cysharp.Threading.Tasks;
+using System.IO;
+using System;
 
 
 public class ConfigBase<U, T> where T : ConfigBase<U, T>, new()
diff --git a/Main/Core.meta b/Main/Core.meta
new file mode 100644
index 0000000..f655051
--- /dev/null
+++ b/Main/Core.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 03a52d181c7e5bf47bd889519e77744c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/GameEngine.meta b/Main/Core/GameEngine.meta
new file mode 100644
index 0000000..c70ce66
--- /dev/null
+++ b/Main/Core/GameEngine.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8182bfd4d894e9743bf6100c8f7b3f8f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/GameEngine/Player.meta b/Main/Core/GameEngine/Player.meta
new file mode 100644
index 0000000..fe8be9e
--- /dev/null
+++ b/Main/Core/GameEngine/Player.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: be6bcaab3cfbf5f469daa9c4d879d7fc
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/GameEngine/Player/PlayerBaseData.cs b/Main/Core/GameEngine/Player/PlayerBaseData.cs
new file mode 100644
index 0000000..f76d5c8
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerBaseData.cs
@@ -0,0 +1,297 @@
+锘縰sing System;
+
+public class PlayerBaseData
+{
+    public ushort mainServerMapIdRecord = 0;
+
+    public string AccID;    //_KEY_i_甯愬彿鍚�, 璇ヨ鑹叉墍鍦ㄧ殑甯愬彿鐨勭敤鎴峰悕
+    public uint PlayerID;    //_IDT_
+    public string PlayerName;    //size = 14
+    public byte GMLevel;    //GM绛夌骇, 0:涓嶆槸GM  >=1 : GM鐨勭瓑绾�
+    public byte Job;    //鑱屼笟, 
+    public ushort LV;    //绛夌骇
+    public int TitleID;
+    public uint ExpPoint;    //鎵╁厖缁忛獙鐐规暟
+    public uint TotalExp;    //鎬荤粡楠�
+    public uint FamilyId;    //瀹舵棌
+    public string FamilyName;    //瀹舵棌鍚嶇О
+    public uint diamond;    //浠欑帀
+    public uint bindDiamond;  //鐏电煶
+    public uint copper;    //閾滈挶
+    public ulong allCopper { get { return (ulong)copper + (ulong)copperExtend * Constants.ExpPointValue; } }
+    public ulong FightPoint;    //鎴樻枟鍊�
+    public ushort MapID;    //瑙掕壊鎵�鍦ㄥ湴鍥�  鍦板浘瑙勫垯锛欳/S涓�涓�瀵瑰簲鐨勫父瑙勫湴鍥撅紝C鍋囧湴鍥撅紙ExAttr14锛夛紝澶欳涓�涓猄鍦板浘锛圗xAttr3锛�
+    public ushort PosX;    //瑙掕壊鍧愭爣
+    public ushort PosY;
+    public ulong HP;    //褰撳墠HP
+    public uint FreePoint;    //鏈垎閰嶇偣鏁�
+    public uint FreeSkillPoint;    //鏈垎閰嶇殑鎶�鑳界偣
+    public int STR;    //鍔涢噺
+    public int PNE;    //鐪熷厓
+    public int PHY;    //绛嬮
+    public int CON;    //浣撻瓌
+    public string Setting;    //璁惧畾
+    public byte AttackMode;    //鏀诲嚮妯″紡
+    public byte FBID;    //fb id
+    public byte realmLevel;    //鏃ф湇鍔$瀹橀樁锛岀幇椤圭洰鐢ㄤ簬澧冪晫
+    public byte VIPLv;    //VIP绛夌骇
+    public uint ExAttr1;    // 鍗忓姪鐩爣鐜╁ID锛岄潪0鍙�0閫�鍑哄崗鍔�
+    public uint teamAutoOperateFlag;    //鎵╁睍灞炴��2锛屽悇椤圭洰涓撶敤
+    public int dungeonLineId;    // 鍓湰绾胯矾id
+    public int dungeonMapId;    // 鍓湰鐢ㄤ綔 DataMapId,鍗曚汉鍓湰瀛樺湪1.鍋囧壇鏈� 2.鏈嶅姟绔�1瀵瑰鎴风澶氬湴鍥惧悓鍒嗙嚎 3.鏈嶅姟绔�1瀵瑰鎴风澶氬湴鍥句笉鍚屽垎绾�
+    public uint shield;    //鎶ょ浘鍊�
+    public uint CrossServerFlag;    //璺ㄦ湇鏍囪瘑锛屽ぇ浜�2鏍囪瘑鍦ㄨ法鏈嶇姸鎬侊紝鍊兼槸璺ㄦ湇鍦板浘鐨刣atamapid
+    public uint copperExtend;    //鎵╁睍灞炴��6锛屽悇椤圭洰涓撶敤
+    public uint sp;    //鎵╁睍灞炴��7锛屽悇椤圭洰涓撶敤
+    public uint spExtend;    //鎵╁睍灞炴��8锛屽悇椤圭洰涓撶敤
+    public uint bubbleId;    //鎵╁睍灞炴��10锛屽悇椤圭洰涓撶敤
+    public uint ExAttr11;    //棰勭暀鐨勬墿灞曞睘鎬у瓧娈碉紝鐢ㄦ潵瀛樻斁椤圭洰鐗瑰畾鐨勫睘鎬�121 鐜伴噾浠e竵锛堜唬閲戝埜锛�
+    public uint ExAttr16;    //棰勭暀鐨勬墿灞曞睘鎬у瓧娈碉紝鐢ㄦ潵瀛樻斁椤圭洰鐗瑰畾鐨勫睘鎬�    鍏ㄨ韩鐗规晥
+    public uint ServerGroupId;    //鏈嶅姟鍣ㄧ粍ID
+    public uint hangTime;//鐜颁负鑴辨満鎸傚墿浣欐椂闂� 23
+    public uint faction; //闃佃惀 107
+    uint m_coinPointTotal;
+    public int face;//澶村儚
+    public int facePic;//澶村儚澶栨
+
+    public uint coinPointTotal { 
+        private get { return m_coinPointTotal; }
+        set {
+            CoinChangeEvent?.Invoke((int)m_coinPointTotal, (int)value);
+            m_coinPointTotal = value;
+        }
+    }//宸插厖鍊奸噾棰濓紝鍗曚綅鍒� 112 瓒婂崡鐩剧湡瀹炲厖鍊奸噾棰�
+
+    public event Action<int, int> CoinChangeEvent;
+    public float coinTotal
+    {
+        get
+        {
+            return UIHelper.GetRealCoin((int)coinPointTotal);
+        }
+    }
+
+    public int BasicsMinimum;//鍩虹鏈�灏忔敾鍑�
+    public int BasicsMaxAttack;//鍩虹鏈�澶ф敾鍑�
+    public int BasicsLife;//鍩虹鐢熷懡
+    public int BasicsDefense;//鍩虹闃插尽
+    public int BasicsScoreAHit;//鍩虹鍛戒腑
+    public int BasicsDodge;//鍩虹闂伩
+    public uint equipShowSwitch;//瑁呭鏄鹃殣寮�鍏�
+    public int mater;//鐏垫牴灞炴�р�斺�旈噾
+    public int wood;//鐏垫牴灞炴�р�斺�旀湪
+    public int water;//鐏垫牴灞炴�р�斺�旀按
+    public int fire;//鐏垫牴灞炴�р�斺�旂伀
+    public int earth;//鐏垫牴灞炴�р�斺�斿湡
+    public int NormalHurt;
+    public int NormalHurtPer;
+    public int FabaoHurt;
+    public int FabaoHurtPer;
+    public int reduceCrit;//鏆村嚮鎶楁��
+    public int reduceHeartHurt;//浼氬績涓�鍑讳激瀹冲浐瀹氬�煎噺鍏�
+    public int reduceFinalHurt;//鏈�缁堜激瀹崇櫨鍒嗘瘮鍑忓厤
+
+    public int yinjiCount;//褰撳墠鍗拌鏁伴噺
+    public int yinjiTime;//鍗拌杞湀鏃堕棿
+
+    public int skillAddPerA;//瀹氭捣绁為拡鎶�鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerB; //鐨撴湀鏋妧鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerC; //楝肩墮鍒冩妧鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerD; //纾愰緳鍗版妧鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerE; //鏉忛粍鏃楁妧鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerF;//鍡滃ぉ鏂ф妧鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillAddPerG; //灏勬棩绁炲紦鎶�鑳戒激瀹崇櫨鍒嗘瘮
+    public int skillReducePerA; //瀹氭捣绁為拡鎶�鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerB; //鐨撴湀鏋妧鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerC; //楝肩墮鍒冩妧鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerD; //纾愰緳鍗版妧鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerE; //鏉忛粍鏃楁妧鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerF; //鍡滃ぉ鏂ф妧鑳藉噺浼ょ櫨鍒嗘瘮
+    public int skillReducePerG; //灏勬棩绁炲紦鎶�鑳藉噺浼ょ櫨鍒嗘瘮
+
+    public int mapRealmSelect;  //鍦板浘澧冪晫闅惧害
+    public int leaveFamilyTime; //绂诲紑瀹舵棌鏃堕棿
+
+    public bool IsActive90Off = true; //浠h〃榛樿婵�娲�0.1鎶�
+    public long treasurePotentialSp
+    {
+        get
+        {
+            return spExtend * (long)Constants.ExpPointValue + sp;
+        }
+    }
+
+    public int reikiRootEffectId
+    {
+        get
+        {
+            return (int)equipShowSwitch / 1000 % 1000;
+        }
+    }
+
+    public int suitLevel
+    {
+        //褰撳墠绌跨殑绗嚑濂楄澶囷紝鍛藉悕鍜屽瑁呮棤鍏�
+        get
+        {
+            return (int)equipShowSwitch / 10 % 100;
+        }
+    }
+
+    public void UpdateData(int temp/*H0102_tagCDBPlayer _serverInfo*/)
+    {
+//         if (_serverInfo.socketType == ServerType.Main)
+//         {
+//             AccID = _serverInfo.AccID;
+//             PlayerID = _serverInfo.PlayerID;
+//             PlayerName = _serverInfo.PlayerName.Trim().Replace("\0", "");
+//             GMLevel = _serverInfo.GMLevel;
+//             Job = _serverInfo.Job;
+//             LV = _serverInfo.LV;
+//             ExpPoint = _serverInfo.ExpPoint;
+//             TotalExp = _serverInfo.TotalExp;
+//             FamilyId = _serverInfo.Family;
+//             FamilyName = _serverInfo.FamilyName.Trim().Replace("\0", "");
+//             diamond = _serverInfo.Gold;
+//             bindDiamond = _serverInfo.GoldPaper;
+//             copper = _serverInfo.Silver;
+//             MapID = _serverInfo.MapID;
+//             mainServerMapIdRecord = MapID;
+//             PosX = _serverInfo.PosX;
+//             PosY = _serverInfo.PosY;
+//             FreePoint = _serverInfo.FreePoint;
+//             FreeSkillPoint = _serverInfo.FreeSkillPoint;
+//             STR = _serverInfo.STR;
+//             PNE = _serverInfo.PNE;
+//             PHY = _serverInfo.PHY;
+//             CON = _serverInfo.CON;
+//             Setting = _serverInfo.Setting;
+//             FBID = _serverInfo.FBID;
+//             ExAttr1 = _serverInfo.ExAttr1;
+//             teamAutoOperateFlag = _serverInfo.ExAttr2;
+//             dungeonLineId = (int)_serverInfo.ExAttr3 % 1000;
+//             dungeonMapId = (int)_serverInfo.ExAttr3 / 1000;
+//             shield = _serverInfo.ExAttr4;
+//             CrossServerFlag = _serverInfo.ExAttr5;
+//             realmLevel = _serverInfo.OfficialRank;
+//             VIPLv = _serverInfo.VIPLv;
+//             copperExtend = _serverInfo.ExAttr6;
+//             sp = _serverInfo.ExAttr7;
+//             spExtend = _serverInfo.ExAttr8;
+//             bubbleId = _serverInfo.ExAttr10;
+//             ExAttr11 = _serverInfo.ExAttr11;
+//             ExAttr16 = _serverInfo.ExAttr16;
+//             ServerGroupId = _serverInfo.ExAttr13;
+//             faction = _serverInfo.Faction;
+//             coinPointTotal = _serverInfo.ChangeCoinPointTotal;
+//             equipShowSwitch = _serverInfo.EquipShowSwitch;
+//             mapRealmSelect = (int)_serverInfo.ExAttr18;
+//             leaveFamilyTime = (int)_serverInfo.ExAttr19;
+//             face = (int)_serverInfo.Face;
+//             facePic = (int)_serverInfo.FacePic;    
+// }
+//         else
+//         {
+//             PlayerName = _serverInfo.PlayerName.Trim().Replace("\0", "");
+//             MapID = _serverInfo.MapID;
+//             dungeonLineId = (int)_serverInfo.ExAttr3 % 1000;
+//             dungeonMapId = (int)_serverInfo.ExAttr3 / 1000;
+//             FBID = _serverInfo.FBID;
+//             PosX = _serverInfo.PosX;
+//             PosY = _serverInfo.PosY;
+//         }
+
+//         if (CrossServerUtility.IsCrossServer())
+//         {
+//             if (_serverInfo.socketType == ServerType.CrossSever)
+//             {
+//                 HP = _serverInfo.HP + _serverInfo.HPEx * Constants.ExpPointValue;
+//                 AttackMode = _serverInfo.AttackMode;
+//             }
+//         }
+//         else
+//         {
+//             HP = _serverInfo.HP + _serverInfo.HPEx * Constants.ExpPointValue;
+//             AttackMode = _serverInfo.AttackMode;
+//         }
+
+//         if (PlayerDatas.Instance.hero != null)
+//         {
+//             PlayerDatas.Instance.hero.ActorInfo.familyID = FamilyId;
+//             if (CrossServerUtility.IsCrossServer())
+//             {
+//                 if (_serverInfo.socketType == ServerType.CrossSever)
+//                 {
+//                     PlayerDatas.Instance.hero.ActorInfo.ResetHp((long)HP);
+//                 }
+//             }
+//             else
+//             {
+//                 PlayerDatas.Instance.hero.ActorInfo.ResetHp((long)HP);
+//             }
+//         }
+
+    }
+
+    // 姣斿璺ㄦ湇鏁版嵁鏇存柊鍚庯紝鐜╁鍥炲埌鏈湇浼氬悓姝ユ柊鏁版嵁锛岄渶鏇存柊
+    public void UpdateData(/*HA112_tagMCDBPlayer serverInfo*/)
+    {
+        // AccID = serverInfo.AccID;
+        // PlayerID = serverInfo.PlayerID;
+        // PlayerName = serverInfo.PlayerName.Trim().Replace("\0", "");
+        // GMLevel = serverInfo.GMLevel;
+        // Job = serverInfo.Job;
+        // LV = serverInfo.LV;
+        // ExpPoint = serverInfo.ExpPoint;
+        // TotalExp = serverInfo.TotalExp;
+        // FamilyId = serverInfo.Family;
+        // FamilyName = serverInfo.FamilyName.Trim().Replace("\0", "");
+        // diamond = serverInfo.Gold;
+        // bindDiamond = serverInfo.GoldPaper;
+        // copper = serverInfo.Silver;
+        // MapID = serverInfo.MapID;
+        // if (serverInfo.socketType == ServerType.Main)
+        // {
+        //     mainServerMapIdRecord = MapID;
+        // }
+        // PosX = serverInfo.PosX;
+        // PosY = serverInfo.PosY;
+        // FreePoint = serverInfo.FreePoint;
+        // FreeSkillPoint = serverInfo.FreeSkillPoint;
+        // STR = serverInfo.STR;
+        // PNE = serverInfo.PNE;
+        // PHY = serverInfo.PHY;
+        // CON = serverInfo.CON;
+        // AttackMode = serverInfo.AttackMode;
+        // FBID = serverInfo.FBID;
+        // ExAttr1 = serverInfo.ExAttr1;
+        // teamAutoOperateFlag = serverInfo.ExAttr2;
+        // dungeonLineId = (int)serverInfo.ExAttr3%1000;
+        // dungeonMapId = (int)serverInfo.ExAttr3 / 1000;
+        // shield = serverInfo.ExAttr4;
+        // CrossServerFlag = serverInfo.ExAttr5;
+        // realmLevel = serverInfo.OfficialRank;
+        // VIPLv = serverInfo.VIPLv;
+        // copperExtend = serverInfo.ExAttr6;
+        // sp = serverInfo.ExAttr7;
+        // spExtend = serverInfo.ExAttr8;
+        // bubbleId = serverInfo.ExAttr10;
+        // ExAttr11 = serverInfo.ExAttr11;
+        // ExAttr16 = serverInfo.ExAttr16;
+        // ServerGroupId = serverInfo.ExAttr13;
+        // faction = serverInfo.Faction;
+        // coinPointTotal = serverInfo.ChangeCoinPointTotal;
+        // HP = serverInfo.HP + serverInfo.HPEx * Constants.ExpPointValue;
+        // if (PlayerDatas.Instance.hero != null)
+        // {
+        //     PlayerDatas.Instance.hero.ActorInfo.ResetHp((long)HP);
+        // }
+        // equipShowSwitch = serverInfo.EquipShowSwitch;
+        // mapRealmSelect = (int)serverInfo.ExAttr18;
+        // leaveFamilyTime = (int)serverInfo.ExAttr19;
+        // face = (int)serverInfo.Face;
+        // facePic = (int)serverInfo.FacePic;
+    }
+
+
+}
diff --git a/Main/Core/GameEngine/Player/PlayerBaseData.cs.meta b/Main/Core/GameEngine/Player/PlayerBaseData.cs.meta
new file mode 100644
index 0000000..d88aa4c
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerBaseData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c642756ec29dbcb45815c8b260da2f13
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/GameEngine/Player/PlayerDatas.cs b/Main/Core/GameEngine/Player/PlayerDatas.cs
new file mode 100644
index 0000000..139b1cd
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerDatas.cs
@@ -0,0 +1,1064 @@
+锘縰sing UnityEngine;
+using System.Collections.Generic;
+using System;
+using LitJson;
+
+
+public class PlayerDatas : Singleton<PlayerDatas>
+{
+    // public GA_Hero hero = null;
+
+    // public H0309_tagPlayerLoginInfo loginInfo;
+    public uint PlayerId { get { return baseData.PlayerID; } }
+
+    PlayerBaseData m_Base = new PlayerBaseData();
+    public PlayerBaseData baseData { get { return m_Base; } }
+
+    PlayerExtersionData m_Extersion = new PlayerExtersionData();
+    public PlayerExtersionData extersion { get { return m_Extersion; } }
+
+    // public PlayerFairyData fairyData = new PlayerFairyData();
+
+    // PlayerSkillDatas m_Skill = new PlayerSkillDatas();
+    // public PlayerSkillDatas skill { get { return m_Skill; } }
+    // PlayerMethodData method { get { return ModelCenter.Instance.GetModel<PlayerMethodData>(); } }
+    // StoreModel StoreModel { get { return ModelCenter.Instance.GetModel<StoreModel>(); } }
+    // DungeonAssistModel assistModel { get { return ModelCenter.Instance.GetModel<DungeonAssistModel>(); } }
+
+    public int totalExpRate { get; set; }
+    public uint worldLv { get; private set; }
+    public uint worldExpRate { get; private set; }
+    public List<uint> maliciousAtkPlayer = new List<uint>();// 鍙戝姩鎭舵剰鏀诲嚮鐨勭帺瀹跺垪琛�
+    private int m_Tick;
+    public uint crossServerTick;
+    public uint changeLV = 0; //褰撳墠鍗噚绾�
+
+    public event Action worldLevelUpdateEvent;
+    public event Action<E_AttackMode> OnSwitchAttackMode;
+
+    public event Action playerDataUpdateEvent;    // 鏃犲尯鍒洿鏂帮紝鎱庣敤
+    public event Action<PlayerDataType> playerDataRefreshEvent;
+    public event Action<PlayerDataType, int> attributePromoteEvent;
+    public event Action<long> spNewGetEvent;
+
+
+    private Dictionary<PlayerDataType, ulong> PlayerDataDict = new Dictionary<PlayerDataType, ulong>();
+
+    public void InitPlayerData(/*H0102_tagCDBPlayer data*/)
+    {
+        // baseData.UpdateData(data);
+        // if (playerDataUpdateEvent != null)
+        // {
+        //     playerDataUpdateEvent();
+        // }
+    }
+
+    public void UpdatePlayerData(/*HA112_tagMCDBPlayer data*/)
+    {
+        // baseData.UpdateData(data);
+        // if (hero != null)
+        // {
+        //     hero.InitBornPos(baseData.PosX, baseData.PosY);
+        //     CameraController.Instance.Apply();
+        // }
+
+        // if (playerDataUpdateEvent != null)
+        // {
+        //     playerDataUpdateEvent();
+        // }
+    }
+
+    public void FightRefreshPlayerHp(ulong hp)
+    {
+        RefreshProperty(false, PlayerDataType.HP, (uint)(hp % Constants.ExpPointValue), (uint)(hp/Constants.ExpPointValue));
+
+        if (playerDataUpdateEvent != null)
+        {
+            playerDataUpdateEvent();
+        }
+
+        if (playerDataRefreshEvent != null)
+        {
+            playerDataRefreshEvent(PlayerDataType.HP);
+        }
+    }
+
+    public void RefreshPlayerData(/*H0418_tagObjInfoRefresh vNetData*/)
+    {
+        // UpdatePlayerData(vNetData);
+        // //StoreModel.RefreshTCBPlayerData(vNetData);
+        // if (playerDataUpdateEvent != null)
+        // {
+        //     playerDataUpdateEvent();
+        // }
+    }
+
+
+    private void UpdatePlayerData(int temp/*H0418_tagObjInfoRefresh vNetData*/)
+    {
+        // if (baseData != null && vNetData.ObjID == baseData.PlayerID)
+        // {
+        //     var deltaValue = -1; //鍙樺寲鍊肩敤浜庡鐞嗚〃鐜�
+        //     switch ((PlayerDataType)vNetData.RefreshType)
+        //     {
+        //         case PlayerDataType.MaxHP:
+        //             deltaValue = (int)(vNetData.Value + vNetData.ValueEx * Constants.ExpPointValue - extersion.MaxHP);
+        //             break;
+        //         case PlayerDataType.MAXATK:
+        //             deltaValue = (int)(vNetData.Value - extersion.MAXATK);
+        //             break;
+        //         case PlayerDataType.MINATK:
+        //             deltaValue = (int)(vNetData.Value - extersion.MINATK);
+        //             break;
+        //         case PlayerDataType.DEF:
+        //             deltaValue = (int)(vNetData.Value - extersion.DEF);
+        //             break;
+        //         case PlayerDataType.HIT:
+        //             deltaValue = (int)(vNetData.Value - extersion.HIT);
+        //             break;
+        //         case PlayerDataType.Miss:
+        //             deltaValue = (int)(vNetData.Value - extersion.Miss);
+        //             break;
+        //         case PlayerDataType.BattleValEx1:
+        //             deltaValue = (int)(vNetData.Value - extersion.battleValEx1);
+        //             break;
+        //         case PlayerDataType.SpeedValue:
+        //             deltaValue = (int)(vNetData.Value - extersion.SpeedValue);
+        //             break;
+        //         default:
+        //             deltaValue = -1;
+        //             break;
+        //     }
+
+        //     if (deltaValue > 0 && attributePromoteEvent != null)
+        //     {
+        //         attributePromoteEvent((PlayerDataType)vNetData.RefreshType, deltaValue);
+        //     }
+
+        //     RefreshProperty(vNetData.socketType == ServerType.Main, (PlayerDataType)vNetData.RefreshType, vNetData.Value, vNetData.ValueEx);
+
+        //     if (PlayerDataDict.ContainsKey((PlayerDataType)vNetData.RefreshType))
+        //     {
+        //         PlayerDataDict[(PlayerDataType)vNetData.RefreshType] = vNetData.Value + vNetData.ValueEx * Constants.ExpPointValue;
+        //     }
+        //     else
+        //     {
+        //         PlayerDataDict.Add((PlayerDataType)vNetData.RefreshType, vNetData.Value + vNetData.ValueEx * Constants.ExpPointValue);
+        //     }
+
+        //     if (playerDataRefreshEvent != null)
+        //     {
+        //         playerDataRefreshEvent((PlayerDataType)vNetData.RefreshType);
+        //     }
+        // }
+    }
+
+    public void RefreshProperty(bool isMainServerData, PlayerDataType _type, uint value, uint valueEx)
+    {
+        switch (_type)
+        {
+            case PlayerDataType.AccountID:
+                baseData.AccID = value.ToString();
+                break;
+            case PlayerDataType.PlayerID:
+                baseData.PlayerID = value;
+                break;
+            case PlayerDataType.PlayerName:
+                break;
+            case PlayerDataType.Sex:
+                break;
+            case PlayerDataType.Job:
+                baseData.Job = (byte)value;
+                break;
+            case PlayerDataType.LV:
+                if (baseData.LV != 0 && value > baseData.LV)
+                {
+                    //  TODO YYL 鍗囩骇鐗规晥
+                    // if (hero != null)
+                    // {
+                    //     if (PlayerDatas.Instance.baseData.MapID == 31080)
+                    //     {
+                    //         SFXPlayUtility.Instance.PlayBattleEffect(1156, hero);
+                    //     }
+                    //     else
+                    //     {
+                    //         SFXPlayUtility.Instance.PlayBattleEffect(1039, hero);
+                    //     }
+
+                    // }
+                }
+                changeLV = value - baseData.LV;
+                baseData.LV = (ushort)value;
+                if (changeLV > 0)
+                {
+                    SDKUtils.Instance.RoleLevelUp();
+                }
+                break;
+            case PlayerDataType.TotalExp:
+                baseData.TotalExp = value;
+                break;
+            case PlayerDataType.Family:
+                baseData.FamilyId = value;
+                if (LocalSave.GetInt("FimilyReport" + PlayerDatas.Instance.baseData.PlayerID) == 0)
+                { 
+                    SDKUtils.Instance.TraceEvent("joinalliance", "", false);
+                    LocalSave.SetInt("FimilyReport" + PlayerDatas.Instance.baseData.PlayerID, 1);
+                }
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.ActorInfo.familyID = value;
+                //     ReCheckAttackTarget();
+                // }
+                break;
+            case PlayerDataType.TeamHornor:
+                break;
+            case PlayerDataType.PKValue:
+                break;
+            case PlayerDataType.FamilyHornor:
+                break;
+            case PlayerDataType.FamilyActiveValue:
+                break;
+            case PlayerDataType.CountryHornor:
+                break;
+            case PlayerDataType.Mate:
+                break;
+            case PlayerDataType.Gold:
+                baseData.diamond = value;
+                break;
+            case PlayerDataType.GoldPaper:
+                baseData.bindDiamond = value;
+                break;
+            case PlayerDataType.Silver:
+                baseData.copper = value;
+                break;
+            case PlayerDataType.SilverPaper:
+                break;
+            case PlayerDataType.FightPoint:
+                break;
+            case PlayerDataType.HappyPoint:
+                break;
+            case PlayerDataType.MapID:
+                baseData.MapID = (ushort)value;
+                if (isMainServerData)
+                {
+                    baseData.mainServerMapIdRecord = baseData.MapID;
+                }
+                break;
+            case PlayerDataType.PosX:
+                baseData.PosX = (ushort)value;//瑙掕壊鍧愭爣x
+                break;
+            case PlayerDataType.PosY:
+                baseData.PosY = (ushort)value;//瑙掕壊鍧愭爣y
+                break;
+            case PlayerDataType.State:
+                break;
+            case PlayerDataType.MaxHP:
+                extersion.MaxHP = value + valueEx * Constants.ExpPointValue;
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.ActorInfo.ResetHp(-1, (long)extersion.MaxHP);
+                // }
+                break;
+            case PlayerDataType.HP:
+                if (CrossServerUtility.IsCrossServer())
+                {
+                    if (!isMainServerData)
+                    {
+                        baseData.HP = value + valueEx * Constants.ExpPointValue;
+                    }
+                }
+                else
+                {
+                    baseData.HP = value + valueEx * Constants.ExpPointValue;
+                }
+                break;
+            case PlayerDataType.MaxMP:
+                extersion.MaxMP = (int)value;
+                break;
+
+            case PlayerDataType.HPRestoreSetting:
+                break;
+            case PlayerDataType.MPRestoreSetting:
+                break;
+            case PlayerDataType.ExpRate:
+                extersion.ExpRate = (int)value;
+                break;
+            case PlayerDataType.DEF:
+                extersion.DEF = (int)value;
+                break;
+            case PlayerDataType.FreePoint:
+                baseData.FreePoint = value;
+                break;
+            case PlayerDataType.FreeSkillPoint:
+                baseData.FreeSkillPoint = value;
+                break;
+            case PlayerDataType.STR:
+                baseData.STR = (int)value;
+                break;
+            case PlayerDataType.PNE:
+                baseData.PNE = (int)value;
+                break;
+            case PlayerDataType.PHY:
+                baseData.PHY = (int)value;
+                break;
+            case PlayerDataType.CON:
+                baseData.CON = (int)value;
+                break;
+            case PlayerDataType.MINATK:
+                extersion.MINATK = (int)value;
+                break;
+            case PlayerDataType.MAXATK:
+                extersion.MAXATK = (int)value;
+                break;
+            case PlayerDataType.MAtkMin:
+                break;
+            case PlayerDataType.MAtkMax:
+                break;
+            case PlayerDataType.MDef:
+                break;
+            case PlayerDataType.HIT:
+                extersion.HIT = (int)value;
+                break;
+            case PlayerDataType.POISIONATK:
+                break;
+            case PlayerDataType.FIREATK:
+                break;
+            case PlayerDataType.REALATK:
+                extersion.realATK = (int)value;
+                break;
+            case PlayerDataType.THUNDERATK:
+                break;
+            case PlayerDataType.WINDATK:
+                break;
+            case PlayerDataType.POISIONDEF:
+                break;
+            case PlayerDataType.FIREDEF:
+                break;
+            case PlayerDataType.REALDEF:
+                extersion.realDEF = (int)value;
+                break;
+            case PlayerDataType.THUNDERDEF:
+                break;
+            case PlayerDataType.WINDDEF:
+                break;
+            case PlayerDataType.Miss:
+                extersion.Miss = (int)value;
+                break;
+            case PlayerDataType.SuperHit:
+                extersion.SuperHit = (int)value;
+                break;
+            case PlayerDataType.Buff:
+                break;
+            case PlayerDataType.Skill:
+                break;
+            case PlayerDataType.Mark:
+                break;
+            case PlayerDataType.SettingH:
+                break;
+            case PlayerDataType.SettingV:
+                break;
+            case PlayerDataType.FightPK:
+                break;
+            case PlayerDataType.ActiveValue:
+                break;
+            case PlayerDataType.NameColor:
+            case PlayerDataType.AtkInterval:
+                extersion.AtkInterval = (int)value;
+                break;
+            case PlayerDataType.Speed:
+                extersion.Speed = (int)value;
+                break;
+            case PlayerDataType.SuperHitRate:
+                extersion.SuperHitRate = (int)value;
+                break;
+            case PlayerDataType.PickupDist:
+                extersion.PickupDist = (int)value;
+                break;
+            case PlayerDataType.CountryLastWeekHornor:
+                break;
+            case PlayerDataType.LastWeekOnlineTime:
+                break;
+            case PlayerDataType.LastWeekFamilyActiveValue:
+                break;
+            case PlayerDataType.FBID:
+                baseData.FBID = (byte)value;
+                break;
+            case PlayerDataType.FamilyLV:
+                break;
+            case PlayerDataType.RealMapID:
+                extersion.RealMapID = (int)value;
+                break;
+            case PlayerDataType.GMLevel:
+                baseData.GMLevel = (byte)value;
+                break;
+            case PlayerDataType.TeamID:
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.ActorInfo.teamID = value;
+                //     ReCheckAttackTarget();
+                // }
+                break;
+            case PlayerDataType.TeamLV:
+                break;
+            case PlayerDataType.FightPower:
+                baseData.FightPoint = value + valueEx * Constants.ExpPointValue;
+                // TODO YYL
+                // ModelCenter.Instance.GetModel<PlayerMainDate>().PowerAdd(baseData.FightPoint);
+                break;
+            case PlayerDataType.RebornMapID:
+                break;
+            case PlayerDataType.RebornPosX:
+                break;
+            case PlayerDataType.RebornPosY:
+                break;
+            case PlayerDataType.Coin:
+                break;
+            case PlayerDataType.BillboardLV:
+                break;
+            case PlayerDataType.Tick:
+#if UNITY_EDITOR
+                Debug.LogFormat("---- 鏀跺埌鏈嶅姟绔疶ick: {0}", value);
+                if (isMainServerData)
+                {
+                    if (extersion.Tick != 0)
+                    {
+                        uint _curWorldTick = GetWorldTick();
+                        uint _diffValue = value > _curWorldTick ? value - _curWorldTick : _curWorldTick - value;
+                        Debug.LogFormat(" |-------- 褰撳墠瀹㈡埛绔疶ick: {0}, 宸紓: {1}", _curWorldTick, _diffValue);
+                        if (_diffValue > 5000)
+                        {
+                            Debug.LogFormat(" |-------- <color=red>鏀跺埌鏈嶅姟绔疻orldTick涓庡綋鍓嶇殑瀹㈡埛绔疶ick宸紓瓒呰繃5绉�</color>");
+                        }
+                    }
+                }
+                else
+                {
+                    if (crossServerTick != 0)
+                    {
+                        uint _curWorldTick = GetWorldTick();
+                        uint _diffValue = value > _curWorldTick ? value - _curWorldTick : _curWorldTick - value;
+                        Debug.LogFormat(" |-------- 褰撳墠瀹㈡埛绔疶ick: {0}, 宸紓: {1}", _curWorldTick, _diffValue);
+                        if (_diffValue > 5000)
+                        {
+                            Debug.LogFormat(" |-------- <color=red>鏀跺埌鏈嶅姟绔疻orldTick涓庡綋鍓嶇殑瀹㈡埛绔疶ick宸紓瓒呰繃5绉�</color>");
+                        }
+                    }
+                }
+#endif
+                if (isMainServerData)
+                {
+                    extersion.Tick = value;
+                }
+                else
+                {
+                    crossServerTick = value;
+                }
+                m_Tick = Environment.TickCount;
+
+                break;
+            case PlayerDataType.CurrentPlayerType:
+                break;
+            case PlayerDataType.FriendFavor:
+                break;
+            case PlayerDataType.BackpackLV:
+                break;
+            case PlayerDataType.ReincarnationLV:
+                break;
+            case PlayerDataType.BaseSTR:
+                break;
+            case PlayerDataType.BasePNE:
+                break;
+            case PlayerDataType.BasePHY:
+                break;
+            case PlayerDataType.BaseCON:
+                break;
+            case PlayerDataType.ReceivedSalary:
+                break;
+            case PlayerDataType.WarehouseLV:
+                break;
+            case PlayerDataType.EquipShowSwitch:
+                baseData.equipShowSwitch = value;
+                // TODO YYL
+//                 if (hero != null)
+//                 {
+//                     hero.SwitchSuit();
+//                     hero.ReqLingGenEffect((int)(baseData.equipShowSwitch / 10 % 100), (int)(baseData.equipShowSwitch / 1000 % 1000));
+//                     hero.horseAwakeId = (int)(value / 1000000);
+// #if UNITY_EDITOR
+//                     if (hero.horseAwakeId != 0)
+//                     {
+//                         Debug.LogFormat("鐜╁楠戝疇瑙夐啋ID鏀瑰彉: {0}", hero.horseAwakeId);
+//                     }
+// #endif
+//                 }
+                break;
+            case PlayerDataType.LuckValue:
+                extersion.luckValue = (int)value;
+                break;
+            case PlayerDataType.ExAttr1:
+                // TODO YYL
+                // if (hero != null && !hero.ActorInfo.serverDie)
+                // {
+                //     if (hero.aiHandler.IsAuto())
+                //     {
+                //         hero.Behaviour.StopHandupAI(true);
+                //     }
+                // }
+                baseData.ExAttr1 = value;
+                // TODO YYL
+                // if (baseData.ExAttr1 == 0)
+                //     assistModel.assistGUID = string.Empty;
+                break;
+            case PlayerDataType.ExAttr2:
+                baseData.teamAutoOperateFlag = value;
+                break;
+            case PlayerDataType.ExAttr3:
+                baseData.dungeonLineId = (int)value % 1000;
+                baseData.dungeonMapId = (int)value / 1000;
+                break;
+            case PlayerDataType.ExAttr4:
+                baseData.shield = value;
+                break;
+            case PlayerDataType.ExAttr5:
+                var oldExAttr5 = baseData.CrossServerFlag;
+                baseData.CrossServerFlag = value;
+
+                // TODO YYL
+                // if (oldExAttr5 > 2 && value <= 2)
+                // {
+                //     if (GameNetSystem.Instance.crossServerConnected_Loigc)
+                //     {
+                //         GameNetSystem.Instance.crossServerConnected_Loigc = false;
+                //         GameNetSystem.Instance.DisconnectCrossServer();
+
+                //         // TODO YYL
+                //         // if (hero != null)
+                //         // {
+                //         //     StatusMgr.Instance.ReleaseActor(hero.ServerInstID);
+                //         // }
+
+                //         extersion.pkState = 0;
+                //         baseData.MapID = baseData.mainServerMapIdRecord;
+                //         baseData.dungeonLineId = 0;
+                //         baseData.dungeonMapId = 0;
+                //         ModelCenter.Instance.GetModel<DungeonModel>().ResetBufData();
+
+                //         StageLoad.Instance.PushSceneLoadCommand(new StageLoad.StageLoadCommand()
+                //         {
+                //             toMapId = baseData.MapID,
+                //             toLineId = 0,
+                //             needEmpty = true,
+                //             needLoadResource = true,
+                //             serverType = ServerType.CrossSever,
+                //             isClientLoadMap = true,
+                //             refreshPlayerDatas = true
+                //         });
+                //     }
+                // }
+                break;
+            case PlayerDataType.Faction:
+                baseData.faction = value;
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.ActorInfo.faction = (int)value;
+                //     ReCheckAttackTarget();
+                //     hero.SetFairyLeagueHeadUp(baseData.MapID == FairyLeagueModel.FAIRY_LEAGUE_DUNGEON);
+                // }
+                break;
+            case PlayerDataType.InfamyValue:
+                break;
+            case PlayerDataType.RealmLevel:
+                baseData.realmLevel = (byte)value;
+                break;
+            case PlayerDataType.IsFindByLabel:
+                break;
+            case PlayerDataType.IsCloseFriendLabel:
+                break;
+            case PlayerDataType.ChangeCoinPointTotal:
+                baseData.coinPointTotal = value;
+                break;
+            case PlayerDataType.VIPLv:
+                // TODO YYL
+                // if (baseData.VIPLv <= 0 && value > 0)
+                // {
+                //     ModelCenter.Instance.GetModel<SetPrivateModel>().SetVipPushNotify((int)value);
+                // }
+                // else if (value <= 0)
+                // {
+                //     ModelCenter.Instance.GetModel<SetPrivateModel>().SetVipPushNotify(0);
+                // }
+                baseData.VIPLv = (byte)value;
+                break;
+            case PlayerDataType.ExAttr6:
+                baseData.copperExtend = value;
+                break;
+            case PlayerDataType.ExAttr7:
+                baseData.sp = value;
+                break;
+            case PlayerDataType.ExAttr8:
+                baseData.spExtend = value;
+                break;
+            case PlayerDataType.ExAttr9:
+                break;
+            case PlayerDataType.ExAttr10:
+                baseData.bubbleId = value;
+                break;
+            case PlayerDataType.ModelMark:
+                break;
+            case PlayerDataType.PrizeCoin:
+                break;
+            case PlayerDataType.ExAttr11:
+                baseData.ExAttr11 = value;
+                break;
+            case PlayerDataType.ExAttr12:
+                break;
+            case PlayerDataType.ExAttr13:
+                baseData.ServerGroupId = value;
+                break;
+            case PlayerDataType.ExAttr14:
+                break;
+            case PlayerDataType.BattleValEx1:
+                extersion.battleValEx1 = (int)value;
+                //  TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.CalculateAtkSpeed((ushort)extersion.battleValEx1);
+                // }
+                break;
+            case PlayerDataType.BattleValEx3:
+                extersion.battleValEx3 = (int)value;
+                break;
+            case PlayerDataType.DamageReduceRate:
+                extersion.damageReduceRate = (int)value;
+                break;
+            case PlayerDataType.LuckyHitRate:
+                extersion.luckHitRate = (int)value;
+                break;
+            case PlayerDataType.LuckyHitVal:
+                extersion.luckHitVal = (int)value;
+                break;
+            case PlayerDataType.ExpPoint:
+                baseData.ExpPoint = value;
+                break;
+            case PlayerDataType.Rune:
+                extersion.runeChip = (int)value;
+                break;
+            case PlayerDataType.RuneSplinters:
+                extersion.runeEssence = (int)value;
+                break;
+            case PlayerDataType.FamilyContribution:
+                // TODO YYL
+                // method.CepaContribution((int)value);
+                break;
+            case PlayerDataType.FamilyStoreScore:
+                break;
+            case PlayerDataType.SuperHitReduce:
+                extersion.SuperHitReduce = (int)value;
+                break;
+            case PlayerDataType.LuckyHitRateReduce:
+                extersion.LuckyHitRateReduce = (int)value;
+                break;
+            case PlayerDataType.SkillAtkRateReduce:
+                extersion.skillAtkRateReduce = (int)value;
+                break;
+            case PlayerDataType.SkillAtkRate:
+                extersion.SkillAtkRate = (int)value;
+                break;
+            case PlayerDataType.DamagePVP:
+                extersion.DamagePVP = (int)value;
+                break;
+            case PlayerDataType.HPRestorePer:
+                extersion.HPRestorePer = (int)value;
+                break;
+            case PlayerDataType.DamageBackRate:
+                extersion.DamageBackRate = (int)value;
+                break;
+            case PlayerDataType.SpeedValue:
+                extersion.SpeedValue = (int)value;
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     hero.CalculateMoveSpeed((ushort)extersion.SpeedValue);
+                // }
+                break;
+            case PlayerDataType.DamagePVE:
+                break;
+            case PlayerDataType.PetDamPer:
+                extersion.PetDamPer = (int)value;
+                break;
+            case PlayerDataType.IgnoreDefRate:
+                extersion.IgnoreDefRate = (int)value;
+                break;
+            case PlayerDataType.IgnoreDefRateReduce:
+                extersion.IgnoreDefRateReduce = (int)value;
+                break;
+            case PlayerDataType.DamChanceDef:
+                extersion.DamChanceDef = (int)value;
+                break;
+            case PlayerDataType.BleedDamage:
+                extersion.BleedDamage = (int)value;
+                break;
+            case PlayerDataType.BattleValEx2:
+                extersion.BattleValEx2 = (int)value;
+                break;
+            case PlayerDataType.FaintRate:
+                extersion.FaintRate = (int)value;
+                break;
+            case PlayerDataType.FaintDefRate:
+                extersion.FaintDefRate = (int)value;
+                break;
+            case PlayerDataType.FinalHurt:
+                extersion.FinalHurt = (int)value;
+                break;
+            case PlayerDataType.FinalHurtReduce:
+                extersion.FinalHurtReduce = (int)value;
+                break;
+            case PlayerDataType.DamagePerPVP:
+                extersion.DamagePerPVP = (int)value;
+                break;
+            case PlayerDataType.DamagePerPVPReduce:
+                extersion.DamagePerPVPReduce = (int)value;
+                break;
+            case PlayerDataType.ComboDamPer:
+                extersion.ComboDamPer = (int)value;
+                break;
+            case PlayerDataType.MaxProDef:
+                extersion.MaxProDef = (int)value;
+                break;
+            case PlayerDataType.ComboDamRate:
+                extersion.ComboDamPerRate = (int)value;
+                break;
+            case PlayerDataType.RealmPoint:
+                extersion.realmPoint = (int)value;
+                break;
+            case PlayerDataType.MagicEssence:
+                extersion.magicEssence = (int)value;
+                break;
+            case PlayerDataType.PlayerPKState:
+                extersion.pkState = (int)value;
+                // TODO YYL
+
+                // if (baseData.MapID != 31220
+                //  && baseData.MapID != 32030
+                //  && baseData.MapID != 22030)
+                // {
+                //     if (hero != null)
+                //     {
+                //         if (value == 1)
+                //         {
+                //             if (MapArea.IsOutMapArea(hero.CurMapArea, MapArea.E_Type.Neutral))
+                //             {
+                //                 hero.SwitchGrayName(true);
+                //             }
+                //         }
+                //         else if (value == 0)
+                //         {
+                //             hero.SwitchGrayName(false);
+                //             if (StatusMgr.Instance.IsExist(PlayerId, StatusMgr.Instance.redNameBuffID))
+                //             {
+                //                 hero.SwitchRedName(true);
+                //             }
+                //         }
+                //     }
+                // }
+                break;
+            case PlayerDataType.IsAttackBossState:
+                extersion.bossState = (int)value;
+                // TODO YYL
+                // if (hero != null)
+                // {
+                //     if (extersion.bossState == 0)
+                //     {
+                //         hero.atkBossID = 0;
+                //     }
+                // }
+                break;
+            case PlayerDataType.BasicsMinimum:
+                baseData.BasicsMinimum = (int)value;
+                break;
+            case PlayerDataType.BasicsMaxAttack:
+                baseData.BasicsMaxAttack = (int)value;
+                break;
+            case PlayerDataType.BasicsLife:
+                baseData.BasicsLife = (int)value;
+                break;
+            case PlayerDataType.BasicsDefense:
+                baseData.BasicsDefense = (int)value;
+                break;
+            case PlayerDataType.BasicsScoreAHit:
+                baseData.BasicsScoreAHit = (int)value;
+                break;
+            case PlayerDataType.BasicsDodge:
+                baseData.BasicsDodge = (int)value;
+                break;
+            case PlayerDataType.OnlyFinalHurt:
+                extersion.OnlyFinalHurt = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_NPCHurtAddPer:
+                extersion.NpcHurtAddPer = (int)value;
+                break;
+            case PlayerDataType.FunalHurtPer:
+                extersion.FunalHurtPer = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_ForbidenTalk:
+                extersion.forbidenTalk = (int)value;
+                //涓庢湇鍔$绾﹀畾 0 鍗曡鑹茶В灏� 1 鍗曡鑹茬瑷�锛�2璁惧绂佽█锛�3璁惧瑙e皝
+                if (value == 2)
+                {
+                    LocalSave.SetBool("ServerForbidenChatDevice1", true);
+                }
+                else if (value == 3)
+                {
+                    //浠绘剰璐﹀彿瑙e皝
+                    LocalSave.SetBool("ServerForbidenChatDevice1", false);
+                }
+                //ModelCenter.Instance.GetModel<ChatCenter>().ServerForbidenChat(extersion.forbidenTalk == 1);
+                break;
+            case PlayerDataType.CDBPlayerRefresh_TalentPoint:
+                extersion.talentPoint = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_GodWeaponLV_1:
+                break;
+            case PlayerDataType.CDBPlayerRefresh_GodWeaponLV_2:
+                break;
+            case PlayerDataType.CDBPlayerRefresh_GodWeaponLV_3:
+                break;
+            case PlayerDataType.CDBPlayerRefresh_GodWeaponLV_4:
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SoulDust:
+                extersion.soulDust = value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SoulSplinters:
+                extersion.soulSplinters = value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SoulCore:
+                extersion.soulCore = value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Honor:
+                extersion.honorValue = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_ZhuxianRate:
+                baseData.ExAttr16 = value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Mater:
+                baseData.mater = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Wood:
+                baseData.wood = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Water:
+                baseData.water = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Fire:
+                baseData.fire = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_Earth:
+                baseData.earth = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_NormalHurt:
+                baseData.NormalHurt = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_NormalHurtPer:
+                baseData.NormalHurtPer = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_FabaoHurt:
+                baseData.FabaoHurt = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_FabaoHurtPer:
+                baseData.FabaoHurtPer = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SuperHitRateReduce:
+                baseData.reduceCrit = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_LuckyHitReduce:
+                baseData.reduceHeartHurt = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_FinalHurtReducePer:
+                baseData.reduceFinalHurt = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_YinjiTime:
+                baseData.yinjiTime = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_YinjiCount:
+                baseData.yinjiCount = (int)value;
+                break;
+
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerA:
+                baseData.skillAddPerA = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerB:
+                baseData.skillAddPerB = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerC:
+                baseData.skillAddPerC = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerD:
+                baseData.skillAddPerD = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerE:
+                baseData.skillAddPerE = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerF:
+                baseData.skillAddPerF = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillAddPerG:
+                baseData.skillAddPerG = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerA:
+                baseData.skillReducePerA = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerB:
+                baseData.skillReducePerB = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerC:
+                baseData.skillReducePerC = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerD:
+                baseData.skillReducePerD = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerE:
+                baseData.skillReducePerE = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerF:
+                baseData.skillReducePerF = (int)value;
+                break;
+            case PlayerDataType.CDBPlayerRefresh_SkillReducePerG:
+                baseData.skillReducePerG = (int)value;
+                break;
+            case PlayerDataType.default9:
+                baseData.mapRealmSelect = (int)value;
+                break;
+            case PlayerDataType.default10:
+                baseData.leaveFamilyTime = (int)value;
+                break;
+
+        }
+    }
+
+    public ulong GetPlayerDataByType(PlayerDataType type)
+    {
+        ulong value = 0;
+        PlayerDataDict.TryGetValue(type, out value);
+        return value;
+    }
+
+    public void ClearPlayerData()
+    {
+        PlayerDataDict.Clear();
+    }
+
+    public void OnRefreshWorldLV(uint worldLv, uint worldExpRate)
+    {
+        this.worldLv = worldLv;
+        this.worldExpRate = worldExpRate;
+        if (worldLevelUpdateEvent != null)
+        {
+            worldLevelUpdateEvent();
+        }
+    }
+
+    public void OnRecv_SwitchAttackMode(byte attackMode)
+    {
+        // baseData.AttackMode = attackMode;
+        // if (OnSwitchAttackMode != null)
+        // {
+        //     OnSwitchAttackMode((E_AttackMode)attackMode);
+        // }
+
+        // if (hero == null)
+        // {
+        //     return;
+        // }
+
+        // ReCheckAttackTarget();
+    }
+
+    public void ReCheckAttackTarget(/*GA_Player _player = null*/)
+    {
+        // if (hero == null)
+        // {
+        //     return;
+        // }
+
+        // if (_player == null)
+        // {
+        //     _player = hero.SelectTarget as GA_Player;
+        // }
+
+        // if (_player != null)
+        // {
+        //     if (_player.CanAtked())
+        //     {
+        //         SelectionManager.Request(SelectionManager.E_Type.Red, _player);
+        //     }
+        //     else
+        //     {
+        //         SelectionManager.Request(SelectionManager.E_Type.Green, _player);
+
+        //         if (hero.aiHandler.IsAuto())
+        //         {
+        //             hero.LockTarget = null;
+        //         }
+        //         else if (hero.aiHandler.currentType == E_HeroAIType.KillUntilDie)
+        //         {
+        //             hero.Behaviour.StopKillUntilDieAI();
+        //         }
+        //     }
+        // }
+
+        // hero.SwitchTarget();
+    }
+
+    /// <summary>
+    /// 鏄惁鏄澶�, 杩欓噷鐨勮澶囨寚鐨勬槸: 姝﹀櫒, 甯藉瓙, 琛f湇, 涓嬭, 闉嬪瓙, 鑵板甫
+    /// </summary>
+    /// <returns></returns>
+    public bool IsEquip(ItemType itemType)
+    {
+        return itemType >= ItemType.Equip_Weapon && itemType <= ItemType.Equip_Shoes;
+    }
+
+    public void RequestWorldTick()
+    {
+        // TODO YYL
+        // CA102_tagCMWorldTick _proto = new CA102_tagCMWorldTick();
+        // if (CrossServerUtility.IsCrossServer())
+        // {
+        //     GameNetSystem.Instance.SendToCrossServer(_proto);
+        // }
+        // else
+        // {
+        //     GameNetSystem.Instance.SendInfo(_proto);
+        // }
+    }
+
+    public void ClearTick()
+    {
+        extersion.Tick = 0;
+        crossServerTick = 0;
+    }
+
+    public bool IsTickVaild()
+    {
+        if (CrossServerUtility.IsCrossServer())
+        {
+            return crossServerTick != 0;
+        }
+        else
+        {
+            return extersion.Tick != 0;
+        }
+    }
+
+    public uint GetWorldTick()
+    {
+        int _currentTick = Environment.TickCount - m_Tick;
+        uint _tick = CrossServerUtility.IsCrossServer() ? crossServerTick + (uint)_currentTick : extersion.Tick + (uint)_currentTick;
+        return _tick;
+    }
+
+}
diff --git a/Main/Core/GameEngine/Player/PlayerDatas.cs.meta b/Main/Core/GameEngine/Player/PlayerDatas.cs.meta
new file mode 100644
index 0000000..f4a733f
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerDatas.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bb823040e2024914599f8c0b3ab148a3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/GameEngine/Player/PlayerExtersionData.cs b/Main/Core/GameEngine/Player/PlayerExtersionData.cs
new file mode 100644
index 0000000..65f51cb
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerExtersionData.cs
@@ -0,0 +1,71 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PlayerExtersionData
+{
+    public ulong MaxHP;             // 鏈�澶P    28,
+    public int MaxMP;              // 鏈�澶P    30,
+    public int ExpRate;            // 褰撳墠缁忛獙鍊嶇巼    鍗曚綅涓虹櫨鍒嗘瘮  35,
+    public int DEF;                // 澶栭槻     42
+    public int MINATK;             // 澶栨敾鏈�灏� 43
+    public int MAXATK;             // 澶栨敾鏈�澶� 44
+    public int HIT;                // 鍛戒腑 48
+    public int realATK;                  //鐪熷疄浼ゅ锛�51
+    public int realDEF;              //鐪熷疄鎶垫姉锛�56
+    public int Miss;               // 闂伩   59,
+    public int SuperHit;           // 鏆村嚮浼ゅ 60,
+    public int AtkInterval;        // 鏀诲嚮閫熷害 70,
+    public int Speed;              // 閫熷害   71,
+    public int SuperHitRate;        // 鑷村懡涓�鍑荤殑鍑犵巼 72,
+    public int PickupDist;         // 鎷惧彇璺濈 73,
+    public int RealMapID;          // 鏁版嵁鍦板浘ID   79,
+    public uint Tick;               // 褰撳墠Tick   89,
+    public int luckValue;         //姘旇繍 101
+    public int battleValEx1;       // <鏀婚��  136
+    public int battleValEx3;       // <鍑忓皯鎵�鏈夋妧鑳紺D  138
+    public int damageReduceRate;  // <鍑忓皯浼ゅ  132
+    public int SkillAtkRate;       // <鎶�鑳戒激瀹�  125
+    public int luckHitRate;// <浼氬績涓�鍑绘満鐜�  126
+    public int luckHitVal;// <浼氬績涓�鍑讳激瀹�  127
+    public int DamageBackRate;// 浼ゅ鍙嶅皠 133
+    public int HPRestorePer; //鐢熷懡鍥炲 141
+    public int SuperHitReduce;     // 鏆村嚮鎶楁�� 146,
+    public int LuckyHitRateReduce;  // 浼氬績涓�鍑绘姉鎬� 147,
+    public int skillAtkRateReduce; //鎶�鑳藉噺浼� 148,
+    public int DamagePVP;           //澧炲姞浼ゅ 149
+    public int SpeedValue;//绉诲姩閫熷害 150
+    public int DamagePVE;           //澧炲姞浼ゅ 151
+    public int IgnoreDefRate;   //鏃犺闃插尽 135
+    public int IgnoreDefRateReduce;//鏃犺闃插尽鎶楁�� 153
+    public int DamChanceDef; //鎶靛尽 154
+    public int BleedDamage;//娴佽浼ゅ 155
+    public int BattleValEx2;//鏀诲嚮鍥炶 137
+    public int FaintRate;//鍑绘檿 156
+    public int FaintDefRate;//鎺у埗鎶垫姉157
+    public int FinalHurt;//杈撳嚭浼ゅ158
+    public int FinalHurtReduce;//鍑忓皯鎵垮彈浼ゅ159
+    public int DamagePerPVP;//PVP浼ゅ澧炲姞160
+    public int DamagePerPVPReduce;//PVP浼ゅ鍑忓皯161
+    public int ComboDamPerRate;//杩炲嚮鍑犵巼162
+    public int ComboDamPer;//杩炲嚮浼ゅ163
+    public int MaxProDef;//鏈�澶ч槻鎶ゅ�� 164
+    public int PetDamPer;  //鐏靛吔澧炲姞浼ゅ 152
+    public int runeEssence;//绗﹀嵃绮惧崕 169
+    public int runeChip;//绗﹀嵃纰庣墖 170
+    public int realmPoint;//澧冪晫淇偧鐐� 171
+    public int magicEssence;//榄旂簿
+    public int pkState;//鏄惁鍦╬k涓� 175 1--杩涘叆鐘舵�� 2--閫�鍑虹姸鎬�
+    public int bossState;//Boss鐘舵��  176 1--杩涘叆鐘舵�� 2--閫�鍑虹姸鎬�
+    public int OnlyFinalHurt;
+    public int forbidenTalk;
+    public int NpcHurtAddPer;//瀵规�墿浼ゅ鍔犳垚 188
+    public int FunalHurtPer;//瀵规�墿浼ゅ鍔犳垚 189
+    public int talentPoint;//澶╄祴鐐规暟 190
+    public uint soulDust;//鑱氶瓊-榄傚皹 196
+    public uint soulSplinters;//鑱氶瓊-纰庣墖 197
+    public uint soulCore;//鑱氶瓊-鏍稿績鐜� 198
+    public int honorValue; //鑽h獕鍊� 199
+    public int zhuxianRate;// 璇涗粰涓�鍑绘鐜�
+    public int zhuxianHurtPer;// 璇涗粰涓�鍑讳激瀹冲��
+}
diff --git a/Main/Core/GameEngine/Player/PlayerExtersionData.cs.meta b/Main/Core/GameEngine/Player/PlayerExtersionData.cs.meta
new file mode 100644
index 0000000..7752a4e
--- /dev/null
+++ b/Main/Core/GameEngine/Player/PlayerExtersionData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dec96d5f276b0b747aef168cae1c172e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login.meta b/Main/Login.meta
new file mode 100644
index 0000000..8bc1ba1
--- /dev/null
+++ b/Main/Login.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 07397eca392dcce41b8e20345535c569
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ClientVersion.meta b/Main/Login/ClientVersion.meta
new file mode 100644
index 0000000..76dea86
--- /dev/null
+++ b/Main/Login/ClientVersion.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fd7ab97ad3c29994d9aee3496ff38f4e
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ClientVersion/VersionConfig.cs b/Main/Login/ClientVersion/VersionConfig.cs
new file mode 100644
index 0000000..e7d86be
--- /dev/null
+++ b/Main/Login/ClientVersion/VersionConfig.cs
@@ -0,0 +1,352 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using LitJson;
+
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+[CreateAssetMenu(menuName = "Config/VersionConfig")]
+
+public class VersionConfig : ScriptableObject
+{
+    public const string VERSION_ALTERNATIVE = "1.0.0";
+
+    [SerializeField] public string m_AppId = string.Empty;
+    public string appId
+    {
+        get
+        {
+            if (!string.IsNullOrEmpty(SDKUtils.Yj_AppID))
+            {
+                return SDKUtils.Yj_AppID;
+            }
+            return m_AppId;
+        }
+    }
+
+    [SerializeField] public string m_SpID = string.Empty;
+    public string SpID
+    {
+        get
+        {
+            if (!string.IsNullOrEmpty(SDKUtils.Yj_SpID))
+            {
+                return SDKUtils.Yj_SpID;
+            }
+            return m_SpID;
+        }
+    }
+
+    [SerializeField] VersionAuthority m_VersionAuthority;
+    public VersionAuthority versionAuthority { get { return m_VersionAuthority; } }
+
+    [SerializeField] public string m_Version;
+    public string version { get { return VersionCompare(m_Version, VERSION_ALTERNATIVE); } }
+
+    [SerializeField] string m_ClientPackageFlag;
+    public string clientPackageFlag { get { return m_ClientPackageFlag; } }
+
+    [SerializeField] int m_Branch = 0;
+    public int branch
+    {
+        get
+        {
+            if (DebugUtility.Instance.debugBranch >= 0)
+            {
+                return DebugUtility.Instance.debugBranch;
+            }
+            else
+            {
+                return m_Branch;
+            }
+        }
+    }
+
+    string m_GameId = string.Empty;
+    public string gameId
+    {
+        get
+        {
+            if (string.IsNullOrEmpty(m_GameId))
+            {
+                var gameText = Resources.Load<TextAsset>("Game");
+                if (gameText != null)
+                {
+                    m_GameId = gameText.text;
+                }
+                else
+                {
+                    m_GameId = "xbqy";
+                }
+            }
+
+            return m_GameId;
+        }
+    }
+
+    [SerializeField] InstalledAsset m_AssetAccess = InstalledAsset.IngoreDownLoad;
+    public InstalledAsset assetAccess { get { return m_AssetAccess; } set { m_AssetAccess = value; } }
+
+    [SerializeField] bool m_PartAssetPackage = false;
+    public bool partAssetPackage { get { return m_PartAssetPackage; } set { m_PartAssetPackage = value; } }
+
+    [SerializeField] string m_ProductName = string.Empty;
+    public string productName { get { return m_ProductName; } }
+
+    [SerializeField] string m_BundleIdentifier = string.Empty;
+    public string bundleIdentifier { get { return m_BundleIdentifier; } }
+
+    [SerializeField] string m_KeystoreFileName;
+    public string keystoreFileName { get { return m_KeystoreFileName; } }
+
+    [SerializeField] string m_KeystorePassword;
+    public string keystorePassword { get { return m_KeystorePassword; } }
+
+    [SerializeField] string m_KeystoreAlias;
+    public string keystoreAlias { get { return m_KeystoreAlias; } }
+
+    [SerializeField] string m_KeystoreAliasPassword;
+    public string keystoreAliasPassword { get { return m_KeystoreAliasPassword; } }
+
+    [SerializeField] string m_AppleDeveloperTeamID;
+    public string appleDeveloperTeamID { get { return m_AppleDeveloperTeamID; } }
+
+    [SerializeField] bool m_DebugVersion = false;
+    public bool debugVersion
+    {
+        get { return m_DebugVersion; }
+        set { m_DebugVersion = value; }
+    }
+
+    [SerializeField] bool m_IsBanShu = false;
+    public bool isBanShu
+    {
+        get { return m_IsBanShu; }
+        set { m_IsBanShu = value; }
+    }
+
+    [SerializeField] string m_BuildTime;
+    public string buildTime
+    {
+        get { return m_BuildTime; }
+        set { m_BuildTime = value; }
+    }
+
+    [SerializeField] int m_BuildIndex;
+    public int buildIndex
+    {
+        get { return m_BuildIndex; }
+        set { m_BuildIndex = value; }
+    }
+
+    [SerializeField] Vector2 m_LogoPosition;
+    public Vector2 logoPosition { get { return m_LogoPosition; } }
+
+    [SerializeField] string m_BanHao;
+    public string banHao
+    {
+        get
+        {
+            if (!string.IsNullOrEmpty(SDKUtils.Yj_BanHao))
+            {
+                return SDKUtils.Yj_BanHao;
+            }
+            return m_BanHao;
+        }
+    }
+
+    // 鎵撳寘鏃秙dk鏂囦欢鍚嶏紝鏈夐厤缃彇杩欎釜鍚嶅瓧锛屾病閰嶇疆鐢╝ppid锛岀敤浜庡悓涓�涓猘ppid鐗堟湰sdk涓嶅悓鐨勬儏鍐�
+    // 鎵撳寘璇诲彇鐨刲ogo鐩綍涓嶅悓锛屽畨鍗撴湁涓や釜sdk
+    [SerializeField] string m_SdkFileName;
+    public string sdkFileName
+    {
+        get { return m_SdkFileName; }
+        set { m_SdkFileName = value; }
+    }
+
+    public void Read(string _data)
+    {
+        var dataStrings = _data.Split('\t');
+        try
+        {
+            m_AppId = dataStrings[2];
+            m_VersionAuthority = (VersionAuthority)int.Parse(dataStrings[3]);
+            m_Version = dataStrings[4];
+            m_ClientPackageFlag = dataStrings[5];
+            m_Branch = int.Parse(dataStrings[6]);
+            m_AssetAccess = (InstalledAsset)int.Parse(dataStrings[8]);
+            m_PartAssetPackage = int.Parse(dataStrings[9]) == 1;
+            m_ProductName = dataStrings[10];
+            m_BundleIdentifier = dataStrings[11];
+            m_KeystoreFileName = dataStrings[12];
+            m_KeystorePassword = dataStrings[13];
+            m_KeystoreAlias = dataStrings[14];
+            m_KeystoreAliasPassword = dataStrings[15];
+            m_AppleDeveloperTeamID = dataStrings[16];
+            m_DebugVersion = int.Parse(dataStrings[17]) == 1;
+            m_IsBanShu = int.Parse(dataStrings[18]) == 1;
+            m_LogoPosition = dataStrings[19].Vector3Parse();
+            m_BanHao = dataStrings[20];
+            m_SpID = dataStrings[21];
+            m_SdkFileName = dataStrings[24];
+        }
+        catch (System.Exception ex)
+        {
+            Debug.Log(ex);
+        }
+    }
+
+    static VersionConfig config = null;
+    public static VersionConfig Get()
+    {
+        if (config == null)
+        {
+            if (Application.isEditor)
+            {
+                config = Resources.Load<VersionConfig>("VersionConfig");
+                //debug鐧诲綍鍚庣浜屾鍚姩榛樿鎭㈠test
+                if (LocalSave.GetBool("RestoreTest"))
+                {
+                    config.m_AppId = "test";
+                    LocalSave.SetBool("RestoreTest", false);
+                    Debug.Log("appid 鎭㈠test");
+                }
+
+            }
+            else
+            {
+                var text = Resources.Load<TextAsset>("VersionConfigEx");
+                if (text != null)
+                {
+                    config = ScriptableObject.CreateInstance<VersionConfig>();
+                    var json = JsonMapper.ToObject(text.text);
+                    ReadJson(json);  //閫愪竴瑙f瀽锛屼笉鐢╒ersionConfig绫荤粨鏋勮鍙栵紝鍥犱负鍙橀噺瀹氫箟鏄寜asset鐨勭粨鏋勫畾涔夌殑
+                }
+            }
+        }
+
+        return config;
+    }
+
+    public static void ReadJson(JsonData _data)
+    {
+        try
+        {
+            config.m_AppId = _data["m_AppId"].ToString();
+            config.m_VersionAuthority = (VersionAuthority)int.Parse(_data["m_VersionAuthority"].ToString());
+            config.m_Version = _data["m_Version"].ToString();
+            config.m_ClientPackageFlag = _data["m_ClientPackageFlag"].ToString();
+            config.m_Branch = int.Parse(_data["m_Branch"].ToString());
+            config.m_AssetAccess = (InstalledAsset)int.Parse(_data["m_AssetAccess"].ToString());
+            config.m_PartAssetPackage = (bool)_data["m_PartAssetPackage"];
+            config.m_ProductName = _data["m_ProductName"].ToString();
+            config.m_BundleIdentifier = _data["m_BundleIdentifier"].ToString();
+            config.m_KeystoreFileName = _data["m_KeystoreFileName"].ToString();
+            config.m_KeystorePassword = _data["m_KeystorePassword"].ToString();
+            config.m_KeystoreAlias = _data["m_KeystoreAlias"].ToString();
+            config.m_KeystoreAliasPassword = _data["m_KeystoreAliasPassword"].ToString();
+            config.m_AppleDeveloperTeamID = _data["m_AppleDeveloperTeamID"].ToString();
+            config.m_DebugVersion = (bool)_data["m_DebugVersion"];
+            config.m_IsBanShu = (bool)_data["m_IsBanShu"];
+            config.m_LogoPosition = JsonMapper.ToObject<Vector2>(_data["m_LogoPosition"].ToJson());
+            config.m_BanHao = _data["m_BanHao"].ToString();
+            config.m_SpID = _data["m_SpID"].ToString();
+            config.m_BuildIndex = int.Parse(_data["m_BuildIndex"].ToString());
+            config.m_BuildTime = _data["m_BuildTime"].ToString();
+            config.m_SdkFileName = _data["m_SdkFileName"].ToString();
+
+            Debug.Log("VersionConfig ReadJson Success");
+        }
+        catch (System.Exception ex)
+        {
+            Debug.Log(ex);
+        }
+    }
+
+    public static void Copy(VersionConfig _from, VersionConfig _to)
+    {
+        _to.m_VersionAuthority = _from.m_VersionAuthority;
+        _to.m_Version = _from.m_Version;
+        _to.m_AppId = _from.m_AppId;
+        _to.m_Branch = _from.m_Branch;
+        _to.m_AssetAccess = _from.m_AssetAccess;
+        _to.m_PartAssetPackage = _from.m_PartAssetPackage;
+        _to.m_BuildTime = _from.m_BuildTime;
+        _to.m_DebugVersion = _from.m_DebugVersion;
+        _to.m_ProductName = _from.m_ProductName;
+        _to.m_BundleIdentifier = _from.m_BundleIdentifier;
+        _to.m_KeystoreFileName = _from.m_KeystoreFileName;
+        _to.m_KeystoreAlias = _from.m_KeystoreAlias;
+        _to.m_KeystorePassword = _from.m_KeystorePassword;
+        _to.m_KeystoreAliasPassword = _from.m_KeystoreAliasPassword;
+        _to.m_AppleDeveloperTeamID = _from.m_AppleDeveloperTeamID;
+        _to.m_IsBanShu = _from.m_IsBanShu;
+        _to.m_ClientPackageFlag = _from.m_ClientPackageFlag;
+        _to.m_LogoPosition = _from.m_LogoPosition;
+        _to.m_BanHao = _from.m_BanHao;
+        _to.m_SpID = _from.m_SpID;
+        _to.m_SdkFileName = _from.m_SdkFileName;
+    }
+
+    /// <summary>
+    /// 姣旇緝涓や釜鐗堟湰锛岃繑鍥炴洿澶х殑閭d釜
+    /// </summary>
+    /// <param name="_lhs"></param>
+    /// <param name="_rhs"></param>
+    /// <returns></returns>
+    static string VersionCompare(string _lhs, string _rhs)
+    {
+        var lhsStrings = _lhs.Split('.');
+        var rhsStrings = _rhs.Split('.');
+
+        if (lhsStrings.Length > rhsStrings.Length)
+        {
+            return _lhs;
+        }
+        else if (lhsStrings.Length < rhsStrings.Length)
+        {
+            return _rhs;
+        }
+        else
+        {
+            var version1 = 0;
+            for (int i = 0; i < lhsStrings.Length; i++)
+            {
+                var input = lhsStrings[i];
+                var intTemp = 0;
+                int.TryParse(input, out intTemp);
+                version1 += intTemp * MathUtility.Power(1000, lhsStrings.Length - 1 - i);
+            }
+
+            var version2 = 0;
+            for (int i = 0; i < rhsStrings.Length; i++)
+            {
+                var input = rhsStrings[i];
+                var intTemp = 0;
+                int.TryParse(input, out intTemp);
+                version2 += intTemp * MathUtility.Power(1000, rhsStrings.Length - 1 - i);
+            }
+
+            return version1 > version2 ? _lhs : _rhs;
+        }
+    }
+
+    public static int GetVersionNumber(string version)
+    {
+        var numberStrings = version.Split('.');
+        var number = 0;
+
+        for (var i = 0; i < Mathf.Min(numberStrings.Length, 3); i++)
+        {
+            var temp = 0;
+            int.TryParse(numberStrings[i], out temp);
+            number += temp * MathUtility.Power(1000, 2 - i);
+        }
+
+        return number;
+    }
+
+}
diff --git a/Main/Login/ClientVersion/VersionConfig.cs.meta b/Main/Login/ClientVersion/VersionConfig.cs.meta
new file mode 100644
index 0000000..f228f0d
--- /dev/null
+++ b/Main/Login/ClientVersion/VersionConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e797e662113028e4cb1c302969102134
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ClientVersion/VersionUtility.cs b/Main/Login/ClientVersion/VersionUtility.cs
new file mode 100644
index 0000000..9fae7c5
--- /dev/null
+++ b/Main/Login/ClientVersion/VersionUtility.cs
@@ -0,0 +1,352 @@
+//--------------------------------------------------------
+//    [Author]:           绗簩涓栫晫
+//    [  Date ]:           Thursday, March 15, 2018
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+using System;
+using LitJson;
+using System.IO;
+using System.Text;
+
+
+
+public class VersionUtility : Singleton<VersionUtility>
+{
+    public static readonly string[] VERSION_URL = new string[] {
+        "http://gamecenter.secondworld.net.cn:11000/center/appversion_new.php/?"};
+
+    public string androidRoot { get { return string.Empty;/*StringUtility.Contact(SDKUtils.Instance.DeviceRootPath, "/", VersionConfig.Get().bundleIdentifier);*/ } }
+
+    public DownloadTask downloadTask;
+    private string versionUrl;
+    public float progress
+    {
+        get { return downloadTask == null ? 0 : (downloadTask.downloadedBytes / ((float)GetApkSize() * 1024)); }
+    }
+
+    public VersionInfo versionInfo { get; private set; }
+    Dictionary<string, ApkDownUrl> apkDownUrls = new Dictionary<string, ApkDownUrl>();
+
+    public bool completed { get { return step == Step.Completed; } }
+
+    Step m_Step = Step.None;
+    public Step step
+    {
+        get { return m_Step; }
+        private set
+        {
+            if (m_Step != value)
+            {
+                m_Step = value;
+                if (downLoadStepChangeEvent != null)
+                {
+                    downLoadStepChangeEvent(m_Step);
+                }
+            }
+        }
+    }
+
+    public event Action<Step> downLoadStepChangeEvent;
+
+    int urlIndex = 0;
+
+    public void RequestVersionCheck()
+    {
+        m_Step = Step.None;
+        //var tables = new Dictionary<string, string>();
+        //tables["channel"] = VersionConfig.Get().appId;
+        //tables["versioncode"] = VersionConfig.Get().version;
+        //if (VersionConfig.Get().branch != 0)
+        //{
+        //    tables["branch"] = VersionConfig.Get().branch.ToString();
+        //}
+
+        //tables["game"] = VersionConfig.Get().gameId;
+
+        //var url = StringUtility.Contact(VERSION_URL[urlIndex % 2], HttpRequest.HashtablaToString(tables));
+        //urlIndex++;
+        //versionUrl = url;
+        //Debug.Log("http鍦板潃:versionUrl  " + url);
+        //HttpRequest.Instance.RequestHttpGet(url, HttpRequest.defaultHttpContentType, 1, OnVersionCheckResult);
+        OnVersionCheckResult(true, ResManager.versionUrlResult);
+    }
+
+    private void OnVersionCheckResult(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            //_result = _result.Replace("{}", "null");
+            versionInfo = JsonMapper.ToObject<VersionInfo>(_result);
+            versionInfo.downAsset = 1;
+            if (NeedNormalUpdate())
+            {
+                if (Application.isMobilePlatform || Application.platform == RuntimePlatform.WindowsEditor)
+                {
+                    RequestApkDownConfigs();
+                }
+                else
+                {
+                    step = Step.Completed;
+                }
+            }
+            else
+            {
+                step = Step.Completed;
+
+                var apkFiles = new DirectoryInfo(ResourcesPath.Instance.ExternalStorePath).GetFiles("*.apk");
+                for (int i = apkFiles.Length - 1; i >= 0; i--)
+                {
+                    File.Delete(apkFiles[i].FullName);
+                }
+            }
+        }
+        else
+        {
+            Debug.Log("Aot 璇锋眰澶辫触" + _result);
+            //Debug.Log("http 鏁版嵁閫氳: VersionUtility:" + versionUrl + "  result:" + _result);
+            ////BuglyAgent.ReportException(new System.Exception(),"http 鏁版嵁閫氳: VersionUtility:" +versionUrl + "  result:" + _result);
+            //step = Step.None;
+            //Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond), RequestVersionCheck);
+        }
+    }
+
+
+    public void RequestApkDownConfigs()
+    {
+        //  YLTODO
+        // UIManager.Instance.OpenWindow<VersionUpdateWin>();
+        //  // WindowCenter.Instance.OpenFromLocal<VersionUpdateWin>();
+    }
+
+    public bool NeedNormalUpdate()
+    {
+        return versionInfo != null && versionInfo.downAsset == 1 && versionInfo.VersionCount > 0;
+    }
+
+    public ApkDownUrl GetApkDownUrl()
+    {
+        var flag = SDKUtils.Instance.GetSplicePackageID();
+        if (apkDownUrls.ContainsKey(flag))
+            return apkDownUrls[flag];
+        else return null;
+    }
+
+    public string GetApkLocalUrl()
+    {
+        var apk = GetApkDownUrl();
+        if (apk == null)
+            return string.Empty;
+        if (!apk.isApk)
+            return string.Empty;
+        var remoteURL = GetApkRemoteUrl();
+        var fileName = Path.GetFileName(remoteURL);
+        return StringUtility.Contact(androidRoot, "/", fileName);
+    }
+
+    public string GetApkRemoteUrl()
+    {
+        if (versionInfo == null)
+        {
+            return string.Empty;
+        }
+
+        var flag = SDKUtils.Instance.GetSplicePackageID();
+        if (apkDownUrls.ContainsKey(flag))
+        {
+            return apkDownUrls[flag].url;
+        }
+        else
+        {
+            return string.Empty;
+        }
+
+    }
+
+    public int GetApkSize()
+    {
+        if (versionInfo == null)
+        {
+            return 0;
+        }
+
+
+        var flag = SDKUtils.Instance.GetSplicePackageID();
+        if (apkDownUrls.ContainsKey(flag))
+        {
+            return apkDownUrls[flag].size;
+        }
+        else
+        {
+            return 0;
+        }
+
+    }
+
+    public string GetUpdateContent()
+    {
+        var apk = GetApkDownUrl();
+        if (apk == null)
+            return string.Empty;
+        return apk.updateContent;
+    }
+
+    public void StartDownLoad()
+    {
+        step = Step.DownLoad;
+        var remoteURL = GetApkRemoteUrl();
+        var apkLocalUrl = GetApkLocalUrl();
+
+        downloadTask = new DownloadTask(remoteURL, apkLocalUrl);
+        downloadTask.BeginDownload(OnDownLoadApkCompleted);
+    }
+
+    private void OnDownLoadApkCompleted(DownloadTask task)
+    {
+        if (task.IsDone)
+        {
+            step = Step.Completed;
+            // VersionUpdateWin.Instance.CloseWindow();
+            //  // WindowCenter.Instance.Close<VersionUpdateWin>();
+            SDKUtils.Instance.InstallAPK(GetApkLocalUrl());
+        }
+        else
+        {
+            step = Step.DownLoadFailed;
+        }
+    }
+
+    public void SkipVersion()
+    {
+        step = Step.Completed;
+    }
+
+
+    /// <summary>
+    /// 鏄惁涓篿os瀹℃牳鏃堕棿鍐�
+    /// </summary>
+    /// <returns></returns>
+    public bool InIosAuditTime()
+    {
+        DateTime dateTime;
+
+        try
+        {
+            var textAsset = Resources.Load<UnityEngine.TextAsset>("Config/AuditTime");
+            var content = string.Empty;
+            if (textAsset != null)
+            {
+                content = textAsset.text;
+                if (DateTime.TryParse(content, out dateTime))
+                {
+                    return DateTime.Now < dateTime;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                return false;
+            }
+        }
+        catch (System.Exception ex)
+        {
+            return false;
+        }
+    }
+
+    public bool NeedDownAsset()
+    {
+        if (versionInfo != null && versionInfo.downAsset == 1 && VersionConfig.Get().assetAccess != InstalledAsset.IngoreDownLoad)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    public class VersionInfo
+    {
+        public JsonData notice_flag;
+        public JsonData resource_url;
+        public string ResourceAward;
+        public int downAsset = 1;   //榛樿鏄�1 娌℃湁浠h〃鎰忎箟 涓嶆竻妤氶�昏緫鍙笉瑕佹敼鍔�
+        public string downUrl;
+        public int VersionCount;    //澶т簬0浠h〃闇�瑕佸己鏇�
+
+
+        public string GetResourcesURL(int _branch)
+        {
+            if (resource_url != null)
+            {
+                return resource_url[_branch.ToString()].ToString();
+            }
+            else
+            {
+                return string.Empty;
+            }
+        }
+
+        public string GetNoticeURL(int _branch)
+        {
+            try
+            {
+                if (notice_flag != null)
+                {
+                    return notice_flag[_branch.ToString()].ToString();
+                }
+                else
+                {
+                    return string.Empty;
+                }
+            }
+            catch (Exception ex)
+            {
+                Debug.Log(ex);
+                return string.Empty;
+            }
+        }
+
+    }
+
+    public class ApkDownUrl
+    {
+        public string flag;
+        public string url;
+        public int size;
+        public bool isApk;//鏄惁鏄痑pk涓嬭浇鍦板潃,0:鍚︼紝1锛氭槸
+        public string updateContent;//鏇存柊鍐呭鎻愮ず
+
+        public ApkDownUrl(string content)
+        {
+            var strings = content.Split('\t');
+
+            flag = strings[0];
+            url = strings[1];
+            int.TryParse(strings[2], out size);
+            isApk = strings[3] == "1";
+            updateContent = strings[4];
+        }
+    }
+
+    public enum Step
+    {
+        None,
+        ApkExist,
+        DownLoadPrepared,
+        DownLoad,
+        DownLoadFailed,
+        Completed,
+    }
+
+}
+
+
+
+
diff --git a/Main/Login/ClientVersion/VersionUtility.cs.meta b/Main/Login/ClientVersion/VersionUtility.cs.meta
new file mode 100644
index 0000000..ed20e52
--- /dev/null
+++ b/Main/Login/ClientVersion/VersionUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2d1716612a52c274298734426b6e95c5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ServerData.cs b/Main/Login/ServerData.cs
new file mode 100644
index 0000000..be7773e
--- /dev/null
+++ b/Main/Login/ServerData.cs
@@ -0,0 +1,148 @@
+锘�// //--------------------------------------------------------
+// //    [Author]:           绗簩涓栫晫
+// //    [  Date ]:           Wednesday, January 10, 2018
+// //--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+using System;
+using LitJson;
+
+
+public class ServerInfoCommon
+{
+    public ServerGroup recommend;
+    public ServerGroup[] common;
+
+    public bool FindServerData(int _id, out ServerData _serverData)
+    {
+        if (common == null)
+        {
+            _serverData = default(ServerData);
+            return false;
+        }
+
+        for (int i = 0; i < common.Length; i++)
+        {
+            if (common[i].FindServerData(_id, out _serverData))
+            {
+                return true;
+            }
+        }
+
+        _serverData = default(ServerData);
+        return false;
+    }
+
+}
+
+
+public class ServerInfoPlayer
+{
+    public ServerGroup player;
+    public ServerGroup gametest;
+    public int white;
+}
+
+
+public class ServerGroup
+{
+    public string group_title;
+    public ServerData[] group_list;
+
+    public bool FindServerData(int _id, out ServerData _serverData)
+    {
+        if (group_list == null)
+        {
+            _serverData = default(ServerData);
+            return false;
+        }
+
+        for (int i = 0; i < group_list.Length; i++)
+        {
+            if (group_list[i].region_flag == _id)
+            {
+                _serverData = group_list[i];
+                return true;
+            }
+        }
+
+        _serverData = default(ServerData);
+        return false;
+    }
+}
+
+
+public struct ServerData
+{
+    public int region_flag;
+    public string name;
+    public int running_status;
+    public int statue;
+    public int is_recommend;
+    public string region_domain;
+    public int login_port;
+    public int game_port;
+    public DateTime start_date;
+    public int job;
+    public string roleid;
+    public int level;
+    public DateTime last_login_time;
+
+    // public ServerData(LoginSeverListConfig config)
+    // {
+    //     region_flag = config.ID;
+    //     name = config.serverName;
+    //     running_status = 1;
+    //     statue = 1;
+    //     is_recommend = 0;
+    //     region_domain = config.ip;
+    //     int.TryParse(config.pagePort, out login_port);
+    //     game_port = config.gatePort;
+    //     start_date = DateTime.Now;
+    //     job = 0;
+    //     roleid = string.Empty;
+    //     level = 0;
+    //     last_login_time = DateTime.Now;
+    // }
+
+    public static int Compare(ServerData _lhs, ServerData _rhs)
+    {
+        if (_lhs.is_recommend != _rhs.is_recommend)
+        {
+            return _lhs.is_recommend == 1 ? -1 : 1;
+        }
+
+        return _lhs.region_flag > _rhs.region_flag ? -1 : 1;
+    }
+
+    public static int LastLoginTimeCompare(ServerData _lhs, ServerData _rhs)
+    {
+        return _lhs.last_login_time > _rhs.last_login_time ? -1 : 1;
+    }
+
+}
+
+public struct ServerDataCouple
+{
+    public ServerData serverData1;
+    public ServerData serverData2;
+
+    public ServerDataCouple(ServerData _data1)
+    {
+        serverData1 = _data1;
+        serverData2 = default(ServerData);
+    }
+
+    public ServerDataCouple(ServerData _data1, ServerData _data2)
+    {
+        serverData1 = _data1;
+        serverData2 = _data2;
+    }
+}
+
+
+
+
+
diff --git a/Main/Login/ServerData.cs.meta b/Main/Login/ServerData.cs.meta
new file mode 100644
index 0000000..f216940
--- /dev/null
+++ b/Main/Login/ServerData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 80cfdbcc56f236b46aaa2790beeaa5c8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ServerListCenter.cs b/Main/Login/ServerListCenter.cs
new file mode 100644
index 0000000..ff403fc
--- /dev/null
+++ b/Main/Login/ServerListCenter.cs
@@ -0,0 +1,564 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using LitJson;
+using System;
+
+public class ServerListCenter : Singleton<ServerListCenter>
+
+{
+    public static readonly string[] JUMP_URL = new string[] { "http://gamecenter.secondworld.net.cn:11000/center/server_list.php/?" };
+
+    public static string SERVERLIST_URL_COMMON = "";
+    public static string SERVERLIST_URL_PLAYER = "";
+
+    public ServerInfoPlayer serverInfoPlayer { get; private set; }
+    public ServerInfoCommon serverInfoCommon { get; private set; }
+
+    ServerData m_CurrentServer;
+    public ServerData currentServer
+    {
+        get { return m_CurrentServer; }
+        set
+        {
+            m_CurrentServer = value;
+            m_SelectedServer = true;
+
+            localSaveServerId = m_CurrentServer.region_flag;
+
+            if (serverSelectEvent != null)
+            {
+                serverSelectEvent();
+            }
+        }
+    }
+
+    string m_CurrentServerGroup = string.Empty;
+    public string currentServerGroup
+    {
+        get
+        {
+            return m_CurrentServerGroup;
+        }
+        set
+        {
+            if (m_CurrentServerGroup != value)
+            {
+                m_CurrentServerGroup = value;
+                if (serverGroupSelectEvent != null)
+                {
+                    serverGroupSelectEvent();
+                }
+            }
+        }
+    }
+
+    bool m_SelectedServer = false;
+
+    bool serverListPlayerPartGot = false;
+    bool serverListCommonPartGot = false;
+
+    public bool serverListGot
+    {
+        get { return serverListCommonPartGot; }
+    }
+
+    string accountNameBuf;
+    private string serverUrl;
+    public event Action onServerListRefreshEvent;
+    public event Action serverGroupSelectEvent;
+    public event Action serverSelectEvent;
+
+    const string LOGIN_SERVER = "LoginServer";
+    public int localSaveServerId
+    {
+        get
+        {
+            return LocalSave.GetInt(LOGIN_SERVER);
+        }
+        set
+        {
+            LocalSave.SetInt(LOGIN_SERVER, value);
+        }
+    }
+
+    int jumpUrlIndex = 0;
+
+    //浠庢湁鏁版嵁鐨勬湇鍔″櫒鍒楄〃 鎴栬�� 鎬诲垪琛ㄨ幏鍙�
+    public ServerData GetServerData(int _id)
+    {
+        if (serverInfoPlayer != null && serverInfoPlayer.player != null && serverInfoPlayer.player.group_list != null)
+        {
+            var serverGroup = serverInfoPlayer.player;
+            for (int i = 0; i < serverGroup.group_list.Length; i++)
+            {
+                var serverData = serverGroup.group_list[i];
+                if (serverData.region_flag == _id)
+                {
+                    return serverData;
+                }
+            }
+        }
+
+        if (serverInfoPlayer != null && serverInfoPlayer.gametest != null && serverInfoPlayer.gametest.group_list != null)
+        {
+            var serverGroup = serverInfoPlayer.gametest;
+            for (int i = 0; i < serverGroup.group_list.Length; i++)
+            {
+                var serverData = serverGroup.group_list[i];
+                if (serverData.region_flag == _id)
+                {
+                    return serverData;
+                }
+            }
+        }
+
+        if (serverInfoCommon == null)
+        {
+            return default(ServerData);
+        }
+        else
+        {
+            if (serverInfoCommon.common != null)
+            {
+                for (int i = 0; i < serverInfoCommon.common.Length; i++)
+                {
+                    var group = serverInfoCommon.common[i];
+                    for (int j = 0; j < group.group_list.Length; j++)
+                    {
+                        var serverData = group.group_list[j];
+                        if (serverData.region_flag == _id)
+                        {
+                            return serverData;
+                        }
+                    }
+                }
+            }
+        }
+
+        return default(ServerData);
+    }
+
+    //浠庢�绘湇鍔″櫒鍒楄〃鑾峰彇
+    public ServerData GetServerDataEx(int _id)
+    {
+        if (serverInfoCommon == null)
+        {
+            return default(ServerData);
+        }
+        else
+        {
+            if (serverInfoCommon.common != null)
+            {
+                for (int i = 0; i < serverInfoCommon.common.Length; i++)
+                {
+                    var group = serverInfoCommon.common[i];
+                    for (int j = 0; j < group.group_list.Length; j++)
+                    {
+                        var serverData = group.group_list[j];
+                        if (serverData.region_flag == _id)
+                        {
+                            return serverData;
+                        }
+                    }
+                }
+            }
+        }
+
+        return default(ServerData);
+    }
+
+    public string GetServerName(int id, bool defaultName = true)
+    {
+        var data = GetServerDataEx(id);
+        if (string.IsNullOrEmpty(data.name))
+        {
+            if (defaultName)
+                return "S" + id;
+            return "";
+        }
+        return data.name.Replace("@gm", "");
+    }
+
+    public void RequestJumpUrl()
+    {
+        if (VersionUtility.Instance.InIosAuditTime())
+        {
+            return;
+        }
+
+        var url = StringUtility.Contact(JUMP_URL[0], "game=xbqy&flag=", VersionConfig.Get().appId, "_", VersionConfig.Get().branch, "_", VersionConfig.Get().version);
+        jumpUrlIndex++;
+        serverUrl = url;
+        Debug.Log("http鍦板潃:serverlist  " + url);
+        HttpRequest.Instance.RequestHttpGet(url, HttpRequest.defaultHttpContentType, 1, OnRequestJumpUrl);
+    }
+
+    private void OnRequestJumpUrl(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            var serverUrls = _result.Split(new string[] { "||" }, StringSplitOptions.RemoveEmptyEntries);
+            SERVERLIST_URL_COMMON = serverUrls[0];
+            SERVERLIST_URL_PLAYER = serverUrls[1];
+
+            RequestServerList();
+        }
+        else
+        {
+            Debug.Log("http 鏁版嵁閫氳: ServerlistCenter:" + serverUrl + "  result:" + _result);
+            //BuglyAgent.ReportException(new System.Exception(), "http 鏁版嵁閫氳: ServerlistCenter:" + serverUrl + "  result:" + _result);
+            Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond), RequestJumpUrl);
+        }
+    }
+
+    public void RequestServerList()
+    {
+        serverListCommonPartGot = false;
+        serverListPlayerPartGot = false;
+        RequestServerCommonList();
+
+        if (VersionConfig.Get().versionAuthority == VersionAuthority.InterTest)
+        {
+            var localSaveAccountName = LocalSave.GetString(LoginManager.Instance.USER_ACCOUNT);
+            RequestServerListPlayer(localSaveAccountName);
+        }
+    }
+
+    public void RequestServerCommonList()
+    {
+        if (VersionUtility.Instance.InIosAuditTime())
+        {
+            return;
+        }
+
+        HttpRequest.Instance.RequestHttpGet(SERVERLIST_URL_COMMON, HttpRequest.defaultHttpContentType, 1, OnGetServerList);
+    }
+
+    private void OnGetServerList(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            ServerListParser.Instance.PushCommonServerListRawData(_result);
+            // NetLinkWin.Hide();
+        }
+        else
+        {
+            Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond), RequestServerCommonList);
+        }
+    }
+
+    public void SetServerlistCommon(ServerInfoCommon common)
+    {
+        serverInfoCommon = common;
+        serverInfoCommon.recommend = new ServerGroup();
+        // serverInfoCommon.recommend.group_title = "TODO"//Language.GetFromLocal(18);
+
+        var recommendServers = new List<ServerData>();
+        for (int i = 0; i < serverInfoCommon.common.Length; i++)
+        {
+            var serverList = serverInfoCommon.common[i].group_list;
+            foreach (var server in serverList)
+            {
+                if (server.is_recommend == 1)
+                {
+                    recommendServers.Add(server);
+                }
+            }
+        }
+
+        serverInfoCommon.recommend.group_list = recommendServers.ToArray();
+        FiltrateDefaultServerAndServerGroup();
+
+        serverListCommonPartGot = true;
+
+        if (onServerListRefreshEvent != null)
+        {
+            onServerListRefreshEvent();
+        }
+    }
+
+    public void RequestServerListPlayer(string _accountName)
+    {
+        if (VersionUtility.Instance.InIosAuditTime())
+        {
+            return;
+        }
+
+        accountNameBuf = _accountName;
+        var url = string.Empty;
+        var tables = new Dictionary<string, string>();
+
+        if (string.IsNullOrEmpty(_accountName))
+        {
+            url = SERVERLIST_URL_PLAYER;
+            return;
+        }
+        else
+        {
+            tables["player"] = _accountName;
+            tables["lang"] = "vi";
+            url = StringUtility.Contact(SERVERLIST_URL_PLAYER, "&", HttpRequest.HashtablaToString(tables));
+        }
+
+        HttpRequest.Instance.RequestHttpGet(url, HttpRequest.defaultHttpContentType, 1, OnGetServerListPlayer);
+    }
+
+    private void OnGetServerListPlayer(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            serverListPlayerPartGot = true;
+            ServerListParser.Instance.PushPlayerServerListRawData(_result);
+        }
+        else
+        {
+            // if (StageLoad.Instance.currentStage == null || StageLoad.Instance.currentStage is LoginStage)
+            // {
+                Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond), () =>
+                {
+                    RequestServerListPlayer(accountNameBuf);
+                });
+            // }
+        }
+    }
+
+    public void SetServerListPlayer(ServerInfoPlayer serverInfoPlayer)
+    {
+        this.serverInfoPlayer = serverInfoPlayer;
+        ProcessRecentServerData();
+        FiltrateDefaultServerAndServerGroup();
+    }
+
+    public bool TryGetServerGroup(string _key, out ServerGroup _group)
+    {
+        if (serverInfoPlayer != null && serverInfoPlayer.player != null && _key == serverInfoPlayer.player.group_title)
+        {
+            _group = serverInfoPlayer.player;
+            return true;
+        }
+        else if (serverInfoPlayer != null && serverInfoPlayer.gametest != null && _key == serverInfoPlayer.gametest.group_title)
+        {
+            _group = serverInfoPlayer.gametest;
+            return true;
+        }
+        else if (serverInfoCommon != null && serverInfoCommon.recommend != null && _key == serverInfoCommon.recommend.group_title)
+        {
+            _group = serverInfoCommon.recommend;
+            return true;
+        }
+        else
+        {
+            for (int i = 0; i < serverInfoCommon.common.Length; i++)
+            {
+                if (_key == serverInfoCommon.common[i].group_title)
+                {
+                    _group = serverInfoCommon.common[i];
+                    return true;
+                }
+            }
+        }
+
+        _group = null;
+        return false;
+    }
+
+    // public void ParseServerLocalServerList()
+    // {
+    //     serverListCommonPartGot = true;
+    //     var configs = LoginSeverListConfig.GetValues();
+    //     var count = configs.Count;
+    //     serverInfoCommon = new ServerInfoCommon();
+    //     serverInfoCommon.common = new ServerGroup[1];
+    //     serverInfoCommon.common[0] = new ServerGroup();
+    //     serverInfoCommon.common[0].group_title = Language.Get("IOSShenhe");
+    //     serverInfoCommon.common[0].group_list = new ServerData[count];
+    //     for (var i = 0; i < count; i++)
+    //     {
+    //         var config = configs[i];
+    //         serverInfoCommon.common[0].group_list[i] = new ServerData(config);
+    //     }
+
+    //     FiltrateDefaultServerAndServerGroup();
+
+    //     if (onServerListRefreshEvent != null)
+    //     {
+    //         onServerListRefreshEvent();
+    //     }
+    // }
+
+    public List<string> GetAllServerGroup()
+    {
+        var serverGroupTitles = new List<string>();
+
+        if (serverInfoPlayer != null && serverInfoPlayer.player != null)
+        {
+            serverGroupTitles.Add(serverInfoPlayer.player.group_title);
+        }
+
+        if (serverInfoPlayer != null && serverInfoPlayer.gametest != null)
+        {
+            serverGroupTitles.Add(serverInfoPlayer.gametest.group_title);
+        }
+
+        if (serverInfoCommon != null && serverInfoCommon.recommend != null && serverInfoCommon.recommend.group_list.Length > 0)
+        {
+            serverGroupTitles.Add(serverInfoCommon.recommend.group_title);
+        }
+
+        for (int i = 0; i < serverInfoCommon.common.Length; i++)
+        {
+            serverGroupTitles.Add(serverInfoCommon.common[i].group_title);
+        }
+
+        return serverGroupTitles;
+    }
+
+    private void ProcessRecentServerData()
+    {
+        if (serverInfoPlayer != null && serverInfoPlayer.player != null && serverInfoPlayer.player.group_list != null)
+        {
+            var group = new List<ServerData>(serverInfoPlayer.player.group_list);
+            for (int i = group.Count - 1; i >= 0; i--)
+            {
+                ServerData serverData;
+                if (!serverInfoPlayer.player.FindServerData(group[i].region_flag, out serverData))
+                {
+                    group.RemoveAt(i);
+                }
+                else
+                {
+                    var originalData = group[i];
+                    group[i] = new ServerData()
+                    {
+                        region_flag = serverData.region_flag,
+                        name = serverData.name,
+                        running_status = serverData.running_status,
+                        statue = serverData.statue,
+                        is_recommend = serverData.is_recommend,
+                        region_domain = serverData.region_domain,
+                        login_port = serverData.login_port,
+                        game_port = serverData.game_port,
+                        start_date = serverData.start_date,
+                        job = originalData.job,
+                        roleid = originalData.roleid,
+                        level = originalData.level,
+                        last_login_time = originalData.last_login_time
+                    };
+                }
+            }
+
+            group.Sort(ServerData.LastLoginTimeCompare);
+            serverInfoPlayer.player.group_list = group.ToArray();
+        }
+    }
+
+
+    //濡傛灉宸茬粡鐧诲綍杩囨父鎴忚繑鍥炵殑闇�瑕侀噸鏂拌姹備竴娆$櫥褰曞垪琛�
+    //杩欒竟璇锋眰鐢ㄧ殑鏄棫璐﹀彿锛宻dk鐧诲綍鎴愬姛浼氱敤鏂拌处鍙疯姹備竴娆★紝鍐呯綉鐧诲綍闇�瑕佹墜鍔ㄧ偣鍑讳竴娆℃湇鍔″櫒鍒楄〃鍒锋柊
+    public void RequestPlayerServerList()
+    {
+        if (LoginManager.Instance.IsLogined)
+        {
+            var account = LoginManager.Instance.localSaveAccountName;
+            if (string.IsNullOrEmpty(account))
+                return;
+            //瑕佺敤鏂拌处鍙疯姹�
+            RequestServerListPlayer(LoginManager.Instance.localSaveAccountName);
+        }
+    }
+
+    //璇锋眰鍏堝悗椤哄簭
+    //1.鍏叡鍒楄〃 鑾峰彇涓婁竴娆$櫥闄嗘湇锛岃褰曚笅鏉ワ紱褰撶浜屾鑾峰緱 鎵撳紑鏈嶅姟鍣ㄥ垪琛ㄧ晫闈㈢殑鎯呭喌涓嶅埛鏂�
+    //2.鐜╁鍒楄〃鍒锋柊 鑻ユ湁鐜╁淇℃伅锛屾煡鎵句笂涓�娆$帺瀹剁櫥闄嗘湇锛屾病鏈夐粯璁ら�変竴涓紱鑻ユ病鏈夌帺瀹朵俊鎭� 榛樿閫夊叕鍏辨湇
+
+    //姝ゅ鑰﹀悎搴︽瘮杈冮珮 闇�璋ㄦ厧淇敼
+    //1.璇锋眰鍙戝叕鍏卞垪琛ㄥ拰鏈�杩戞湇 鏄厛鍚庨『搴忓埛鏂�
+    //2.鏈嶅姟鍣ㄥ垪琛ㄧ晫闈㈠埛鏂伴�昏緫娌″仛濂斤紝serverGroupSelectEvent鐨勮皟鐢ㄧ洿鎺ュ喅瀹氫簡鐣岄潰鏄剧ず
+    public void FiltrateDefaultServerAndServerGroup()
+    {
+        if (LoginManager.Instance.IsLogined)
+        {
+            return;
+        }
+
+        if (serverInfoCommon != null)
+        {
+            var findTarget = false;
+            for (int i = 0; i < serverInfoCommon.common.Length; i++)
+            {
+                var serverDatas = serverInfoCommon.common[i].group_list;
+                for (int j = 0; j < serverDatas.Length; j++)
+                {
+                    if (localSaveServerId == serverDatas[j].region_flag)
+                    {
+                        findTarget = true;
+                        currentServer = serverDatas[j];
+                        if (string.IsNullOrEmpty(currentServerGroup))
+                        {
+                            currentServerGroup = serverInfoCommon.common[i].group_title;
+                        }
+                        else
+                        {
+                            serverGroupSelectEvent?.Invoke();
+                        }
+                        break;
+                    }
+                }
+
+                if (findTarget)
+                {
+                    break;
+                }
+            }
+
+            if (!findTarget)
+            {
+                if (serverInfoPlayer != null && serverInfoPlayer.player != null && serverInfoPlayer.player.group_list != null && serverInfoPlayer.player.group_list.Length > 0)
+                {
+                    if (string.IsNullOrEmpty(currentServer.name))
+                    {
+                        var serverDatas = serverInfoPlayer.player.group_list;
+                        for (int j = 0; j < serverDatas.Length; j++)
+                        {
+                            if (localSaveServerId == serverDatas[j].region_flag)
+                            {
+                                findTarget = true;
+                                currentServer = serverDatas[j];
+                                if (string.IsNullOrEmpty(currentServerGroup))
+                                {
+                                    currentServerGroup = serverInfoPlayer.player.group_title;
+                                }
+                                else
+                                {
+                                    serverGroupSelectEvent?.Invoke();
+                                }
+                                break;
+                            }
+                        }
+                        if (!findTarget)
+                        {
+                            currentServer = serverInfoPlayer.player.group_list[0];
+                            currentServerGroup = serverInfoPlayer.player.group_title;
+                        }
+                    }
+                    else
+                    {
+                        serverGroupSelectEvent?.Invoke();
+                    }
+                    return;
+                }
+
+                var serverGroup = serverInfoCommon.common[serverInfoCommon.common.Length - 1];
+
+                var serverList = new List<ServerData>(serverGroup.group_list);
+                serverList.Sort(ServerData.Compare);
+                currentServer = serverList[0];
+                currentServerGroup = serverGroup.group_title;
+            }
+
+        }
+
+    }
+
+}
diff --git a/Main/Login/ServerListCenter.cs.meta b/Main/Login/ServerListCenter.cs.meta
new file mode 100644
index 0000000..6704884
--- /dev/null
+++ b/Main/Login/ServerListCenter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bff0cd613e091784ca1d06e04847d327
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Login/ServerListParser.cs b/Main/Login/ServerListParser.cs
new file mode 100644
index 0000000..8f5cc63
--- /dev/null
+++ b/Main/Login/ServerListParser.cs
@@ -0,0 +1,81 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.Threading;
+using LitJson;
+
+public class ServerListParser : SingletonMonobehaviour<ServerListParser>
+{
+
+    bool hasCommonResult = false;
+    ServerInfoCommon serverInfoCommon;
+    bool hasPlayerResult = false;
+    ServerInfoPlayer serverInfoPlayer;
+
+    public void PushCommonServerListRawData(string content)
+    {
+        hasCommonResult = false;
+        ThreadPool.QueueUserWorkItem((object aaa) =>
+        {
+            serverInfoCommon = JsonMapper.ToObject<ServerInfoCommon>(content);
+            hasCommonResult = true;
+        });
+    }
+
+    public void PushPlayerServerListRawData(string content)
+    {
+        hasPlayerResult = false;
+        Debug.Log("ServerListParser:" + content);
+        if (content == "" || content == "{}")
+            return;
+        JsonData RankArr = JsonMapper.ToObject(content);
+        if (RankArr["player"]["group_list"].Count == 0)
+            return;
+
+        ThreadPool.QueueUserWorkItem((object aaa) =>
+        {
+            serverInfoPlayer = JsonMapper.ToObject<ServerInfoPlayer>(content);
+            hasPlayerResult = true;
+            SetIsInWhiteList();
+        });
+    }
+
+    public void ReportCommonResult()
+    {
+        if (serverInfoCommon != null)
+        {
+            ServerListCenter.Instance.SetServerlistCommon(serverInfoCommon);
+        }
+    }
+
+    public void ReportPlayerResult()
+    {
+        if (serverInfoPlayer != null)
+        {
+            ServerListCenter.Instance.SetServerListPlayer(serverInfoPlayer);
+        }
+    }
+
+    public void SetIsInWhiteList()
+    {
+        //TODO YYL
+        //DebugUtility.Instance.isWhiteListAccount = serverInfoPlayer.white == 1;
+    }
+
+
+    private void Update()
+    {
+        if (hasCommonResult)
+        {
+            ReportCommonResult();
+            hasCommonResult = false;
+        }
+
+        if (hasPlayerResult)
+        {
+            ReportPlayerResult();
+            hasPlayerResult = false;
+        }
+    }
+
+}
diff --git a/Main/Login/ServerListParser.cs.meta b/Main/Login/ServerListParser.cs.meta
new file mode 100644
index 0000000..0c821ef
--- /dev/null
+++ b/Main/Login/ServerListParser.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e514ef0345e61404497ea0c9585812c0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Main.cs b/Main/Main.cs
index 5cdc543..09735ac 100644
--- a/Main/Main.cs
+++ b/Main/Main.cs
@@ -16,10 +16,10 @@
     /// <summary>
     /// 鍒濆鍖栧嚱鏁帮紝鐢盠aunch绫昏皟鐢�
     /// </summary>
-    public static async UniTask Init()
+    public static void Init()
     {
         Debug.Log("Main.Init() 琚皟鐢�");
-        await InitSystems();
+        InitSystems();
 
         Debug.Log("鍏抽棴鍔犺浇鐣岄潰");
         LaunchLoadingWin.Instance.CloseWindow();
@@ -30,10 +30,10 @@
     /// <summary>
     /// 鍒濆鍖栨父鎴忕郴缁�
     /// </summary>
-    private static async UniTask InitSystems()
+    private static void InitSystems()
     {
         // 杩欓噷鍙互鍒濆鍖栧ぇ鍨嬬郴缁� 璐┛鏁翠釜娓告垙鐨勭郴缁�
-        await ResManager.Instance.Init();
+        ResManager.Instance.Init();
         UIManager.Instance.Init();
         StageManager.Instance.Init();
         LoginManager.Instance.Init();
diff --git a/Main/Manager/ConfigManager.cs b/Main/Manager/ConfigManager.cs
index 61d235e..09e54f0 100644
--- a/Main/Manager/ConfigManager.cs
+++ b/Main/Manager/ConfigManager.cs
@@ -3,6 +3,7 @@
 using UnityEngine;
 using Cysharp.Threading.Tasks;
 using System.Reflection;
+using System.IO;
 
 
 public class ConfigManager : ManagerBase<ConfigManager>
@@ -57,10 +58,10 @@
         {
             configName = configName.Substring(0, configName.Length - 6);
         }
-        TextAsset textAsset = await ResManager.Instance.LoadAsset<TextAsset>("Config", configName);
-        if (textAsset != null)
+        string texts = await Load(configName);
+        if (!string.IsNullOrEmpty(texts))
         {
-            string[] lines = textAsset.text.Split('\n');
+            string[] lines = texts.Split('\n');
             var methodInfo = configType.GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy);
             if (methodInfo != null)
             {
@@ -80,7 +81,7 @@
         }
         else
         {
-            Debug.LogError($"鎵句笉鍒伴厤缃枃浠�: {configName}");
+            Debug.LogError($"{configName} 鍐呭涓虹┖鎴栧姞杞藉け璐�");
         }
     }
 
@@ -88,10 +89,10 @@
     {
         string configName = typeof(T).Name;
 
-        TextAsset textAsset = await ResManager.Instance.LoadAsset<TextAsset>("Config", configName);
-        if (textAsset != null)
+        string texts = await Load(configName);
+        if (!string.IsNullOrEmpty(texts))
         {
-            string[] lines = textAsset.text.Split('\n');
+            string[] lines = texts.Split('\n');
             var methodInfo = typeof(T).GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
             if (methodInfo != null)
             {
@@ -111,7 +112,7 @@
         }
         else
         {
-            Debug.LogError($"鎵句笉鍒伴厤缃枃浠�: {configName}");
+            Debug.LogError($"{configName} 鍐呭涓虹┖鎴栧姞杞藉け璐�");
         }
     }
 
@@ -130,6 +131,23 @@
         }
     }
 
+    public static async UniTask<string> Load(string configName)
+    {
+		var path = string.Empty;
+        if (AssetSource.refdataFromEditor)
+        {
+            path = ResourcesPath.CONFIG_FODLER + $"/{configName}.txt";
+        }
+        else
+        {
+            path = AssetVersionUtility.GetAssetFilePath($"config/{configName}.txt");
+        }
+
+        string texts = await File.ReadAllTextAsync(path);
+
+        return texts;
+    }
+
     public override void Release()
     {
         // 娓呯┖ FamilyConfig 瀛楀吀
diff --git a/Main/Manager/LoginManager.cs b/Main/Manager/LoginManager.cs
index 176e289..4edbfcd 100644
--- a/Main/Manager/LoginManager.cs
+++ b/Main/Manager/LoginManager.cs
@@ -4,6 +4,30 @@
 
 public class LoginManager : ManagerBase<LoginManager>
 {
+    public string USER_ACCOUNT;
+
+    public string localSaveAccountName
+    {
+        get
+        {
+            return PlayerPrefs.GetString("localSaveAccountName", "");
+        }
+    }
+
+    public bool IsLogined
+    {
+        get
+        {
+            return false;
+        }
+    }
+
+    public bool sdkLogined
+    {
+        get;
+        set;
+    } = false;
+
     public override void Init()
     {
 
@@ -13,4 +37,9 @@
     {
         
     }   
+
+    public void AccountLogin(string ip, int port, int gamePort)
+    {
+
+    }
 }
diff --git a/Main/Manager/StageManager.cs b/Main/Manager/StageManager.cs
index c1c72ee..28251b9 100644
--- a/Main/Manager/StageManager.cs
+++ b/Main/Manager/StageManager.cs
@@ -64,7 +64,7 @@
     {
         UIManager.Instance.DestroyAllUI();
 
-        ResManager.Instance.PrewarmResources();
+        // ResManager.Instance.PrewarmResources();
 
         AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Game");
 
diff --git a/Main/NetworkPackage/Clock.cs b/Main/NetworkPackage/Clock.cs
deleted file mode 100644
index 30bf498..0000000
--- a/Main/NetworkPackage/Clock.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-锘縰sing System;
-using UnityEngine;
-using System.Collections.Generic;
-using UnityEngine.Events;
-using StartAot;
-
-public class Clock
-{
-    public bool stopped { get; set; }
-    DateTime alarmTime;
-    UnityAction alarmCallBack;
-
-    public Clock(DateTime alarmTime, UnityAction callBack)
-    {
-        this.alarmTime = alarmTime;
-        this.alarmCallBack = callBack;
-    }
-
-    public bool CanAlarm()
-    {
-        return DateTime.Now >= alarmTime;
-    }
-
-    public void Execute()
-    {
-        if (alarmCallBack != null)
-        {
-            alarmCallBack();
-            alarmCallBack = null;
-        }
-    }
-
-    static List<Clock> clocks = new List<Clock>();
-
-    public static void Init()
-    {
-        new LogicUpdate().Start(OnUpdate);
-    }
-
-    public static Clock AlarmAt(DateTime alarmTime, UnityAction callBack)
-    {
-        var clock = new Clock(alarmTime, callBack);
-
-        clocks.Add(clock);
-        return clock;
-    }
-
-    public static Clock AlarmAfter(double seconds, UnityAction callBack)
-    {
-        var clock = new Clock(DateTime.Now.AddSeconds(seconds), callBack);
-
-        clocks.Add(clock);
-        return clock;
-    }
-
-    public static void Stop(Clock clock)
-    {
-        if (clocks.Contains(clock))
-        {
-            clock.stopped = true;
-        }
-    }
-
-    static void OnUpdate()
-    {
-        for (var i = clocks.Count - 1; i >= 0; i--)
-        {
-            var clock = clocks[i];
-            if (clock.stopped)
-            {
-                clocks.RemoveAt(i);
-                continue;
-            }
-
-            if (clock.CanAlarm())
-            {
-                try
-                {
-                    clock.Execute();
-                    clocks.RemoveAt(i);
-                }
-                catch (Exception e)
-                {
-                    Debug.LogException(e);
-                }
-            }
-        }
-    }
-
-}
diff --git a/Main/NetworkPackage/Clock.cs.meta b/Main/NetworkPackage/Clock.cs.meta
deleted file mode 100644
index 197d025..0000000
--- a/Main/NetworkPackage/Clock.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7122809994ef46c4a876e823b99c2473
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/ResModule.meta b/Main/ResModule.meta
new file mode 100644
index 0000000..d8cc1dd
--- /dev/null
+++ b/Main/ResModule.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d2e811822a918ad4db74e6e337ab9484
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AnimatorBuildConfig.cs b/Main/ResModule/AnimatorBuildConfig.cs
new file mode 100644
index 0000000..d86b6e6
--- /dev/null
+++ b/Main/ResModule/AnimatorBuildConfig.cs
@@ -0,0 +1,62 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+
+//#if UNITY_EDITOR
+//using UnityEditor;
+//#endif
+
+public class AnimatorBuildConfig : ScriptableObject {
+
+    //public List<string> animatorStateName;
+    public List<ClipConfig> clipConfigs;
+
+    [System.Serializable]
+    public class ClipConfig {
+        public string stateName;
+        public List<string> clipNames;
+    }
+
+}
+
+//#if UNITY_EDITOR
+//[CustomEditor(typeof(AnimatorBuildConfig))]
+//public class AnimatorBuildConfigEditor : Editor {
+
+//    public override void OnInspectorGUI() {
+
+//        base.OnInspectorGUI();
+        //serializedObject.Update();
+
+        //AnimatorBuildConfig _target = target as AnimatorBuildConfig;
+
+        //EditorGUILayout.BeginHorizontal();
+
+        //EditorGUILayout.BeginVertical();
+
+        //EditorGUILayout.LabelField("鐘舵�佸悕绉�", GUILayout.Width(80));
+        //for (int i = 0; i < _target.animatorStateName.Count; ++i) {
+        //}
+
+        //EditorGUILayout.EndVertical();
+
+        //EditorGUILayout.BeginVertical();
+
+        //EditorGUILayout.LabelField("鍔ㄧ敾鍚嶇О", GUILayout.Width(80));
+        //for (int i = 0; i < _target.clipConfigs.Count; ++i) {
+        //}
+
+        //EditorGUILayout.EndVertical();
+
+        //EditorGUILayout.EndHorizontal();
+
+
+
+        //if (GUI.changed) {
+        //    EditorUtility.SetDirty(target);
+        //    serializedObject.ApplyModifiedProperties();
+        //}
+    //}
+
+//}
+
+//#endif
\ No newline at end of file
diff --git a/Main/ResModule/AnimatorBuildConfig.cs.meta b/Main/ResModule/AnimatorBuildConfig.cs.meta
new file mode 100644
index 0000000..0ab3f9f
--- /dev/null
+++ b/Main/ResModule/AnimatorBuildConfig.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3da86f3ac75b8a34d95b08c1e1b1f5e8
+timeCreated: 1503230097
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AnimatorControllerLoader.cs b/Main/ResModule/AnimatorControllerLoader.cs
new file mode 100644
index 0000000..51f9a40
--- /dev/null
+++ b/Main/ResModule/AnimatorControllerLoader.cs
@@ -0,0 +1,126 @@
+锘縰sing UnityEngine;
+
+
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+
+public class AnimatorControllerLoader
+{
+    public static readonly string controllerSuffix = "AnimatorController_";
+    public static readonly string controllerUISuffix = "AnimatorController_UI_";
+    public static readonly string controllerShowSuffix = "AnimatorController_Show_";
+    public static readonly string controllerRealmSuffix = "AnimatorController_Realm_";
+
+    public static AnimationClip LoadAnimationClip(string name, string clipName)
+    {
+
+        AnimationClip _animationClip = null;
+        if (AssetSource.mobFromEditor)
+        {
+#if UNITY_EDITOR
+            string _resourcesPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+                                                          "gmodels/",
+                                                          name,
+                                                          "/AnimationClips/",
+                                                          clipName,
+                                                          ".anim");
+
+            _animationClip = AssetDatabase.LoadAssetAtPath<AnimationClip>(_resourcesPath);
+
+#endif
+        }
+        else
+        {
+            string _bundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME,
+                                           ResourcesPath.MOB_SUFFIX,
+                                           name);
+
+            string _assetName = clipName;
+            AssetInfo _assetInfo = new AssetInfo(_bundleName, _assetName);
+
+            _animationClip = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as AnimationClip;
+        }
+
+        if (_animationClip == null)
+        {
+            Debug.LogErrorFormat("LoadAnimationClip.Load() => 鍔犺浇涓嶅埌璧勬簮: {0} => {1}.", name, clipName);
+        }
+
+        return _animationClip;
+    }
+
+    public static RuntimeAnimatorController LoadDefaultMobAnimatorController_Fight()
+    {
+        return AnimatorControllerLoader.LoadMobController(AnimatorControllerLoader.controllerSuffix,
+                                                          GeneralDefine.ModeDefaultConfig[1][1].Replace("Prefab_Race_", ""));
+    }
+
+    public static RuntimeAnimatorController LoadDefaultMobAnimatorController_Func()
+    {
+        return AnimatorControllerLoader.LoadMobController(AnimatorControllerLoader.controllerSuffix,
+                                                          GeneralDefine.ModeDefaultConfig[0][1].Replace("Prefab_Race_", ""));
+    }
+
+    public static RuntimeAnimatorController LoadDefaultMobAnimatorController_Horse()
+    {
+        return AnimatorControllerLoader.LoadMobController(AnimatorControllerLoader.controllerSuffix,
+                                                          GeneralDefine.ModeDefaultConfig[3][1].Replace("Prefab_Horse_", ""));
+    }
+
+    public static RuntimeAnimatorController LoadDefaultMobAnimatorController_Pet()
+    {
+        return AnimatorControllerLoader.LoadMobController(AnimatorControllerLoader.controllerSuffix,
+                                                          GeneralDefine.ModeDefaultConfig[2][1].Replace("Prefab_Race_", ""));
+    }
+
+    // public static RuntimeAnimatorController Load(string suffix, int id)
+    // {
+    //     ModelResConfig _modelRes = ModelResConfig.Get(id);
+    //     string _name = _modelRes.ResourcesName;
+    //     if (_name.IndexOf('/') != -1)
+    //     {
+    //         _name = _name.Substring(0, _modelRes.ResourcesName.IndexOf('/'));
+    //     }
+
+    //     return LoadMobController(suffix, _name);
+    // }
+
+    public static RuntimeAnimatorController LoadMobController(string suffix, string _name)
+    {
+        RuntimeAnimatorController _controller = null;
+        if (AssetSource.mobFromEditor)
+        {
+#if UNITY_EDITOR
+            string _resourcesPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+                                                          "gmodels/",
+                                                         _name,
+                                                          "/",
+                                                          suffix,
+                                                          _name,
+                                                          ".controller");
+            _controller = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(_resourcesPath);
+
+#endif
+        }
+        else
+        {
+            string _bundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME,
+                                           ResourcesPath.MOB_SUFFIX,
+                                           _name.ToLower());
+
+            string _assetName = StringUtility.Contact(suffix, _name);
+            AssetInfo _assetInfo = new AssetInfo(_bundleName, _assetName);
+
+            _controller = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as RuntimeAnimatorController;
+        }
+
+        if (_controller == null)
+        {
+            Debug.LogErrorFormat("AnimatorControllerLoader.Load() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _name);
+        }
+
+        return _controller;
+    }
+}
diff --git a/Main/ResModule/AnimatorControllerLoader.cs.meta b/Main/ResModule/AnimatorControllerLoader.cs.meta
new file mode 100644
index 0000000..9d0c5ba
--- /dev/null
+++ b/Main/ResModule/AnimatorControllerLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ca5529344511289448b11828ad5068ab
+timeCreated: 1504086729
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AssetBundle.meta b/Main/ResModule/AssetBundle.meta
new file mode 100644
index 0000000..d5574f2
--- /dev/null
+++ b/Main/ResModule/AssetBundle.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 9ef2259ecf91d7c469a73b310f6fd21d
+folderAsset: yes
+timeCreated: 1502193196
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AssetBundle/AssetBundleInfo.cs b/Main/ResModule/AssetBundle/AssetBundleInfo.cs
new file mode 100644
index 0000000..6aa9859
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetBundleInfo.cs
@@ -0,0 +1,16 @@
+锘縰sing UnityEngine;
+
+public class AssetBundleInfo
+{
+
+    public string name = null;
+    public Hash128 hash;
+    public string[] dependentBundles = null;
+
+    public AssetBundleInfo(string bundleName, Hash128 hash128, string[] dependentBundleArray)
+    {
+        name = bundleName;
+        hash = hash128;
+        dependentBundles = dependentBundleArray;
+    }
+}
diff --git a/Main/ResModule/AssetBundle/AssetBundleInfo.cs.meta b/Main/ResModule/AssetBundle/AssetBundleInfo.cs.meta
new file mode 100644
index 0000000..86915b0
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetBundleInfo.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 56be0f7b1a31b334c9cf821ba184df71
+timeCreated: 1502209319
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AssetBundle/AssetBundleUtility.cs b/Main/ResModule/AssetBundle/AssetBundleUtility.cs
new file mode 100644
index 0000000..abc9bc8
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetBundleUtility.cs
@@ -0,0 +1,754 @@
+锘縰sing System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+
+public class AssetBundleUtility : SingletonMonobehaviour<AssetBundleUtility>
+{
+    private List<AssetBundleInfo> m_AssetBundleInfoList = new List<AssetBundleInfo>();
+    private List<string> m_LoadingAssetBundleList = new List<string>();
+    private List<string> m_LoadingAssetList = new List<string>();
+    private Dictionary<string, AssetInfo> m_AssetInfoDict = new Dictionary<string, AssetInfo>();
+    private Dictionary<string, AssetBundle> m_AssetBundleDict = new Dictionary<string, AssetBundle>();
+    private Dictionary<string, Dictionary<string, UnityEngine.Object>> m_AssetDict = new Dictionary<string, Dictionary<string, UnityEngine.Object>>();
+
+    public bool initialized { get; private set; }
+    public bool initializedUIAssetBundle { get; private set; }
+
+    public void InitBuiltInAsset()
+    {
+        var path = AssetVersionUtility.GetBuiltInAssetFilePath(StringUtility.Contact(AssetVersionUtility.EncodeFileName("builtin"), "_assetbundle"), false);
+        var assetBundle = AssetBundle.LoadFromFile(path);
+        if (assetBundle == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+        }
+
+        var manifest = assetBundle.LoadAsset<AssetBundleManifest>(ResourcesPath.AssetDependentFileAssetName);
+        if (manifest == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+        }
+
+        var bundles = manifest.GetAllAssetBundles();
+        foreach (var bundle in bundles)
+        {
+            var dependenices = manifest.GetAllDependencies(bundle);
+            var hash = manifest.GetAssetBundleHash(bundle);
+            var assetBundleInfo = new AssetBundleInfo(bundle, hash, dependenices);
+            m_AssetBundleInfoList.Add(assetBundleInfo);
+        }
+
+        assetBundle.Unload(true);
+        assetBundle = null;
+    }
+
+    public void ReInitBuiltInAsset()
+    {
+        // WindowConfig.Release();
+        // CloseAllIgnoreWindowConfig.Release();
+        UnloadAssetBundle("builtin/scriptableobjects", true, false);
+
+        var path = AssetVersionUtility.GetBuiltInAssetFilePath(StringUtility.Contact(AssetVersionUtility.EncodeFileName("builtin"), "_assetbundle"), false);
+        var assetBundle = AssetBundle.LoadFromFile(path);
+        if (assetBundle == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+        }
+
+        var manifest = assetBundle.LoadAsset<AssetBundleManifest>(ResourcesPath.AssetDependentFileAssetName);
+        if (manifest == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+        }
+
+        for (int i = m_AssetBundleInfoList.Count - 1; i >= 0; i--)
+        {
+            var item = m_AssetBundleInfoList[i];
+            if (item.name.Contains("builtin"))
+            {
+                m_AssetBundleInfoList.Remove(item);
+            }
+        }
+
+        var keys = new List<string>(m_AssetBundleDict.Keys);
+        for (int i = keys.Count - 1; i >= 0; i--)
+        {
+            var item = keys[i];
+            if (item.Contains("builtin"))
+            {
+                m_AssetBundleDict[item].Unload(false);
+                m_AssetBundleDict.Remove(item);
+            }
+        }
+
+        var bundles = manifest.GetAllAssetBundles();
+        foreach (var bundle in bundles)
+        {
+            var dependenices = manifest.GetAllDependencies(bundle);
+            var hash = manifest.GetAssetBundleHash(bundle);
+            var assetBundleInfo = new AssetBundleInfo(bundle, hash, dependenices);
+            m_AssetBundleInfoList.Add(assetBundleInfo);
+        }
+
+        assetBundle.Unload(true);
+        assetBundle = null;
+    }
+
+    public IEnumerator Initialize()
+    {
+        yield return StartCoroutine(Co_LoadMainfestFile("audio"));
+        yield return StartCoroutine(Co_LoadMainfestFile("video"));
+        yield return StartCoroutine(Co_LoadMainfestFile("mobeffectshader"));
+        yield return StartCoroutine(Co_LoadMainfestFile("config"));
+        yield return StartCoroutine(Co_LoadMainfestFile("maps"));
+        yield return StartCoroutine(Co_LoadMainfestFile("ui"));
+
+        yield return StartCoroutine(Co_LoadAssetBundle(ResourcesPath.windowFileBundleName));
+        yield return StartCoroutine(Co_LoadAssetBundle(ResourcesPath.uiprefabFileBundleName));
+
+        initializedUIAssetBundle = true;
+        initialized = true;
+    }
+
+    private IEnumerator Co_LoadMainfestFile(string _category)
+    {
+        var path = AssetVersionUtility.GetAssetFilePath(StringUtility.Contact(AssetVersionUtility.EncodeFileName(_category), "_assetbundle"), false);
+        var _assetBundle = AssetBundle.LoadFromFile(path);
+
+        if (_assetBundle == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+            yield break;
+        }
+
+        AssetBundleManifest _assetBundleManifest = _assetBundle.LoadAsset<AssetBundleManifest>(ResourcesPath.AssetDependentFileAssetName);
+        if (_assetBundleManifest == null)
+        {
+            Debug.LogErrorFormat("AssetBundleManifest鐨勫寘鏂囦欢涓虹┖鎴栬�呭姞杞藉嚭閿�.  Path:{0}", path);
+            yield break;
+        }
+
+        string[] _assetBundleNames = _assetBundleManifest.GetAllAssetBundles();
+        foreach (var _assetBundleName in _assetBundleNames)
+        {
+            string[] _dependenices = _assetBundleManifest.GetAllDependencies(_assetBundleName);
+            Hash128 _hash = _assetBundleManifest.GetAssetBundleHash(_assetBundleName);
+            AssetBundleInfo _assetBundleInfo = new AssetBundleInfo(_assetBundleName, _hash, _dependenices);
+            m_AssetBundleInfoList.Add(_assetBundleInfo);
+        }
+
+        _assetBundle.Unload(true);
+        _assetBundle = null;
+    }
+
+    public AssetBundleInfo GetAssetBundleInfo(string assetBundleName)
+    {
+        return m_AssetBundleInfoList.Find((x) => { return x.name == assetBundleName; });
+    }
+
+    #region 瀵笰ssetBundle璧勬簮杩涜寮傛鍗忕▼鍔犺浇鐨勬柟娉�
+
+    public void Co_LoadAsset(AssetInfo assetInfo, Action<bool, UnityEngine.Object> callBack = null)
+    {
+        Co_LoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
+    }
+
+    public void Co_LoadAsset(string assetBundleName, string assetName, Action<bool, UnityEngine.Object> callBack = null)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        if (JudgeExistAsset(assetBundleName, assetName))
+        {
+            if (callBack != null)
+            {
+                callBack(true, m_AssetDict[assetBundleName][assetName]);
+            }
+
+            return;
+        }
+
+        StartCoroutine(Co_DoLoadAsset(assetBundleName, assetName, callBack));
+    }
+
+    private IEnumerator Co_LoadAssetBundle(string assetBundleName)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        if (JudgeExistAssetBundle(assetBundleName))
+        {
+            yield break;
+        }
+
+        if (m_LoadingAssetBundleList.Contains(assetBundleName))
+        {
+            while (!m_AssetBundleDict.ContainsKey(assetBundleName))
+            {
+                // Debug.Log(Time.frameCount + " ] 姝e湪鍔犺浇AssetBundle: " + assetBundleName + ", 璇风瓑寰�...");
+                yield return null;
+            }
+            yield break;
+        }
+
+        m_LoadingAssetBundleList.Add(assetBundleName);
+
+        var _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
+        if (_assetBundleInfo == null)
+        {
+            Debug.LogErrorFormat("Co_LoadAssetBundle(): {0}鍑虹幇閿欒 => 涓嶅瓨鍦ˋssetBundleInfo. ", assetBundleName);
+            yield break;
+        }
+
+        if (_assetBundleInfo.dependentBundles.Length > 0)
+        {
+            yield return Co_LoadAssetBundleDependenice(_assetBundleInfo);
+        }
+
+        var isBuiltin = assetBundleName.Contains("builtin");
+        var filePath = isBuiltin ? AssetVersionUtility.GetBuiltInAssetFilePath(assetBundleName) : AssetVersionUtility.GetAssetFilePath(assetBundleName);
+
+        Debug.LogFormat("Co_LoadAssetBundle(): 灏嗚鍔犺浇鐨刟ssetBundle鍖呰矾寰� => {0}", filePath);
+
+        var _request = AssetBundle.LoadFromFileAsync(filePath);
+        while (!_request.isDone)
+        {
+            yield return null;
+        }
+
+        CacheAssetBundle(assetBundleName, _request.assetBundle);
+
+        m_LoadingAssetBundleList.Remove(assetBundleName);
+    }
+
+    private IEnumerator Co_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
+    {
+        AssetBundle _assetBundle = null;
+
+        if (assetBundleInfo.dependentBundles == null
+         || assetBundleInfo.dependentBundles.Length == 0)
+        {
+            yield break;
+        }
+
+        for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
+        {
+
+            if (m_AssetBundleDict.TryGetValue(assetBundleInfo.dependentBundles[i], out _assetBundle) == false)
+            {
+                yield return Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
+            }
+            else
+            {
+                if (_assetBundle == null)
+                {
+                    yield return Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
+                }
+            }
+        }
+    }
+
+    private IEnumerator Co_DoLoadAsset(string assetBundleName, string assetName, Action<bool, UnityEngine.Object> callBack = null)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+#if UNITY_EDITOR
+        RunTimeABLoadLog.AddLog(assetBundleName, assetName, UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
+#endif
+
+        yield return Co_LoadAssetBundle(assetBundleName);
+
+        if (!m_AssetBundleDict.ContainsKey(assetBundleName))
+        {
+            if (callBack != null)
+            {
+                callBack(false, null);
+            }
+            yield break;
+        }
+
+        string _checkTag = assetBundleName + "@" + assetName;
+        if (m_LoadingAssetList.Contains(_checkTag))
+        {
+            while (!m_AssetDict.ContainsKey(assetBundleName)
+                || !m_AssetDict[assetBundleName].ContainsKey(assetName))
+            {
+                //                Debug.Log(Time.frameCount + " ] 姝e湪鍔犺浇Asset: " + _checkTag + ", 璇风瓑寰�...");
+                yield return null;
+            }
+
+            if (callBack != null)
+            {
+                callBack(true, m_AssetDict[assetBundleName][assetName]);
+            }
+
+            yield break;
+        }
+
+        m_LoadingAssetList.Add(_checkTag);
+
+        var request = m_AssetBundleDict[assetBundleName].LoadAssetAsync(assetName);
+        while (!request.isDone)
+        {
+            yield return null;
+        }
+
+        if (request.asset != null)
+        {
+            CacheAsset(assetBundleName, assetName, request.asset);
+            if (callBack != null)
+            {
+                callBack(true, m_AssetDict[assetBundleName][assetName]);
+            }
+        }
+        else
+        {
+            if (callBack != null)
+            {
+                callBack(false, null);
+            }
+        }
+
+        m_LoadingAssetList.Remove(_checkTag);
+    }
+
+    private IEnumerator Co_DoLoadAsset(AssetInfo assetInfo, Action<bool, UnityEngine.Object> callBack = null)
+    {
+        if (assetInfo == null)
+        {
+            Debug.LogErrorFormat("Co_DoLoadAsset(): {0}, 鍑虹幇閿欒 => 瀛樺叆鐨凙ssetInfo涓簄ull. ", assetInfo);
+            yield break;
+        }
+        yield return Co_DoLoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
+    }
+
+    #endregion
+
+    #region 瀵笰ssetBundle璧勬簮杩涜鍚屾鍔犺浇鐨勬柟娉�
+
+    public void Sync_LoadAll(string assetBundleName)
+    {
+        if (JudgeExistAssetBundle(assetBundleName))
+        {
+            return;
+        }
+
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        Sync_LoadAssetBundle(assetBundleName);
+    }
+
+    public void Sync_LoadAllAssets(string assetBundleName)
+    {
+        if (JudgeExistAssetBundle(assetBundleName))
+        {
+            return;
+        }
+
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        Sync_LoadAssetBundle(assetBundleName);
+
+        if (m_AssetBundleDict.ContainsKey(assetBundleName))
+        {
+            var assetBundle = m_AssetBundleDict[assetBundleName];
+            assetBundle.LoadAllAssets();
+        }
+    }
+
+    public UnityEngine.Object Sync_LoadAsset(AssetInfo assetInfo, Type _type = null)
+    {
+        return Sync_LoadAsset(assetInfo.assetBundleName, assetInfo.name, _type);
+    }
+
+    public UnityEngine.Object Sync_LoadAsset(string assetBundleName, string assetName, Type _type = null)
+    {
+
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        UnityEngine.Object _object = null;
+
+        if (JudgeExistAsset(assetBundleName, assetName))
+        {
+
+            _object = m_AssetDict[assetBundleName][assetName];
+
+        }
+        else
+        {
+#if UNITY_EDITOR
+            RunTimeABLoadLog.AddLog(assetBundleName, assetName, UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
+#endif
+
+            Sync_LoadAssetBundle(assetBundleName);
+            if (m_AssetBundleDict.ContainsKey(assetBundleName))
+            {
+                if (_type != null)
+                {
+                    _object = m_AssetBundleDict[assetBundleName].LoadAsset(assetName, _type);
+                }
+                else
+                {
+                    _object = m_AssetBundleDict[assetBundleName].LoadAsset(assetName);
+                }
+
+                if (_object != null)
+                {
+                    CacheAsset(assetBundleName, assetName, _object);
+                }
+            }
+
+        }
+
+        if (_object == null)
+        {
+            Debug.LogErrorFormat("Sync_LoadAsset(): {0} 鍑虹幇閿欒 => null. ", assetName);
+        }
+
+        return _object;
+    }
+
+    private void Sync_LoadAssetBundle(string assetBundleName)
+    {
+        if (JudgeExistAssetBundle(assetBundleName))
+        {
+            return;
+        }
+
+        AssetBundleInfo _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
+        if (_assetBundleInfo == null)
+        {
+            Debug.LogErrorFormat("Sync_LoadAssetBundle(): {0} 鍑虹幇閿欒 => 涓嶅瓨鍦ˋssetBundleInfo. ", assetBundleName);
+            return;
+        }
+
+        Sync_LoadAssetBundleDependenice(_assetBundleInfo);
+
+        var isBuiltin = assetBundleName.Contains("builtin");
+        string _path = isBuiltin ? AssetVersionUtility.GetBuiltInAssetFilePath(assetBundleName) : AssetVersionUtility.GetAssetFilePath(assetBundleName);
+        AssetBundle _assetBundle = AssetBundle.LoadFromFile(_path);
+
+        CacheAssetBundle(assetBundleName, _assetBundle);
+    }
+
+    private void Sync_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
+    {
+        if (assetBundleInfo.dependentBundles == null
+         || assetBundleInfo.dependentBundles.Length == 0)
+        {
+            return;
+        }
+
+        AssetBundle _assetBundle = null;
+
+        for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
+        {
+            if (m_AssetBundleDict.TryGetValue(assetBundleInfo.dependentBundles[i], out _assetBundle) == false)
+            {
+                Sync_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
+            }
+            else
+            {
+                if (_assetBundle == null)
+                {
+                    Sync_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
+                }
+            }
+        }
+    }
+
+    #endregion
+
+    #region 瀵笰ssetBundle璧勬簮杩涜寮傛绾跨▼鍔犺浇鐨勬柟娉�
+    #endregion
+
+    #region AssetBundle璧勬簮鍗歌浇鏂规硶
+
+    public void UnloadAssetBundle(string assetBundleName, bool unloadAllLoadedObjects, bool includeDependenice)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+
+        if (JudgeExistAssetBundle(assetBundleName) == false)
+        {
+            Debug.LogWarningFormat("UnloadAssetBundle(): 瑕佸嵏杞界殑鍖呬笉鍦ㄧ紦瀛樹腑鎴栬�呭凡缁忚鍗歌浇 => {0}. ", assetBundleName);
+            return;
+        }
+
+        AssetBundleInfo _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
+
+        UnloadAssetBundle(_assetBundleInfo, unloadAllLoadedObjects, includeDependenice);
+    }
+
+    public void UnloadAsset(string assetBundleName, string assetName)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+        string _assembleName = StringUtility.Contact(assetBundleName, "@", assetName);
+
+        if (JudgeExistAsset(assetBundleName, assetName) == false)
+        {
+            Debug.LogWarningFormat("UnloadAsset(): 瑕佸嵏杞界殑璧勬簮涓嶅湪缂撳瓨涓� => {0}. ", _assembleName);
+            return;
+        }
+
+        UnityEngine.Object _assetObject = m_AssetDict[assetBundleName][assetName];
+
+        m_AssetDict[assetBundleName].Remove(assetName);
+
+        if (_assetObject is GameObject)
+        {
+            Debug.LogFormat("UnloadAsset(): 鎴愬姛鍗歌浇asset璧勬簮 => {0}. 绫诲瀷涓簕1}, 涓嶅仛鍏朵粬澶勭悊. ", assetName, _assetObject.GetType().Name);
+        }
+        else
+        {
+            Resources.UnloadAsset(_assetObject);
+            Debug.LogFormat("UnloadAsset(): 鎴愬姛鍗歌浇asset璧勬簮 => {0}. 绫诲瀷涓簕1}, 鎵цResources.UnloadAsset(). ", assetName, _assetObject.GetType().Name);
+        }
+
+        if (Application.isEditor)
+        {
+            Transform _asset = transform.Find(assetBundleName + "/Asset:" + assetName);
+            if (_asset)
+            {
+                Destroy(_asset.gameObject);
+            }
+        }
+    }
+
+    public void UnloadAsset(AssetInfo assetInfo)
+    {
+        UnloadAsset(assetInfo.assetBundleName, assetInfo.name);
+    }
+
+    public void UnloadAll()
+    {
+
+        List<string> _assetBundleNameList = new List<string>(m_AssetBundleDict.Keys);
+
+        foreach (var _assetBundleName in _assetBundleNameList)
+        {
+            UnloadAssetBundle(_assetBundleName, true, true);
+        }
+    }
+
+    private void UnloadAssetBundle(AssetBundleInfo assetBundleInfo, bool unloadAllLoadedObjects, bool includeDependenice)
+    {
+
+        // 鏄惁鍗歌浇渚濊禆璧勬簮
+        if (includeDependenice)
+        {
+            if (assetBundleInfo.dependentBundles != null
+             && assetBundleInfo.dependentBundles.Length > 0)
+            {
+
+                for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
+                {
+                    UnloadAssetBundle(assetBundleInfo.dependentBundles[i], unloadAllLoadedObjects, includeDependenice);
+                }
+
+            }
+        }
+
+        if (m_AssetDict.ContainsKey(assetBundleInfo.name))
+        {
+
+            List<string> _assetNames = new List<string>(m_AssetDict[assetBundleInfo.name].Keys);
+
+            // 鍗歌浇瀵瑰簲缂撳瓨浣忕殑asset璧勬簮
+            foreach (var _assetName in _assetNames)
+            {
+                UnloadAsset(assetBundleInfo.name, _assetName);
+            }
+            m_AssetDict.Remove(assetBundleInfo.name);
+        }
+        else
+        {
+            Debug.LogFormat("UnloadAssetBundle(): 瑕佸嵏杞絘ssetBundle鍖� {0} 娌℃湁璧勬簮琚姞杞�. ", assetBundleInfo.name);
+        }
+
+        // assetBundle鍖呭嵏杞�
+        m_AssetBundleDict[assetBundleInfo.name].Unload(unloadAllLoadedObjects);
+
+        //m_AssetDict.Remove(assetBundleInfo.name);
+
+        // 鍗歌浇缂撳瓨鐨刟ssetBundle璧勬簮
+        m_AssetBundleDict.Remove(assetBundleInfo.name);
+
+        Debug.LogFormat("UnloadAssetBundle(): 鎴愬姛鍗歌浇assetBundle鍖� => {0}. ", assetBundleInfo.name);
+
+        if (Application.isEditor)
+        {
+
+            Transform _asset = transform.Find(assetBundleInfo.name);
+            Transform _parent = _asset.parent;
+
+            if (_asset)
+            {
+                DestroyImmediate(_asset.gameObject);
+            }
+
+            if (_parent.childCount == 0 && _parent != transform)
+            {
+                DestroyImmediate(_parent.gameObject);
+            }
+        }
+    }
+
+    #endregion
+
+    public bool JudgeExistAsset(string assetBundleName, string assetName)
+    {
+#if UNITY_5||UNITY_5_3_OR_NEWER
+        assetBundleName = assetBundleName.ToLower();
+#endif
+        if (string.IsNullOrEmpty(assetBundleName)
+         || string.IsNullOrEmpty(assetName))
+        {
+            return false;
+        }
+
+        if (JudgeExistAssetBundle(assetBundleName) == false)
+        {
+            return false;
+        }
+
+        if (m_AssetDict.ContainsKey(assetBundleName) == false
+         || m_AssetDict[assetBundleName].ContainsKey(assetName) == false
+         || m_AssetDict[assetBundleName][assetName] == null)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    public bool JudgeExistAssetBundle(string assetBundleName)
+    {
+        assetBundleName = assetBundleName.ToLower();
+
+        if (m_AssetBundleDict.ContainsKey(assetBundleName) == false)
+        {
+            return false;
+        }
+
+        if (m_AssetBundleDict[assetBundleName] == null)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    private void CacheAsset(string assetBundleName, string assetName, UnityEngine.Object asset)
+    {
+        if (asset == null)
+        {
+            return;
+        }
+
+        if (asset is GameObject)
+        {
+            (asset as GameObject).SetActive(true);
+        }
+
+        if (m_AssetDict.ContainsKey(assetBundleName) == false)
+        {
+            Dictionary<string, UnityEngine.Object> _temp = new Dictionary<string, UnityEngine.Object>();
+            m_AssetDict.Add(assetBundleName, _temp);
+        }
+
+        m_AssetDict[assetBundleName][assetName] = asset;
+
+        string _assembleName = StringUtility.Contact(assetBundleName, "@", assetName);
+        if (m_AssetInfoDict.ContainsKey(_assembleName) == false)
+        {
+            AssetInfo _assetInfo = new AssetInfo(assetBundleName, assetName);
+            m_AssetInfoDict[_assembleName] = _assetInfo;
+        }
+
+        Debug.LogFormat("CacheAsset(): 鎴愬姛缂撳瓨asset => {0}. ", assetName);
+
+        //         if (Application.isEditor)
+        //         {
+        //             GameObject _go = new GameObject("Asset:" + assetName);
+        //             Transform _parent = transform.Find(assetBundleName);
+        //             if (_parent)
+        //             {
+        //                 _go.transform.SetParent(_parent);
+        //             }
+        //         }
+    }
+
+    private void CacheAssetBundle(string assetBundleName, AssetBundle assetBundle)
+    {
+
+        if (assetBundle == null)
+        {
+            Debug.LogErrorFormat("CacheAssetBundle(): {0}鍑虹幇閿欒 => 灏嗚缂撳瓨鐨勫寘涓� null. ", assetBundleName);
+            return;
+        }
+
+        if (m_AssetBundleDict.ContainsKey(assetBundleName))
+        {
+            Debug.LogErrorFormat("CacheAssetBundle(): {0}鍑虹幇閿欒 => 灏嗚缂撳瓨鐨勫寘宸茬粡鍦ㄧ紦瀛樹腑. ", assetBundleName);
+            return;
+        }
+
+        m_AssetBundleDict[assetBundleName] = assetBundle;
+        if (Application.isEditor)
+        {
+            string[] _names = assetBundleName.Split('/');
+            string _selfPath = string.Empty;
+            string _parentPath = string.Empty;
+            for (int i = 0; i < _names.Length; ++i)
+            {
+                _selfPath = _names[0];
+                for (int j = 1; j <= i; ++j)
+                {
+                    _selfPath = _selfPath + "/" + _names[j];
+                }
+                if (transform.Find(_selfPath))
+                {
+                    continue;
+                }
+                GameObject _go = new GameObject(_names[i]);
+                if (i == 0)
+                {
+                    _go.transform.parent = transform;
+                }
+                else
+                {
+                    _parentPath = _names[0];
+                    for (int j = 1; j < i; ++j)
+                    {
+                        _parentPath = _parentPath + "/" + _names[j];
+                    }
+                    Transform _parent = transform.Find(_parentPath);
+                    if (_parent)
+                    {
+                        _go.transform.parent = _parent;
+                    }
+                }
+            }
+        }
+
+        Debug.LogFormat("CacheAssetBundle(): 鎴愬姛缂撳瓨assetBundle鍖呰祫婧� => {0}. 鐩墠鏈� {1} 涓祫婧�.", assetBundleName, m_AssetBundleDict.Count);
+    }
+
+}
diff --git a/Main/ResModule/AssetBundle/AssetBundleUtility.cs.meta b/Main/ResModule/AssetBundle/AssetBundleUtility.cs.meta
new file mode 100644
index 0000000..f026f82
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetBundleUtility.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b0cd7ed6aaddea94fbf7029b0a883c9d
+timeCreated: 1502200578
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AssetBundle/AssetInfo.cs b/Main/ResModule/AssetBundle/AssetInfo.cs
new file mode 100644
index 0000000..cc83f4f
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetInfo.cs
@@ -0,0 +1,18 @@
+锘�
+public class AssetInfo {
+
+    public string assetBundleName;
+    public string name;
+    public string path;
+
+    public AssetInfo(string assetPath, string bundleName, string assetName) {
+        path = assetPath;
+        assetBundleName = bundleName;
+        name = assetName;
+    }
+
+    public AssetInfo(string bundleName, string assetName) {
+        assetBundleName = bundleName;
+        name = assetName;
+    }
+}
diff --git a/Main/ResModule/AssetBundle/AssetInfo.cs.meta b/Main/ResModule/AssetBundle/AssetInfo.cs.meta
new file mode 100644
index 0000000..313e3d8
--- /dev/null
+++ b/Main/ResModule/AssetBundle/AssetInfo.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: bcac3370b93bcf943b79f9996b5443da
+timeCreated: 1502209319
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/AudioLoader.cs b/Main/ResModule/AudioLoader.cs
new file mode 100644
index 0000000..f250808
--- /dev/null
+++ b/Main/ResModule/AudioLoader.cs
@@ -0,0 +1,60 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using System;
+
+public class AudioLoader
+{
+    static string AUDIO_EXTERSION = ".wav";
+
+    public static AudioClip LoadAudio(string _folderName, string _clipName)
+    {
+        AudioClip audioClip = null;
+        if (AssetSource.audioFromEditor)
+        {
+#if UNITY_EDITOR
+            var fileName = StringUtility.Contact("/", _clipName, AUDIO_EXTERSION);
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, ResourcesPath.AUDIO_SUFFIX, _folderName, fileName);
+
+            audioClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo(StringUtility.Contact("audio/", _folderName), _clipName);
+            audioClip = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as AudioClip;
+        }
+
+        if (audioClip == null)
+        {
+            Debug.LogErrorFormat("AudioLoader.LoadSkillAudio() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _clipName);
+        }
+
+        return audioClip;
+    }
+
+    public static void LoadAudioAsync(string _folderName, string _clipName, Action<bool, UnityEngine.Object> _callBack)
+    {
+        AudioClip audioClip = null;
+        if (AssetSource.audioFromEditor)
+        {
+#if UNITY_EDITOR
+            var fileName = StringUtility.Contact("/", _clipName, AUDIO_EXTERSION);
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, ResourcesPath.AUDIO_SUFFIX, _folderName, fileName);
+            audioClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>(path);
+
+            if (_callBack != null)
+            {
+                _callBack(true, audioClip);
+            }
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo(StringUtility.Contact("audio/", _folderName).ToLower(), _clipName);
+            AssetBundleUtility.Instance.Co_LoadAsset(assetInfo, _callBack);
+        }
+
+    }
+
+}
+
diff --git a/Main/ResModule/AudioLoader.cs.meta b/Main/ResModule/AudioLoader.cs.meta
new file mode 100644
index 0000000..05f5b6a
--- /dev/null
+++ b/Main/ResModule/AudioLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0121695112429d74daf438c07b2871b0
+timeCreated: 1505657207
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/BuiltInLoader.cs b/Main/ResModule/BuiltInLoader.cs
new file mode 100644
index 0000000..3dad5ea
--- /dev/null
+++ b/Main/ResModule/BuiltInLoader.cs
@@ -0,0 +1,209 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.U2D;
+
+public class BuiltInLoader
+{
+    readonly static string PREFAB_EXTENSION = ".prefab";
+    readonly static string SPRITE_EXTENSION = ".png";
+    readonly static string AUDIO_EXTENSION = ".wav";
+
+    readonly static List<string> excludePngs = new List<string>() { "Launch_1.png", "Launch_2.png", "Launch_3.png", "LoginBackGround.png", "TB_DL_Logo.png" };
+
+    public static Sprite LoadSprite(string name)
+    {
+        Sprite sprite = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            if (excludePngs.Contains(StringUtility.Contact(name, SPRITE_EXTENSION)))
+            {
+                var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/Sprites/", name, SPRITE_EXTENSION);
+                sprite = UnityEditor.AssetDatabase.LoadAssetAtPath<Sprite>(path);
+            }
+            else
+            {
+                var spriteAtlas = UnityEditor.AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/ResourcesOut/BuiltIn/Sprites/sprites.spriteatlasv2");
+                sprite = spriteAtlas.GetSprite(name);
+            }
+#endif
+        }
+        else
+        {
+            //var assetInfo = new AssetInfo("builtin/sprites", "sprites");
+            //var spriteAtlas = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(SpriteAtlas)) as SpriteAtlas;
+            //sprite = spriteAtlas?.GetSprite(name);
+            //if (sprite == null)
+            {
+                var assetInfo = new AssetInfo("builtin/sprites", name);
+                sprite = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(Sprite)) as Sprite;
+            }
+        }
+
+        if (sprite == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadSprite() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return sprite;
+    }
+
+    public static GameObject LoadPrefab(string name)
+    {
+        GameObject prefab = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/Prefabs/", name, PREFAB_EXTENSION);
+            prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/prefabs", name);
+            prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+        }
+
+        if (prefab == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadPrefab() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return prefab;
+    }
+
+    public static void UnLoadPrefab(string name)
+    {
+        if (!AssetSource.builtInFromEditor)
+        {
+            AssetBundleUtility.Instance.UnloadAsset("builtin/prefabs", name);
+        }
+    }
+
+    public static AudioClip LoadMusic(string name)
+    {
+        AudioClip audioClip = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/Musics/", name, AUDIO_EXTENSION);
+            audioClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/musics", name);
+            audioClip = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as AudioClip;
+        }
+
+        if (audioClip == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadMusic() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return audioClip;
+    }
+
+    public static AnimationClip LoadAnimationClip(string name)
+    {
+        AnimationClip clip = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/AnimationClips/", name, ".anim");
+            clip = UnityEditor.AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/animationclips", name);
+            clip = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as AnimationClip;
+        }
+
+        if (clip == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadAnimationClip() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return clip;
+    }
+
+    public static Material LoadMaterial(string name)
+    {
+        Material material = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/Materials/", name, ".mat");
+            material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/materials", name);
+            material = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as Material;
+        }
+
+        if (material == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadMaterial() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return material;
+    }
+
+    public static T LoadScriptableObject<T>(string name) where T : ScriptableObject
+    {
+
+        T config = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+                                                   "BuiltIn/ScriptableObjects/", name, ".asset");
+
+            config = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(resourcePath);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/scriptableobjects", name);
+            config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as T;
+        }
+
+        if (config == null)
+        {
+            Debug.LogErrorFormat("BuiltIn.LoadScriptableObject() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return config;
+    }
+
+    public static Font LoadFont(string fontName)
+    {
+        Font font = null;
+        if (AssetSource.builtInFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+                                       "BuiltIn/Font/", fontName, ".ttf");
+            font = UnityEditor.AssetDatabase.LoadAssetAtPath<Font>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("builtin/font", fontName);
+            font = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(Font)) as Font;
+        }
+
+        if (font == null)
+        {
+            Debug.LogErrorFormat("BuiltInLoader.LoadFont() => 鍔犺浇涓嶅埌璧勬簮: {0}.", fontName);
+        }
+
+        return font;
+    }
+
+
+}
diff --git a/Main/ResModule/BuiltInLoader.cs.meta b/Main/ResModule/BuiltInLoader.cs.meta
new file mode 100644
index 0000000..0b0a52f
--- /dev/null
+++ b/Main/ResModule/BuiltInLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 90d4474ca18a3f641af2abaf246763e2
+timeCreated: 1540434103
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/DebugItem.cs b/Main/ResModule/DebugItem.cs
new file mode 100644
index 0000000..31c0eb5
--- /dev/null
+++ b/Main/ResModule/DebugItem.cs
@@ -0,0 +1,6 @@
+锘縰sing UnityEngine;
+
+public class DebugItem : MonoBehaviour
+{
+    public GameObject target;
+}
\ No newline at end of file
diff --git a/Main/ResModule/DebugItem.cs.meta b/Main/ResModule/DebugItem.cs.meta
new file mode 100644
index 0000000..90521db
--- /dev/null
+++ b/Main/ResModule/DebugItem.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e61def40e4351eb45b8ebac66b4b0898
+timeCreated: 1517489958
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/GameObjectPoolManager.cs b/Main/ResModule/GameObjectPoolManager.cs
new file mode 100644
index 0000000..eec9c1e
--- /dev/null
+++ b/Main/ResModule/GameObjectPoolManager.cs
@@ -0,0 +1,637 @@
+锘�// using System.Collections.Generic;
+// using UnityEngine;
+// using System;
+
+
+
+// public class GameObjectPoolManager : SingletonMonobehaviour<GameObjectPoolManager>
+// {
+// #if UNITY_EDITOR
+//     private Dictionary<int, DebugItem> m_DebugInstIDDict = null;
+// #endif
+//     private Dictionary<int, GameObjectPool> m_PoolDict = null;
+
+//     // 涓嶉渶瑕侀攢姣佺殑瀵硅薄鍒楄〃
+//     private List<int> dontDestoryGoInstIDList = null;
+
+//     private Transform m_TargetContainer;
+
+//     public void Initialize()
+//     {
+//         if (m_PoolDict == null)
+//         {
+//             m_PoolDict = new Dictionary<int, GameObjectPool>();
+//         }
+
+//         if (!m_TargetContainer)
+//         {
+//             m_TargetContainer = new GameObject("Container").transform;
+//             m_TargetContainer.SetParent(transform);
+//         }
+
+//         if (dontDestoryGoInstIDList == null)
+//         {
+//             dontDestoryGoInstIDList = new List<int>();
+//         }
+
+// #if UNITY_EDITOR
+//         if (m_DebugInstIDDict == null)
+//         {
+//             m_DebugInstIDDict = new Dictionary<int, DebugItem>();
+//         }
+// #endif
+//     }
+
+//     public void AddDontDestroyGoInstID(int id)
+//     {
+//         if (!dontDestoryGoInstIDList.Contains(id))
+//         {
+//             dontDestoryGoInstIDList.Add(id);
+//         }
+//     }
+
+//     public bool ExistPool(GameObject prefab)
+//     {
+//         if (prefab == null)
+//         {
+//             return false;
+//         }
+
+//         if (m_PoolDict.ContainsKey(prefab.GetInstanceID()))
+//         {
+//             return true;
+//         }
+
+//         return false;
+//     }
+
+//     public GameObjectPool RequestPool(GameObject prefab)
+//     {
+//         if (prefab == null)
+//         {
+//             return null;
+//         }
+
+//         int _prefabInstanceId = prefab.GetInstanceID();
+
+//         GameObjectPool _pool = null;
+//         if (m_PoolDict.TryGetValue(_prefabInstanceId, out _pool))
+//         {
+//             return _pool;
+//         }
+
+//         _pool = new GameObjectPool(prefab);
+//         m_PoolDict[_prefabInstanceId] = _pool;
+
+//         return _pool;
+//     }
+
+
+//     public void CacheGameObject(GameObject prefab, int count, bool _prefabActive)
+//     {
+//         if (prefab == null)
+//         {
+//             return;
+//         }
+
+//         RequestPool(prefab).Cache(count, _prefabActive);
+//     }
+
+//     public GameObject RequestGameObject(GameObject prefab)
+//     {
+//         if (prefab == null)
+//         {
+//             return null;
+//         }
+
+//         return RequestPool(prefab).Request();
+//     }
+
+//     public GameObject RequestEmptyJY()
+//     {
+//         var _prefab = InstanceResourcesLoader.LoadEmptyJY();
+//         if (!_prefab)
+//         {
+//             return null;
+//         }
+
+//         var _pool = RequestPool(_prefab);
+//         _pool.assetName = InstanceResourcesLoader.emptyJyName;
+//         _pool.assetBundleName = "gmodels/prefab_race_jy";
+
+//         return _pool.Request();
+//     }
+
+//     public void ReleaseEmptyJY(GameObject go)
+//     {
+//         var _prefab = InstanceResourcesLoader.LoadEmptyJY();
+//         if (!_prefab)
+//         {
+//             return;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         if (_pool != null)
+//         {
+//             _pool.Release(go);
+//         }
+//     }
+
+//     public GameObject RequestDefaultPet()
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[2][0],
+//                                                              GeneralDefine.ModeDefaultConfig[2][1]);
+
+//         if (!_prefab)
+//         {
+//             return null;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         _pool.assetName = GeneralDefine.ModeDefaultConfig[2][1];
+//         _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[2][0];
+
+//         return _pool.Request();
+//     }
+
+//     public GameObject RequestDefaultFightNpc()
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[1][0],
+//                                                              GeneralDefine.ModeDefaultConfig[1][1]);
+
+//         if (!_prefab)
+//         {
+//             return null;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         _pool.assetName = GeneralDefine.ModeDefaultConfig[1][1];
+//         _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[1][0];
+
+//         return _pool.Request();
+//     }
+
+//     public GameObject RequestDefaultFuncNpc()
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[0][0],
+//                                                              GeneralDefine.ModeDefaultConfig[0][1]);
+
+//         if (!_prefab)
+//         {
+//             return null;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         _pool.assetName = GeneralDefine.ModeDefaultConfig[0][1];
+//         _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[0][0];
+
+//         return _pool.Request();
+//     }
+
+//     public void ReleaseDefaultPet(GameObject go)
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[2][0],
+//                                                              GeneralDefine.ModeDefaultConfig[2][1]);
+//         if (!_prefab)
+//         {
+//             return;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         if (_pool != null)
+//         {
+//             _pool.Release(go);
+//         }
+//     }
+
+//     public void ReleaseDefaultHorse(GameObject go)
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[3][0],
+//                                                              GeneralDefine.ModeDefaultConfig[3][1]);
+//         if (!_prefab)
+//         {
+//             return;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         if (_pool != null)
+//         {
+//             _pool.Release(go);
+//         }
+//     }
+
+//     public void ReleaseDefaultFightNPC(GameObject go)
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[1][0],
+//                                                              GeneralDefine.ModeDefaultConfig[1][1]);
+
+//         if (!_prefab)
+//         {
+//             return;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         if (_pool != null)
+//         {
+//             _pool.Release(go);
+//         }
+//     }
+
+//     public void ReleaseDefaultFuncNPC(GameObject go)
+//     {
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[0][0],
+//                                                              GeneralDefine.ModeDefaultConfig[0][1]);
+
+//         if (!_prefab)
+//         {
+//             return;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         if (_pool != null)
+//         {
+//             _pool.Release(go);
+//         }
+//     }
+
+//     public GameObject RequestNpcGameObject(int npcID)
+//     {
+//         string _assetName;
+//         string _assetBundleName;
+
+//         NPCConfig _m = NPCConfig.Get(npcID);
+
+//         if (_m == null || _m.MODE.Equals("0"))
+//         {
+//             return null;
+//         }
+
+//         if (GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName))
+//         {
+//             _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID];
+//         }
+//         else
+//         {
+//             _assetName = StringUtility.Contact(InstanceResourcesLoader.raceSuffix, _m.MODE);
+//             _assetBundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, _assetName);
+//             GAMgr.Instance.s_NpcID2Assetname[npcID] = _assetName;
+//             GAMgr.Instance.s_NpcID2BundleName[npcID] = _assetBundleName;
+//         }
+
+//         GameObject _prefab = InstanceResourcesLoader.LoadMob(_assetBundleName, _assetName);
+
+//         if (!_prefab)
+//         {
+//             return null;
+//         }
+
+//         GameObjectPool _pool = RequestPool(_prefab);
+
+//         _pool.assetBundleName = _assetBundleName;
+//         _pool.assetName = _assetName;
+
+//         return _pool.Request();
+//     }
+
+//     public void ReleaseGameObject(GameObject prefab, GameObject go)
+//     {
+//         GameObjectPool _pool = RequestPool(prefab);
+//         if (_pool == null)
+//         {
+//             return;
+//         }
+//         _pool.Release(go);
+//     }
+
+//     public void Release(GameObject prefab)
+//     {
+//         int _prefabInstanceId = prefab.GetInstanceID();
+
+//         GameObjectPool _pool = null;
+//         if (m_PoolDict.TryGetValue(_prefabInstanceId, out _pool))
+//         {
+//             _pool.Clear();
+
+//             if (_pool.IsEmpty())
+//             {
+//                 m_PoolDict.Remove(_pool.PrefabInstanceId);
+//             }
+//         }
+//     }
+
+//     public void UnLoadNPC(int npcID)
+//     {
+//         if (!AssetSource.mobFromEditor)
+//         {
+//             string _assetName;
+//             string _assetBundleName;
+
+//             if (!GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName))
+//             {
+//                 return;
+//             }
+//             _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID];
+
+//             if (!AssetBundleUtility.Instance.JudgeExistAssetBundle(_assetBundleName))
+//             {
+//                 return;
+//             }
+
+//             GameObject _prefab = InstanceResourcesLoader.LoadMob(_assetBundleName, _assetName);
+
+//             if (!_prefab)
+//             {
+//                 return;
+//             }
+
+//             if (!ExistPool(_prefab))
+//             {
+//                 return;
+//             }
+
+//             GameObjectPool _pool = RequestPool(_prefab);
+//             _pool.Clear();
+//             m_PoolDict.Remove(_pool.PrefabInstanceId);
+//         }
+//     }
+
+//     public void UnLoadAll(bool force = false)
+//     {
+//         List<int> _removeList = new List<int>();
+//         foreach (var _pool in m_PoolDict.Values)
+//         {
+//             if (GAMgr.Instance.needDestroyPrefabList.Contains(_pool.Prefab))
+//             {
+//                 _pool.Clear();
+//                 _removeList.Add(_pool.PrefabInstanceId);
+//             }
+//         }
+
+//         for (int i = 0; i < _removeList.Count; ++i)
+//         {
+//             m_PoolDict.Remove(_removeList[i]);
+//         }
+//     }
+
+//     public class GameObjectPool
+//     {
+//         private GameObject m_Prefab = null;
+//         public GameObject Prefab
+//         {
+//             get
+//             {
+//                 return m_Prefab;
+//             }
+//         }
+//         public int PrefabInstanceId
+//         {
+//             get; private set;
+//         }
+
+//         public List<GameObject> m_ActiveList = null;
+//         private List<GameObject> m_FreeList = null;
+
+//         Action<GameObject> releaseCallBack;
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//         private Transform m_DebugContainer;
+//         private Transform m_DebugActive;
+//         private Transform m_DebugFree;
+// #endif
+
+//         public string assetBundleName;
+//         public string assetName;
+
+//         internal protected GameObjectPool(GameObject prefab)
+//         {
+//             m_Prefab = prefab;
+//             PrefabInstanceId = m_Prefab.GetInstanceID();
+//             m_ActiveList = new List<GameObject>();
+//             m_FreeList = new List<GameObject>();
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//             m_DebugContainer = new GameObject(prefab.name).transform;
+//             m_DebugActive = new GameObject("Active").transform;
+//             m_DebugFree = new GameObject("Free").transform;
+//             m_DebugActive.SetParent(m_DebugContainer);
+//             m_DebugFree.SetParent(m_DebugContainer);
+//             m_DebugContainer.SetParent(Instance.transform);
+// #endif
+//         }
+
+//         public void AddReleaseListener(Action<GameObject> _callBack)
+//         {
+//             releaseCallBack = _callBack;
+//         }
+
+//         public void RemoveReleaseListener()
+//         {
+//             releaseCallBack = null;
+//         }
+
+//         public void Cache(int count, bool _prefabActive)
+//         {
+//             GameObject _go;
+//             for (int i = 0; i < count; ++i)
+//             {
+//                 _go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity);
+//                 m_FreeList.Add(_go);
+//                 _go.transform.SetParent(Instance.m_TargetContainer);
+//                 _go.transform.position = Constants.Special_Hide_Position;
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+
+//                 DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent<DebugItem>();
+//                 _debugItem.transform.SetParent(m_DebugFree);
+//                 _debugItem.target = _go;
+//                 Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem;
+// #endif
+//                 var animator = _go.GetComponent<Animator>();
+//                 if (animator != null)
+//                 {
+//                     animator.enabled = false;
+//                 }
+//                 _go.SetActive(_prefabActive);
+//             }
+//         }
+
+//         public GameObject Request()
+//         {
+//             GameObject _go = null;
+
+//             while (m_FreeList.Count > 0)
+//             {
+//                 if (m_FreeList[0] != null)
+//                 {
+//                     _go = m_FreeList[0];
+
+//                     m_ActiveList.Add(_go);
+//                     m_FreeList.RemoveAt(0);
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                     if (Instance.m_DebugInstIDDict.ContainsKey(_go.GetInstanceID()))
+//                     {
+//                         DebugItem _debugItem = Instance.m_DebugInstIDDict[_go.GetInstanceID()];
+//                         _debugItem.transform.SetParent(m_DebugActive);
+//                     }
+// #endif
+//                     break;
+//                 }
+//                 else
+//                 {
+//                     m_FreeList.RemoveAt(0);
+//                 }
+//             }
+
+//             if (_go == null)
+//             {
+//                 _go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity);
+//                 m_ActiveList.Add(_go);
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                 DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent<DebugItem>();
+//                 _debugItem.transform.SetParent(m_DebugActive);
+//                 _debugItem.target = _go;
+//                 Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem;
+// #endif
+//             }
+
+//             _go.transform.SetParent(null);
+//             _go.transform.localScale = Vector3.one;
+
+//             return _go;
+//         }
+
+//         public void Release(GameObject go)
+//         {
+//             if (go == null)
+//             {
+//                 return;
+//             }
+//             if (m_ActiveList.Contains(go))
+//             {
+//                 m_ActiveList.Remove(go);
+//             }
+//             if (m_FreeList.Contains(go))
+//             {
+//                 return;
+//             }
+
+//             m_FreeList.Add(go);
+//             go.transform.SetParent(Instance.m_TargetContainer);
+//             go.transform.position = Constants.Special_Hide_Position;
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//             if (Instance.m_DebugInstIDDict.ContainsKey(go.GetInstanceID()))
+//             {
+//                 DebugItem _debugItem = Instance.m_DebugInstIDDict[go.GetInstanceID()];
+//                 _debugItem.transform.SetParent(m_DebugFree);
+//             }
+// #endif
+
+//             if (releaseCallBack != null)
+//             {
+//                 releaseCallBack(go);
+//             }
+//         }
+
+//         public void ReleaseAll()
+//         {
+//             for (int i = m_ActiveList.Count - 1; i >= 0; i--)
+//             {
+//                 var _go = m_ActiveList[i];
+//                 m_ActiveList.Remove(_go);
+
+//                 if (!m_FreeList.Contains(_go))
+//                 {
+//                     m_FreeList.Add(_go);
+//                 }
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                 DebugItem _debugItem = Instance.m_DebugInstIDDict[_go.GetInstanceID()];
+//                 _debugItem.transform.SetParent(m_DebugFree);
+// #endif
+//                 _go.transform.SetParent(Instance.m_TargetContainer);
+//                 _go.transform.position = Constants.Special_Hide_Position;
+
+//                 if (releaseCallBack != null)
+//                 {
+//                     releaseCallBack(_go);
+//                 }
+//             }
+//         }
+
+//         public void Clear()
+//         {
+//             for (int i = m_ActiveList.Count - 1; i >= 0; --i)
+//             {
+//                 if (m_ActiveList[i] == null
+//                 || Instance.dontDestoryGoInstIDList.Contains(m_ActiveList[i].GetInstanceID()))
+//                     continue;
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                 Destroy(Instance.m_DebugInstIDDict[m_ActiveList[i].GetInstanceID()].gameObject);
+// #endif
+//                 Destroy(m_ActiveList[i]);
+//                 m_ActiveList.RemoveAt(i);
+//             }
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//             if (m_ActiveList.Count != 0)
+//             {
+//                 Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓椿璺冨璞�. ", m_Prefab.name, m_ActiveList.Count);
+//                 for (int i = 0; i < m_ActiveList.Count; ++i)
+//                 {
+//                     Debug.LogWarningFormat(" |-- {0}", m_ActiveList[i].name);
+//                 }
+//             }
+// #endif
+
+//             for (int i = m_FreeList.Count - 1; i >= 0; --i)
+//             {
+//                 if (m_FreeList[i] == null
+//                  || Instance.dontDestoryGoInstIDList.Contains(m_FreeList[i].GetInstanceID()))
+//                     continue;
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                 Destroy(Instance.m_DebugInstIDDict[m_FreeList[i].GetInstanceID()].gameObject);
+// #endif
+//                 Destroy(m_FreeList[i]);
+//                 m_FreeList.RemoveAt(i);
+//             }
+
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//             if (m_FreeList.Count != 0)
+//             {
+//                 Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓┖闂插璞�. ", m_Prefab.name, m_FreeList.Count);
+//                 for (int i = 0; i < m_FreeList.Count; ++i)
+//                 {
+//                     Debug.LogWarningFormat(" |-- {0}", m_FreeList[i].name);
+//                 }
+//             }
+// #endif
+//             if (IsEmpty())
+//             {
+//                 m_Prefab = null;
+// #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
+//                 Destroy(m_DebugContainer.gameObject);
+// #endif
+//             }
+
+//             if (!string.IsNullOrEmpty(assetBundleName) && !string.IsNullOrEmpty(assetName))
+//             {
+//                 InstanceResourcesLoader.UnloadAsset(assetBundleName, assetName);
+//             }
+//         }
+
+//         public bool IsEmpty()
+//         {
+//             return m_ActiveList.Count == 0 && m_FreeList.Count == 0;
+//         }
+//     }
+// }
diff --git a/Main/ResModule/GameObjectPoolManager.cs.meta b/Main/ResModule/GameObjectPoolManager.cs.meta
new file mode 100644
index 0000000..9741ee8
--- /dev/null
+++ b/Main/ResModule/GameObjectPoolManager.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 27d561bd4736c5d4c997bf253c83d47e
+timeCreated: 1502507579
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/InstanceResourcesLoader.cs b/Main/ResModule/InstanceResourcesLoader.cs
new file mode 100644
index 0000000..180f3c3
--- /dev/null
+++ b/Main/ResModule/InstanceResourcesLoader.cs
@@ -0,0 +1,547 @@
+锘�// using UnityEngine;
+
+// using System;
+// #if UNITY_EDITOR
+// using UnityEditor;
+// #endif
+
+
+// public class InstanceResourcesLoader
+// {
+//     public static readonly string raceSuffix = "Prefab_Race_";
+//     public static readonly string horseSuffix = "Prefab_Horse_";
+//     public static readonly string weaponSuffix = "Prefab_Weapon_";
+//     public static readonly string secondarySuffix = "Prefab_Secondary_";
+//     public static readonly string handSuffix = "Prefab_Hand_";
+//     public static readonly string wingSuffix = "Prefab_Wing_";
+//     public static readonly string emptyJyName = "Prefab_Race_JY";
+
+//     public static GameObject LoadEmptyJY()
+//     {
+//         GameObject _prefab = null;
+
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/",
+//                                                         emptyJyName,
+//                                                         ".prefab");
+
+//             _prefab = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             _prefab = AssetBundleUtility.Instance.Sync_LoadAsset("gmodels/prefab_race_jy", emptyJyName) as GameObject;
+//         }
+
+//         if (_prefab == null)
+//         {
+//             Debug.LogErrorFormat("InstanceResourcesLoader.LoadModel() => 鍔犺浇涓嶅埌璧勬簮: {0}/{1} ", "gmodels/prefab_race_jy", emptyJyName);
+//         }
+
+//         return _prefab;
+//     }
+
+//     // public static GameObject LoadNpc(int id)
+//     // {
+//     //     NPCConfig _m = NPCConfig.Get(id);
+
+//     //     if (_m == null || string.IsNullOrEmpty(_m.MODE) || _m.MODE.Equals("0"))
+//     //     {
+//     //         return null;
+//     //     }
+
+//     //     return LoadModelPrefab(raceSuffix, _m.MODE);
+//     // }
+
+//     public static GameObject LoadDefaultFightNPC()
+//     {
+//         return LoadMob(GeneralDefine.ModeDefaultConfig[1][0],
+//                        GeneralDefine.ModeDefaultConfig[1][1]);
+//     }
+
+//     public static GameObject LoadDefaultFuncNPC()
+//     {
+//         return LoadMob(GeneralDefine.ModeDefaultConfig[0][0],
+//                        GeneralDefine.ModeDefaultConfig[0][1]);
+//     }
+
+//     public static void AsyncLoadDefaultFuncNpc(Action<bool, UnityEngine.Object> callBack)
+//     {
+//         AsyncLoadNpc(GeneralDefine.ModeDefaultConfig[0][0],
+//                      GeneralDefine.ModeDefaultConfig[0][1],
+//                      callBack);
+//     }
+//     public static void AsyncLoadDefaultFightNpc(Action<bool, UnityEngine.Object> callBack)
+//     {
+//         AsyncLoadNpc(GeneralDefine.ModeDefaultConfig[1][0],
+//                      GeneralDefine.ModeDefaultConfig[1][1],
+//                      callBack);
+//     }
+//     public static void AsyncLoadDefaultPet(Action<bool, UnityEngine.Object> callBack)
+//     {
+//         AsyncLoadNpc(GeneralDefine.ModeDefaultConfig[2][0],
+//                      GeneralDefine.ModeDefaultConfig[2][1],
+//                      callBack);
+//     }
+
+//     public static GameObject LoadDefaultHorse()
+//     {
+//         return LoadMob(GeneralDefine.ModeDefaultConfig[3][0],
+//                        GeneralDefine.ModeDefaultConfig[3][1]);
+//     }
+
+//     public static GameObject LoadDefaultPet()
+//     {
+//         return LoadMob(GeneralDefine.ModeDefaultConfig[2][0],
+//                        GeneralDefine.ModeDefaultConfig[2][1]);
+//     }
+
+//     // public static GameObject LoadNpcPrefab(int npcID)
+//     // {
+//     //     NPCConfig _m = NPCConfig.Get(npcID);
+
+//     //     if (_m == null || _m.MODE.Equals("0"))
+//     //     {
+//     //         return null;
+//     //     }
+
+//     //     string _assetName;
+//     //     string _assetBundleName;
+
+//     //     if (GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName))
+//     //     {
+//     //         _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID];
+//     //     }
+//     //     else
+//     //     {
+//     //         _assetName = StringUtility.Contact(raceSuffix, _m.MODE);
+//     //         _assetBundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, _assetName);
+//     //         GAMgr.Instance.s_NpcID2Assetname[npcID] = _assetName;
+//     //         GAMgr.Instance.s_NpcID2BundleName[npcID] = _assetBundleName;
+//     //     }
+
+//     //     return LoadMob(_assetBundleName, _assetName);
+//     // }
+
+//     public static GameObject LoadModelRes(int id, bool _ui = false)
+//     {
+
+//         ModelResConfig _m = ModelResConfig.Get(id);
+
+//         if (_m == null)
+//         {
+//             return null;
+//         }
+
+//         string _name = _m.ResourcesName;
+//         int _index = _name.IndexOf('/');
+//         if (_index != -1)
+//         {
+//             _name = _name.Substring(_index + 1);
+//         }
+
+//         if (_m.Type == (int)E_ModelResType.Suit)
+//         {
+//             return LoadModelPrefab(raceSuffix, _name, _ui);
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Horse)
+//         {
+//             return LoadModelPrefab(horseSuffix, _name, _ui);
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Wing)
+//         {
+//             return LoadModelPrefab(wingSuffix, _name, _ui);
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Weapon)
+//         {
+//             return LoadModelPrefab(weaponSuffix, _name, _ui);
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Secondary)
+//         {
+//             return LoadModelPrefab(secondarySuffix, _name, _ui);
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Hand)
+//         {
+//             return LoadModelPrefab(handSuffix, _name, _ui);
+//         }
+//         return null;
+//     }
+
+//     public static void LoadCreateRole(int job, Action<bool, UnityEngine.Object> _callBack)
+//     {
+//         string _name = "Zs";
+//         switch (job)
+//         {
+//             case 1:
+//                 _name = "Zs";
+//                 break;
+//             case 2:
+//                 _name = "Fs";
+//                 break;
+//             case 3:
+//                 _name = "Zs";
+//                 break;
+//             case 4:
+//                 _name = "Zs";
+//                 break;
+//         }
+
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/CreateRole/",
+//                                                         _name,
+//                                                         ".prefab");
+
+//             var gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+
+//             if (_callBack != null)
+//             {
+//                 _callBack(true, gameObject);
+//             }
+// #endif
+//         }
+//         else
+//         {
+//             var assetInfo = new AssetInfo("gmodels/createrole", _name);
+//             AssetBundleUtility.Instance.Co_LoadAsset(assetInfo, _callBack);
+//         }
+//     }
+
+//     private static GameObject LoadModelPrefab(string _suffix, string name)
+//     {
+//         GameObject _gameObject = null;
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/",
+//                                                         _suffix + name,
+//                                                         ".prefab");
+
+//             _gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _bundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, "prefab_race_" + name.Replace("_UI", ""));
+//             string _assetName = _suffix + name;
+//             _gameObject = AssetBundleUtility.Instance.Sync_LoadAsset(_bundleName, _assetName) as GameObject;
+//         }
+
+//         if (_gameObject == null)
+//         {
+//             Debug.LogErrorFormat("InstanceResourcesLoader.LoadModel() => 鍔犺浇涓嶅埌璧勬簮: {0} ", name);
+//         }
+
+//         return _gameObject;
+//     }
+
+//     public static GameObject LoadModelPrefab(string _suffix, string name, bool _ui)
+//     {
+//         var prefab = LoadModelPrefab(_suffix, _ui ? name + "_UI" : name);
+//         if (prefab == null)
+//         {
+//             prefab = LoadModelPrefab(_suffix, name);
+//         }
+
+//         return prefab;
+//     }
+
+//     public static void AsyncLoadModelRes(int id, Action<bool, UnityEngine.Object> callback = null)
+//     {
+//         ModelResConfig _m = ModelResConfig.Get(id);
+
+//         if (_m == null)
+//         {
+//             return;
+//         }
+
+//         string _name = _m.ResourcesName;
+//         int _index = _name.IndexOf('/');
+//         if (_index != -1)
+//         {
+//             _name = _name.Substring(_index + 1);
+//         }
+
+//         string _suffix = string.Empty;
+
+//         if (_m.Type == (int)E_ModelResType.Suit)
+//         {
+//             _suffix = raceSuffix;
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Horse)
+//         {
+//             _suffix = horseSuffix;
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Wing)
+//         {
+//             _suffix = wingSuffix;
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Weapon)
+//         {
+//             _suffix = weaponSuffix;
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Secondary)
+//         {
+//             _suffix = secondarySuffix;
+//         }
+//         else if (_m.Type == (int)E_ModelResType.Hand)
+//         {
+//             _suffix = handSuffix;
+//         }
+
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/",
+//                                                         _suffix + _name,
+//                                                         ".prefab");
+
+//             var _gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+
+//             if (_gameObject)
+//             {
+//                 if (callback != null)
+//                 {
+//                     callback(true, _gameObject);
+//                 }
+//             }
+//             else
+//             {
+//                 if (callback != null)
+//                 {
+//                     callback(false, null);
+//                 }
+//             }
+// #endif
+//         }
+//         else
+//         {
+//             string _bundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, "prefab_race_" + _name.Replace("_UI", ""));
+//             string _assetName = _suffix + _name;
+
+//             AssetBundleUtility.Instance.Co_LoadAsset(_bundleName, _assetName, callback);
+//         }
+//     }
+
+//     public static GameObject LoadMob(string assetBundleName, string assetName)
+//     {
+//         GameObject _gameObject = null;
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/",
+//                                                         assetName,
+//                                                         ".prefab");
+
+//             _gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             _gameObject = AssetBundleUtility.Instance.Sync_LoadAsset(assetBundleName, assetName) as GameObject;
+//         }
+
+//         if (_gameObject == null)
+//         {
+//             Debug.LogErrorFormat("InstanceResourcesLoader.LoadModel() => 鍔犺浇涓嶅埌璧勬簮: {0}/{1} ", assetBundleName, assetName);
+//         }
+
+//         return _gameObject;
+//     }
+
+//     public static void UnloadAsset(string bundleName, string assetName)
+//     {
+//         if (!AssetSource.mobFromEditor)
+//         {
+//             AssetBundleUtility.Instance.UnloadAsset(bundleName, assetName);
+//             AssetBundleUtility.Instance.UnloadAssetBundle(bundleName, true, false);
+//         }
+//     }
+
+//     public static GameObject LoadEffect(int id)
+//     {
+//         GameObject _gameObject = null;
+
+//         EffectConfig _effectModel = EffectConfig.Get(id);
+
+//         if (_effectModel == null)
+//         {
+//             return null;
+//         }
+
+//         if (AssetSource.effectFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                     "Effect/",
+//                                                     _effectModel.packageName,
+//                                                     "/",
+//                                                     _effectModel.fxName,
+//                                                     ".prefab");
+//             _gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _bundleName = StringUtility.Contact(ResourcesPath.EFFECT_Folder_Name, _effectModel.packageName);
+//             _gameObject = AssetBundleUtility.Instance.Sync_LoadAsset(_bundleName, _effectModel.fxName) as GameObject;
+//         }
+
+//         if (_gameObject == null)
+//         {
+//             Debug.LogErrorFormat("InstanceResourcesLoader.LoadSkillEffect() => 鍔犺浇涓嶅埌璧勬簮: {0}", _effectModel.fxName);
+//         }
+
+//         return _gameObject;
+//     }
+
+//     public static void LoadEffectAsync(int _id, Action<bool, UnityEngine.Object> _callBack = null)
+//     {
+//         GameObject gameObject = null;
+//         var config = EffectConfig.Get(_id);
+//         if (config == null)
+//         {
+//             return;
+//         }
+
+//         if (AssetSource.effectFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                     "Effect/",
+//                                                     config.packageName,
+//                                                     "/",
+//                                                     config.fxName,
+//                                                     ".prefab");
+//             gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+
+//             if (_callBack != null)
+//             {
+//                 _callBack(gameObject != null, gameObject);
+//             }
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = StringUtility.Contact(ResourcesPath.EFFECT_Folder_Name, config.packageName);
+//             AssetBundleUtility.Instance.Co_LoadAsset(bundleName, config.fxName, _callBack);
+//         }
+//     }
+
+//     public static void AsyncLoadNpc(int npcID, Action<bool, UnityEngine.Object> callBack = null)
+//     {
+//         NPCConfig _m = NPCConfig.Get(npcID);
+
+//         if (_m == null || _m.MODE.Equals("0"))
+//         {
+//             if (callBack != null)
+//             {
+//                 callBack(false, null);
+//             }
+//         }
+
+//         string _assetName;
+//         string _assetBundleName;
+
+//         if (GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName))
+//         {
+//             _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID];
+//         }
+//         else
+//         {
+//             _assetName = StringUtility.Contact(raceSuffix, _m.MODE);
+//             _assetBundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, _assetName);
+//             GAMgr.Instance.s_NpcID2Assetname[npcID] = _assetName;
+//             GAMgr.Instance.s_NpcID2BundleName[npcID] = _assetBundleName;
+//         }
+
+//         AsyncLoadNpc(_assetBundleName, _assetName, callBack);
+//     }
+
+//     public static void AsyncLoadNpc(string assetBundleName, string assetName, Action<bool, UnityEngine.Object> callBack = null)
+//     {
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                         "Gmodels/",
+//                                                         assetName,
+//                                                         ".prefab");
+
+//             var _p = AssetDatabase.LoadAssetAtPath<GameObject>(_resourcePath);
+//             if (callBack != null)
+//             {
+//                 callBack(true, _p);
+//             }
+// #endif
+//         }
+//         else
+//         {
+//             AssetBundleUtility.Instance.Co_LoadAsset(assetBundleName, assetName, callBack);
+//         }
+//     }
+
+//     public static void PreloadSkillEffect(int id)
+//     {
+//         var _skillInfo = SkillHelper.Instance.Get(id);
+//         // 鎶�鑳界壒鏁堥鍔犺浇
+//         if (_skillInfo.config.EffectName > 0)
+//         {
+//             InstanceResourcesLoader.LoadEffectAsync(_skillInfo.config.EffectName);
+//         }
+//         if (_skillInfo.config.BuffEffectID > 0)
+//         {
+//             InstanceResourcesLoader.LoadEffectAsync(_skillInfo.config.EffectName);
+//         }
+
+//         var _soSkill = _skillInfo.soFile;
+//         if (_soSkill != null)
+//         {
+//             for (int i = 0; i < _soSkill.animationEventList.Count; ++i)
+//             {
+//                 if (_soSkill.animationEventList[i].frameEventType == E_FrameEventType.OnPlayEffect)
+//                 {
+//                     if (_soSkill.animationEventList[i].intParam > 0)
+//                     {
+//                         InstanceResourcesLoader.LoadEffectAsync(_soSkill.animationEventList[i].intParam);
+//                     }
+//                 }
+//                 else if (_soSkill.animationEventList[i].frameEventType == E_FrameEventType.OnSkillEvent)
+//                 {
+//                     var _param = _soSkill.animationEventList[i].intParam;
+//                     var _type = SoSkill.GetAttactType(_param);
+//                     var _id = SoSkill.GetFrameEventId(_param);
+//                     if (_type == SoSkill.E_AttackType.Sweep)
+//                     {
+//                         var _config = ScriptableObjectLoader.LoadSoSweepHit(_id);
+//                         if (_config.hitEffectId > 0)
+//                         {
+//                             InstanceResourcesLoader.LoadEffectAsync(_config.hitEffectId);
+//                         }
+//                     }
+//                     else if (_type == SoSkill.E_AttackType.FlyObject)
+//                     {
+//                         var _config = ScriptableObjectLoader.LoadSoFlyObject(_id);
+//                         if (_config.hitEffectId > 0)
+//                         {
+//                             InstanceResourcesLoader.LoadEffectAsync(_config.hitEffectId);
+//                         }
+
+//                         if (_config.ammoEffectId > 0)
+//                         {
+//                             InstanceResourcesLoader.LoadEffectAsync(_config.hitEffectId);
+//                         }
+//                     }
+//                 }
+//             }
+//         }
+//     }
+// }
diff --git a/Main/ResModule/InstanceResourcesLoader.cs.meta b/Main/ResModule/InstanceResourcesLoader.cs.meta
new file mode 100644
index 0000000..8cbff6a
--- /dev/null
+++ b/Main/ResModule/InstanceResourcesLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 69cc1ce5d10840542886d9f847f257ad
+timeCreated: 1504151459
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/MaterialLoader.cs b/Main/ResModule/MaterialLoader.cs
new file mode 100644
index 0000000..1597cdb
--- /dev/null
+++ b/Main/ResModule/MaterialLoader.cs
@@ -0,0 +1,126 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+
+public class MaterialLoader
+{
+    readonly static Dictionary<string, ObjectPool<Material>> s_MatDict = new Dictionary<string, ObjectPool<Material>>();
+
+//     public static Material LoadClothesMaterial(int id, bool isUI, bool isSuit)
+//     {
+//         var _modelResConfig = ModelResConfig.Get(id);
+//         if (_modelResConfig == null)
+//         {
+//             return null;
+
+//         }
+
+//         string _assetName = string.Empty;
+
+//         if (isSuit)
+//         {
+//             if (isUI)
+//             {
+//                 _assetName = _modelResConfig.Material_UI_Suit;
+//             }
+//             else
+//             {
+//                 _assetName = _modelResConfig.Material_Fight_Suit;
+//             }
+//         }
+//         else
+//         {
+//             if (isUI)
+//             {
+//                 _assetName = _modelResConfig.Material_UI_Normal;
+//             }
+//             else
+//             {
+//                 _assetName = _modelResConfig.Material_Fight_Normal;
+//             }
+//         }
+
+//         if (string.IsNullOrEmpty(_assetName))
+//         {
+//             return null;
+//         }
+
+//         //Debug.LogFormat("鎯宠鍔犺浇鐨勬潗璐ㄧ殑鍚嶇О: {0}", _assetName);
+
+//         ObjectPool<Material> _pool = null;
+
+//         if (s_MatDict.TryGetValue(_assetName, out _pool))
+//         {
+//             if (_pool.inactivedCount > 0)
+//             {
+//                 //Debug.Log(" |-- 姹犻噷鏈�, 浠庢睜閲屽彇");
+//                 return _pool.Get();
+//             }
+//         }
+
+//         string _name = _modelResConfig.ResourcesName;
+//         int _index = _name.IndexOf('/');
+//         if (_index != -1)
+//         {
+//             _name = _name.Substring(_index + 1);
+//         }
+
+//         var _parentDirName = string.Empty;
+
+//         if (_name.Contains("A_Zs"))
+//         {
+//             _parentDirName = "A_Zs";
+//         }
+//         else if (_name.Contains("A_Fs"))
+//         {
+//             _parentDirName = "A_Fs";
+//         }
+
+//         Material _mat = null;
+//         if (AssetSource.mobFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                     "Gmodels/",
+//                                                     _parentDirName,
+//                                                     "/Materials/",
+//                                                     _assetName,
+//                                                     ".mat");
+//             _mat = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _bundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, InstanceResourcesLoader.raceSuffix, _name.ToLower());
+//             AssetInfo _assetInfo = new AssetInfo(_bundleName, _assetName);
+//             _mat = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as Material;
+//         }
+
+//         if (_mat == null)
+//         {
+//             Debug.LogErrorFormat("MaterialLoader.Load() => 鍔犺浇涓嶅埌璧勬簮: {0}", _assetName);
+//         }
+
+//         return _mat;
+//     }
+
+//     public static void Release(Material mat)
+//     {
+//         if (!mat)
+//         {
+//             return;
+//         }
+
+//         var _name = mat.name.Replace(" (Instance)", "");
+//         //Debug.LogFormat("瑕侀噴鏀剧殑鏉愯川鐨勫悕绉�: {0}, 淇敼鍚庣殑鍚嶇О: {1}", mat.name, _name);
+
+//         ObjectPool<Material> _pool = null;
+
+//         if (!s_MatDict.TryGetValue(_name, out _pool))
+//         {
+//             _pool = new ObjectPool<Material>(null, null);
+//             s_MatDict.Add(_name, _pool);
+//         }
+
+//         _pool.Add(mat);
+//     }
+}
diff --git a/Main/ResModule/MaterialLoader.cs.meta b/Main/ResModule/MaterialLoader.cs.meta
new file mode 100644
index 0000000..1322a57
--- /dev/null
+++ b/Main/ResModule/MaterialLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 284a42a931dfa414c8ff5db85f34c88e
+timeCreated: 1504158381
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/ObjectPool.cs b/Main/ResModule/ObjectPool.cs
new file mode 100644
index 0000000..f747a11
--- /dev/null
+++ b/Main/ResModule/ObjectPool.cs
@@ -0,0 +1,93 @@
+锘縰sing System.Collections.Generic;
+using System;
+using UnityEngine;
+
+public class ObjectPool<T>
+{
+    /// <summary>
+    /// 姹犵殑鍫嗘爤
+    /// </summary>
+    private readonly Stack<T> m_Inactived = new Stack<T>();
+
+    /// <summary>
+    /// 姹犲璞℃�绘暟锛屽寘鎷凡婵�娲诲拰鏈縺娲�
+    /// </summary>
+    public int totalCount;
+
+    /// <summary>
+    /// 鍙栧緱褰撳墠杩樻湁澶氬皯婵�娲诲璞�
+    /// </summary>
+    public int activedCount
+    {
+        get
+        {
+            return totalCount - inactivedCount;
+        }
+    }
+
+    /// <summary>
+    /// 鍙栧緱姹犻噷杩樻湁澶氬皯瀵硅薄
+    /// </summary>
+    public int inactivedCount
+    {
+        get
+        {
+            return m_Inactived.Count;
+        }
+    }
+
+    private Action<T> m_OnObjectGet;// 渚涘閮ㄤ紶鍏ョ殑鍥炶皟鏂规硶锛屽湪鑾峰彇瀵硅薄鐨勬椂鍊欏璇ュ璞¤繘琛屼竴浜涘彲鑳芥槸鍒濆鍖栫殑鎿嶄綔
+    private Action<T> m_OnObjectRelease;// 渚涘閮ㄤ紶鍏ョ殑鍥炶皟鏂规硶锛屽湪閲婃斁瀵硅薄鐨勬椂鍊欏璇ュ璞¤繘琛屼竴浜涘彲鑳芥槸閲嶇疆鐨勬搷浣�
+
+    public ObjectPool(Action<T> onGetAction, Action<T> onReleaseAction)
+    {
+        m_OnObjectGet = onGetAction;
+        m_OnObjectRelease = onReleaseAction;
+    }
+
+    public void Add(T element)
+    {
+        m_Inactived.Push(element);
+        totalCount++;
+    }
+
+    public T Get()
+    {
+        T element;
+        // 閿欒淇濇姢
+        if (inactivedCount == 0)
+        {
+            Debug.LogWarningFormat("鑾峰彇姹犲璞℃椂锛屾睜宸茬粡涓虹┖.");
+            return default(T);
+        }
+        // 鍙栧緱姹犲璞�
+        element = m_Inactived.Pop();
+        // 鎵ц鑾峰彇閫昏緫
+        if (m_OnObjectGet != null)
+        {
+            m_OnObjectGet(element);
+        }
+        return element;
+    }
+
+    public void Release(T element)
+    {
+        // 閿欒淇濇姢
+        if (inactivedCount > 0 && ReferenceEquals(element, m_Inactived.Peek()))
+        {
+            Debug.LogWarningFormat("鍚戞睜閲婃斁瀵硅薄鐨勬椂鍊欏彂鐜帮紝璇ュ璞″凡缁忚閲婃斁浜�.", element.ToString());
+            return;
+        }
+        // 鎵ц澶栭儴浼犲叆鐨勯噴鏀鹃�昏緫
+        if (m_OnObjectRelease != null)
+        {
+            m_OnObjectRelease(element);
+        }
+        m_Inactived.Push(element);
+    }
+
+    public void Clear()
+    {
+        m_Inactived.Clear();
+    }
+}
\ No newline at end of file
diff --git a/Main/ResModule/ObjectPool.cs.meta b/Main/ResModule/ObjectPool.cs.meta
new file mode 100644
index 0000000..57ea840
--- /dev/null
+++ b/Main/ResModule/ObjectPool.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6a7055a3f3fdbf94685a497b5acf5bab
+timeCreated: 1504525306
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/SceneLoader.cs b/Main/ResModule/SceneLoader.cs
new file mode 100644
index 0000000..042d780
--- /dev/null
+++ b/Main/ResModule/SceneLoader.cs
@@ -0,0 +1,57 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SceneLoader
+{
+
+    public static GameObject LoadCreateRole(string name)
+    {
+        GameObject prefab = null;
+        if (AssetSource.sceneFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, "Scene/CreateRole/", name, ".prefab");
+            prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("maps/createrole", name);
+            prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+        }
+
+        if (prefab == null)
+        {
+            Debug.LogErrorFormat("SceneLoader.LoadCreateRole() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return prefab;
+    }
+
+    public static Texture2D LoadTexture(string folder, string name)
+    {
+        Texture2D texture2D = null;
+        if (AssetSource.sceneFromEditor)
+        {
+#if UNITY_EDITOR
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, "Scene/", folder, "/", name, ".jpg");
+            texture2D = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture2D>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo(StringUtility.Contact("maps/", folder).ToLower(), name);
+            texture2D = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as Texture2D;
+        }
+
+        if (texture2D == null)
+        {
+            Debug.LogErrorFormat("SceneLoader.LoadTexture() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+        }
+
+        return texture2D;
+    }
+
+
+}
diff --git a/Main/ResModule/SceneLoader.cs.meta b/Main/ResModule/SceneLoader.cs.meta
new file mode 100644
index 0000000..341c974
--- /dev/null
+++ b/Main/ResModule/SceneLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9965235d149da744dbefdf8340b2b351
+timeCreated: 1547718608
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/ScriptableObjectLoader.cs b/Main/ResModule/ScriptableObjectLoader.cs
new file mode 100644
index 0000000..9c11130
--- /dev/null
+++ b/Main/ResModule/ScriptableObjectLoader.cs
@@ -0,0 +1,490 @@
+锘縰sing UnityEngine;
+using System;
+
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+public class ScriptableObjectLoader
+{
+
+//     public const string bundleName = "config/scriptableobjects";
+//     public const string SoActor_Suffix = "SoActor_";
+//     public const string SoSkill_Suffix = "SoSkill_";
+//     public const string SoFlyObject_Suffix = "SoFlyObject_";
+//     public const string SoBodyControl_Suffix = "SoBodyControl_";
+//     public const string SoSweepHit_Suffix = "SoSweepHit_";
+//     public const string SoCameraSFX_Suffix = "SoCameraSFX_";
+//     public const string SoDeadFly_Suffix = "SoDeadFly_";
+//     public const string SoGhostShadow_Suffix = "SoGhostShadow_";
+//     public const string SoNewBieGuide_Suffix = "NewBieGuideStep_";
+//     public const string SoFunctionalGuide_Suffix = "FunctionalGuideStep_";
+//     public const string SoMapObjectGenerate_Suffix = "SoMapObjectGenerate_";
+//     public const string SoTreasureMeridian_Suffix = "SoTreasureMeridian_";
+//     public const string SoTreasure3D_Suffix = "SoTreasure3D_";
+//     public const string SoDemonDungeon_Suffix = "SoDemonDungeon_";
+//     public const string SoHazyMapNpc_Suffix = "SoHazyMapNpc_";
+
+//     public static SoMap LoadSoMapObjectGenerate(int mapID)
+//     {
+//         SoMap _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                        "Refdata/ScriptableObject/SoMapObjectGenerate/",
+//                                                        SoMapObjectGenerate_Suffix,
+//                                                        mapID,
+//                                                        ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoMap>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoMapObjectGenerate_Suffix, mapID);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoMap;
+//         }
+
+//         if (_config == null)
+//         {
+//             DebugEx.LogErrorFormat("ScriptableObjectLoader.LoadSoActor() => 鍔犺浇涓嶅埌璧勬簮: {0}.", mapID);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoActor LoadSoActor(int raceId)
+//     {
+//         SoActor _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoActor/",
+//                                                    SoActor_Suffix,
+//                                                    raceId,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoActor>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoActor_Suffix, raceId);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoActor;
+//         }
+
+//         if (_config == null)
+//         {
+//             DebugEx.LogErrorFormat("ScriptableObjectLoader.LoadSoActor() => 鍔犺浇涓嶅埌璧勬簮: {0}.", raceId);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoSkill LoadSoSkill(int skillId)
+//     {
+//         SoSkill _config = null;
+
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoSkill/",
+//                                                    SoSkill_Suffix,
+//                                                    skillId,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoSkill>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoSkill_Suffix, skillId);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoSkill;
+//         }
+
+//         if (_config == null)
+//         {
+//             //Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoSkill() => 鍔犺浇涓嶅埌璧勬簮: {0}.", skillId);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoFlyObject LoadSoFlyObject(int id)
+//     {
+//         SoFlyObject _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoFlyObject/",
+//                                                    SoFlyObject_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoFlyObject>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoFlyObject_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoFlyObject;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoFlyObject() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoSweepHit LoadSoSweepHit(int id)
+//     {
+//         SoSweepHit _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoSweepHit/",
+//                                                    SoSweepHit_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoSweepHit>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoSweepHit_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoSweepHit;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoSweepHit() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoBodyControl LoadSoBodyControl(int id)
+//     {
+//         SoBodyControl _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoBodyControl/",
+//                                                    SoBodyControl_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoBodyControl>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoBodyControl_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoBodyControl;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoBodyControl() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+//     }
+
+//     public static SoCameraSFX LoadSoCameraSFX(int id)
+//     {
+//         SoCameraSFX _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoCameraSFX/",
+//                                                    SoCameraSFX_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoCameraSFX>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoCameraSFX_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoCameraSFX;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoCameraSFX() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+//     }
+
+//     public static SoDeadFly LoadSoDeadFly(int id)
+//     {
+//         SoDeadFly _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoDeadFly/",
+//                                                    SoDeadFly_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoDeadFly>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoDeadFly_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoDeadFly;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoCameraSFX() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+
+//     }
+
+//     public static SoGhostShadow LoadSoGhostShadow(int id)
+//     {
+//         SoGhostShadow _config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             string _resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoGhostShadow/",
+//                                                    SoGhostShadow_Suffix,
+//                                                    id,
+//                                                    ".asset");
+
+//             _config = AssetDatabase.LoadAssetAtPath<SoGhostShadow>(_resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             string _assetName = StringUtility.Contact(SoGhostShadow_Suffix, id);
+//             AssetInfo _assetInfo = new AssetInfo(bundleName, _assetName);
+//             _config = AssetBundleUtility.Instance.Sync_LoadAsset(_assetInfo) as SoGhostShadow;
+//         }
+
+//         if (_config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoGhostShadow() => 鍔犺浇涓嶅埌璧勬簮: {0}.", id);
+//         }
+
+//         return _config;
+//     }
+
+//     public static NewBieGuideScriptableObject LoadSoNewBieGuideStep(int _id)
+//     {
+//         NewBieGuideScriptableObject config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoNewBieGuide/",
+//                                                    SoNewBieGuide_Suffix,
+//                                                    _id,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<NewBieGuideScriptableObject>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoNewBieGuide_Suffix, _id);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as NewBieGuideScriptableObject;
+//         }
+
+//         if (config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoNewBieGuideStep() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _id);
+//         }
+
+//         return config;
+//     }
+
+//     public static NewBieGuideScriptableObject LoadSoFunctionalGuideStep(int _id)
+//     {
+//         NewBieGuideScriptableObject config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoNewBieGuide/",
+//                                                    SoFunctionalGuide_Suffix,
+//                                                    _id,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<NewBieGuideScriptableObject>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoFunctionalGuide_Suffix, _id);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as NewBieGuideScriptableObject;
+//         }
+
+//         if (config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoFunctionalGuideStep() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _id);
+//         }
+
+//         return config;
+//     }
+
+//     public static TreasureMeridianConfig LoadSoTreasureMeridian(int _id)
+//     {
+//         TreasureMeridianConfig config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoTreasureMeridian/",
+//                                                    SoTreasureMeridian_Suffix,
+//                                                    _id,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<TreasureMeridianConfig>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoTreasureMeridian_Suffix, _id);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as TreasureMeridianConfig;
+//         }
+
+//         if (config == null)
+//         {
+//             Debug.LogErrorFormat("ScriptableObjectLoader.TreasureMeridianConfig() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _id);
+//         }
+
+//         return config;
+//     }
+
+//     public static Treasure3DConfig LoadSoTreasure3DConfig(int _id)
+//     {
+//         Treasure3DConfig config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoTreasure3D/",
+//                                                    SoTreasure3D_Suffix,
+//                                                    _id,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<Treasure3DConfig>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoTreasure3D_Suffix, _id);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as Treasure3DConfig;
+//         }
+
+//         if (config == null)
+//         {
+//             //Debug.LogErrorFormat("ScriptableObjectLoader.TreasureMeridianConfig() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _id);
+//         }
+
+//         return config;
+//     }
+
+//     public static DemonDungeonScriptable LoadSoDemonDungeon(int _id)
+//     {
+//         DemonDungeonScriptable config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoDemonDungeon/",
+//                                                    SoDemonDungeon_Suffix,
+//                                                    _id,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<DemonDungeonScriptable>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoDemonDungeon_Suffix, _id);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as DemonDungeonScriptable;
+//         }
+
+//         if (config == null)
+//         {
+//             //Debug.LogErrorFormat("ScriptableObjectLoader.TreasureMeridianConfig() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _id);
+//         }
+
+//         return config;
+//     }
+
+//     public static HazyMapNpcScriptableObject LoadSoHazyMapNpc(int _mapId)
+//     {
+//         HazyMapNpcScriptableObject config = null;
+//         if (AssetSource.refdataFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                    "Refdata/ScriptableObject/SoHazyMapNpc/",
+//                                                    SoHazyMapNpc_Suffix,
+//                                                    _mapId,
+//                                                    ".asset");
+
+//             config = AssetDatabase.LoadAssetAtPath<HazyMapNpcScriptableObject>(resourcePath);
+// #endif
+//         }
+//         else
+//         {
+//             var assetName = StringUtility.Contact(SoHazyMapNpc_Suffix, _mapId);
+//             var assetInfo = new AssetInfo(bundleName, assetName);
+//             config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as HazyMapNpcScriptableObject;
+//         }
+
+//         if (config == null)
+//         {
+//         }
+
+//         return config;
+//     }
+}
\ No newline at end of file
diff --git a/Main/ResModule/ScriptableObjectLoader.cs.meta b/Main/ResModule/ScriptableObjectLoader.cs.meta
new file mode 100644
index 0000000..3ca2583
--- /dev/null
+++ b/Main/ResModule/ScriptableObjectLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a931a089f7045294f91a15bc047d72e2
+timeCreated: 1504164167
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/UILoader.cs b/Main/ResModule/UILoader.cs
new file mode 100644
index 0000000..b965037
--- /dev/null
+++ b/Main/ResModule/UILoader.cs
@@ -0,0 +1,374 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+using System.IO;
+using UnityEngine.U2D;
+
+
+// public class UILoader
+// {
+//     readonly static string PREFAB_EXTERSION = ".prefab";
+//     readonly static string SPRITE_EXTERSION = ".png"; 
+//     readonly static string Spriteatlas_EXTERSION = ".spriteatlasv2";
+
+//     public static GameObject LoadWindow(string name)
+//     {
+//         GameObject window = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var isPriority = false;//PriorityWindowConfig.Get().priorityWindows.Contains(name);
+
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                 isPriority ? ResourcesPath.UI_PRIORITYWINDOW_SUFFIX : ResourcesPath.UI_WINDOW_SUFFIX, "/",
+//                                                                 name,
+//                                                                 PREFAB_EXTERSION);
+
+//             window = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             // var isPriority = PriorityWindowConfig.Get().priorityWindows.Contains(name);
+//             var bundleName = "ui/window";
+
+//             var assetInfo = new AssetInfo(bundleName, name);
+
+//             window = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (window == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadWindow() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+//         }
+
+//         return window;
+//     }
+
+//     public static void LoadWindowAsync(string _name, Action<bool, UnityEngine.Object> _callBack)
+//     {
+//         GameObject window = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var isPriority = PriorityWindowConfig.Get().priorityWindows.Contains(_name);
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                isPriority ? ResourcesPath.UI_PRIORITYWINDOW_SUFFIX : ResourcesPath.UI_WINDOW_SUFFIX, "/",
+//                                                                _name,
+//                                                                PREFAB_EXTERSION);
+
+//             window = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+//             if (_callBack != null)
+//             {
+//                 _callBack(window != null, window);
+//             }
+// #endif
+//         }
+//         else
+//         {
+//             var isPriority = PriorityWindowConfig.Get().priorityWindows.Contains(_name);
+//             var bundleName = isPriority ? StringUtility.Contact("ui/prioritywindow/", _name) : "ui/window";
+//             var assetInfo = new AssetInfo(bundleName, _name);
+
+//             AssetBundleUtility.Instance.Co_LoadAsset(assetInfo, _callBack);
+//         }
+//     }
+
+//     public static void UnLoadWindowAsset(string _assetName)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             var isPriority = PriorityWindowConfig.Get().priorityWindows.Contains(_assetName);
+//             var bundleName = isPriority ? StringUtility.Contact("ui/prioritywindow/", _assetName) : "ui/window";
+
+//             AssetBundleUtility.Instance.UnloadAsset(bundleName, _assetName);
+//         }
+//     }
+
+//     public static void UnLoadPriorityWindow(string windowName)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             var assetBundleName = StringUtility.Contact("ui/prioritywindow/", windowName.ToLower());
+//             AssetBundleUtility.Instance.UnloadAssetBundle(assetBundleName, true, false);
+
+//             switch (windowName)
+//             {
+//                 case "LoginWin":
+//                     AssetBundleUtility.Instance.UnloadAssetBundle("ui/sprite/login", true, false);
+//                     break;
+//                 case "SelectRoleWin":
+//                 case "CreateRoleWin":
+//                     AssetBundleUtility.Instance.UnloadAssetBundle("ui/sprite/createrole", true, false);
+//                     break;
+//             }
+//         }
+//     }
+
+//     public static GameObject LoadPrefab(string _name)
+//     {
+//         GameObject prefab = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                    ResourcesPath.UI_PREFAB_SUFFIX, "/",
+//                                                                    _name,
+//                                                                    PREFAB_EXTERSION);
+
+//             prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = ResourcesPath.UI_PREFAB_SUFFIX.ToLower();
+//             var assetInfo = new AssetInfo(bundleName, _name);
+
+//             prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (prefab == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadPrefab() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _name);
+//         }
+
+//         return prefab;
+//     }
+
+//     public static void UnLoadPrefab(string _assetName)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             AssetBundleUtility.Instance.UnloadAsset("ui/prefab", _assetName);
+//         }
+//     }
+
+//     public static Sprite LoadSprite(string _iconKey)
+//     {
+//         var iconConfig = IconConfig.Get(_iconKey);
+//         if (iconConfig == null)
+//         {
+//             return null;
+//         }
+
+//         return LoadSprite(iconConfig.folder, iconConfig.sprite);
+//     }
+
+//     public static Sprite LoadSprite(string _folder, string _file)
+//     {
+//         var folder = _folder;
+//         var file = _file;
+
+//         Sprite sprite = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var relativePath = folder;
+//             var rootPath = ResourcesPath.UI_SPRITE_SUFFIX;
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                  rootPath, "/",
+//                                                                  relativePath,
+//                                                                  Spriteatlas_EXTERSION);
+
+//             var spriteAtlas = UnityEditor.AssetDatabase.LoadAssetAtPath<SpriteAtlas>(path);
+//             sprite = spriteAtlas.GetSprite(file);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = StringUtility.Contact("ui/sprite/", folder.ToLower());
+//             //var assetInfo = new AssetInfo(bundleName, folder);
+
+//             //var spriteAtlas = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(SpriteAtlas)) as SpriteAtlas;
+//             //sprite = spriteAtlas?.GetSprite(_file);
+//             var assetInfo = new AssetInfo(bundleName, file);
+
+//             sprite = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(Sprite)) as Sprite;
+//         }
+
+//         if (sprite == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadSprite() => 鍔犺浇涓嶅埌璧勬簮: {0}.", file);
+//         }
+
+//         return sprite;
+//     }
+
+//     public static void UnLoadSprite(string _iconKey)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             var iconConfig = IconConfig.Get(_iconKey);
+//             if (iconConfig != null)
+//             {
+//                 var bundleName = StringUtility.Contact("ui/sprite/", iconConfig.folder.ToLower());
+//                 AssetBundleUtility.Instance.UnloadAsset(bundleName, iconConfig.sprite);
+//             }
+//         }
+
+//     }
+
+//     public static Font LoadFont(string _fontName)
+//     {
+//         Font font = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var rootPath = ResourcesPath.UI_FONT_SUFFIX;
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, rootPath, "/", _fontName, ".ttf");
+//             font = UnityEditor.AssetDatabase.LoadAssetAtPath<Font>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var assetInfo = new AssetInfo("ui/font", _fontName);
+//             font = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(Font)) as Font;
+//         }
+
+//         if (font == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadFont() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _fontName);
+//         }
+
+//         return font;
+//     }
+
+//     public static void UnLoadFont(string _fontName)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             AssetBundleUtility.Instance.UnloadAsset("ui/font", _fontName);
+//         }
+//     }
+
+//     public static GameObject LoadTreasure(string folder, string name)
+//     {
+//         GameObject prefab = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                    "UI/Treasure/", folder, "/",
+//                                                                    name,
+//                                                                    PREFAB_EXTERSION);
+
+//             prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = StringUtility.Contact("ui/treasure/", folder).ToLower();
+//             var assetInfo = new AssetInfo(bundleName, name);
+
+//             prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (prefab == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadPrefab() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+//         }
+
+//         return prefab;
+//     }
+
+//     public static void UnLoadTreasure(string folder, string _assetName)
+//     {
+//         if (!AssetSource.uiFromEditor)
+//         {
+//             AssetBundleUtility.Instance.UnloadAsset(StringUtility.Contact("ui/treasure/", folder).ToLower(), _assetName);
+//         }
+//     }
+
+//     public static GameObject LoadFaqi(string pathName, string name)
+//     {
+//         GameObject prefab = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                    //"UI/Treasure/", folder, "/",
+//                                                                    pathName,
+//                                                                    name,
+//                                                                    PREFAB_EXTERSION);
+
+//             prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = pathName; //StringUtility.Contact("ui/treasure/", folder).ToLower();
+//             var assetInfo = new AssetInfo(bundleName, name);
+
+//             prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (prefab == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadFaqi() => 鍔犺浇涓嶅埌璧勬簮: {0}.", name);
+//         }
+
+//         return prefab;
+//     }
+
+
+//     public static GameObject LoadGodWeapon(string _name)
+//     {
+//         GameObject prefab = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                    "UI/GodWeapon/",
+//                                                                    _name,
+//                                                                    PREFAB_EXTERSION);
+
+//             prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = "ui/godweapon";
+//             var assetInfo = new AssetInfo(bundleName, _name);
+//             prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (prefab == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadGodWeapon() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _name);
+//         }
+
+//         return prefab;
+//     }
+
+//     public static GameObject LoadBossShow(string _name)
+//     {
+//         GameObject prefab = null;
+//         if (AssetSource.uiFromEditor)
+//         {
+// #if UNITY_EDITOR
+//             var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
+//                                                                    "UI/BossShow/",
+//                                                                    _name,
+//                                                                    PREFAB_EXTERSION);
+
+//             prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
+// #endif
+//         }
+//         else
+//         {
+//             var bundleName = "ui/bossshow";
+//             var assetInfo = new AssetInfo(bundleName, _name);
+//             prefab = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as GameObject;
+//         }
+
+//         if (prefab == null)
+//         {
+//             Debug.LogErrorFormat("UILoader.LoadBossShow() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _name);
+//         }
+
+//         return prefab;
+//     }
+
+// }
diff --git a/Main/ResModule/UILoader.cs.meta b/Main/ResModule/UILoader.cs.meta
new file mode 100644
index 0000000..1445d3f
--- /dev/null
+++ b/Main/ResModule/UILoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8b5d63ac5989cdc46ad7406f238ba446
+timeCreated: 1504310902
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/ResModule/VideoLoader.cs b/Main/ResModule/VideoLoader.cs
new file mode 100644
index 0000000..4afbcbf
--- /dev/null
+++ b/Main/ResModule/VideoLoader.cs
@@ -0,0 +1,61 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Video;
+
+public class VideoLoader
+{
+
+    static string MP4_EXTERSION = ".mp4";
+
+    public static VideoClip Load(string _clipName)
+    {
+        VideoClip videoClip = null;
+        if (AssetSource.videoFromEditor)
+        {
+#if UNITY_EDITOR
+            var fileName = StringUtility.Contact("/", _clipName, MP4_EXTERSION);
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, ResourcesPath.VIDEO_SUFFIX, fileName);
+            videoClip = UnityEditor.AssetDatabase.LoadAssetAtPath<VideoClip>(path);
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("video/" + _clipName, _clipName);
+            videoClip = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as VideoClip;
+        }
+
+        if (videoClip == null)
+        {
+            Debug.LogErrorFormat("AudioLoader.LoadSkillAudio() => 鍔犺浇涓嶅埌璧勬簮: {0}.", _clipName);
+        }
+
+        return videoClip;
+    }
+
+    public static void LoadAsync(string _folderName, string _clipName, Action<bool, UnityEngine.Object> _callBack)
+    {
+        VideoClip videoClip = null;
+        if (AssetSource.audioFromEditor)
+        {
+#if UNITY_EDITOR
+            var fileName = StringUtility.Contact("/", _clipName, MP4_EXTERSION);
+            var path = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, ResourcesPath.VIDEO_SUFFIX, _folderName, fileName);
+            videoClip = UnityEditor.AssetDatabase.LoadAssetAtPath<VideoClip>(path);
+
+            if (_callBack != null)
+            {
+                _callBack(true, videoClip);
+            }
+#endif
+        }
+        else
+        {
+            var assetInfo = new AssetInfo("video/mp4", _clipName);
+            AssetBundleUtility.Instance.Co_LoadAsset(assetInfo, _callBack);
+        }
+
+    }
+
+}
diff --git a/Main/ResModule/VideoLoader.cs.meta b/Main/ResModule/VideoLoader.cs.meta
new file mode 100644
index 0000000..d95b9e4
--- /dev/null
+++ b/Main/ResModule/VideoLoader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 288ed29d137c09c43959063f8d4e3dd2
+timeCreated: 1557279838
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/SDK.meta b/Main/SDK.meta
new file mode 100644
index 0000000..77636e4
--- /dev/null
+++ b/Main/SDK.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 85959cd8b16df0c498f19d7fca26b339
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/SDK/SDKUtils.cs b/Main/SDK/SDKUtils.cs
new file mode 100644
index 0000000..041f154
--- /dev/null
+++ b/Main/SDK/SDKUtils.cs
@@ -0,0 +1,1463 @@
+锘縰sing UnityEngine;
+using LitJson;
+using UnityEngine.Events;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System;
+using UnityEngine.Android;
+
+public class SDKUtils : SingletonMonobehaviour<SDKUtils>
+{
+    public enum E_ChargingType
+    {
+        NoCharging = 1,
+        Charging = 2,
+        ChargingFull = 3,
+    }
+
+    public enum E_ChannelPlatform
+    {
+        Free = 1,// 鑷敱
+        Mr = 2,// 鐚��
+        Sp = 3,// 鎬濈挒
+        Js = 4,// 鏋侀��
+        Yj = 5,// 鏄撴帴
+        Yl = 6,// 鏄撲箰
+        Xn = 7,// 灏忕墰
+        Cjm = 8,// 瓒呯骇姊�
+        Ky = 9,//鎭鸿嫳
+        Quick = 10, //quick
+        SanXia = 11, //涓夊场锛堟腐鍙颁娇鐢級
+        SanXiaiOS = 12, //涓夊场 锛堟腐鍙癷os浣跨敤锛�
+        Hy = 15, //娆㈡父
+        hygt = 16, //娆㈡父娓彴
+        mlgt = 17, //鍜櫆娓彴
+        newyn = 19, //鏂扮殑瓒婂崡锛堟娓�0.1锛�
+        en = 20, //鑻辨枃鐗�
+    }
+
+    //鏉冮檺鐢宠鍥炶皟
+    private Action<string, int> onPermissionCallBack;
+
+    public event Action<int, JsonData> onSdkMsg;
+
+    public E_ChannelPlatform ChannelPlatform { get; set; }
+
+    public static string Yj_AppID
+    {
+        get; private set;
+    }
+
+    public static string ThirdPartVersion
+    {
+        get; private set;
+    }
+
+    public static string Yj_SpID
+    {
+        get; private set;
+    }
+
+    public static string ThirdPartAppID
+    {
+        get; private set;
+    }
+
+    public static string Yj_BanHao
+    {
+        get; private set;
+    }
+
+    // 鏄惁鍚屾剰闅愮鏀跨瓥
+    public bool IsAgreeSecret = false;
+
+    /// <summary>
+    /// sdk鍒濆鍖栨槸鍚﹀畬鎴愭爣璇�
+    /// 瀹㈡埛绔竴鑸渶瑕佺瓑寰呰繖涓�间负true鎵嶇户缁�昏緫
+    /// </summary>
+    public bool InitFinished { get; private set; }
+
+    #region 鍩虹瀹氫箟涓庡洖璋�
+
+    /// <summary>
+    /// 褰撳墠璁惧鐢甸噺鍊�
+    /// </summary>
+    public int BatteryLevel { get; private set; }
+    /// <summary>
+    /// 璁惧鐢甸噺鍊兼敼鍙樺洖璋�
+    /// </summary>
+    public UnityAction<int> OnBatteryLevelChanged;
+
+    /// <summary>
+    /// 褰撳墠鍏呯數鐘舵��
+    /// </summary>
+    public E_ChargingType ChargingType { get; private set; }
+    /// <summary>
+    /// 褰撳墠鍏呯數鐘舵�佹敼鍙樺洖璋�
+    /// </summary>
+    public UnityAction<E_ChargingType> OnChargingTypeChanged;
+
+    /// <summary>
+    /// 璁惧淇℃伅
+    /// </summary>
+    public DeviceInfo Device { get; private set; }
+    /// <summary>
+    /// 璁惧淇℃伅鏀瑰彉鍥炶皟
+    /// </summary>
+    public UnityAction<DeviceInfo> OnDeviceInfoChanged;
+
+    /// <summary>
+    /// 褰撳墠缃戠粶鐘舵��
+    /// </summary>
+    public NetworkReachability NetworkType { get; private set; }
+    /// <summary>
+    /// 褰撳墠缃戠粶鐘舵�佹敼鍙樺洖璋�
+    /// </summary>
+    public UnityAction<NetworkReachability> OnNetworkStatusChanged;
+
+    public static bool builtinAssetCopyFinished { get; private set; }
+
+    /// <summary>
+    /// 鏄惁宸茬粡灏哠treamingAsset鎷疯礉鑷崇洰鏍囪矾寰�
+    /// </summary>
+    public bool AssetCopyFinished { get; private set; }
+
+    /// <summary>
+    /// 瀹夊崜璁惧鏍圭洰褰�
+    /// </summary>
+    public string DeviceRootPath { get; private set; }
+
+    #endregion
+
+    #region 鏋佸厜鎺ㄩ��
+    public string RegistrationID { get; private set; }
+    #endregion
+
+    #region 鑷敱sdk
+    public FP_LoginOk FreePlatformInfo { get; private set; }
+    #endregion
+
+    private JsonData m_Json = new JsonData();
+
+    public void Init()
+    {
+        Device = new DeviceInfo();
+        string uid = LocalSave.GetString("Device_uniqueID");
+        //Debug.Log(Math.Abs(System.Environment.TickCount));
+        if (uid.Length <= 5)
+        {
+            long tick = Math.Abs(System.Environment.TickCount);
+            uid = tick.ToString() + UnityEngine.Random.Range(1, ulong.MaxValue/*Constants.ExpPointValue*/).ToString();
+            LocalSave.SetString("Device_uniqueID", uid);
+        }
+        Device.uniqueID = uid;
+
+        Debug.Log(Device.uniqueID);
+
+        Yj_AppID = string.Empty;
+        Yj_SpID = string.Empty;
+        ThirdPartVersion = string.Empty;
+        RegistrationID = string.Empty;
+        AssetCopyFinished = false;
+        ChannelPlatform = E_ChannelPlatform.Free;
+        NetworkType = NetworkReachability.NotReachable;
+        BatteryLevel = 100;
+
+#if !UNITY_EDITOR
+        if (InitFinished)
+        {
+            return;
+        }
+#if UNITY_ANDROID
+        var builtinAssetsCopyFinishVersion = LocalSave.GetString("BuiltInAssetCopyCompleted_Android");
+        if (string.IsNullOrEmpty(builtinAssetsCopyFinishVersion))
+        {
+            builtinAssetCopyFinished = false;
+        }
+        else
+        {
+            builtinAssetCopyFinished = VersionConfig.Get().version == builtinAssetsCopyFinishVersion;
+        }
+#endif
+#if UNITY_IOS || UNITY_STANDALONE
+        var builtinAssetsCopyFinishVersion = LocalSave.GetString("BuiltInAssetCopyCompleted_IOSorStandalone");
+        if (string.IsNullOrEmpty(builtinAssetsCopyFinishVersion))
+        {
+            builtinAssetCopyFinished = false;
+        }
+        else
+        {
+            builtinAssetCopyFinished = VersionConfig.Get().version == builtinAssetsCopyFinishVersion;
+        }
+
+        var assetsCopyFinishVersion = LocalSave.GetString("AssetCopyCompleted_IOSorStandalone");
+        if (string.IsNullOrEmpty(assetsCopyFinishVersion))
+        {
+            AssetCopyFinished = false;
+        }
+        else
+        {
+            AssetCopyFinished = VersionConfig.Get().version == assetsCopyFinishVersion;
+        }
+
+#elif UNITY_ANDROID
+        SyncClientPackageID();
+#endif
+
+        InitFinished = false;
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.Init;
+        m_Json["appID"] = VersionConfig.Get().appId;
+        m_Json["gameID"] = VersionConfig.Get().gameId;
+        SendMessageToSDK(m_Json);
+#endif
+        StartCoroutine("ProcessNetworkStatus");
+    }
+
+    private void OnApplicationFocus(bool focus)
+    {
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        if (focus)
+        {
+            m_Json["code"] = CodeU2A.BatteryListenStart;
+            StopCoroutine("ProcessNetworkStatus");
+            StartCoroutine("ProcessNetworkStatus");
+        }
+        else
+        {
+            m_Json["code"] = CodeU2A.BatteryListenStop;
+            StopCoroutine("ProcessNetworkStatus");
+        }
+        SendMessageToSDK(m_Json);
+#endif
+    }
+
+    private IEnumerator ProcessNetworkStatus()
+    {
+        while (true)
+        {
+            if (Application.internetReachability != NetworkType)
+            {
+                NetworkType = Application.internetReachability;
+
+                if (OnNetworkStatusChanged != null)
+                {
+                    OnNetworkStatusChanged(NetworkType);
+                }
+            }
+
+            yield return new WaitForSeconds(1f);
+            // yield return WaitingForSecondConst.WaitMS1000;
+        }
+    }
+
+    #region 涓氬姟灞傚畾涔夌浉鍏抽�昏緫
+
+    public void InstallAPK(string path)
+    {
+        if (Application.platform == RuntimePlatform.Android)
+        {
+            var dllPath1 = ResourcesPath.Instance.ExternalStorePath + "Assembly-CSharp-firstpass.dll";
+            if (File.Exists(dllPath1))
+            {
+                File.Delete(dllPath1);
+            }
+
+            var dllPath2 = ResourcesPath.Instance.ExternalStorePath + "Assembly-CSharp.dll";
+            if (File.Exists(dllPath2))
+            {
+                File.Delete(dllPath2);
+            }
+        }
+
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.InstallAPK;
+        m_Json["path"] = path;
+        SendMessageToSDK(m_Json);
+    }
+
+    //0 :鎷疯礉鎵�鏈夎祫婧� 1:鎷疯礉Config
+    public void CopyAsset(int copyType = 0)
+    {
+        if (AssetCopyFinished)
+        {
+            return;
+        }
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.CopyAsset;
+        m_Json["copyType"] = copyType;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void CopyOneAsset(string relationPath)
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.CopyOneAsset;
+        m_Json["fileName"] = relationPath;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void CopyContent(string content)
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.CopyContent;
+        m_Json["content"] = content;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void RestartApp()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.RestartApp;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void OpenUrl(string url)
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.OpenWebView;
+        m_Json["url"] = url;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void MakeKeyAndVisible()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.MakeKeyAndVisible;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void SyncClientPackageID()
+    {
+#if UNITY_ANDROID
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.ClientPackage;
+        m_Json["clientPkgID"] = VersionConfig.Get().clientPackageFlag;
+        SendMessageToSDK(m_Json);
+#endif
+    }
+
+    //鐢宠Android 鏉冮檺
+    public void RequestAndroidPermission(string permission, Action<string, int> callBack)
+    {
+        onPermissionCallBack += callBack;
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.RequestPermission;
+        m_Json["permission"] = permission;
+        SendMessageToSDK(m_Json);
+    }
+
+    //鐢宠Android 鏉冮檺 鍚姩鏃�
+    public void RequestAndroidPermissionStart()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.RequestPermissionStart;
+        SendMessageToSDK(m_Json);
+    }
+
+
+    //璺宠浆搴旂敤鍟嗗簵
+    public void GoToAppStore(string url, string marketPkg = "")
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.GoToAppStore;
+        m_Json["marketPkg"] = marketPkg;
+        m_Json["url"] = url;
+        SendMessageToSDK(m_Json);
+    }
+
+    #endregion
+
+    #region 澶勭悊涓嶴DK浜や簰鐨勫簳灞傛柟娉�
+
+    public static AndroidJavaObject GetApplicationContext()
+    {
+        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
+        {
+            using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
+            {
+                return jo.Call<AndroidJavaObject>("getApplicationContext");
+            }
+        }
+    }
+
+    public string GetSplicePackageID()
+    {
+        var _result = "default";
+        switch (Application.platform)
+        {
+            case RuntimePlatform.Android:
+                if (ChannelPlatform == E_ChannelPlatform.Sp)
+                {
+                    using (AndroidJavaClass _jc = new AndroidJavaClass("com.sp.sdk.utils.SDKManagerUtils"))
+                    {
+                        using (AndroidJavaObject _jo = _jc.CallStatic<AndroidJavaObject>("getAssetPropConfig", GetApplicationContext(), "plugin_config.properties"))
+                        {
+                            _result = _jo.Call<string>("get", "game_id");
+                        }
+                    }
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.Mr)
+                {
+                    using (AndroidJavaClass _jc = new AndroidJavaClass("com.secondworld.univeralsdk.UniversalUtil"))
+                    {
+                        _result = _jc.CallStatic<string>("getMetaString", "Mr_GAME_ID");
+                    }
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.Js)
+                {
+                    using (AndroidJavaClass _jc = new AndroidJavaClass("com.secondworld.univeralsdk.UniversalUtil"))
+                    {
+                        _result = _jc.CallStatic<string>("getMetaString", "LL_APPID");
+                    }
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.Free)
+                {
+                    _result = "freeplatform";
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.Yl)
+                {
+                    _result = "yileplatform";
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.Ky)
+                {
+                    _result = "kyplatform";
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.hygt)
+                {
+                    _result = "hygt";
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.newyn)
+                {
+                    _result = "vn";
+                }
+                else if (ChannelPlatform == E_ChannelPlatform.en)
+                {
+                    _result = "en";
+                }
+                break;
+            case RuntimePlatform.IPhonePlayer:
+                _result = "ios";//ios骞冲彴鍥哄畾杩斿洖ios
+                break;
+        }
+
+        return _result;
+    }
+
+    private void SendMessageToSDK(JsonData json)
+    {
+
+#if !UNITY_EDITOR
+#if UNITY_ANDROID
+        using (AndroidJavaClass H2engineSDK = new AndroidJavaClass("com.secondworld.sdk.UnityMsgHandler"))
+        {
+            H2engineSDK.CallStatic("onUnityMessage", json.ToJson());
+        }
+#elif UNITY_IOS
+        AotSdkUtility.IOSUniyMessageHandle(json.ToJson());
+#elif UNITY_STANDALONE
+        InitFinished=true;
+#endif
+        
+#endif
+
+    }
+
+    public void HandleMsgWithSDK(string jsonString)
+    {
+//         Debug.Log("鏀跺埌SDK鍙戞潵鐨勪俊鎭�: " + jsonString);
+//         var _json = JsonMapper.ToObject(jsonString);
+//         var _code = (int)_json["code"];
+//         switch (_code)
+//         {
+//             case CodeA2U.DeviceInfo:
+
+
+//                 //Device.uniqueID = _json["unique_id"].ToString();
+//                 Device.androidID = _json["android_id"].ToString();// ios骞冲彴涓嬩负idfa
+//                 Device.userAgent = _json["userAgent"].ToString();
+// #if UNITY_ANDROID
+//                 Device.macAddress = _json["mac"].ToString();
+//                 if (_json["imei"] != null)
+//                 {
+//                     Device.imei = _json["imei"].ToString();
+//                 }
+//                 else
+//                 {
+//                     Device.imei = Device.uniqueID;
+//                 }
+//                 Device.totalMemory = (int)_json["memoryTotal"];
+// #endif
+//                 if (OnDeviceInfoChanged != null)
+//                 {
+//                     OnDeviceInfoChanged(Device);
+//                 }
+
+//                 break;
+//             case CodeA2U.AssetCopyFinished:
+//                 AssetCopyFinished = true;
+//                 break;
+//             case CodeA2U.BatteryLevel:
+
+//                 BatteryLevel = (int)_json["level"];
+//                 if (OnBatteryLevelChanged != null)
+//                 {
+//                     OnBatteryLevelChanged(BatteryLevel);
+//                 }
+
+//                 break;
+//             case CodeA2U.BatteryCharging:
+
+//                 ChargingType = (E_ChargingType)((int)_json["status"]);
+//                 if (OnChargingTypeChanged != null)
+//                 {
+//                     OnChargingTypeChanged(ChargingType);
+//                 }
+
+//                 break;
+//             case CodeA2U.SdkInitComplete:
+//                 InitFinished = true;
+//                 var _dict = _json as IDictionary;
+//                 if (_dict != null && _dict.Contains("channelPlatform"))
+//                 {
+//                     var _channelPlatform = _json["channelPlatform"].ToString();
+//                     if (!string.IsNullOrEmpty(_channelPlatform))
+//                     {
+//                         if (_channelPlatform.Equals("hygame"))
+//                         {
+//                             ChannelPlatform = E_ChannelPlatform.Hy;
+//                         }
+//                         else if (_channelPlatform.Equals("quick"))
+//                         {
+//                             ChannelPlatform = E_ChannelPlatform.Quick;
+//                         }
+//                         else if (_channelPlatform.Equals("hyyn"))
+//                         {
+//                             ChannelPlatform = E_ChannelPlatform.newyn;
+//                         }
+//                         else if (_channelPlatform.Equals("hygtgame"))
+//                         {
+//                             ChannelPlatform = E_ChannelPlatform.hygt;
+//                         }
+//                         else if (_channelPlatform.Equals("hyenglish"))
+//                         {
+//                             ChannelPlatform = E_ChannelPlatform.en;
+//                         }
+//                     }
+//                 }
+
+//                 //Sdk 鍙兘浼氫慨鏀规笭閬撲俊鎭紝鎵�浠ラ渶瑕侀噸鏂拌幏鍙�
+//                 if (_dict.Contains("yj_appid"))
+//                 {
+//                     Yj_AppID = _json["yj_appid"].ToString();
+//                 }
+
+//                 if (_dict.Contains("yj_spid"))
+//                 {
+//                     Yj_SpID = _json["yj_spid"].ToString();
+//                 }
+
+//                 if (_dict.Contains("banhao"))
+//                 {
+//                     Yj_BanHao = _json["banhao"].ToString();
+//                 }
+
+//                 break;
+//             case CodeA2U.PushClientID:
+//                 RegistrationID = _json["clientID"].ToString();
+//                 break;
+//             case CodeA2U.ExternalStorage:
+//                 DeviceRootPath = _json["path"].ToString();
+//                 break;
+//             case CodeA2U.PermissionCallBack:
+//                 {
+//                     var state = (int)_json["state"];
+//                     var permission = (string)_json["permission"];
+//                     onPermissionCallBack?.Invoke(permission, state);
+//                     onPermissionCallBack = null;
+//                     break;
+//                 }
+//             case CodeA2U.FreePlatformInitOk:
+
+//                 if (onFreePlatformInitOk != null)
+//                 {
+//                     onFreePlatformInitOk();
+//                 }
+
+//                 break;
+//             case CodeA2U.FreePlatformInitFail:
+//                 if (onFreePlatformInitFail != null)
+//                 {
+//                     onFreePlatformInitFail();
+//                 }
+//                 break;
+//             case CodeA2U.FreePlatformRegisterOk:
+//                 // HandleFreePlatformRegisteOk(_json);
+//                 OperationLogCollect.Instance.RecordEvent(5);
+//                 var values = new JsonData();
+//                 if (_json.Keys.Contains("reg_type"))
+//                     values["af_registration_method"] = _json["reg_type"];
+//                 break;
+//             case CodeA2U.FreePlatformLoginOk:
+//                 HandleFreePlatformLoginOk(_json["info"]);
+//                 OperationLogCollect.Instance.RecordEvent(6);
+//                 break;
+//             case CodeA2U.FreePlatformLoginFail:
+//                 if (onFreePlatformLoginFail != null)
+//                 {
+//                     onFreePlatformLoginFail();
+//                 }
+//                 break;
+//             case CodeA2U.FreePlatformLogoutOk:
+//                 if (onFreePlatformLogoutOk != null)
+//                 {
+//                     onFreePlatformLogoutOk();
+//                 }
+//                 FreePlatformInfo = null;
+//                 break;
+//             case CodeA2U.FreePlatformSwitchAccountOk:
+//                 BuildFreePlatformInfo(_json["info"]);
+//                 if (onFreePlatformLogoutOk != null)
+//                 {
+//                     onFreePlatformLogoutOk();
+//                 }
+//                 FreePlatformInfo = null;
+//                 break;
+//             case CodeA2U.FreePlatformLogoutFail:
+//                 if (onFreePlatformLogoutFail != null)
+//                 {
+//                     onFreePlatformLogoutFail();
+//                 }
+//                 break;
+//             case CodeA2U.FreePlatformPayOk:
+//                 if (onFreePlatformPayOk != null)
+//                 {
+//                     onFreePlatformPayOk();
+//                 }
+//                 //SnxxzGame.Instance.StartCoroutine(DelayQueryRecharge());
+//                 break;
+//             case CodeA2U.FreePlatformPayFail:
+//                 if (onFreePlatformPayFail != null)
+//                 {
+//                     onFreePlatformPayFail();
+//                 }
+//                 break;
+//             case CodeA2U.FreePlatformPayCancel:
+//                 if (onFreePlatformPayCancel != null)
+//                 {
+//                     onFreePlatformPayCancel();
+//                 }
+//                 break;
+//             case CodeA2U.ShareCallBack:
+//                 {
+//                     var state = int.Parse(_json["state"].ToString());
+//                     if (state == CallBackState.Success)
+//                         LocalSave.SetInt("ShareToFBDay" + PlayerDatas.Instance.baseData.PlayerID, TimeUtility.ServerNow.DayOfYear);
+
+//                     onShareFBResult?.Invoke();
+//                     break;
+//                 }
+//             case CodeA2U.ExitGame:
+//                 if (ChannelPlatform == E_ChannelPlatform.Free)
+//                 {
+//                     vnxbqy.UI.WindowCenter.Instance.Open<vnxbqy.UI.ExitGameWin>();
+//                 }
+//                 else
+//                 {
+//                     //榛樿閮芥槸閫�鍑烘父鎴�
+//                     Application.Quit();
+//                 }
+//                 break;
+//         }
+//         onSdkMsg?.Invoke(_code, _json);
+    }
+
+    #endregion
+
+    #region 浜や簰鐩稿叧绾﹀畾缂栧彿
+
+    //鍥炶皟鐨勭浉鍏崇姸鎬�
+    public static class CallBackState
+    {
+        public const int Cancel = 0;
+        public const int Success = 1;
+        public const int Error = 2;
+    }
+
+    public static class CodeA2U
+    {
+        #region 鍩虹sdk_code
+        /**
+         * 璧勬簮鎷疯礉瀹屾垚
+         */
+        public const int AssetCopyFinished = 0;
+        /**
+         * 鐢甸噺鏀瑰彉
+         */
+        public const int BatteryLevel = 1;
+        /**
+         * 鍏呯數鐘舵�佹敼鍙�
+         */
+        public const int BatteryCharging = 2;
+        /**
+         * 鍥炶皟sdk閫昏緫瀹屾瘯
+         * */
+        public const int SdkInitComplete = 3;
+        /**
+         * 鍥炶皟android璁惧淇℃伅
+         * */
+        public const int DeviceInfo = 4;
+        /**
+         * 鍥炶皟鎺ㄩ�佺殑鐙珛id
+         * */
+        public const int PushClientID = 5;
+        /**
+         * 鍥炶皟澶栭儴瀛樺偍鏍圭洰褰曞湴鍧�
+         */
+        public const int ExternalStorage = 6;
+        /**
+         * 瑙﹀彂浜嗛��鍑烘父鎴忛�昏緫, 鎵撳紑浜屾纭鐣岄潰
+         */
+        public const int ExitGame = 7;
+
+        /**
+        * 鏉冮檺鐢宠缁撴灉
+        */
+        public const int PermissionCallBack = 8;
+
+        #endregion
+
+        #region 鑷敱sdk_code
+        public const int FreePlatformInitOk = 100;
+        public const int FreePlatformInitFail = 101;
+        public const int FreePlatformLoginOk = 102;
+        public const int FreePlatformLoginFail = 103;
+        public const int FreePlatformLoginCancel = 104;
+        public const int FreePlatformLogoutOk = 105;
+        public const int FreePlatformLogoutFail = 106;
+        public const int FreePlatformSwitchAccountOk = 107;
+        public const int FreePlatformPayOk = 108;
+        public const int FreePlatformPayFail = 109;
+        public const int FreePlatformPayCancel = 110;
+        public const int FreePlatformRegisterOk = 111;
+        public const int ShareCallBack = 112;
+        public const int PingfenCallBack = 113;  //璇勫垎鍥炶皟 鍜� GotoShopOK 涓嶄竴鏍� 鍏蜂綋鐪嬩娇鐢ㄥ尯鍒�
+        public const int GotoShopOK = 115;  //鍓嶅線鍟嗗簵鎴愬姛
+        public const int GotoFBOK = 116;
+        #endregion
+    }
+
+    private static class CodeU2A
+    {
+        /**
+         * 鎵ц璧勬簮鎷疯礉
+         */
+        public const int CopyAsset = 0;
+        /**
+         * 鎵ц寮�濮嬬數閲忔敼鍙�,鍏呯數鐘舵�佹敼鍙樼洃鍚�
+         */
+        public const int BatteryListenStart = 1;
+        /**
+         * 鎵ц鍋滄鐢甸噺鏀瑰彉,鍏呯數鐘舵�佹敼鍙樼洃鍚�
+         */
+        public const int BatteryListenStop = 2;
+        /**
+         * 鑾峰彇鍞竴璇嗗埆鐮�
+         */
+        public const int UniqueID = 3;
+        /**
+         * 鐢宠鍦ˋndroidManifest鏂囦欢涓�
+         */
+        public const int RequestManifestPermissions = 4;
+        /**
+         * 鍗曠嫭鍔ㄦ�佺敵璇锋煇涓�涓潈闄�
+         */
+        public const int RequestPermission = 5;
+        /**
+         * 閲嶅惎搴旂敤
+         */
+        public const int RestartApp = 6;
+        /**
+         * 鎷疯礉鏂囨湰淇℃伅
+         */
+        public const int CopyContent = 7;
+        /**
+         * 鎵撳紑缃戝潃
+         */
+        public const int OpenWebView = 8;
+        /**
+         * SDK鍒濆鍖�, 瀹屽叏鑷姩鍒濆鍖栫殑娴佺▼, 瀹屾垚蹇呰閫昏緫鍚庡啀鍥炶皟鍥炲幓
+         */
+        public const int Init = 9;
+        /**
+         * 瀹夎搴旂敤
+         */
+        public const int InstallAPK = 10;
+        /**
+         * 澶栭儴瀛樺偍鏍圭洰褰曞湴鍧�
+         */
+        public const int ExteneralStorage = 11;
+        public const int CopyOneAsset = 12;
+
+        //鎵撳紑搴旂敤鍟嗗簵
+        public const int GoToAppStore = 13;
+
+        // 鍚姩鏃剁敵璇锋潈闄愶紝鐢宠瑙勫垯sdk鍐冲畾
+        public const int RequestPermissionStart = 14;
+
+        /**
+         * 鑷敱sdk鐩稿叧
+         * */
+        public const int FreePlatformInit = 100;
+        public const int FreePlatformLogin = 101;
+        public const int FreePlatformLogout = 102;
+        public const int FreePlatformSwitchAccount = 103;
+        public const int FreePlatformPay = 104;
+        public const int PayFinished = 105;
+        public const int CreateRole = 106;
+        public const int RoleLogin = 107;
+        public const int RoleLevelUp = 108;
+        public const int TencentLogin = 109;
+        public const int DownloadStart = 110;
+        public const int DownloadEnd = 111;
+        public const int ShareToFaceBook = 112;
+        public const int GoToPingfen = 113;  //鍓嶅線璇勫垎  鍜� GotoShop = 121; 鏈夊尯鍒�
+        public const int ShowAccountView = 114;
+        public const int RoleLoginOut = 119; //瑙掕壊鐧诲嚭
+        public const int FansHouse = 120; //绮変笣灞� 璁哄潧绛�
+        public const int GotoShop = 121; //鍓嶅線鍟嗗簵
+        public const int TrackEvent = 122; //鑷畾涔変簨浠�
+        /**
+         * 鏋佸厜鎺ㄩ��
+         * */
+        public const int JPushAddLocalMessage = 200;
+        public const int JPushRemoveLocalMessage = 201;
+        /**
+         * IOS鐗规畩闇�姹�
+         */
+        public const int MakeKeyAndVisible = 300;
+        /**
+         * ClientPackage鍚憇dk鍙戦�佸垎鍖卛d
+         */
+        public const int ClientPackage = 400;
+        /**
+         * 鍙戦�佹敞鍐屼簨浠�
+         */
+        public static int SendRegistEvent = 500;
+        /**
+         * 鍙戦�佹敞鍐屼簨浠�
+         */
+        public static int SendLoginEvent = 600;
+        /**
+         * 闅愯棌鎮诞绐�
+         */
+        public static int HideFloatIcon = 700;
+        /**
+         * 鏄剧ず鎮诞绐�
+         */
+        public static int ShowFloatIcon = 701;
+
+
+    }
+
+    #endregion
+    public class DeviceInfo
+    {
+        public string imei;
+        public string macAddress;
+        public string androidID;
+        public string uniqueID;
+        public string userAgent;
+        public int totalMemory;
+    }
+
+    #region 鑷敱sdk鐩稿叧
+
+    public UnityAction onFreePlatformInitOk;
+    public UnityAction onFreePlatformInitFail;
+    public UnityAction<FP_LoginOk> onFreePlatformLoginOk;
+    public UnityAction onFreePlatformLoginFail;
+    public UnityAction onFreePlatformLogoutOk;
+    public UnityAction onFreePlatformLogoutFail;
+    public UnityAction onFreePlatformPayOk;
+    public UnityAction onFreePlatformPayFail;
+    public UnityAction onFreePlatformPayCancel;
+    public UnityAction onFreePlatformBindOk;
+    public UnityAction onFreePlatformBindFail;
+    public UnityAction onShareFBResult;
+    public class FP_LoginOk
+    {
+        public string account;//蹇呴�夛紝璐﹀彿
+        public string token;//蹇呴��
+        public string tokenExpire;
+        public int phone;
+        public int accountID;
+        public string gameId;
+        public string timeStamp;
+        public string sessionID;
+        public string yjAppId;
+        public string yjSdkId;
+        public string qkUserName; // 鐩墠褰撳仛鍘熷UID浣跨敤,鍥犱负娓告垙涓細缁熶竴灏忓啓
+    }
+
+    public struct FP_CheckIDAuthentication
+    {
+        public string errorcode;
+        public string errordesc;
+        public string type;
+        public string card_id;
+    }
+
+    public struct FP_DoIDAuthentication
+    {
+        public string errorcode;
+        public string errordesc;
+        public string card_id;
+    }
+
+    string authenticationCardId = "";
+    public string channelId = "1000";
+    public string platfromId = "1000";
+
+    public void FreePlatformInit()
+    {
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.FreePlatformInit;
+        SendMessageToSDK(m_Json);
+#endif
+    }
+
+    public void FreePlatformBindPhone()
+    {
+#if UNITY_ANDROID
+        AndroidJavaClass _jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
+        AndroidJavaObject _jo = _jc.GetStatic<AndroidJavaObject>("currentActivity");
+        _jo.Call("BindPhone");
+#endif
+    }
+
+    /// <summary>
+    /// 鑷敱SDK鐧婚檰
+    /// </summary>
+    public void FreePlatformLogin()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.FreePlatformLogin;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void TencentLogin(string param)
+    {
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.TencentLogin;
+        if (!string.IsNullOrEmpty(param))
+        {
+            m_Json["param"] = param;
+        }
+        SendMessageToSDK(m_Json);
+#endif
+    }
+
+    /// <summary>
+    /// 鑷敱SDK鐧诲嚭
+    /// </summary>
+    public void FreePlatformLoginout()
+    {
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.FreePlatformLogout;
+        SendMessageToSDK(m_Json);
+        if (ChannelPlatform == E_ChannelPlatform.Yl)
+        {
+            FreePlatformLogin();
+        }
+#endif
+    }
+    public void ShowAccountView()
+    {
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.ShowAccountView;
+        SendMessageToSDK(m_Json);
+        if (ChannelPlatform == E_ChannelPlatform.Yl)
+        {
+            FreePlatformLogin();
+        }
+#endif
+    }
+    public void FreePlatformSwitchAccount()
+    {
+#if UNITY_ANDROID
+        AndroidJavaClass _jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
+        AndroidJavaObject _jo = _jc.GetStatic<AndroidJavaObject>("currentActivity");
+        _jo.Call("SwitchAccount");
+#endif
+    }
+
+    private Dictionary<string, string> m_PaymentTable = new Dictionary<string, string>();
+    private string m_EncodeKey = "03sujm7gerywdvyd5vkkk772rs4by230";
+
+    //private IEnumerator DelayQueryRecharge()
+    //{
+    //    yield return WaitingForSecondConst.WaitMS3000;
+    //    var _package = new CA806_tagCMQueryRecharge();
+    //    GameNetSystem.Instance.SendInfo(_package);
+
+    //}
+
+    /// <summary>
+    /// 鑷敱SDK鏀粯 fixed sdk 鏀粯閫昏緫淇敼
+    /// </summary>
+    /// 
+    public void FreePlatformPay(string title, float money, string cpInfo)
+    {
+        // 鎻愮ず鏄惁浣跨敤浠i噾鍒�
+        // var gameCash = UIHelper.GetAllVourcher();
+
+        // bool isBuyGameCash = false; //浠i噾鍒告湰韬殑鍏呭�间笉鑳界敤浠i噾鍒歌喘涔� 閫犳垚寰幆
+        // int ctgID = ModelCenter.Instance.GetModel<VipModel>().orderInfoToCTGID[cpInfo];
+        // if (ctgID != 0)
+        // {
+        //     isBuyGameCash = CTGConfig.Get(ctgID).PayType == 17;
+        // }
+
+
+        // if (!isBuyGameCash && gameCash >= money * 100 && !LoginAwardModel.rechargeLimit.Contains(ctgID))
+        // {
+
+        //     WindowCenter.Instance.Close<GotoChargeWin>();
+        //     if (DayRemind.Instance.GetDayRemind(DayRemind.DJQTip))
+        //     {
+        //         var pack = new CA125_tagCMCoinBuyOrderInfo();
+        //         pack.AppID = VersionConfig.Get().appId;
+        //         pack.AppIDLen = (byte)pack.AppID.Length;
+        //         pack.OrderInfo = cpInfo;
+        //         pack.OrderInfoLen = (byte)pack.OrderInfo.Length;
+        //         GameNetSystem.Instance.SendInfo(pack);
+        //     }
+        //     else
+        //     {
+        //         ConfirmCancel.ToggleConfirmCancel(Language.Get("Mail101"), Language.Get("GameCashRule1", money), Language.Get("TodayNoNotify"), (bool isOk, bool isToggle) =>
+        //         {
+        //             if (isOk)
+        //             {
+        //                 var pack = new CA125_tagCMCoinBuyOrderInfo();
+        //                 pack.AppID = VersionConfig.Get().appId;
+        //                 pack.AppIDLen = (byte)pack.AppID.Length;
+        //                 pack.OrderInfo = cpInfo;
+        //                 pack.OrderInfoLen = (byte)pack.OrderInfo.Length;
+        //                 GameNetSystem.Instance.SendInfo(pack);
+        //             }
+        //             if (isToggle)
+        //             {
+        //                 DayRemind.Instance.SetDayRemind(DayRemind.DJQTip, true);
+        //             }
+        //         });
+        //     }
+        // }
+        // else
+        // { 
+        //     FreePlatformPayEx(title, money, cpInfo);
+        // }
+    }
+
+    public void FreePlatformPayEx(string title, float money, string cpInfo)
+    {
+//         OrderInfoConfig orderInfo = null;
+//         VipModel vipModel = ModelCenter.Instance.GetModel<VipModel>();
+//         if (vipModel.orderInfoToCTGID.ContainsKey(cpInfo) && vipModel.orderInfoToCTGID[cpInfo] != 0)
+//         {
+//             vipModel.TryGetOrderInfo(vipModel.orderInfoToCTGID[cpInfo], out orderInfo);
+//         }
+//         else
+//         {
+//             var keys = OrderInfoConfig.GetKeys();
+//             for (int i = 0; i < keys.Count; i++)
+//             {
+//                 orderInfo = OrderInfoConfig.Get(keys[i]);
+//                 if (orderInfo != null && orderInfo.OrderInfo == cpInfo)
+//                 {
+//                     break;
+//                 }
+//             }
+//         }
+// //#if !(UNITY_IOS || UNITY_IPHONE)
+// //        string storeOrderInfo = orderInfo.StoreOrderInfo;
+// //#else
+// //        string storeOrderInfo = orderInfo.StoreOrderInfo2;
+// //#endif
+
+// #if UNITY_EDITOR
+//         Debug.LogFormat("鍏呭��: {0}-{1}-{2}", title, money, cpInfo);
+//         return;
+// #endif
+
+//         m_Json.Clear();
+//         m_Json["code"] = CodeU2A.FreePlatformPay;
+//         m_Json["orderId"] = DateTime.Now.ToString("yyyyMMddHHmmss") + UnityEngine.Random.Range(100000, 999999).ToString();
+//         m_Json["mount"] = money.ToString();
+//         m_Json["cpInfo"] = cpInfo;
+//         //m_Json["storeOrderInfo"] = storeOrderInfo;
+//         m_Json["title"] = title;
+//         m_Json["roleID"] = PlayerDatas.Instance.baseData.PlayerID;
+//         m_Json["roleName"] = PlayerDatas.Instance.baseData.PlayerName;
+//         m_Json["level"] = PlayerDatas.Instance.baseData.LV.ToString();
+//         m_Json["sid"] = ServerListCenter.Instance.currentServer.region_flag;
+//         m_Json["serverName"] = ServerListCenter.Instance.currentServer.name;
+//         m_Json["familyName"] = PlayerDatas.Instance.baseData.FamilyName;
+//         m_Json["job"] = PlayerDatas.Instance.baseData.Job.ToString();
+//         m_Json["money"] = PlayerDatas.Instance.baseData.diamond.ToString();
+//         m_Json["gameName"] = VersionConfig.Get().productName;
+//         m_Json["vipLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
+//         m_Json["createTime"] = TimeUtility.CreateSeconds.ToString();
+//         m_Json["familyID"] = PlayerDatas.Instance.baseData.FamilyId.ToString();
+//         m_Json["fightPower"] = PlayerDatas.Instance.baseData.FightPoint.ToString();
+
+// #if UNITY_IOS
+//         m_Json["identifier"] = VersionConfig.Get().bundleIdentifier;
+// #endif
+//         SendMessageToSDK(m_Json);
+    }
+
+
+    /// <summary>
+    ///  鍒嗕韩鍒癴acebook
+    /// /// </summary>
+    public void ShareToFaceBook(int type)
+    {
+        // Debug.Log("瓒婂崡鍒嗕韩");
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.ShareToFaceBook;
+        // m_Json["type"] = type;
+        // SendMessageToSDK(m_Json);
+    }
+
+    /// <summary>
+    /// 鍘诲晢搴楄瘎璁�
+    /// </summary>
+    public void GoToPingfen()
+    {
+        // Debug.Log("瓒婂崡璇勫垎");
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.GoToPingfen;
+        // SendMessageToSDK(m_Json);
+    }
+
+    //鍓嶅線鍟嗗簵
+    public void GoToShop()
+    {
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.GotoShop;
+        // SendMessageToSDK(m_Json);
+    }
+
+
+    /**
+     * @param context
+     * @param event 浜嬩欢鍚�
+     * @param value 浜嬩欢鍊硷紝濡傛灉娌℃湁鍙互浼�""
+     * @param isRepeatReport 鏄惁閲嶅涓婃姤銆傛牴鎹繍钀ラ渶姹傛槸鍚︽帓閲嶄笂鎶ワ紝true鍙互閲嶅涓婃姤锛宖alse浠呬笂鎶ヤ竴娆�
+     */
+    public void TraceEvent(string eventName, string value, bool isRepeatReport)
+    {
+        // Debug.Log("瓒婂崡浜嬩欢姹囨姤 锛�" + eventName);
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.TrackEvent;
+        // m_Json["eventName"] = eventName;
+        // m_Json["value"] = value;
+        // m_Json["isRepeatReport"] = isRepeatReport;
+        // SendMessageToSDK(m_Json);
+    }
+
+    private void BuildFreePlatformInfo(JsonData json)
+    {
+        // if (FreePlatformInfo == null)
+        // {
+        //     FreePlatformInfo = new FP_LoginOk();
+        // }
+
+        // IDictionary _iDict = json as IDictionary;
+
+        // if (_iDict.Contains("token"))
+        // {
+        //     FreePlatformInfo.token = json["token"].ToString();
+        // }
+        // if (_iDict.Contains("token_expire"))
+        // {
+        //     FreePlatformInfo.tokenExpire = json["token_expire"].ToString();
+        // }
+        // else
+        // {
+        //     FreePlatformInfo.tokenExpire = "";
+        // }
+        // if (_iDict.Contains("account"))
+        // {
+        //     FreePlatformInfo.account = json["account"].ToString();
+        // }
+
+        // if (_iDict.Contains("account_id"))
+        // {
+        //     int.TryParse(json["account_id"].ToString(), out FreePlatformInfo.accountID);
+        // }
+
+        // if (_iDict.Contains("session_id"))
+        // {
+        //     FreePlatformInfo.sessionID = (string)json["session_id"];
+        // }
+
+        // if (_iDict.Contains("game_id"))
+        // {
+        //     FreePlatformInfo.gameId = (string)json["game_id"];
+        // }
+
+        // if (_iDict.Contains("timeStamp"))
+        // {
+        //     FreePlatformInfo.timeStamp = (string)json["timeStamp"];
+        // }
+        // if (_iDict.Contains("userName"))
+        // {
+        //     FreePlatformInfo.qkUserName = json["userName"].ToString();
+        // }
+        // FreePlatformInfo.phone = 0;
+    }
+
+    private void HandleFreePlatformRegisteOk(JsonData json)
+    {
+        // BuildFreePlatformInfo(json);
+    }
+
+    private void HandleFreePlatformLoginOk(JsonData data)
+    {
+        // BuildFreePlatformInfo(data);
+
+        // Debug.LogFormat("sdk鐧诲綍鎴愬姛锛歿0}", data.ToJson());
+        // if (onFreePlatformLoginOk != null)
+        // {
+        //     onFreePlatformLoginOk(FreePlatformInfo);
+        // }
+    }
+
+
+    // public void OnServerChargeOk(HA106_tagMCCoinToGoldReport pack)
+    // {
+    //     string orderID = pack.OrderID;
+    //     uint coin = pack.Coin;
+    //     OperationLogCollect.Instance.RecordEvent(9, coin);
+
+    //     if (onFreePlatformPayOk != null)
+    //     {
+    //         onFreePlatformPayOk();
+    //     }
+
+    //     m_Json.Clear();
+    //     m_Json["code"] = CodeU2A.PayFinished;
+    //     m_Json["orderID"] = orderID;
+    //     m_Json["payType"] = "_default_";
+    //     m_Json["moneyType"] = "CNY";
+    //     m_Json["money"] = (float)coin / 100;
+    //     SendMessageToSDK(m_Json);
+    // }
+
+    public void SendRegistEvent(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            if (!_result.Equals("0"))
+            {
+                m_Json.Clear();
+                m_Json["code"] = CodeU2A.SendRegistEvent;
+                SendMessageToSDK(m_Json);
+            }
+        }
+    }
+
+    public void SendLoginEvent()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.SendLoginEvent;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void SendHideFloatWin()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.HideFloatIcon;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void SendShowFloatWin()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.ShowFloatIcon;
+        SendMessageToSDK(m_Json);
+    }
+
+    public void CreateRoleOk(string roleID, string roleName, string time)
+    {
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.CreateRole;
+
+        // m_Json["roleID"] = roleID;
+        // m_Json["roleName"] = roleName;
+        // m_Json["sid"] = ServerListCenter.Instance.currentServer.region_flag;
+        // m_Json["serverName"] = ServerListCenter.Instance.currentServer.name;
+        // m_Json["familyName"] = PlayerDatas.Instance.baseData.FamilyName;
+        // m_Json["level"] = "1";
+        // m_Json["job"] = PlayerDatas.Instance.baseData.Job.ToString();
+        // m_Json["money"] = PlayerDatas.Instance.baseData.diamond.ToString();
+        // m_Json["gameName"] = VersionConfig.Get().productName;
+        // m_Json["vipLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
+        // m_Json["createTime"] = time;
+        // m_Json["familyID"] = PlayerDatas.Instance.baseData.FamilyId.ToString();
+        // m_Json["fightPower"] = PlayerDatas.Instance.baseData.FightPoint.ToString();
+        // SendMessageToSDK(m_Json);
+    }
+
+    public void DownloadStart()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.DownloadStart;
+
+        SendMessageToSDK(m_Json);
+    }
+
+    public void DownloadEnd()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.DownloadEnd;
+
+        SendMessageToSDK(m_Json);
+    }
+
+    public void RoleLogin()
+    {
+        // m_Json.Clear();
+        // m_Json["code"] = CodeU2A.RoleLogin;
+
+        // m_Json["roleID"] = PlayerDatas.Instance.baseData.PlayerID.ToString();
+        // m_Json["roleName"] = PlayerDatas.Instance.baseData.PlayerName;
+        // m_Json["sid"] = ServerListCenter.Instance.currentServer.region_flag;
+        // m_Json["serverName"] = ServerListCenter.Instance.currentServer.name;
+        // m_Json["familyName"] = PlayerDatas.Instance.baseData.FamilyName;
+        // m_Json["level"] = PlayerDatas.Instance.baseData.LV;
+        // m_Json["job"] = PlayerDatas.Instance.baseData.Job.ToString();
+        // m_Json["money"] = PlayerDatas.Instance.baseData.diamond.ToString();
+        // m_Json["gameName"] = VersionConfig.Get().productName;
+        // m_Json["vipLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
+        // m_Json["createTime"] = TimeUtility.CreateSeconds.ToString();
+        // m_Json["familyID"] = PlayerDatas.Instance.baseData.FamilyId.ToString();
+        // m_Json["fightPower"] = PlayerDatas.Instance.baseData.FightPoint.ToString();
+        // SendMessageToSDK(m_Json);
+    }
+
+    public void RoleLevelUp()
+    {
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.RoleLevelUp;
+
+        m_Json["roleID"] = PlayerDatas.Instance.PlayerId.ToString();
+        m_Json["roleName"] = PlayerDatas.Instance.baseData.PlayerName;
+        m_Json["sid"] = ServerListCenter.Instance.currentServer.region_flag;
+        m_Json["serverName"] = ServerListCenter.Instance.currentServer.name;
+        m_Json["familyName"] = PlayerDatas.Instance.baseData.FamilyName;
+        m_Json["level"] = PlayerDatas.Instance.baseData.LV;
+        m_Json["job"] = PlayerDatas.Instance.baseData.Job.ToString();
+        m_Json["money"] = PlayerDatas.Instance.baseData.diamond.ToString();
+        m_Json["gameName"] = VersionConfig.Get().productName;
+        m_Json["vipLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
+        m_Json["levelUpTime"] = TimeUtility.AllSeconds.ToString();
+        m_Json["createTime"] = TimeUtility.CreateSeconds.ToString();
+        m_Json["familyID"] = PlayerDatas.Instance.baseData.FamilyId.ToString();
+        m_Json["fightPower"] = PlayerDatas.Instance.baseData.FightPoint.ToString();
+        SendMessageToSDK(m_Json);
+    }
+
+
+    public void RoleLoginOut()
+    {
+        if (PlayerDatas.Instance.PlayerId == 0/* || PlayerDatas.Instance.hero == null*/)
+            return;
+
+        
+        // TODO YYL if (DTC0403_tagPlayerLoginLoadOK.neverLoginOk) return;
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.RoleLoginOut;
+
+        m_Json["roleID"] = PlayerDatas.Instance.PlayerId.ToString();
+        m_Json["roleName"] = PlayerDatas.Instance.baseData.PlayerName;
+        m_Json["sid"] = ServerListCenter.Instance.currentServer.region_flag;
+        m_Json["serverName"] = ServerListCenter.Instance.currentServer.name;
+        m_Json["familyName"] = PlayerDatas.Instance.baseData.FamilyName;
+        m_Json["level"] = PlayerDatas.Instance.baseData.LV;
+        m_Json["job"] = PlayerDatas.Instance.baseData.Job.ToString();
+        m_Json["money"] = PlayerDatas.Instance.baseData.diamond.ToString();
+        m_Json["gameName"] = VersionConfig.Get().productName;
+        m_Json["vipLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
+        m_Json["levelUpTime"] = TimeUtility.AllSeconds.ToString();
+        m_Json["createTime"] = TimeUtility.CreateSeconds.ToString();
+        m_Json["familyID"] = PlayerDatas.Instance.baseData.FamilyId.ToString();
+        m_Json["fightPower"] = PlayerDatas.Instance.baseData.FightPoint.ToString();
+        SendMessageToSDK(m_Json);
+    }
+
+    public void GotoFansHouse()
+    {
+        Debug.Log("瓒婂崡鐐硅禐");
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.FansHouse;
+
+        SendMessageToSDK(m_Json);
+    }
+
+#endregion
+
+    #region 鎻掍欢鐩稿叧
+
+    #endregion
+
+    #region 鏋佸厜鎺ㄩ�佺浉鍏�
+    public void GeTui_SendLocalMessage(JsonData jsonData)
+    {
+        return;
+        Debug.Log("GeTui_SendLocalMessage:" + jsonData["id"]);
+        //      ------ 涓句緥 ------
+        //		JsonData _params = new JsonData ();
+        //		_params ["code"] = 2005;
+        //		_params ["id"] = 5;// id 閲嶈, 鏍囩ず姣忎釜閫氱煡鐨勬洿鏂版垨鑰呯Щ闄�
+        //		_params ["title"] = "the title";// 鎺ㄩ�佹爣棰�
+        //		_params ["subtitle"] = "the subtitle";// 鍓爣棰�
+        //		_params ["content"] = "the content";// 鍏蜂綋鍐呭
+        //		_params ["badge"] = -1;// 瑙掓爣
+        //
+        //		// 浠ヤ笅涓哄喅瀹氬簲璇ュ涔呭悗寮瑰嚭姝ら�氱煡
+        //		System.TimeSpan ts = System.DateTime.UtcNow - new System.DateTime (1970, 1, 1, 0, 0, 0, 0);
+        //		long ret = System.Convert.ToInt64 (ts.TotalSeconds) + 3;// 琛ㄧず3绉掑悗
+        //		_params ["fireTime"] = ret;
+#if !UNITY_EDITOR
+        jsonData["code"] = CodeU2A.JPushAddLocalMessage;
+#if UNITY_ANDROID
+        jsonData["fireTime"] = (long)jsonData["fireTime"] * 1000;
+#endif
+        SendMessageToSDK(jsonData);
+#endif
+    }
+
+    public void GeTui_RemoveLocalMessage(string id)
+    {
+        return;
+        Debug.Log("GeTui_RemoveLocalMessage:" + id);
+#if !UNITY_EDITOR
+        m_Json.Clear();
+        m_Json["code"] = CodeU2A.JPushRemoveLocalMessage;
+        m_Json["id"] = id;// id 閲嶈, 鏍囩ず姣忎釜閫氱煡鐨勬洿鏂版垨鑰呯Щ闄�
+
+        SendMessageToSDK(m_Json);
+#endif
+    }
+
+    #endregion
+}
diff --git a/Main/SDK/SDKUtils.cs.meta b/Main/SDK/SDKUtils.cs.meta
new file mode 100644
index 0000000..0f04f78
--- /dev/null
+++ b/Main/SDK/SDKUtils.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8d82a67d446bbb6428de6b6c10e2c13c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System.meta b/Main/System.meta
new file mode 100644
index 0000000..8953177
--- /dev/null
+++ b/Main/System.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a0c2ea8c32032254d80bbe5b17108f0a
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion.meta b/Main/System/AssetVersion.meta
new file mode 100644
index 0000000..2ec039d
--- /dev/null
+++ b/Main/System/AssetVersion.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 23614c1d62af47640a2f77b61b528739
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/AssetVersion.cs b/Main/System/AssetVersion/AssetVersion.cs
new file mode 100644
index 0000000..a4ef086
--- /dev/null
+++ b/Main/System/AssetVersion/AssetVersion.cs
@@ -0,0 +1,222 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+
+
+public class AssetVersion
+{
+    string m_RelativePath = string.Empty;
+    public string relativePath { get { return m_RelativePath; } }
+
+    string m_FileName;
+    public string fileName { get { return m_FileName; } }
+
+    string m_Extersion = string.Empty;
+    public string extersion { get { return m_Extersion; } }
+
+    string m_Md5 = string.Empty;
+    public string md5 { get { return m_Md5; } }
+
+    int m_Size = 0;
+    public int size { get { return m_Size; } }       //瀛楄妭     
+
+    StorageLocation m_FileLocation = StorageLocation.ExternalStore;
+    public StorageLocation fileLocation { get { return m_FileLocation; } }
+
+    bool m_LocalValid = false;
+    public bool localValid
+    {
+        get { return m_LocalValid; }
+        set { m_LocalValid = value; }
+    }
+
+    public AssetVersion(string _versionString)
+    {
+        var strings = _versionString.Split('\t');
+
+        m_RelativePath = strings[0];
+        m_Extersion = strings[1];
+        int.TryParse(strings[2], out m_Size);
+        m_Md5 = strings[3];
+
+        var paths = m_RelativePath.Split('/');
+
+        var lastPath = paths[paths.Length - 1];
+        var index = lastPath.LastIndexOf('.');
+        if (index != -1)
+        {
+            m_FileName = lastPath.Substring(0, index);
+        }
+        else
+        {
+            m_FileName = lastPath;
+        }
+    }
+
+    public AssetCategory GetAssetCategory()
+    {
+        if (extersion == ".dll")
+            return AssetCategory.Dll;
+        else if (m_RelativePath.StartsWith("ui/"))
+            return AssetCategory.UI;
+        else if (m_RelativePath.StartsWith("audio/"))
+            return AssetCategory.Audio;
+        else if (m_RelativePath.StartsWith("gmodels/"))
+            return AssetCategory.Mob;
+        else if (m_RelativePath.StartsWith("maps/"))
+            return AssetCategory.Scene;
+        else if (m_RelativePath.StartsWith("effect/"))
+            return AssetCategory.Effect;
+        else if (m_RelativePath.StartsWith("config/"))
+            return AssetCategory.Config;
+        else if (m_RelativePath.StartsWith("graphic/"))
+            return AssetCategory.Shader;
+        else if (m_RelativePath.StartsWith("video/"))
+            return AssetCategory.Video;
+        else
+            return AssetCategory.Other;
+    }
+
+    public bool CheckLocalFileValid(bool _completeFile)
+    {
+        if (_completeFile)
+        {
+            var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, m_RelativePath);
+            var fileInfo = new FileInfo(path);
+
+            if (!fileInfo.Exists)
+            {
+                Debug.LogFormat("鏂囦欢涓嶅瓨鍦� {0}", path);
+                return false;
+            }
+            if (fileInfo.Length != size)
+            {
+                Debug.LogFormat("{0}鏂囦欢澶у皬涓嶅{1}-{2}", path, size, fileInfo.Length);
+                return false;
+            }
+            var fileMD5 = FileExtersion.GetMD5HashFromFile(path);
+            if (fileMD5 != md5)
+            {
+                Debug.LogFormat("{0}鏂囦欢md5涓嶅{1}-{2}", path, md5, fileMD5);
+                return false;
+            }
+            return true;
+        }
+        else
+        {
+            if (extersion == ".manifest" || extersion == ".bytes" || extersion == ".txt" || extersion == ".dll")
+            {
+                var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, m_RelativePath);
+                var fileInfo = new FileInfo(path);
+
+                if (!fileInfo.Exists || fileInfo.Length != size || md5 != FileExtersion.GetMD5HashFromFile(path))
+                {
+                    return false;
+                }
+            }
+            else if (string.IsNullOrEmpty(extersion) || extersion.Length == 0)
+            {
+                var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, m_RelativePath);
+                var fileInfo = new FileInfo(path);
+
+                var manifestAssetVersion = AssetVersionUtility.GetAssetVersion(StringUtility.Contact(m_RelativePath, ".manifest"));
+                if (!fileInfo.Exists || fileInfo.Length != size || manifestAssetVersion == null || !manifestAssetVersion.CheckLocalFileValid(false))
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, m_RelativePath);
+                var fileInfo = new FileInfo(path);
+                if (!fileInfo.Exists || fileInfo.Length != size)
+                {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    // 妫�鏌ュ閮ㄥ瓨鍌ㄦ枃浠舵槸鍚﹀瓨鍦�
+    // 涓嶅瓨鍦ㄥ垯璇诲彇闅忓寘鏂囦欢杩涜姣旇緝
+    // 瀛樺湪鍒欐瘮杈�
+    public bool CheckLocalFileValid(AssetVersion otherAssetInfo)
+    {
+        string path = string.Concat(ResourcesPath.Instance.ExternalStorePath, m_RelativePath);
+
+        if (!File.Exists(path) && !m_RelativePath.Contains(".txt"))
+        {
+            //Debug.LogFormat("杞煡StreamingAssetPath - 鏂囦欢涓嶅瓨鍦� {0} ", path);
+            if (otherAssetInfo == null || string.IsNullOrEmpty(otherAssetInfo.relativePath))
+                return false;
+
+            if (otherAssetInfo.size != size)
+            {
+                Debug.LogFormat("StreamingAssetPath 鏂囦欢澶у皬涓嶅{0}-{1}", size, otherAssetInfo.size);
+                return false;
+            }
+
+            if (otherAssetInfo.md5 != md5)
+            {
+                Debug.LogFormat("StreamingAssetPath 鏂囦欢md5涓嶅{0}-{1}", md5, otherAssetInfo.md5);
+                return false;
+            }
+
+            return true;
+        }
+
+        return CheckLocalFileValid(false);
+
+    }
+
+
+    public bool IsPriorAsset()
+    {
+        if (VersionConfig.Get().partAssetPackage)
+        {
+            //濡傛灉杩欏彴鏈哄櫒鏇剧粡瀹屾暣鐨勪笅杞借繃鎵�鏈夎祫婧愶紝閭d箞灏变笉鍐嶄娇鐢ㄥ垎鍖呬笅杞界瓥鐣ワ紝鍦ㄨ祫婧愮儹鏇存柊鐨勬椂鍊欒繖绉嶆儏鍐典細瑙﹀彂銆�
+            if (AssetVersionUtility.hasDownLoadFullAsset)
+            {
+                return true;
+            }
+            else
+            {
+                var category = GetAssetCategory();
+                // var prior = PriorBundleConfig.GetAssetPrior(category, AssetVersionUtility.DecodeFileName(m_FileName));
+                // return prior <= 1;
+                return false;
+            }
+        }
+        else
+        {
+            return true;
+        }
+
+    }
+
+    public enum StorageLocation
+    {
+        StreamingAsset,
+        ExternalStore
+    }
+
+    public enum AssetCategory
+    {
+        UI,
+        Audio,
+        Mob,
+        Scene,
+        Effect,
+        Config,
+        Shader,
+        Dll,
+        Video,
+        Other,
+        Patch,//琛ヤ竵
+        Logic,//鐑洿閫昏緫浠g爜
+    }
+
+}
diff --git a/Main/System/AssetVersion/AssetVersion.cs.meta b/Main/System/AssetVersion/AssetVersion.cs.meta
new file mode 100644
index 0000000..a06a3e7
--- /dev/null
+++ b/Main/System/AssetVersion/AssetVersion.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5076127edfecf424ca8734ed846e6233
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/AssetVersionUtility.cs b/Main/System/AssetVersion/AssetVersionUtility.cs
new file mode 100644
index 0000000..b460ea3
--- /dev/null
+++ b/Main/System/AssetVersion/AssetVersionUtility.cs
@@ -0,0 +1,412 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using System.IO;
+using System.Threading;
+using System.Linq;
+
+public class AssetVersionUtility
+{
+
+    public static string assetVersionsLocalMd5
+    {
+        get { return LocalSave.GetString("AssetVersionsLocalMd5"); }
+        set { LocalSave.SetString("AssetVersionsLocalMd5", value); }
+    }
+
+    static bool m_HasDownLoadFullAsset = LocalSave.GetBool("HasDownLoadFullAsset");
+    public static bool hasDownLoadFullAsset
+    {
+        get { return m_HasDownLoadFullAsset; }
+        set { LocalSave.SetBool("HasDownLoadFullAsset", value); }
+    }
+
+    static bool m_PriorAssetDownLoadDone = false;
+    public static bool priorAssetDownLoadDone
+    {
+        get
+        {
+            if (VersionUtility.Instance.NeedDownAsset())
+            {
+                return m_PriorAssetDownLoadDone;
+            }
+            else
+            {
+                return true;
+            }
+        }
+    }
+
+    static bool m_UnPriorAssetDownLoadDone = false;
+    public static bool unPriorAssetDownLoadDone
+    {
+        get
+        {
+            if (VersionUtility.Instance.NeedDownAsset())
+            {
+                return m_UnPriorAssetDownLoadDone;
+            }
+            else
+            {
+                return true;
+            }
+        }
+    }
+
+    public static DateTime assetsBuildTime = DateTime.MinValue;
+
+    static Dictionary<string, AssetVersion> assetVersions = new Dictionary<string, AssetVersion>();
+    //鏈湴LogicBytes鏂囦欢鍜� assetVersions 姣旇緝鏄惁闇�瑕佷笅杞�
+    static Dictionary<string, AssetVersion> localAssetVersions = new Dictionary<string, AssetVersion>();
+    static List<AssetVersion> priorDownLoadAssetVersions = new List<AssetVersion>();
+    static List<AssetVersion> unpriorDownLoadAssetVersions = new List<AssetVersion>();
+    public static bool checkAssetCompleted { get; private set; }
+    private static string assetVerUrl;
+    public static void Init()
+    {
+
+    }
+
+    public static void OnDownLoadPriorBundle(DownloadTask task)
+    {
+        if (task.IsDone)
+        {
+            //  TODO CYL
+            // PriorBundleConfig.Init(true);
+            GetAssetVersionFile();
+        }
+        else
+        {
+            //涓�鐩村皾璇曚笅杞�
+            task.BeginDownload(OnDownLoadPriorBundle);
+            Debug.Log("OnDownLoadPriorBundle fail - before AssetVersion");
+        }
+    }
+
+    public static void GetAssetVersionFile()
+    {
+        checkAssetCompleted = false;
+        Debug.LogFormat("寮�濮嬭幏鍙栬祫婧愮増鏈枃浠讹細鏃堕棿 {0}", DateTime.Now);
+        var assetVersionUrl = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), Language.fixPath, "/AssetsVersion.txt");
+        assetVerUrl = assetVersionUrl;
+        Debug.Log("http鍦板潃:assetVersionUrl  " + assetVersionUrl);
+        HttpRequest.Instance.UnityWebRequestGet(assetVersionUrl, 5, OnGetAssetVersionFile);
+    }
+
+    private static void OnGetAssetVersionFile(bool _ok, string _result)
+    {
+        Debug.LogFormat("鑾峰彇璧勬簮鐗堟湰鏂囦欢缁撴灉锛氭椂闂� {0}锛岀粨鏋� {1}, 鏂囦欢澶у皬 {2}", DateTime.Now, _ok, _result.Length);
+        if (_ok)
+        {
+            assetVersionsLocalMd5 = FileExtersion.GetStringMD5Hash(_result);
+            var assetVersions = UpdateAssetVersions(_result);
+            BeginCheckAssets();
+        }
+        else
+        {
+            Debug.Log("http 鏁版嵁閫氳: AssetVersionUtility:" + assetVerUrl + "  result:" + _result);
+            Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 3), GetAssetVersionFile);
+        }
+    }
+
+    private static void BeginCheckAssets()
+    {
+        bool checkStream = true;
+#if UNITY_EDITOR
+        if (InGameDownTestUtility.enable && !InGameDownTestUtility.isReadStreamingAssets)
+            checkStream = false;
+#endif
+
+        ThreadPool.QueueUserWorkItem(
+            (object aaa) =>
+            {
+                foreach (var assetVersion in assetVersions.Values)
+                {
+                    bool checkReuslt;
+                    if (checkStream)
+                    {
+                        AssetVersion localAssetVersion = null;
+                        localAssetVersions.TryGetValue(assetVersion.relativePath, out localAssetVersion);
+                        checkReuslt = assetVersion.CheckLocalFileValid(localAssetVersion);
+                    }
+                    else
+                    {
+                        checkReuslt = assetVersion.CheckLocalFileValid(false);
+                    }
+                    if (!checkReuslt)
+                    {
+                        if (assetVersion.IsPriorAsset())
+                        {
+                            priorDownLoadAssetVersions.Add(assetVersion);
+                        }
+                        else
+                        {
+                            unpriorDownLoadAssetVersions.Add(assetVersion);
+                        }
+
+                        assetVersion.localValid = false;
+                    }
+                    else
+                    {
+                        assetVersion.localValid = true;
+                    }
+                }
+
+                m_PriorAssetDownLoadDone = priorDownLoadAssetVersions.Count <= 0;
+                m_UnPriorAssetDownLoadDone = unpriorDownLoadAssetVersions.Count <= 0;
+
+                checkAssetCompleted = true;
+            }
+            );
+    }
+
+    public static void BeginDownLoadTask(bool _prior)
+    {
+        if (_prior)
+        {
+            m_PriorAssetDownLoadDone = false;
+            DownLoadAndDiscompressTask.Instance.Prepare(priorDownLoadAssetVersions, () => { m_PriorAssetDownLoadDone = true; });
+        }
+        else
+        {
+            m_UnPriorAssetDownLoadDone = false;
+            InGameDownLoad.Instance.AssignTasks(unpriorDownLoadAssetVersions, () =>
+            {
+                m_UnPriorAssetDownLoadDone = true;
+                hasDownLoadFullAsset = true;
+            });
+        }
+    }
+
+    public static Dictionary<string, AssetVersion> UpdateAssetVersions(string _assetVersionFile)
+    {
+        InitPackageVersionInfo();
+        var lines = _assetVersionFile.Split(new string[] { FileExtersion.lineSplit }, StringSplitOptions.RemoveEmptyEntries);
+        assetVersions.Clear();
+        for (int i = 0; i < lines.Length; i++)
+        {
+            var assetVersion = new AssetVersion(lines[i]);
+            assetVersions[assetVersion.relativePath] = assetVersion;
+        }
+        return assetVersions;
+    }
+
+    static void InitPackageVersionInfo()
+    {
+        var text = Resources.Load<TextAsset>("AssetsVersionCmp");
+        if (text != null)
+        {
+            var lines = text.text.Split(new string[] { FileExtersion.lineSplit }, StringSplitOptions.RemoveEmptyEntries);
+            localAssetVersions.Clear();
+            for (int i = 0; i < lines.Length; i++)
+            {
+                var assetVersion = new AssetVersion(lines[i]);
+                localAssetVersions[assetVersion.relativePath] = assetVersion;
+            }
+        }
+    }
+
+    public static AssetVersion GetAssetVersion(string assetKey)
+    {
+        if (assetVersions.ContainsKey(assetKey))
+        {
+            return assetVersions[assetKey];
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static Dictionary<string, AssetVersion> GetVersionsInfo()
+    {
+        return assetVersions;
+    }
+
+    public static bool IsAssetValid(string assetKey)
+    {
+        assetKey = EncodeFileName(assetKey);
+        if (assetVersions.ContainsKey(assetKey))
+        {
+            return assetVersions[assetKey].localValid;
+        }
+        else
+        {
+            if (VersionUtility.Instance.NeedDownAsset())
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+        }
+    }
+
+    public static bool IsSceneAssetValid(int mapId, int lineId)
+    {
+        // if (AssetSource.sceneFromEditor || mapId < 100)
+        // {
+        //     return true;
+        // }
+
+        // var dataMapId = MapUtility.GetDataMapId(mapId);
+        // lineId = MapUtility.GetLineId(mapId, lineId);
+        // var mapResConfig = MapResourcesConfig.GetConfig(dataMapId, lineId);
+        // if (mapResConfig == null)
+        // {
+        //     return false;
+        // }
+
+        // if (!IsAssetValid(StringUtility.Contact("maps/", mapResConfig.MapResources.ToLower())))
+        // {
+        //     return false;
+        // }
+
+        // if (dataMapId != 10010)
+        // {
+        //     ActorShowConfig actorShowConfig = null;
+        //     if (ActorShowConfig.GetActoreShowConfigByMapIdAndLineId(dataMapId, lineId, out actorShowConfig))
+        //     {
+        //         var npcs = actorShowConfig.showNpcs;
+        //         foreach (var item in npcs)
+        //         {
+        //             if (item == 1)
+        //             {
+        //                 continue;
+        //             }
+
+        //             var npcConfig = NPCConfig.Get(item);
+        //             if (npcConfig != null)
+        //             {
+        //                 var assetbundleName = StringUtility.Contact("prefab_race_", npcConfig.MODE.ToLower());
+        //                 if (!IsAssetValid(StringUtility.Contact("gmodels/", assetbundleName)))
+        //                 {
+        //                     return false;
+        //                 }
+        //             }
+        //         }
+        //     }
+        // }
+
+        return true;
+    }
+
+    //灏嗘枃浠跺悕鍊掑簭锛屽姞涓奯aop鍚庣紑
+    public static string EncodeFileName(string name)
+    {
+        return name;
+        //name = name.Replace("\\", "/");
+        //int index = name.LastIndexOf("/");
+        //string headString;
+        //if (index >= 0)
+        //{
+        //    int dotLastIndex = name.LastIndexOf(".");
+        //    if (dotLastIndex == -1)
+        //    {
+        //        headString = name.Substring(0, index);
+        //        name = name.Substring(index + 1);
+        //        return StringUtility.Contact(headString, "/", new string(name.Reverse().ToArray()), "_aop");
+        //    }
+        //    else
+        //    {
+        //        headString = name.Substring(0, index);
+        //        var ext = name.Substring(dotLastIndex);
+        //        name = name.Substring(index + 1, dotLastIndex - index - 1);
+        //        return StringUtility.Contact(headString, "/", new string(name.Reverse().ToArray()), "_aop", ext);
+        //    }
+        //}
+        //else
+        //{
+        //    int dotLastIndex = name.LastIndexOf(".");
+        //    if (dotLastIndex == -1)
+        //        return StringUtility.Contact(new string(name.Reverse().ToArray()), "_aop");
+        //    else
+        //    {
+        //        var ext = name.Substring(dotLastIndex);
+        //        name = name.Substring(0, dotLastIndex);
+        //        return StringUtility.Contact(new string(name.Reverse().ToArray()), "_aop", ext);
+        //    }
+        //}
+
+    }
+
+    public static string DecodeFileName(string name)
+    {
+        return name;
+        //name = name.Replace("\\", "/");
+        //int index = name.LastIndexOf("/");
+        //string headString;
+        //if (index >= 0)
+        //{
+        //    int dotLastIndex = name.LastIndexOf(".");
+        //    if (dotLastIndex == -1)
+        //    {
+        //        headString = name.Substring(0, index);
+        //        name = name.Substring(index + 1);
+        //        return StringUtility.Contact(headString, "/", new string(name.Replace("_aop", "").Reverse().ToArray()));
+        //    }
+        //    else
+        //    {
+        //        headString = name.Substring(0, index);
+        //        var ext = name.Substring(dotLastIndex);
+        //        name = name.Substring(index + 1, dotLastIndex - index - 1);
+        //        return StringUtility.Contact(headString, "/", new string(name.Replace("_aop", "").Reverse().ToArray()), ext);
+        //    }
+        //}
+        //else
+        //{
+        //    int dotLastIndex = name.LastIndexOf(".");
+        //    if (dotLastIndex == -1)
+        //        return new string(name.Replace("_aop", "").Reverse().ToArray());
+        //    else
+        //    {
+        //        var ext = name.Substring(dotLastIndex);
+        //        name = name.Substring(0, dotLastIndex);
+        //        return new string(name.Replace("_aop", "").Reverse().ToArray()) + ext;
+        //    }
+        //}
+    }
+
+
+    public static string GetAssetFilePath(string _assetKey, bool reverse = true)
+    {
+        if (reverse)
+            _assetKey = EncodeFileName(_assetKey);
+        var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, _assetKey);
+        if (!File.Exists(path))
+        {
+            path = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, _assetKey);
+        }
+
+        return path;
+    }
+
+    public static string GetBuiltInAssetFilePath(string _assetKey, bool reverse = true)
+    {
+        if (reverse)
+            _assetKey = EncodeFileName(_assetKey);
+        var path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, _assetKey);
+        if (!File.Exists(path))
+        {
+            path = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, _assetKey);
+        }
+
+        return path;
+    }
+
+    public static bool IsUnpriorAssetDownLoadOk()
+    {
+        if (VersionUtility.Instance.NeedDownAsset())
+        {
+            return unPriorAssetDownLoadDone;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+
+}
diff --git a/Main/System/AssetVersion/AssetVersionUtility.cs.meta b/Main/System/AssetVersion/AssetVersionUtility.cs.meta
new file mode 100644
index 0000000..b5372b5
--- /dev/null
+++ b/Main/System/AssetVersion/AssetVersionUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cb5546ce12cd67d4ea20556d74729054
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs b/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs
new file mode 100644
index 0000000..ee38e50
--- /dev/null
+++ b/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs
@@ -0,0 +1,204 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+using Cysharp.Threading.Tasks;
+
+
+public class DownLoadAndDiscompressTask : Singleton<DownLoadAndDiscompressTask>
+
+{
+    public const int BYTE_PER_KILOBYTE = 1024;
+    public const int BYTE_PER_MILLIONBYTE = 1048576;
+
+    public float progress { get { return Mathf.Clamp01((float)DownloadMgr.Instance.DownloadedBytes / totalSize); } }
+
+    List<AssetVersion> tasks = new List<AssetVersion>();
+    public bool isDone { get { return step == Step.Completed; } }
+    public int totalSize { get; private set; }
+    public int totalCount { get; private set; }
+    public bool restartApp { get; private set; }
+    public bool reinitedBuiltInAsset { get; private set; }
+
+    public event Action<Step> downLoadStepChangeEvent;
+
+    Action downLoadOkCallBack;
+
+    Step m_Step = Step.None;
+    public Step step
+    {
+        get { return m_Step; }
+        set
+        {
+            if (m_Step != value)
+            {
+                m_Step = value;
+
+                if (downLoadStepChangeEvent != null)
+                {
+                    downLoadStepChangeEvent(m_Step);
+                }
+            }
+        }
+    }
+
+    public void Prepare(List<AssetVersion> _downLoadTasks, Action _downLoadOkCallBack)
+    {
+        tasks = _downLoadTasks;
+        downLoadOkCallBack = _downLoadOkCallBack;
+
+        totalCount = tasks.Count;
+        step = Step.DownLoadPrepared;
+        restartApp = false;
+        reinitedBuiltInAsset = false;
+        totalSize = 0;
+
+        for (int i = 0; i < tasks.Count; i++)
+        {
+            var task = tasks[i];
+            totalSize += task.size;
+#if UNITY_ANDROID
+            if (!restartApp && task.GetAssetCategory() == AssetVersion.AssetCategory.Dll)
+            {
+                restartApp = true;
+            }
+#endif
+
+            if (!reinitedBuiltInAsset && task.relativePath.Contains("builtin"))
+            {
+                reinitedBuiltInAsset = true;
+            }
+        }
+
+        if (totalSize > BYTE_PER_MILLIONBYTE)
+        {
+            //  TODO YYL
+            // UIManager.Instance.OpenWindow<DownLoadWin>();
+            // WindowCenter.Instance.OpenFromLocal<DownLoadWin>();
+        }
+        else
+        {
+            StartDownLoad();
+        }
+        SDKUtils.Instance.DownloadStart();
+    }
+
+    public void StartDownLoad()
+    {
+        step = Step.DownLoad;
+
+        Co_StartDownLoad();
+        // SnxxzGame.Instance.StartCoroutine(Co_StartDownLoad());
+
+        // TODO YYL
+        // GameNotice.OpenGameNotice();
+    }
+
+    protected async UniTask Co_StartDownLoad()
+    {
+        while (tasks.Count > 0)
+        {
+            DownloadMgr.Instance.Prepare();
+            for (int i = 0; i < tasks.Count; i++)
+            {
+                var assetVersion = tasks[i];
+                var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), Language.fixPath, "/", assetVersion.relativePath);
+                var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath);
+                DownloadMgr.Instance.AddTask(new DownloadTask(remoteURL, localURL));
+            }
+
+            DownloadMgr.Instance.Begin();
+
+            while (!DownloadMgr.Instance.IsFinished)
+            {
+                await UniTask.DelayFrame(1);
+            }
+
+            //妫�鏌ヤ笅杞藉畬鎴愬悗鐨勬枃浠舵槸鍚︽湁鏁�
+            var filledTasks = new List<AssetVersion>();//鏃犳晥鐨勬枃浠�
+            for (int i = 0; i < tasks.Count; i++)
+            {
+                var assetVersion = tasks[i];
+                var correctFile = assetVersion.CheckLocalFileValid(true);
+                if (correctFile)
+                    assetVersion.localValid = true;
+                else
+                    filledTasks.Add(assetVersion);
+            }
+            if (filledTasks.Count > 0)
+                Debug.LogErrorFormat("璧勬簮涓嬭浇瀹屽悗鏈墈0}涓枃浠舵棤鏁�({1})锛岄噸鏂板紑濮嬩笅杞�", filledTasks.Count, filledTasks[0].fileName);
+            tasks = filledTasks;
+        }
+
+        Debug.Log("璧勬簮鍏ㄩ儴涓嬭浇瀹屾垚");
+
+        step = Step.Completed;
+
+
+        //  TODO YYL
+        // UIManager.Instance.OpenWindow<DownLoadWin>();
+        // UIManager.Instance.OpenWindow<InGameDownLoadWin>();
+
+        // WindowCenter.Instance.Close<DownLoadWin>();
+        // WindowCenter.Instance.Close<InGameDownLoadWin>();
+
+        if (downLoadOkCallBack != null)
+        {
+            downLoadOkCallBack();
+            downLoadOkCallBack = null;
+        }
+
+        try
+        {
+            if (reinitedBuiltInAsset)
+            {
+                AssetBundleUtility.Instance.ReInitBuiltInAsset();
+            }
+        }
+        catch (System.Exception ex)
+        {
+            Debug.Log(ex);
+        }
+
+        if (restartApp)
+        {
+            SDKUtils.Instance.RestartApp();
+        }
+        SDKUtils.Instance.DownloadEnd();
+    }
+
+    // private void OnFileDownLoadCompleted(bool _ok, AssetVersion _assetVersion)
+    // {
+    //     var correctFile = false;
+    //     if (_ok)
+    //     {
+    //         correctFile = _assetVersion.CheckLocalFileValid(true);
+    //     }
+
+    //     if (_ok && correctFile)
+    //     {
+    //         okCount++;
+    //         _assetVersion.localValid = true;
+    //     }
+    //     else
+    //     {
+    //         ExceptionCatcher.ReportException("娓告垙鍚姩闃舵鏂囦欢涓嬭浇澶辫触", "鏂囦欢鍚嶏細" + _assetVersion.relativePath);
+    //         var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), "/", Language.Id, "/", _assetVersion.relativePath);
+    //         var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, _assetVersion.relativePath);
+
+    //         var remoteFile = new RemoteFile();
+    //         remoteFile.Init(remoteURL, localURL, _assetVersion);
+    //         remoteFile.Begin(OnFileDownLoadCompleted);
+    //     }
+    // }
+
+    public enum Step
+    {
+        None,
+        DownLoadPrepared,
+        DownLoad,
+        Completed,
+    }
+
+}
diff --git a/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs.meta b/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs.meta
new file mode 100644
index 0000000..4978ba0
--- /dev/null
+++ b/Main/System/AssetVersion/DownLoadAndDiscompressTask.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 88bd48354e00ee948a2ffc12590cf179
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/DownloadMgr.cs b/Main/System/AssetVersion/DownloadMgr.cs
new file mode 100644
index 0000000..6b48357
--- /dev/null
+++ b/Main/System/AssetVersion/DownloadMgr.cs
@@ -0,0 +1,483 @@
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.Networking;
+using Cysharp.Threading.Tasks;
+
+
+public class DownloadMgr : SingletonMonobehaviour<DownloadMgr>
+{
+    #region 閰嶇疆
+    public static int MaxRetryTimes = 5;//鏈�澶ч噸璇曠殑娆℃暟
+    public static int MaxDownLoadTask = 15;//鏈�澶у悓鏃朵笅杞芥暟閲�
+    public static int TimeOut = 10;//涓嬭浇瓒呮椂鏃堕棿
+    #endregion
+
+    #region 浠诲姟鍒楄〃
+    private Dictionary<string, DownloadTask> allTask = new Dictionary<string, DownloadTask>();    //鎵�鏈変换鍔$粍
+    private Queue<DownloadTask> waitTask = new Queue<DownloadTask>();    //褰撳墠绛夊緟涓嬭浇鐨勪换鍔�
+    private Dictionary<string, DownloadTask> downloadTask = new Dictionary<string, DownloadTask>();    //褰撳墠姝e湪涓嬭浇鐨勪换鍔�
+    #endregion 浠诲姟鍒楄〃
+
+    private bool isBegin;
+    private int startTickcount = 0;
+    private Func<bool, DownloadTask, bool> onTaskCompleted;//鏂囦欢涓嬭浇瀹屾垚鍥炶皟锛�<鏄惁鍏ㄩ儴瀹屾垚锛屼换鍔″璞★紝return true:绔嬪嵆閲嶈瘯锛宖alse:鍒伴槦灏鹃噸璇�>
+
+    //鎬婚�熷害
+    private float speed;
+    public float Speed { get { UpdateValue(); return speed; } }
+    public string SpeedFormat { get { return StringUtility.FormatSpeed(Speed); } }
+
+    //鎬诲凡涓嬭浇澶у皬
+    private long finishedBytes;//宸插畬鎴愪换鍔$殑澶у皬
+    private long downloadedBytes;
+    private long downloadedBytesRef;
+    public long DownloadedBytes { get { UpdateValue(); return downloadedBytes; } }
+
+    public bool IsBegin { get { return isBegin; } }
+    public bool IsFinished { get { return allTask.Count == 0; } }
+
+    //鏇存柊鏁板��
+    public void UpdateValue()
+    {
+        if (startTickcount == 0)//浠诲姟杩樻湭寮�濮�
+            return;
+        float second = Mathf.Abs(TimeUtility.AllSeconds - startTickcount);
+        Debug.LogFormat("鏇存柊鏁板��:{0}  {1}  {2}", TimeUtility.AllSeconds, startTickcount, second);
+        if (second < 1f)//鍒锋柊闂撮殧1绉�
+            return;
+        long bytes = 0;
+        long length = 0;
+        foreach (var pair in downloadTask)
+        {
+            var task = pair.Value;
+            bytes += task.downloadedBytes;
+            length += task.remoteLength;
+        }
+        downloadedBytes = finishedBytes + bytes;
+        // totalLength = length;
+
+        var delta = downloadedBytes < downloadedBytesRef || downloadedBytesRef == 0 ? 0 : downloadedBytes - downloadedBytesRef;
+        downloadedBytesRef = downloadedBytes;
+        speed = delta / second;
+        startTickcount = TimeUtility.AllSeconds;
+    }
+
+    //娣诲姞浠诲姟
+    public DownloadMgr AddTask(DownloadTask task)
+    {
+        if (allTask.ContainsKey(task.Key))
+        {
+            Debug.LogFormat("DownloadMgr-宸插瓨鍦ㄧ浉鍚岀殑涓嬭浇浠诲姟锛歿0}", task.Key);
+            return this;
+        }
+        allTask.Add(task.Key, task);
+        waitTask.Enqueue(task);
+        return this;
+    }
+
+    //鍑嗗涓嬭浇锛岄噸缃姸鎬�
+    public DownloadMgr Prepare()
+    {
+        Stop();
+        this.onTaskCompleted = null;
+        //娓呴櫎鎵�鏈変换鍔�
+        allTask.Clear();
+        waitTask.Clear();
+        downloadTask.Clear();
+        finishedBytes = 0;
+        return this;
+    }
+
+    /// <summary>
+    /// 寮�濮嬩笅杞�
+    /// </summary>
+    /// <param name="onTaskCompleted">浠诲姟缁撴潫鍥炶皟</param>
+    /// <returns></returns>
+    public DownloadMgr Begin(Func<bool, DownloadTask, bool> onTaskCompleted = null)
+    {
+        this.onTaskCompleted = onTaskCompleted;
+        startTickcount = TimeUtility.AllSeconds;
+        downloadedBytesRef = 0;
+        isBegin = true;
+        foreach (var pair in downloadTask)
+        {
+            //閲嶆柊寮�濮嬩笅杞戒换鍔�
+            if (pair.Value.BeginDownload(OnTaskCompleted))
+                Debug.LogFormat("閲嶆柊寮�濮嬩笅杞斤細{0}", pair.Key);
+        }
+        return this;
+    }
+
+    //鍋滄涓嬭浇
+    public void Stop()
+    {
+        startTickcount = 0;
+        isBegin = false;
+        foreach (var pair in downloadTask)
+        {
+            pair.Value.Stop();//鍋滄鎵�鏈変笅杞戒换鍔�
+        }
+    }
+
+    private void Update()
+    {
+        if (!isBegin)
+            return;
+        if (waitTask.Count == 0)
+            return;
+        if (downloadTask.Count >= MaxDownLoadTask)
+            return;
+        
+        //Debug.LogFormat("涓嬭浇鏈�澶т换鍔★細{0}", MaxDownLoadTask);
+        var task = waitTask.Dequeue();
+        if (task.IsDone)
+            return;
+        //寮�濮嬩笅杞�
+        if (!downloadTask.ContainsKey(task.Key))
+            downloadTask.Add(task.Key, task);
+        task.BeginDownload(OnTaskCompleted);
+    }
+
+    // 浠诲姟涓嬭浇瀹屾垚
+    private void OnTaskCompleted(DownloadTask task)
+    {
+        downloadTask.Remove(task.Key);
+        if (task.IsDone)//涓嬭浇鎴愬姛
+        {
+            finishedBytes += task.downloadedBytes;
+            allTask.Remove(task.Key);
+            this.onTaskCompleted?.Invoke(IsFinished, task);
+        }
+        else//涓嬭浇澶辫触
+        {
+            var prior = this.onTaskCompleted == null ? false : this.onTaskCompleted(IsFinished, task);//杩斿洖鍊间负鏄惁绔嬪嵆閲嶈瘯
+            //鎵�鏈変换鍔′腑涓嶅瓨鍦紝璇存槑宸茬粡琚竻闄や簡,灏变笉閲嶆柊鎺掗槦
+            if (allTask.ContainsKey(task.Key))
+            {
+                if (prior) //涓嶆帓闃燂紝鐩存帴閲嶆柊寮�濮�
+                {
+                    downloadTask.Add(task.Key, task);
+                    if (isBegin)
+                        task.BeginDownload(OnTaskCompleted);
+                }
+                else
+                    waitTask.Enqueue(task); //閲嶆柊鎺掗槦
+            }
+        }
+        //TODO:杩欓噷鏆傛椂鐢ㄦ棤闄愰噸澶嶄笅杞斤紝涓嶅仛涓婇檺澶勭悊
+        // if (task.failedTimes >= MaxRetryTimes)//閲嶈瘯娆℃暟宸茶揪鍒颁笂闄愶紝浠诲姟澶辫触
+        // task.team.OnFailed(task);
+        // else//閲嶈瘯娆℃暟鏈揪鍒颁笂闄�,閲嶆柊鍔犲叆绛夊緟闃熷垪
+        // waitTask.Enqueue(task);
+    }
+}
+
+
+
+public class DownloadTask
+{
+    //涓嬭浇浠诲姟鐘舵��
+    public enum TaskState
+    {
+        Wait,
+        Working,
+        Succeed,
+        Failed
+    }
+    public readonly string remoteUrl; //杩滅▼杩炴帴鍦板潃
+    public readonly string localFile; //鏈湴鍦板潃
+    public readonly string tempFile;//涓存椂鏂囦欢鍦板潃
+    private readonly bool clearCache;//鏄惁娓呴櫎鏃х殑涓嬭浇缂撳瓨锛岋紙鏂偣缁紶锛�
+    public readonly object obj; //鑷畾涔夊璞�
+    private Action<DownloadTask> onCompleted;//涓嬭浇瀹屾垚鍥炶皟
+    private TaskState state;//涓嬭浇鐘舵��
+
+    public bool isStop;//涓嬭浇琚仠姝�
+    public int failedTimes = 0;//澶辫触鐨勬鏁�
+    private bool requestHeaderOk = false;//鏄惁宸茶幏鍙栧ご淇℃伅
+    private System.DateTime remoteLastModified; //杩滅鏂囦欢鏈�鍚庝慨鏀规椂闂�
+    public long remoteLength;//杩滅鏂囦欢澶у皬
+    private bool isAcceptRange = false;//鏈嶅姟绔槸鍚︽敮鎸佹柇鐐圭画浼�
+    private string errorStr;//閿欒淇℃伅
+    public long downloadedBytes;//褰撳墠宸蹭笅杞芥暟鎹�
+    public float downloadedSpeed;//褰撳墠涓嬭浇閫熷害
+    private int beginTickCount;
+
+    private UnityWebRequest fileRequest;
+
+    public string Key { get { return remoteUrl; } }
+
+    public string SpeedFormat { get { return StringUtility.FormatSpeed(downloadedSpeed); } }
+
+    //鏈湴鏂囦欢澶у皬
+    public long LocalLength { get { return (File.Exists(tempFile)) ? (new FileInfo(tempFile)).Length : 0L; } }
+
+    //鏈湴鏂囦欢鏈�鍚庝慨鏀规椂闂�
+    private System.DateTime LocalLastModified { get { return File.Exists(tempFile) ? File.GetLastWriteTime(tempFile) : DateTime.MinValue; } }
+    public bool IsWorking { get { return state == TaskState.Working; } }
+    public bool IsDone { get { return state == TaskState.Succeed; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="remoteUrl">涓嬭浇鍦板潃</param>
+    /// <param name="localUrl">鏈湴淇濆瓨鍦板潃</param>
+    /// <param name="obj">鑷畾涔夊璞�</param>
+    /// <param name="clearCache">鏄惁娓呴櫎涓婃涓嬭浇鐨勭紦瀛�</param>
+    public DownloadTask(string remoteUrl, string localUrl, object obj = null, bool clearCache = false)
+    {
+        this.remoteUrl = remoteUrl;
+        this.localFile = localUrl;
+        this.tempFile = localFile + ".temp";
+        this.obj = obj;
+        this.clearCache = clearCache;
+        this.state = TaskState.Wait;
+    }
+
+    private bool IsOutdated //鏈湴鏂囦欢鏄惁宸茶繃鏃�
+    {
+        get {
+            if (File.Exists(tempFile))
+                return remoteLastModified > LocalLastModified;
+            return false;
+        }
+    }
+
+    private void SetSucceed()
+    {
+        state = TaskState.Succeed;
+    }
+
+    private void SetFailed(string error)
+    {
+        this.state = TaskState.Failed;
+        this.errorStr = error;
+        this.failedTimes++;
+    }
+
+    public void BeginGetHeader()
+    {
+        if (IsWorking)
+            return;
+
+        Co_GetHeader();
+        // SnxxzGame.Instance.StartCoroutine(Co_GetHeader());
+    }
+
+    public bool BeginDownload(Action<DownloadTask> onCompleted)
+    {
+        if ((IsWorking && requestHeaderOk) || IsDone)//宸茬粡鍦ㄤ笅杞戒换鍔′腑鎴栧凡缁忎笅杞藉畬鎴愪簡
+            return false;
+        if (state == TaskState.Wait)//绗竴娆″皾璇�
+            failedTimes = 0;
+        this.onCompleted = onCompleted;
+        this.isStop = false;
+        Co_DownloadFile();
+        // SnxxzGame.Instance.StartCoroutine(Co_DownloadFile());
+        return true;
+    }
+
+    //鍋滄涓嬭浇
+    public void Stop()
+    {
+        isStop = true;
+        if (fileRequest != null && !fileRequest.isDone)
+            fileRequest.Abort();
+        Debug.LogFormat("鏆傚仠浠诲姟锛歿0}", remoteUrl);
+    }
+
+    //鑾峰彇鏂囦欢澶翠俊鎭�
+    private async UniTask Co_GetHeader()
+    {
+        this.state = TaskState.Working;
+        FileExtersion.MakeSureDirectory(tempFile);
+        Debug.LogFormat("寮�濮嬭幏鍙栧ご淇℃伅锛歿0}", remoteUrl);
+        using (var www = UnityWebRequest.Head(remoteUrl))
+        {
+            www.timeout = DownloadMgr.TimeOut;
+            await www.SendWebRequest();
+            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
+            {
+                Debug.LogErrorFormat("澶翠俊鎭幏鍙栧け璐ワ細{0}锛沞rror锛歿1}", remoteUrl, www.error);
+                requestHeaderOk = false;
+                SetFailed(www.error);
+                www.Dispose();
+                await UniTask.CompletedTask;
+            }
+            long.TryParse(www.GetResponseHeader(HttpHeader.ContentLength), out this.remoteLength);
+            this.remoteLastModified = DateTime.Parse(www.GetResponseHeader(HttpHeader.LastModified));
+            var acceptRange = www.GetResponseHeader(HttpHeader.AcceptRanges);
+            this.isAcceptRange = acceptRange != "none";
+            Debug.LogFormat("澶翠俊鎭幏鍙栨垚鍔燂細{0}锛涘ぇ灏忥細{1}锛涗慨鏀规椂闂达細{2}锛涙槸鍚︽敮鎸佺画浼狅細{3}", remoteUrl, remoteLength, remoteLastModified, acceptRange);
+            requestHeaderOk = true;
+            state = TaskState.Wait;
+            www.Dispose();
+        }
+    }
+    private async UniTask Co_DownloadFile()
+    {
+        state = TaskState.Working;
+        while (TimeUtility.AllSeconds < beginTickCount + 5)//闄愬埗閲嶆柊涓嬭浇鐨勬椂闂撮棿闅�
+        {
+            if (isStop)
+                await UniTask.CompletedTask;
+            else
+                await UniTask.DelayFrame(1);
+        }
+        beginTickCount = TimeUtility.AllSeconds;
+        if (!requestHeaderOk)
+            await Co_GetHeader();
+        if (!requestHeaderOk)//澶存枃浠惰幏鍙栧け璐�
+        {
+            onCompleted?.Invoke(this);
+            await UniTask.CompletedTask;
+        }
+        try
+        {
+            if (clearCache && File.Exists(tempFile))
+            {
+                File.Delete(localFile);//娓呴櫎涓婃涓嬭浇鐨勪复鏃舵枃浠�
+                Debug.LogFormat("宸叉竻闄ょ紦瀛樻枃浠讹細{0}", tempFile);
+            }
+        }
+        catch (Exception e)
+        {
+            Debug.LogFormat("娓呴櫎缂撳瓨鏂囦欢澶辫触锛歿0}锛沞rror锛歿1}", tempFile, e);
+        }
+        if (File.Exists(tempFile))//涓存椂鏂囦欢瀛樺湪
+        {
+            var _localLength = LocalLength;
+            var _outdated = IsOutdated;
+            //鏂囦欢瀹屾暣涓旀湭杩囨湡锛屾棤椤诲啀涓嬭浇浜�
+            if (_localLength == remoteLength && !_outdated)
+            {
+                await Move(tempFile, localFile);//鎶婁复鏃舵枃浠舵敼鍚嶄负姝e紡鏂囦欢
+                onCompleted?.Invoke(this);
+                await UniTask.CompletedTask;
+            }
+            else if (_localLength > remoteLength || _outdated)//鏂囦欢涓嶅鎴栬繃鏈熶簡
+            {
+                if (!_outdated) Debug.LogFormat("鏈湴鏂囦欢澶т簬鏈嶅姟鍣ㄧ鏂囦欢锛歿0}", tempFile);
+                if (_outdated) Debug.LogFormat("鏂囦欢宸茶繃鏈燂細{0}", tempFile);
+                try
+                {
+                    if (File.Exists(tempFile))
+                        File.Delete(tempFile);
+                }
+                catch (Exception e)
+                {
+                    Debug.LogErrorFormat("鍒犻櫎涓存椂鏂囦欢鍑洪敊锛歿0}锛沞rror锛歿1}", tempFile, e);
+                    isAcceptRange = false;//濡傛灉鍒犻櫎涓存椂鏂囦欢鍑洪敊锛屽彇娑堢画浼狅紝瑕嗗啓鏂囦欢
+                }
+            }
+        }
+        if (isStop)//浠诲姟琚殏鍋�
+        {
+            state = TaskState.Wait;
+            await UniTask.CompletedTask;
+        }
+        Debug.LogFormat("涓嬭浇浠诲姟寮�濮嬶細{0}", remoteUrl);
+        fileRequest = UnityWebRequest.Get(remoteUrl);
+
+        fileRequest.downloadHandler = new DownloadHandlerFile(tempFile, this.isAcceptRange);
+        if (LocalLength != 0L && isAcceptRange)
+            fileRequest.SetRequestHeader(HttpHeader.Range, "bytes=" + LocalLength + "-");
+        Debug.LogFormat("涓嬭浇璇锋眰鑼冨洿锛歿0} 锛沚ytes={1}", remoteUrl, LocalLength);
+        var localLength = LocalLength;
+        this.downloadedBytes = localLength;
+        fileRequest.SendWebRequest();
+        while (!fileRequest.isDone)
+        {
+            var length = localLength + (long)fileRequest.downloadedBytes;//鏈湴鏂囦欢澶у皬+鏈涓嬭浇鐨勬暟鎹ぇ灏�
+            this.downloadedSpeed = Math.Max(0, (length - this.downloadedBytes) / Time.deltaTime);
+            this.downloadedBytes = length;
+            await UniTask.DelayFrame(1);
+        }
+        if (fileRequest.result == UnityWebRequest.Result.ConnectionError || fileRequest.result == UnityWebRequest.Result.ProtocolError)
+        {
+            if (isStop)//浠诲姟琚殏鍋�
+            {
+                state = TaskState.Wait;
+            }
+            else //浠诲姟澶辫触
+            {
+                SetFailed(fileRequest.error);
+                onCompleted?.Invoke(this);
+                Debug.LogErrorFormat("鏂囦欢涓嬭浇澶辫触锛歿0}锛沞rror锛歿1}", remoteUrl, fileRequest.error);
+            }
+            fileRequest.Dispose();
+            fileRequest = null;
+            await UniTask.CompletedTask;
+        }
+        Debug.LogFormat("鏂囦欢涓嬭浇鎴愬姛锛歿0}锛�", tempFile);
+        fileRequest.Dispose();
+        fileRequest = null;
+
+        FileInfo tempFileInfo = new FileInfo(tempFile);
+        if (tempFileInfo.Exists)
+        {
+            //鍒ゆ柇涓存椂鏂囦欢鍜岃繙绋嬫枃浠跺ぇ灏忔槸鍚︿竴鑷�
+            if (tempFileInfo.Length != remoteLength && remoteLength != 0L)
+            {
+                Debug.LogErrorFormat("涓嬭浇瀹屾垚鍚庝絾鏄ぇ灏忎笉涓�鑷达細{0}锛� {1} || {2}", remoteUrl, tempFileInfo.Length, remoteLastModified);
+                SetFailed("鏂囦欢涓嬭浇瀹屾垚鍚庝絾鏄ぇ灏忎笉涓�鑷�");
+            }
+            else
+            {  //澶у皬涓�鑷� 
+                await Move(tempFile, localFile);
+            }
+        }
+        else
+        {   //涓存椂鏂囦欢涓嶅瓨鍦�
+            Debug.LogErrorFormat("涓嬭浇瀹屾垚浣嗘槸涓存椂鏂囦欢涓嶅瓨鍦細{0}", tempFile);
+            SetFailed("涓嬭浇瀹屾垚浣嗘槸鏂囦欢涓嶅瓨鍦�");
+        }
+        onCompleted?.Invoke(this);
+    }
+
+    //鎷疯礉鏂囦欢锛屾妸涓存椂鏂囦欢鏀规垚姝e紡鏂囦欢
+    private IEnumerator Move(string sourceFile, string destFile)
+    {
+        var copyState = 0;//澶嶅埗鏂囦欢鐘舵�侊紝0绛夊緟锛�1鎴愬姛锛�2澶辫触
+        try
+        {
+            // if (speedLimit)
+            ThreadPool.QueueUserWorkItem((object _obj) =>
+            {
+                if (File.Exists(destFile))
+                    File.Delete(destFile);
+                File.Move(sourceFile, destFile);
+                System.Threading.Interlocked.Exchange(ref copyState, 1);
+            });
+            // else
+            // {
+            //     if (File.Exists(destFile))
+            //         File.Delete(destFile);
+            //     File.Move(sourceFile, destFile);
+            //     copyState = 1;
+            // }
+        }
+        catch (Exception ex)
+        {
+            Debug.LogErrorFormat("涓存椂鏂囦欢鏀瑰悕鍑洪敊锛歿0}", ex);
+            copyState = 1;
+        }
+        while (copyState == 0)
+            yield return null;
+        if (copyState == 1)
+        {
+            Debug.LogFormat("鏂囦欢澶嶅埗鎴愬姛锛歿0}", localFile);
+            SetSucceed();
+        }
+        else
+            SetFailed("涓存椂鏂囦欢鏀瑰悕鍑洪敊");
+    }
+
+}
+
diff --git a/Main/System/AssetVersion/DownloadMgr.cs.meta b/Main/System/AssetVersion/DownloadMgr.cs.meta
new file mode 100644
index 0000000..5331741
--- /dev/null
+++ b/Main/System/AssetVersion/DownloadMgr.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4d766a115145d75469c8ec8e641f3f8a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/InGameDownLoad.cs b/Main/System/AssetVersion/InGameDownLoad.cs
new file mode 100644
index 0000000..648a5a7
--- /dev/null
+++ b/Main/System/AssetVersion/InGameDownLoad.cs
@@ -0,0 +1,722 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using System.Text.RegularExpressions;
+
+
+public class InGameDownLoad : SingletonMonobehaviour<InGameDownLoad>
+{
+    public const int BYTE_PER_KILOBYTE = 1024;//b 杞� kb
+    public const int BYTE_PER_MILLIONBYTE = 1048576;//b 杞� mb
+
+    List<AssetVersion> assets = new List<AssetVersion>(); //鎵�鏈夎祫婧�
+    Dictionary<int, List<AssetVersion>> mapTasks = new Dictionary<int, List<AssetVersion>>();//鍦板浘涓撳睘鐨勮祫婧�
+
+    public bool inGameDownLoadAllow = false; //鏄惁鍙互涓嬭浇
+    public bool downLoadGo = false; //鏄惁鍔犻�熶笅杞�
+
+    public float progress //涓嬭浇杩涘害
+    {
+        get
+        {
+            return Mathf.Clamp01((float)showDownLoadedSize / showTotalSize);
+        }
+    }
+
+    public bool isDone { get { return state == State.Completed; } } //鏄惁鍏ㄩ儴涓嬭浇瀹屾垚
+
+    //绐楀彛涓樉绀虹殑宸蹭笅杞藉ぇ灏�
+    public long showDownLoadedSize { get { return DownloadMgr.Instance.DownloadedBytes - backGroundDownLoadSizeRecord; } }
+    public long showTotalSize { get { return totalSize - backGroundDownLoadSizeRecord; } }//绐楀彛涓樉绀虹殑鎬诲ぇ灏�
+    public int showTotalCount { get { return totalCount - downLoadedCountRecord; } }//绐楀彛涓樉绀虹殑鎬绘暟閲�
+    public int showOkCount { get { return okCount - downLoadedCountRecord; } }//绐楀彛涓樉绀虹殑涓嬭浇瀹屾垚鏁伴噺
+
+    long totalSize = 0; //璧勬簮鎬诲ぇ灏�
+    int totalCount = 0;//璧勬簮鎬绘暟閲�
+    int okCount = 0;//涓嬭浇瀹屾垚鐨勬暟閲�
+
+    long backGroundDownLoadSizeRecord = 0;//鍚庡彴鍋峰伔宸茬粡涓嬭浇鍒拌祫婧愰噺
+    int downLoadedCountRecord = 0;//鍚庡彴宸茬粡涓嬭浇瀹屾垚鐨勮祫婧愬寘鏁伴噺
+
+    public event Action<State> downLoadStateChangeEvent;
+    public event Action<Dominant> dominantDownLoadEvent;
+
+    Action onDownLoadOk;//璧勬簮鍏ㄩ儴涓嬭浇瀹屾垚鍥炶皟
+
+    Dominant m_DominantState = Dominant.None;
+    public Dominant dominantState
+    {
+        get { return m_DominantState; }
+        private set
+        {
+            if (m_DominantState != value)
+            {
+                m_DominantState = value;
+                if (dominantDownLoadEvent != null)
+                {
+                    dominantDownLoadEvent(m_DominantState);
+                }
+            }
+        }
+    }
+
+    State m_State = State.None;
+    public State state
+    {
+        get { return m_State; }
+        set
+        {
+            if (m_State != value)
+            {
+                m_State = value;
+
+                if (downLoadStateChangeEvent != null)
+                {
+                    downLoadStateChangeEvent(m_State);
+                }
+            }
+        }
+    }
+
+    // TaskModel taskModel { get { return ModelCenter.Instance.GetModel<TaskModel>(); } }
+
+    public List<Reward> rewards = new List<Reward>();
+    public bool hasReward { get; private set; }//鏄惁鏈夊鍔�
+    public string completeDownLoadAccount
+    {
+        get { return LocalSave.GetString("InGameDownLoadCompleteAccount"); }
+        set { LocalSave.SetString("InGameDownLoadCompleteAccount", value); }
+    }
+
+    //  TODO YYL
+    // public Redpoint downLoadRedpoint = new Redpoint(116);
+
+    private void Awake()
+    {
+        DownloadMgr.MaxDownLoadTask = GetMaxTask();
+    }
+
+    private void LateUpdate()
+    {
+        if (state == State.None || state == State.Award || state == State.Completed)
+        {
+            return;
+        }
+
+        netCheckTimer += Time.deltaTime;
+
+        if (InGameDownTestUtility.enable)
+        {
+            simulateWifi = InGameDownTestUtility.isWifi;
+        }
+        else
+        {
+            if (netCheckTimer > 3f)
+            {
+                netCheckTimer = 0f;
+                networkReachability = Application.internetReachability;
+            }
+        }
+
+        if (mapId != 0)
+        {
+            var progress = GetMapAssetDownLoadProgress(mapId);
+            if (progress > 0.9999f)
+            {
+                if (mapAssetDownLoadOk != null)
+                {
+                    mapAssetDownLoadOk();
+                    mapAssetDownLoadOk = null;
+                    mapId = 0;
+                }
+            }
+        }
+
+    }
+
+    //寮�濮嬪垎閰嶄换鍔�
+    public void AssignTasks(List<AssetVersion> assets, Action _onDownLoadOk)
+    {
+        // TODO YYL
+        // this.inGameDownLoadAllow = false;
+        // this.assets = assets;
+        // this.assets.Sort(this.AssetDownLoadPriorCompare);//鎵�鏈変换鍔℃牴鎹紭鍏堢骇鎺掑簭
+        // onDownLoadOk = _onDownLoadOk;
+
+        // totalCount = this.assets.Count;
+        // okCount = 0;
+        // totalSize = 0;
+
+        // DownloadMgr.Instance.Prepare();
+
+        // for (int i = 0; i < this.assets.Count; i++)
+        // {
+        //     var assetVersion = this.assets[i];
+        //     totalSize += assetVersion.size;//缁熻璧勬簮鎬诲ぇ灏�
+        //     //缁熻鍦板浘涓撳睘鐨勮祫婧�
+        //     var mapId = PriorBundleConfig.GetAssetBelongToMap(assetVersion.GetAssetCategory(), AssetVersionUtility.DecodeFileName(assetVersion.fileName));
+        //     if (mapId != 0)
+        //     {
+        //         if (!mapTasks.ContainsKey(mapId))
+        //         {
+        //             mapTasks[mapId] = new List<AssetVersion>();
+        //         }
+        //         mapTasks[mapId].Add(assetVersion);
+        //     }
+        //     //娣诲姞涓嬭浇浠诲姟
+        //     var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), Language.fixPath, "/", assetVersion.relativePath);
+        //     var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath);
+        //     DownloadMgr.Instance.AddTask(new DownloadTask(remoteURL, localURL, assetVersion));
+        // }
+
+        // state = State.None;
+
+        // TaskModel.Event_MainlineTask -= OnMainTaskChange;
+        // TaskModel.Event_MainlineTask += OnMainTaskChange;
+
+        // PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange;
+        // PlayerDatas.Instance.playerDataRefreshEvent += OnPlayerLevelChange;
+    }
+
+    //浠诲姟鏍规嵁浼樺厛绾ф帓搴�
+    private int AssetDownLoadPriorCompare(AssetVersion lhs, AssetVersion rhs)
+    {
+        var categoryA = lhs.GetAssetCategory();
+        var categoryB = rhs.GetAssetCategory();
+
+        //  TODO YYL
+
+        // var priorA = PriorBundleConfig.GetAssetPrior(categoryA, AssetVersionUtility.DecodeFileName(lhs.fileName));
+        // var priorB = PriorBundleConfig.GetAssetPrior(categoryB, AssetVersionUtility.DecodeFileName(rhs.fileName));
+
+        // if (priorA != priorB)
+        // {
+        //     return priorA < priorB ? -1 : 1;
+        // }
+        // else
+        {
+            var isManifestA = lhs.extersion == ".manifest";
+            var isManifestB = rhs.extersion == ".manifest";
+
+            if (!isManifestA && isManifestB)
+            {
+                return -1;
+            }
+            else if (isManifestA && !isManifestB)
+            {
+                return 1;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+
+    public void TryDownLoad(Dominant _dominant)
+    {
+        if (!inGameDownLoadAllow)
+        {
+            return;
+        }
+
+        if (assets == null || assets.Count == 0 || isDone)
+        {
+            return;
+        }
+
+        if (_dominant < dominantState)
+        {
+            return;
+        }
+
+        switch (_dominant)
+        {
+            case Dominant.None:
+                if (InGameDownTestUtility.enable)
+                {
+                    if (InGameDownTestUtility.isWifi)
+                    {
+                        StartDownLoad();
+                    }
+                }
+                else
+                {
+                    if (Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork)
+                    {
+                        StartDownLoad();
+                    }
+                }
+                break;
+            case Dominant.Half:
+                if (dominantState == Dominant.None)
+                {
+                    backGroundDownLoadSizeRecord = DownloadMgr.Instance.DownloadedBytes;
+                    downLoadedCountRecord = okCount;
+                }
+                StartDownLoad();
+                dominantState = Dominant.Half;
+                break;
+            case Dominant.Whole:
+                if (dominantState == Dominant.None)
+                {
+                    backGroundDownLoadSizeRecord = DownloadMgr.Instance.DownloadedBytes;
+                    downLoadedCountRecord = okCount;
+                    Pause();
+                    state = State.Prepared;
+                }
+                else if (dominantState == Dominant.Half)
+                {
+                    Pause();
+                    state = State.Prepared;
+                }
+                dominantState = Dominant.Whole;
+                //  TODO YYL
+                // UIManager.Instance.ShowWindow<InGameDownLoadWin>();
+                // // WindowCenter.Instance.Open<InGameDownLoadWin>();
+                break;
+        }
+    }
+
+    //寮�濮嬩笅杞�
+    public void StartDownLoad()
+    {
+        if (state == State.None || state == State.Prepared || state == State.Pause)
+        {
+            state = State.DownLoad;
+            DownloadMgr.Instance.Begin(OnFileDownLoadCompleted);
+        }
+    }
+
+    //鏆傚仠涓嬭浇
+    public void Pause()
+    {
+        if (state == State.DownLoad)
+        {
+            DownloadMgr.Instance.Stop();
+            state = State.Pause;
+        }
+    }
+
+    //鏂囦欢涓嬭浇瀹屾垚鍥炶皟
+    private bool OnFileDownLoadCompleted(bool finished, DownloadTask task)
+    {
+        if (task.IsDone && task.obj is AssetVersion)
+        {
+            (task.obj as AssetVersion).localValid = true;
+            okCount++;
+        }
+        if (finished)
+            OnDownLoadFinished();
+        return true;//杩斿洖true琛ㄧず濡傛灉涓嬭浇澶辫触锛屼笉閲嶆柊鎺掗槦锛岀珛鍗抽噸璇�
+    }
+
+    //鎵�鏈変换鍔″畬鎴�
+    private void OnDownLoadFinished()
+    {
+        //  TODO YYL
+        // TaskModel.Event_MainlineTask -= OnMainTaskChange;
+        // PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange;
+
+        // WindowCenter.Instance.Close<InGameDownLoadWin>();
+
+        // if (!hasReward)
+        // {
+        //     if (dominantState == Dominant.None)
+        //     {
+        //         RequestDownLoadReward(false);
+        //         state = State.Completed;
+        //     }
+        //     else
+        //     {
+        //         completeDownLoadAccount = PlayerDatas.Instance.baseData.AccID;
+        //         state = State.Award;
+        //     }
+        // }
+        // else
+        // {
+        //     state = State.Completed;
+        // }
+
+        
+        // downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None;
+
+        // if (onDownLoadOk != null)
+        // {
+        //     onDownLoadOk();
+        //     onDownLoadOk = null;
+        // }
+    }
+
+    public void ParseRewardConfig()
+    {
+        // //  TODO YYL
+        // var rewardString = FuncConfigConfig.Get("DownReward").Numerical1;
+        // var matches = Regex.Matches(rewardString, "(\\d+,\\d+,\\d+)");
+        // for (int i = 0; i < matches.Count; i++)
+        // {
+        //     rewards.Add(new Reward(matches[i].Value));
+        // }
+    }
+
+    //  TODO YYL
+    // public void UpdateRewardInfo(HA319_tagMCPackDownloadRecord _package)
+    // {
+    //     hasReward = _package.Record == 1;
+
+    //     if (AssetVersionUtility.unPriorAssetDownLoadDone)
+    //     {
+    //         state = !hasReward && completeDownLoadAccount == PlayerDatas.Instance.baseData.AccID ? State.Award : State.Completed;
+    //     }
+
+    //     downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None;
+    // }
+
+    public void RequestDownLoadReward(bool _manual)
+    {
+        //  TODO YYL
+        // var send = new CA504_tagCMPlayerGetReward();
+        // send.RewardType = 15;
+        // send.DataEx = (byte)(_manual ? 0 : 1);
+        // GameNetSystem.Instance.SendInfo(send);
+    }
+
+    public float GetMapAssetDownLoadProgress(int mapId)
+    {
+        if (!mapTasks.ContainsKey(mapId))
+        {
+            return 1f;
+        }
+
+        var tasks = mapTasks[mapId];
+        var total = tasks.Count;
+        if (total == 0)
+        {
+            return 1f;
+        }
+
+        var completeCount = 0;
+        foreach (var task in tasks)
+        {
+            if (task.localValid)
+            {
+                completeCount++;
+            }
+        }
+
+        return completeCount / (float)total;
+    }
+
+    int mapId = 0;
+    Action mapAssetDownLoadOk;
+    public void RegisterMapAssetDownLoadOk(int mapId, Action callBack)
+    {
+        var progress = GetMapAssetDownLoadProgress(mapId);
+        if (progress < 0.999f)
+        {
+            this.mapId = mapId;
+            mapAssetDownLoadOk = callBack;
+        }
+    }
+
+    public void UnRegisterMapAssetDownLoadOk()
+    {
+        this.mapId = 0;
+        mapAssetDownLoadOk = null;
+    }
+
+    Clock netSwitchClock;
+    NetworkReachability m_NetworkReachability = NetworkReachability.NotReachable;
+    NetworkReachability networkReachability
+    {
+        get { return m_NetworkReachability; }
+        set
+        {
+            if (m_NetworkReachability != value)
+            {
+                m_NetworkReachability = value;
+
+                if (dominantState != Dominant.Whole)
+                {
+                    switch (m_NetworkReachability)
+                    {
+                        case NetworkReachability.ReachableViaCarrierDataNetwork:
+                            Pause();
+                            var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 3);
+                            if (netSwitchClock != null)
+                            {
+                                Clock.Stop(netSwitchClock);
+                            }
+
+                            netSwitchClock = Clock.AlarmAt(endTime, () =>
+                             {
+                                 if (CheckDominantDownLoad())
+                                 {
+                                     TryDownLoad(Dominant.Whole);
+                                 }
+                             });
+                            break;
+                        case NetworkReachability.ReachableViaLocalAreaNetwork:
+                            TryDownLoad(Dominant.None);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    bool m_SimulateWifi = true;
+    public bool simulateWifi
+    {
+        get { return m_SimulateWifi; }
+        set
+        {
+            if (m_SimulateWifi != value)
+            {
+                m_SimulateWifi = value;
+
+                if (dominantState != Dominant.Whole)
+                {
+                    if (m_SimulateWifi)
+                    {
+                        TryDownLoad(Dominant.None);
+                    }
+                    else
+                    {
+                        Pause();
+                        var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 10);
+                        Clock.AlarmAt(endTime, () =>
+                        {
+                            if (CheckDominantDownLoad())
+                            {
+                                TryDownLoad(Dominant.Whole);
+                            }
+                        });
+                    }
+                }
+            }
+
+        }
+    }
+
+    float netCheckTimer = 0f;
+
+    public bool CheckDominantDownLoad()
+    {
+        if (assets == null || assets.Count == 0 || isDone || dominantState == Dominant.Whole /*|| NewBieCenter.Instance.inGuiding*/)
+        {
+            return false;
+        }
+
+        if (GeneralDefine.inGameDownLoadLevelCheckPoints == null || GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0)
+        {
+            return false;
+        }
+
+        if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadLevelCheckPoints[0])
+        {
+            return false;
+        }
+
+        if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadHighLevel)
+        {
+            if (InGameDownTestUtility.enable)
+            {
+                if (InGameDownTestUtility.isWifi)
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if (Application.internetReachability != NetworkReachability.ReachableViaCarrierDataNetwork)
+                {
+                    return false;
+                }
+            }
+        }
+
+
+        // TODO YYL
+        // if (!WindowCenter.Instance.IsOpen("MainInterfaceWin"))
+        // {
+        //     return false;
+        // }
+
+        // if (WindowCenter.Instance.ExistAnyFullScreenOrMaskWin())
+        // {
+        //     return false;
+        // }
+
+        return true;
+    }
+
+    public bool IsHighLevelPlayer()
+    {
+        if (GeneralDefine.inGameDownLoadLevelCheckPoints == null
+            || GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0)
+        {
+            return false;
+        }
+
+        var level = PlayerDatas.Instance.baseData.LV;
+        return level > GeneralDefine.inGameDownLoadHighLevel;
+    }
+
+    //鐜╁鍗囩骇
+    private void OnPlayerLevelChange(PlayerDataType refreshType)
+    {
+        switch (refreshType)
+        {
+            case PlayerDataType.LV:
+                var level = PlayerDatas.Instance.baseData.LV;
+                var count = GeneralDefine.inGameDownLoadLevelCheckPoints.Count;
+                var lastLevelCheckPoint = GeneralDefine.inGameDownLoadLevelCheckPoints[count - 1];
+                if (GeneralDefine.inGameDownLoadLevelCheckPoints.Contains(level) || IsHighLevelPlayer())
+                {
+                    if (CheckDominantDownLoad())
+                    {
+                        TryDownLoad(Dominant.Whole);
+                    }
+                }
+                break;
+        }
+    }
+
+    //涓荤嚎浠诲姟浠诲姟鐘舵�佸彉鏇村拰鍒锋柊
+    private void OnMainTaskChange(int _taskId, int _state)
+    {
+        // TODO YYL
+        // var mainTaskId = taskModel.currentMission;
+        // if (GeneralDefine.inGameDownLoadTaskCheckPoints.Contains(mainTaskId)
+        //     && taskModel.currentMissionState == 1)
+        // {
+        //     if (CheckDominantDownLoad())
+        //     {
+        //         TryDownLoad(Dominant.Whole);
+        //     }
+        // }
+    }
+
+    //鑾峰彇鏈�澶т笅杞戒换鍔℃暟
+    public int GetMaxTask()
+    {
+        //  TODO YYL
+        // if (!LoginWin.firstOpenEnd)
+        //     return 20;
+
+        if (downLoadGo)
+            return 20;
+
+        switch (Application.platform)
+        {
+            case RuntimePlatform.Android:
+                if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.2f * 1024)
+                {
+                    return 2;
+                }
+                else
+                {
+                    return 1;
+                }
+            case RuntimePlatform.IPhonePlayer:
+                if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024)
+                {
+                    return 2;
+                }
+                else
+                {
+                    return 1;
+                }
+            case RuntimePlatform.WindowsEditor:
+                return 2;
+            default:
+                return 1;
+        }
+    }
+
+    public struct Reward
+    {
+        public int id;
+        public int count;
+        public bool bind;
+
+        public Reward(string _input)
+        {
+            var matches = Regex.Matches(_input, "\\d+");
+
+            if (matches.Count > 0)
+            {
+                int.TryParse(matches[0].Value, out id);
+            }
+            else
+            {
+                id = 0;
+            }
+
+            if (matches.Count > 1)
+            {
+                int.TryParse(matches[1].Value, out count);
+            }
+            else
+            {
+                count = 0;
+            }
+
+            if (matches.Count > 2)
+            {
+                var temp = 0;
+                int.TryParse(matches[2].Value, out temp);
+                bind = temp == 1;
+            }
+            else
+            {
+                bind = false;
+            }
+        }
+
+    }
+
+    public enum State
+    {
+        None,
+        Prepared,
+        DownLoad,
+        Pause,
+        Award,
+        Completed,
+    }
+
+    public enum Dominant
+    {
+        None = 0,
+        Half = 1,
+        Whole = 2,
+    }
+
+    #region 鐧诲綍涓嬭浇鐣岄潰 DownLoadWin
+    // 澧炲姞涓嬭浇濂栧姳 鏍规嵁鏍囪瘑鍐冲畾澶氭鍙戞斁;娉ㄦ剰涓嶈涓庢父鎴忓唴鐨勫畬鏁翠笅杞芥贩娣�
+    // 鍚庣画鏀规垚appversion_new澧炲姞鎵╁睍淇℃伅杩斿洖涓嬭浇鏍囪瘑锛岀敤浜庢帶鍒跺綋鍓嶆槸鍚︽樉绀哄鍔�,姝ゅ棣栧寘杩樻湭鍖呭惈鍥剧墖璧勬簮
+
+    public int downloadMark = 0;
+
+    public bool IsShowDownloadAward()
+    {
+        int downloadMark = 0;
+        int.TryParse(VersionUtility.Instance.versionInfo.ResourceAward, out downloadMark);
+        var mark = LocalSave.GetInt("downloadMark");
+        return downloadMark > mark;
+
+    }
+
+    //涓嬭浇瀹屾瘯鎴愬姛鐧诲綍娓告垙鍗冲彲璁剧疆
+    public void SetDownloadMark()
+    {
+        LocalSave.SetInt("downloadMark", int.Parse(FuncConfigConfig.Get("DownReward").Numerical4));
+    }
+
+    #endregion
+}
\ No newline at end of file
diff --git a/Main/System/AssetVersion/InGameDownLoad.cs.meta b/Main/System/AssetVersion/InGameDownLoad.cs.meta
new file mode 100644
index 0000000..3c89b78
--- /dev/null
+++ b/Main/System/AssetVersion/InGameDownLoad.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b83759c2c0e44024fb6f3a3ebb5c455c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/AssetVersion/InGameDownTestUtility.cs b/Main/System/AssetVersion/InGameDownTestUtility.cs
new file mode 100644
index 0000000..bd23e4a
--- /dev/null
+++ b/Main/System/AssetVersion/InGameDownTestUtility.cs
@@ -0,0 +1,85 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using System;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+public class InGameDownTestUtility
+{
+
+    public static bool enable
+    {
+        get { return LocalSave.GetBool("InGameDownLoadTestEanble", false); }
+        set { LocalSave.SetBool("InGameDownLoadTestEanble", value); }
+    }
+
+    public static bool isWifi
+    {
+        get { return LocalSave.GetBool("InGameDownLoadWifi", true); }
+        set { LocalSave.SetBool("InGameDownLoadWifi", value); }
+    }
+
+    public static bool isReadStreamingAssets
+    {
+        get { return LocalSave.GetBool("isReadStreamingAssets", false); }
+        set { LocalSave.SetBool("isReadStreamingAssets", value); }
+    }
+
+    public static bool isReadVesionEx
+    {
+        get { return LocalSave.GetBool("isReadVesionEx", false); }
+        set { LocalSave.SetBool("isReadVesionEx", value); }
+    }
+
+
+    public static bool isPartPackage
+    {
+        get { return LocalSave.GetBool("InGameDownLoadPartPackage", false); }
+        set { LocalSave.SetBool("InGameDownLoadPartPackage", value); }
+    }
+
+    public static void ClearAssets()
+    {
+        Directory.Delete(Application.persistentDataPath, true);
+        LocalSave.DeleteKey("HasDownLoadFullAsset");
+    }
+
+#if UNITY_EDITOR
+    [RuntimeInitializeOnLoadMethod]
+    public static void Init()
+    {
+        if (InGameDownTestUtility.enable)
+        {
+            VersionConfig.Get().assetAccess = InstalledAsset.NullAsset;
+        }
+        else
+        {
+            VersionConfig.Get().assetAccess = InstalledAsset.IngoreDownLoad;
+        }
+
+        VersionConfig.Get().partAssetPackage = InGameDownTestUtility.isPartPackage;
+    }
+#endif
+
+    public static bool GetReadVerionEx()
+    {
+#if UNITY_EDITOR
+        //鐢熸垚VersionConfigEx.txt 鎻愪緵缁橝OT鍚姩鏃朵娇鐢�
+        var json = JsonUtility.ToJson(VersionConfig.Get());
+        string versionConfigExFile = Application.dataPath + "/Resources/VersionConfigEx.txt";
+        if (File.Exists(versionConfigExFile))
+        {
+            File.Delete(versionConfigExFile);
+        }
+        File.WriteAllText(versionConfigExFile, json);
+        AssetDatabase.SaveAssets();
+        AssetDatabase.Refresh();
+        Debug.Log("鍚屾VersionConfigEx.txt鎴愬姛");
+#endif
+        return enable && isReadVesionEx;
+    }
+}
+
diff --git a/Main/System/AssetVersion/InGameDownTestUtility.cs.meta b/Main/System/AssetVersion/InGameDownTestUtility.cs.meta
new file mode 100644
index 0000000..5b98e69
--- /dev/null
+++ b/Main/System/AssetVersion/InGameDownTestUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 439dd15ae7a22824c8d0920a49c42504
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/CrossServer.meta b/Main/System/CrossServer.meta
new file mode 100644
index 0000000..9b835f6
--- /dev/null
+++ b/Main/System/CrossServer.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c71a88df2a94ead49be660ed7e37f48c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/CrossServer/CrossServerUtility.cs b/Main/System/CrossServer/CrossServerUtility.cs
new file mode 100644
index 0000000..78a9437
--- /dev/null
+++ b/Main/System/CrossServer/CrossServerUtility.cs
@@ -0,0 +1,67 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+
+public class CrossServerUtility
+{
+
+    public static bool IsCrossServer()
+    {
+        return PlayerDatas.Instance.baseData.CrossServerFlag > 2;
+    }
+
+    public const int CrossServerRedKey = 213;
+    static Redpoint crossServerRedpoint = new Redpoint(CrossServerRedKey);
+
+    public static void UpdateCrossServerRedpoint()
+    {
+        // TODO YYL
+        // var oneVsOneCount = CrossServerOneVsOnePKSeason.Instance.isSatisfyMatch
+        //     ? CrossServerOneVsOnePlayerInfo.Instance.GetDayRemainNum() : 0;
+        // var crossServerBossCount = ModelCenter.Instance.GetModel<CrossServerBossModel>().redpoint.count;
+
+        // var count = oneVsOneCount + crossServerBossCount;
+        // if (count > 0)
+        // {
+        //     crossServerRedpoint.count = count;
+        //     crossServerRedpoint.state = RedPointState.Quantity;
+        // }
+        // else
+        // {
+        //     crossServerRedpoint.count = 0;
+        //     crossServerRedpoint.state = RedPointState.None;
+        // }
+    }
+
+    //璺ㄦ湇鎺掍綅璧涚敤姝ゅ嚱鏁版ā鎷燂紝鍚庣画闇�瑕佹暣鐞嗕笁鑰咃紙鏇村锛夊叧绯� ArenaManager.isArenaClient
+    public static bool IsCrossServerOneVsOne()
+    {
+        // TODO YYL
+
+        // if (ClientCrossServerOneVsOne.isClientCrossServerOneVsOne)
+        // {
+        //     return true;
+        // }
+
+        // var dungeonModel = ModelCenter.Instance.GetModel<DungeonModel>();
+        // var dataMapId = dungeonModel.GetDataMapIdByMapId(PlayerDatas.Instance.baseData.MapID);
+
+        // return dataMapId == CrossServerOneVsOneModel.CrossServerDataMapId || dataMapId == 32070;
+
+        return false;
+    }
+
+    public static bool IsCrossServerBoss()
+    {
+        // TODO YYL
+        // if (PlayerDatas.Instance.baseData.CrossServerFlag <= 2)
+        //     return false;
+
+        // return PlayerDatas.Instance.baseData.MapID == 32080
+        //     || PlayerDatas.Instance.baseData.MapID == CrossServerBossModel.DATA_MAPID;
+
+        return false;
+    }
+
+}
diff --git a/Main/System/CrossServer/CrossServerUtility.cs.meta b/Main/System/CrossServer/CrossServerUtility.cs.meta
new file mode 100644
index 0000000..24dc7a6
--- /dev/null
+++ b/Main/System/CrossServer/CrossServerUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 968873529aa87514e876d1d10d4cec27
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug.meta b/Main/System/Debug.meta
new file mode 100644
index 0000000..ba50181
--- /dev/null
+++ b/Main/System/Debug.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c74009eba139c934a9f80151562dac0e
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugAsset.cs b/Main/System/Debug/DebugAsset.cs
new file mode 100644
index 0000000..10407cf
--- /dev/null
+++ b/Main/System/Debug/DebugAsset.cs
@@ -0,0 +1,106 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class DebugAsset : MonoBehaviour
+{
+    [SerializeField] Toggle m_AllAsset;
+    [SerializeField] Toggle m_Audio;
+    [SerializeField] Toggle m_Effect;
+    [SerializeField] Toggle m_Scene;
+    [SerializeField] Toggle m_Mob;
+    [SerializeField] Toggle m_Refdata;
+    [SerializeField] Toggle m_Shader;
+    [SerializeField] Toggle m_UI;
+    [SerializeField] Toggle m_BuiltIn;
+
+    private void OnEnable()
+    {
+        m_AllAsset.isOn = AssetSource.allFromEditor;
+        m_Audio.isOn = AssetSource.audioFromEditor;
+        m_Effect.isOn = AssetSource.effectFromEditor;
+        m_Scene.isOn = AssetSource.sceneFromEditor;
+        m_Mob.isOn = AssetSource.mobFromEditor;
+        m_Refdata.isOn = AssetSource.refdataFromEditor;
+        m_Shader.isOn = AssetSource.shaderFromEditor;
+        m_UI.isOn = AssetSource.uiFromEditor;
+        m_BuiltIn.isOn = AssetSource.builtInFromEditor;
+
+        m_AllAsset.AddListener(OnAllAssetValueChange);
+        m_Audio.AddListener(OnAudioValueChange);
+        m_Effect.AddListener(OnEffectValueChange);
+        m_Scene.AddListener(OnSceneValueChange);
+        m_Mob.AddListener(OnMobValueChange);
+        m_Refdata.AddListener(OnRefdataValueChange);
+        m_Shader.AddListener(OnShaderValueChange);
+        m_UI.AddListener(OnUIValueChange);
+        m_BuiltIn.AddListener(OnBuildInValueChange);
+    }
+
+    private void OnDisable()
+    {
+        m_AllAsset.RemoveAllListeners();
+        m_Audio.RemoveAllListeners();
+        m_Effect.RemoveAllListeners();
+        m_Scene.RemoveAllListeners();
+        m_Mob.RemoveAllListeners();
+        m_Refdata.RemoveAllListeners();
+        m_Shader.RemoveAllListeners();
+        m_UI.RemoveAllListeners();
+    }
+
+    private void OnAllAssetValueChange(bool _value)
+    {
+        AssetSource.allFromEditor = _value;
+
+        m_Audio.isOn = _value;
+        m_Effect.isOn = _value;
+        m_Scene.isOn = _value;
+        m_Mob.isOn = _value;
+        m_Refdata.isOn = _value;
+        m_Shader.isOn = _value;
+        m_UI.isOn = _value;
+    }
+
+    private void OnAudioValueChange(bool _value)
+    {
+        AssetSource.audioFromEditor = _value;
+    }
+
+    private void OnEffectValueChange(bool _value)
+    {
+        AssetSource.effectFromEditor = _value;
+    }
+
+    private void OnSceneValueChange(bool _value)
+    {
+        AssetSource.sceneFromEditor = _value;
+    }
+
+    private void OnMobValueChange(bool _value)
+    {
+        AssetSource.mobFromEditor = _value;
+    }
+
+    private void OnRefdataValueChange(bool _value)
+    {
+        AssetSource.refdataFromEditor = _value;
+    }
+
+    private void OnShaderValueChange(bool _value)
+    {
+        AssetSource.shaderFromEditor = _value;
+    }
+
+    private void OnUIValueChange(bool _value)
+    {
+        AssetSource.uiFromEditor = _value;
+    }
+
+    private void OnBuildInValueChange(bool _value)
+    {
+        AssetSource.builtInFromEditor = _value;
+    }
+
+}
diff --git a/Main/System/Debug/DebugAsset.cs.meta b/Main/System/Debug/DebugAsset.cs.meta
new file mode 100644
index 0000000..83c2ebe
--- /dev/null
+++ b/Main/System/Debug/DebugAsset.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ad93fc17b11e5dc46b185c861eb6ce1e
+timeCreated: 1515414774
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugController.cs b/Main/System/Debug/DebugController.cs
new file mode 100644
index 0000000..78beec4
--- /dev/null
+++ b/Main/System/Debug/DebugController.cs
@@ -0,0 +1,99 @@
+锘�//--------------------------------------------------------
+//    [Author]:           Mechanist Games
+//    [  Date ]:           Wednesday, August 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+
+
+public class DebugController : MonoBehaviour
+{
+
+    // [SerializeField] FPS m_Fps;
+    // [SerializeField] Toggle m_ToggleFPS;
+
+    // [SerializeField] DebugVersionShow m_DebugVersion;
+    // [SerializeField] Toggle m_ToggleVersion;
+
+    private void OnEnable()
+    {
+        // if (m_Fps != null)
+        // {
+        //     m_Fps.SetActive(m_ToggleFPS.isOn);
+        // }
+
+        // m_ToggleFPS.RemoveAllListeners();
+        // m_ToggleFPS.AddListener(ToggleFPS);
+
+        // if (m_DebugVersion != null)
+        // {
+        //     m_DebugVersion.SetActive(m_ToggleVersion.isOn);
+        // }
+
+        // m_ToggleVersion.RemoveAllListeners();
+        // m_ToggleVersion.AddListener(ToggleVersion);
+    }
+
+    void ToggleFPS(bool _value)
+    {
+        // if (m_Fps != null)
+        // {
+        //     m_Fps.SetActive(_value);
+        // }
+    }
+
+    void ToggleVersion(bool _value)
+    {
+        // if (m_DebugVersion != null)
+        // {
+        //     m_DebugVersion.SetActive(_value);
+        // }
+    }
+
+    public void OpenGM()
+    {
+        // if (!WindowCenter.Instance.IsOpen<GMInputWin>())
+        // {
+        //     WindowCenter.Instance.Open<GMInputWin>();
+        // }
+    }
+
+    public void OpenGMCommond()
+    {
+        // WindowCenter.Instance.Open<GMCmdPanel>();
+    }
+
+    // //public void SendSpecialCTG()
+    // //{
+    // //    var model = ModelCenter.Instance.GetModel<VipModel>();
+    // //    var list = model.GetCTGConfigs(VersionConfig.Get().appId);
+    // //    for (int i = 0; i < list.Count; i++)
+    // //    {
+    // //        var config = CTGConfig.Get(list[i]);
+    // //        if (config.PayType == 4)
+    // //        {
+    // //            model.CTG(config.RecordID);
+    // //            return;
+    // //        }
+    // //    }
+    // //}
+
+    public void CleanNewBranchSet()
+    {
+        LocalSave.DeleteKey("#@#BrancH");
+        // ScrollTip.ShowTip("娓呯悊鍒嗘敮璁剧疆");
+    }
+
+    public void PrintLastCrashLog()
+    {
+        // if (CrashReport.lastReport != null)
+        // {
+        //     DebugEx.LogFormat("宕╂簝鏃ュ織:{0}", CrashReport.lastReport);
+        // }
+    }
+
+}
+
+
+
diff --git a/Main/System/Debug/DebugController.cs.meta b/Main/System/Debug/DebugController.cs.meta
new file mode 100644
index 0000000..346ff15
--- /dev/null
+++ b/Main/System/Debug/DebugController.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 37d7ac19293cb8147a5f511230eb34cf
+timeCreated: 1502265210
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugLogRecorder.cs b/Main/System/Debug/DebugLogRecorder.cs
new file mode 100644
index 0000000..583d62f
--- /dev/null
+++ b/Main/System/Debug/DebugLogRecorder.cs
@@ -0,0 +1,173 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+using System;
+
+
+    public class DebugLogRecorder : MonoBehaviour
+    {
+
+        [SerializeField]
+        Text m_LogPanel;
+
+        List<LogData> logs = new List<LogData>();
+        float timer = 0f;
+
+        private void Awake()
+        {
+        }
+
+        private void OnEnable()
+        {
+            LogRenderer();
+        }
+
+        private void LateUpdate()
+        {
+            timer += Time.deltaTime;
+            if (timer > 1f)
+            {
+                timer = 0f;
+                for (int i = logs.Count - 1; i >= 0; i--)
+                {
+                    if (logs[i].dieTime < DateTime.Now)
+                    {
+                        logs.RemoveAt(i);
+                    }
+                }
+
+                LogRenderer();
+            }
+        }
+
+        private void OnDisable()
+        {
+            logs.Clear();
+        }
+
+        private void OnDestroy()
+        {
+        }
+
+        public void SetLogVisible()
+        {
+            Debug.developerConsoleVisible = !Debug.developerConsoleVisible;
+        }
+
+        void AddLogRenderer(string _log, string _callStack, LogType _type)
+        {
+            if (!DebugUtility.Instance.debugAccount)
+            {
+                return;
+            }
+
+            if (!LocalSave.GetBool("DebugDrawAtGameView"))
+            {
+                return;
+            }
+
+            bool allow = false;
+            switch (_type)
+            {
+                case LogType.Log:
+                    allow = Launch.Instance.EnableLog || Launch.Instance.EnableNetLog;
+                    break;
+                case LogType.Warning:
+                    allow = Launch.Instance.EnableLogWarning;
+                    break;
+                case LogType.Error:
+                case LogType.Exception:
+                case LogType.Assert:
+                    allow = Launch.Instance.EnableLogError;
+                    break;
+            }
+
+            if (!allow)
+            {
+                return;
+            }
+
+            var content = string.Empty;
+            if (LocalSave.GetBool("DebugCallStack"))
+            {
+                content = _log + "\n" + _callStack;
+            }
+            else
+            {
+                content = _log;
+            }
+
+            logs.Add(new LogData(_type, content, 5));
+            if (logs.Count == 1)
+            {
+                timer = 0f;
+            }
+
+            LogRenderer();
+        }
+
+        void LogRenderer()
+        {
+            var contents = string.Empty;
+            for (int i = logs.Count - 1; i >= 0; i--)
+            {
+                if (logs.Count - 1 == i)
+                {
+                    contents += logs[i].content;
+                }
+                else
+                {
+                    contents += "\n" + logs[i].content;
+                }
+            }
+
+            if (contents.Length > 5000)
+            {
+                m_LogPanel.text = contents.Substring(contents.Length - 5000, 5000);
+            }
+            else
+            {
+                m_LogPanel.text = contents;
+            }
+
+        }
+
+        struct LogData
+        {
+            public string content;
+            public DateTime dieTime;
+
+            public LogData(LogType _logType, string _content, int _seconds)
+            {
+                switch (_logType)
+                {
+                    case LogType.Log:
+                        this.content = "[Log]: " + _content;
+                        break;
+                    case LogType.Warning:
+                        this.content = "[<color=yellow>Warning</color>]: " + _content;
+                        break;
+                    case LogType.Assert:
+                        this.content = "[<color=red>Assert</color>]: " + _content;
+                        break;
+                    case LogType.Exception:
+                        this.content = "[<color=red>Exception</color>]: " + _content;
+                        break;
+                    case LogType.Error:
+                        this.content = "[<color=red>Error</color>]: " + _content;
+                        break;
+                    default:
+                        this.content = _content;
+                        break;
+                }
+
+                this.dieTime = DateTime.Now + new TimeSpan(_seconds * TimeSpan.TicksPerSecond);
+            }
+        }
+
+    }
+
+
+
+
diff --git a/Main/System/Debug/DebugLogRecorder.cs.meta b/Main/System/Debug/DebugLogRecorder.cs.meta
new file mode 100644
index 0000000..7e96bfc
--- /dev/null
+++ b/Main/System/Debug/DebugLogRecorder.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 34bc3df760d720048a9c8fe286d669bc
+timeCreated: 1502266121
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugLogSetting.cs b/Main/System/Debug/DebugLogSetting.cs
new file mode 100644
index 0000000..dd3b35d
--- /dev/null
+++ b/Main/System/Debug/DebugLogSetting.cs
@@ -0,0 +1,72 @@
+锘縰sing UnityEngine;
+using System.Collections;
+using UnityEngine.UI;
+using System.Collections.Generic;
+using System;
+
+
+public class DebugLogSetting : MonoBehaviour
+{
+
+    bool m_DrawLog {
+        get { return LocalSave.GetBool("DebugDrawAtGameView", false); }
+        set { LocalSave.SetBool("DebugDrawAtGameView", value); }
+    }
+
+    bool m_CallStack {
+        get {
+            return LocalSave.GetBool("DebugCallStack");
+        }
+        set {
+            LocalSave.SetBool("DebugCallStack", value);
+        }
+    }
+
+    [SerializeField]
+    Toggle m_ToggleDrawLog;
+    [SerializeField]
+    Toggle m_ToggleLog;
+    [SerializeField]
+    Toggle m_ToggleWarning;
+    [SerializeField]
+    Toggle m_ToggleError;
+
+    [SerializeField]
+    Toggle m_ToggleNet;
+
+    [SerializeField]
+    Toggle m_ToggleCallStack;
+
+    private void Awake()
+    {
+        m_ToggleDrawLog.isOn = m_DrawLog;
+        m_ToggleLog.isOn = Launch.Instance.EnableLog;
+        m_ToggleWarning.isOn = Launch.Instance.EnableLogWarning;
+        m_ToggleError.isOn = Launch.Instance.EnableLogError;
+        m_ToggleNet.isOn = Launch.Instance.EnableNetLog;
+        m_ToggleCallStack.isOn = m_CallStack;
+
+        m_ToggleDrawLog.AddListener(SetLogRenderActive);
+        m_ToggleLog.AddListener(DebugUtility .SetLogAble);
+        m_ToggleWarning.AddListener(DebugUtility.SetLogWarningAble);
+        m_ToggleError.AddListener(DebugUtility.SetLogErrorAble);
+        m_ToggleNet.AddListener(DebugUtility.SetLogNetAble);
+        m_ToggleCallStack.AddListener(SetCallStackActive);
+    }
+
+    void SetLogRenderActive(bool _value)
+    {
+        m_DrawLog = _value;
+    }
+
+    void SetCallStackActive(bool _value)
+    {
+        m_CallStack = _value;
+    }
+
+
+}
+
+
+
+
diff --git a/Main/System/Debug/DebugLogSetting.cs.meta b/Main/System/Debug/DebugLogSetting.cs.meta
new file mode 100644
index 0000000..27ee506
--- /dev/null
+++ b/Main/System/Debug/DebugLogSetting.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0ea4b8d250c36c640ae1755b5f03aa4b
+timeCreated: 1504925918
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugLogin.cs b/Main/System/Debug/DebugLogin.cs
new file mode 100644
index 0000000..0ffee1b
--- /dev/null
+++ b/Main/System/Debug/DebugLogin.cs
@@ -0,0 +1,126 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using LitJson;
+
+public class DebugLogin : MonoBehaviour
+{
+    public InputField appid;
+    public InputField serverId;
+    public InputField account;
+    public InputField password;
+    public InputField platform;
+
+    public Toggle isToken;
+
+    string appidRecorder {
+        get { return LocalSave.GetString("DebugLogin_AppId"); }
+        set { LocalSave.SetString("DebugLogin_AppId", value); }
+    }
+
+    string serverIdRecorder {
+        get { return LocalSave.GetString("DebugLogin_ServerId"); }
+        set { LocalSave.SetString("DebugLogin_ServerId", value); }
+    }
+
+
+    string accountRecorder {
+        get { return LocalSave.GetString("DebugLogin_Account"); }
+        set { LocalSave.SetString("DebugLogin_Account", value); }
+    }
+
+    string passwordRecorder {
+        get { return LocalSave.GetString("DebugLogin_Password"); }
+        set { LocalSave.SetString("DebugLogin_Password", value); }
+    }
+
+    int platformRecorder {
+        get {
+            return LocalSave.GetInt("DebugLoging_Platform", 1);
+        }
+        set {
+            LocalSave.SetInt("DebugLoging_Platform", value);
+        }
+    }
+
+    bool istokenRecorder {
+        get { return LocalSave.GetBool("DebugLogin_IsToken", false); }
+        set { LocalSave.SetBool("DebugLogin_IsToken", value); }
+    }
+
+    private void OnEnable()
+    {
+        appid.text = appidRecorder;
+        serverId.text = serverIdRecorder;
+        account.text = accountRecorder;
+        password.text = passwordRecorder;
+        platform.text = platformRecorder.ToString();
+        isToken.isOn = istokenRecorder;
+    }
+
+    public void Login()
+    {
+        appidRecorder = appid.text;
+        serverIdRecorder = serverId.text;
+        accountRecorder = account.text;
+        passwordRecorder = password.text;
+        var platformTemp = 0;
+        int.TryParse(platform.text, out platformTemp);
+        platformRecorder = platformTemp;
+        istokenRecorder = isToken.isOn;
+
+        if (!string.IsNullOrEmpty(appid.text))
+        {
+            bool needRestore = VersionConfig.Get().m_AppId != appid.text;
+            VersionConfig.Get().m_AppId = appid.text;
+#if UNITY_EDITOR
+            //debug鐧诲綍鍚庣浜屾鍚姩榛樿鎭㈠test
+            if (needRestore)
+                LocalSave.SetBool("RestoreTest", true);
+#endif
+        }
+
+        SDKUtils.Instance.ChannelPlatform = (SDKUtils.E_ChannelPlatform)int.Parse(platform.text);
+
+        if (isToken.isOn)
+        {
+            // var loginModel = ModelCenter.Instance.GetModel<LoginModel>();
+            // LoginManager.Instance.sdkLoginResult = new SDKUtils.FP_LoginOk()
+            // {
+            //     account = account.text,
+            //     token = password.text,
+            //     tokenExpire = "1519750743000",
+            //     phone = 0,
+            //     accountID = 1000
+            // };
+
+            LoginManager.Instance.sdkLogined = true;
+            var ip = ServerListCenter.Instance.currentServer.region_domain;
+            var port = ServerListCenter.Instance.currentServer.login_port;
+            var gamePort = ServerListCenter.Instance.currentServer.game_port;
+            if (!string.IsNullOrEmpty(serverId.text))
+            {
+                var serverData = ServerListCenter.Instance.currentServer;
+                serverData.region_flag = int.Parse(serverId.text);
+                ServerListCenter.Instance.currentServer = serverData;
+            }
+
+            LoginManager.Instance.AccountLogin(ip, port, gamePort);
+        }
+
+    }
+
+
+
+    struct SDKLoginResult
+    {
+        public string errorcode;
+        public string errordesc;
+        public string token;
+        public string account;
+        public string token_expire;
+        public string phone;
+        public string account_id;
+    }
+}
diff --git a/Main/System/Debug/DebugLogin.cs.meta b/Main/System/Debug/DebugLogin.cs.meta
new file mode 100644
index 0000000..6e2bb8d
--- /dev/null
+++ b/Main/System/Debug/DebugLogin.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 17a676a416cbca045a12353e0543b257
+timeCreated: 1520921181
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugRoot.cs b/Main/System/Debug/DebugRoot.cs
new file mode 100644
index 0000000..47b4bfa
--- /dev/null
+++ b/Main/System/Debug/DebugRoot.cs
@@ -0,0 +1,69 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class DebugRoot : MonoBehaviour
+{
+    [SerializeField] RectTransform m_DebugBasic;
+    [SerializeField] RectTransform m_Trigger;
+
+    float lastClickTime = 0f;
+    int clickIndex = 0;
+    float duration = 5f;
+
+    bool alreadyOpen = false;
+
+    private void Awake()
+    {
+        if (DebugUtility.Instance.debugAccount)
+        {
+            m_DebugBasic.SetActive(true);
+            m_Trigger.SetActive(true);
+            alreadyOpen = true;
+        }
+        else
+        {
+            m_DebugBasic.SetActive(false);
+            m_Trigger.SetActive(false);
+            alreadyOpen = false;
+        }
+    }
+
+    private void LateUpdate()
+    {
+        if (alreadyOpen)
+        {
+            return;
+        }
+
+        if (DebugUtility.Instance.isWhiteListAccount)
+        {
+            if (Input.GetMouseButtonDown(0))
+            {
+                if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, Input.mousePosition, CameraManager.uiCamera))
+                {
+                    if (Time.time - lastClickTime > duration)
+                    {
+                        clickIndex = 1;
+                        lastClickTime = Time.time;
+                    }
+                    else
+                    {
+                        clickIndex++;
+                    }
+
+                    if (clickIndex >= 10)
+                    {
+                        m_DebugBasic.SetActive(true);
+                        m_Trigger.SetActive(true);
+                        alreadyOpen = true;
+                    }
+
+                }
+            }
+        }
+
+    }
+
+
+}
diff --git a/Main/System/Debug/DebugRoot.cs.meta b/Main/System/Debug/DebugRoot.cs.meta
new file mode 100644
index 0000000..0a8c6b5
--- /dev/null
+++ b/Main/System/Debug/DebugRoot.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dd2aa5d5810ead6449513ce730d68f36
+timeCreated: 1523878959
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugSwitch.cs b/Main/System/Debug/DebugSwitch.cs
new file mode 100644
index 0000000..251c5c4
--- /dev/null
+++ b/Main/System/Debug/DebugSwitch.cs
@@ -0,0 +1,67 @@
+锘�//--------------------------------------------------------
+//    [Author]:           Mechanist Games
+//    [  Date ]:           Wednesday, August 09, 2017
+//--------------------------------------------------------
+using UnityEngine;
+using System.Collections;
+using UnityEngine.EventSystems;
+using System;
+
+
+    public class DebugSwitch : MonoBehaviour
+    {
+
+        public GameObject container;
+
+        Vector2 startPosition;
+        Vector2 endPosition;
+        bool valid = false;
+
+        private void LateUpdate()
+        {
+            if (DebugUtility.Instance.debugAccount)
+            {
+                if (Input.GetMouseButtonDown(0))
+                {
+                    if (!RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, Input.mousePosition, CameraManager.uiCamera))
+                    {
+                        startPosition = Input.mousePosition;
+                        valid = true;
+                    }
+                }
+
+                if (valid)
+                {
+                    if (Input.GetMouseButton(0))
+                    {
+                        if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, Input.mousePosition, CameraManager.uiCamera))
+                        {
+                            endPosition = Input.mousePosition;
+                            Trigger();
+                        }
+                    }
+                }
+            }
+
+        }
+
+        private void Awake()
+        {
+            container.SetActive(false);
+        }
+
+        private void Trigger()
+        {
+            var gesture = MathUtility.GetGestureDirection(startPosition, endPosition);
+            if (gesture == GestureType.Up)
+            {
+                container.SetActive(true);
+                valid = false;
+            }
+        }
+
+    }
+
+
+
+
diff --git a/Main/System/Debug/DebugSwitch.cs.meta b/Main/System/Debug/DebugSwitch.cs.meta
new file mode 100644
index 0000000..2dcb756
--- /dev/null
+++ b/Main/System/Debug/DebugSwitch.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 45e0a6d99f5dcd34db39c89361df141c
+timeCreated: 1502263362
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugUtility.cs b/Main/System/Debug/DebugUtility.cs
new file mode 100644
index 0000000..000c3e6
--- /dev/null
+++ b/Main/System/Debug/DebugUtility.cs
@@ -0,0 +1,208 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using LitJson;
+using System.IO;
+using UnityEngine.UI;
+
+
+public class DebugUtility : Singleton<DebugUtility>
+{
+
+    GameObject debugRoot;
+
+    bool m_DebugAccount = false;
+    public bool debugAccount
+    {
+        get { return m_DebugAccount; }
+        private set
+        {
+            if (m_DebugAccount != value)
+            {
+                m_DebugAccount = value;
+                if (m_DebugAccount)
+                {
+                    RunTimeExceptionUtility.Instance.Init();
+                }
+            }
+        }
+    }
+
+    public int debugBranch = -1;
+
+    public bool isWhiteListAccount { get; set; }
+
+    public bool autoLogin { get; private set; }
+
+    public void Init()
+    {
+        isWhiteListAccount = false;
+        if (VersionConfig.Get().debugVersion)
+        {
+            debugAccount = true;
+        }
+        else
+        {
+            var parentDirectory = Directory.GetParent(Application.persistentDataPath);
+            debugAccount = File.Exists(parentDirectory + "/Debug");
+        }
+
+        if (LocalSave.GetString("#@#BrancH") != string.Empty)
+        {
+            var branch = LocalSave.GetString("#@#BrancH");
+            int tmpbranch;
+            int.TryParse(LocalSave.GetString("#@#BrancH").Substring(1), out tmpbranch);
+            if (branch.StartsWith("d") && tmpbranch != 0)
+            {
+                debugBranch = tmpbranch;
+                debugAccount = true;
+            }
+            else if (branch.StartsWith("r") && tmpbranch != 0)
+            {
+                debugBranch = tmpbranch;
+                debugAccount = false;
+            }
+        }
+
+        if (debugAccount)
+        {
+            if (Application.isMobilePlatform)
+            {
+                var parentDirectory = Directory.GetParent(Application.persistentDataPath);
+                if (File.Exists(parentDirectory + "/Debug"))
+                {
+                    var content = File.ReadAllText(parentDirectory + "/Debug");
+                    if (!string.IsNullOrEmpty(content))
+                    {
+                        var json = JsonMapper.ToObject<DebugBranch>(File.ReadAllText(parentDirectory + "/Debug"));
+                        debugBranch = json.branch;
+                    }
+                }
+            }
+        }
+
+
+
+
+        if (debugAccount)
+        {
+            Launch.Instance.EnableLog = LocalSave.GetBool("DesignEnableLog", true);
+            Launch.Instance.EnableLogWarning = LocalSave.GetBool("DesignEnableLogWarning", true);
+            Launch.Instance.EnableLogError = LocalSave.GetBool("DesignEnableLogError", true);
+            Launch.Instance.EnableNetLog = false;
+        }
+        else
+        {
+            Launch.Instance.EnableLog = false;
+            Launch.Instance.EnableLogWarning = false;
+            Launch.Instance.EnableLogError = false;
+            Launch.Instance.EnableNetLog = false;
+        }
+
+        autoLogin = Resources.Load<TextAsset>("AutoLogin") != null;
+        if (autoLogin)
+        {
+            var update = new LogicUpdate(3f);
+            update.Start(OnAutoLoginUpdate);
+        }
+    }
+
+    private void OnAutoLoginUpdate()
+    {
+        // TODO YYL
+        // if (StageLoad.Instance.currentStage is LoginStage)
+        // {
+        //     var loginWin = WindowCenter.Instance.Get<LoginWin>();
+        //     if (loginWin != null)
+        //     {
+        //         var accountIpf = loginWin.transform.FindComponent("InputField", "Container_Account/AccountInput");
+        //         if (accountIpf != null)
+        //         {
+        //             (accountIpf as InputField).text = StringUtility.Contact("Test_", UnityEngine.Random.Range(10000, 99999));
+        //         }
+
+        //         var enterGame = loginWin.transform.FindComponent("Button", "Container_EnterGame/LoginButton");
+        //         (enterGame as Button).onClick.Invoke();
+        //     }
+        // }
+
+
+        // if (StageLoad.Instance.currentStage is CreateRoleStage)
+        // {
+        //     var win = WindowCenter.Instance.Get<CreateRoleWin>();
+        //     if (win != null)
+        //     {
+        //         var enterGame = win.transform.FindComponent("Button", "Container_Right/Btn_CreateRole");
+        //         if (enterGame is Button)
+        //         {
+        //             (enterGame as Button).onClick.Invoke();
+        //         }
+        //     }
+        // }
+    }
+
+    public void CreateDebugRoot()
+    {
+        if (debugRoot == null)
+        {
+            var prefab = BuiltInLoader.LoadPrefab("UIRootDebug");
+            debugRoot = GameObject.Instantiate(prefab);
+            MonoBehaviour.DontDestroyOnLoad(debugRoot);
+            debugRoot.name = "UIRootDebug";
+        }
+    }
+
+    public void RequestWhiteListAuthority(string _account)
+    {
+        //isWhiteListAccount = false;
+        //var tables = new Dictionary<string, string>();
+        //tables["channel"] = VersionConfig.Get().appId;
+        //tables["player"] = ModelCenter.Instance.GetModel<LoginModel>().sdkLoginResult.account;
+        //tables["game"] = VersionConfig.Get().gameId;
+
+        //HttpRequest.Instance.RequestHttpGet(StringUtility.Contact(url, HttpRequest.HashtablaToString(tables)), HttpRequest.defaultHttpContentType, 1, OnDebugAuthority);
+    }
+
+    private void OnDebugAuthority(bool _ok, string _result)
+    {
+        if (_ok)
+        {
+            var debugAuthority = JsonMapper.ToObject<DebugAuthority>(_result);
+            isWhiteListAccount = debugAuthority.dbg == 1;
+        }
+    }
+
+    public static void SetLogAble(bool _able)
+    {
+        LocalSave.SetBool("DesignEnableLog", _able);
+        Launch.Instance.EnableLog = _able;
+    }
+
+    public static void SetLogWarningAble(bool _able)
+    {
+        LocalSave.SetBool("DesignEnableLogWarning", _able);
+        Launch.Instance.EnableLogWarning = _able;
+    }
+
+    public static void SetLogErrorAble(bool _able)
+    {
+        LocalSave.SetBool("DesignEnableLogError", _able);
+        Launch.Instance.EnableLogError = _able;
+    }
+
+    public static void SetLogNetAble(bool _able)
+    {
+        Launch.Instance.EnableNetLog = _able;
+    }
+
+    struct DebugAuthority
+    {
+        public int dbg;
+    }
+
+    public class DebugBranch
+    {
+        public int branch = -1;
+    }
+
+}
diff --git a/Main/System/Debug/DebugUtility.cs.meta b/Main/System/Debug/DebugUtility.cs.meta
new file mode 100644
index 0000000..97eae0e
--- /dev/null
+++ b/Main/System/Debug/DebugUtility.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: cfb1eb8f346fd8242935ef5ba1c14999
+timeCreated: 1523877317
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/GeneralConfig.meta b/Main/System/GeneralConfig.meta
new file mode 100644
index 0000000..e2bc94b
--- /dev/null
+++ b/Main/System/GeneralConfig.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 9ba8bc026cbbbfd4ea2590a44801e4b7
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/GeneralConfig/ConstDefine.cs b/Main/System/GeneralConfig/ConstDefine.cs
new file mode 100644
index 0000000..e3d784a
--- /dev/null
+++ b/Main/System/GeneralConfig/ConstDefine.cs
@@ -0,0 +1,16 @@
+public static class HttpHeader
+{
+    public const string ContentLength = "Content-Length";//鍐呭闀垮害
+    public const string ContentType = "Content-Type";//琛ㄧず鍚庨潰鐨勬枃妗e睘浜庝粈涔圡IME绫诲瀷銆�
+    public const string Date = "Date";//褰撳墠鐨凣MT鏃堕棿銆�
+    public const string LastModified = "Last-Modified";//鏂囨。鐨勬渶鍚庢敼鍔ㄦ椂闂�
+    public const string AcceptRanges = "Accept-Ranges";//鏄惁鏀寔鑼冨洿璇锋眰
+    public const string Range = "Range";//璇锋眰鑼冨洿
+}
+
+//Android 鍔ㄦ�佺敵璇风殑鏉冮檺鍒楄〃
+public static class AndroidPermissions
+{
+    public const string RECORD_AUDIO = "android.permission.RECORD_AUDIO"; //褰曢煶
+
+}
\ No newline at end of file
diff --git a/Main/System/GeneralConfig/ConstDefine.cs.meta b/Main/System/GeneralConfig/ConstDefine.cs.meta
new file mode 100644
index 0000000..8102037
--- /dev/null
+++ b/Main/System/GeneralConfig/ConstDefine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0d4b467ed17462041ace70f28b3a8542
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/GeneralConfig/GeneralDefine.cs b/Main/System/GeneralConfig/GeneralDefine.cs
new file mode 100644
index 0000000..86830b6
--- /dev/null
+++ b/Main/System/GeneralConfig/GeneralDefine.cs
@@ -0,0 +1,1168 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using LitJson;
+using System;
+using System.Text.RegularExpressions;
+using System.Linq;
+
+public class GeneralDefine
+{
+    public const int CrossBattleFieldMapID = 32060;
+    public const int CrossFamilyBattleMapID = 32090;
+    public static int initDepotGridCount { get; private set; }
+    public static int maxDepotGridCount { get; private set; }
+    public static int initBagGridCount { get; private set; }
+    public static int maxBagGridCount { get; private set; }
+    public static int maxXBGridCount { get; private set; }
+    public static int playerMaxLevel { get; private set; }
+    public static int[] kylinHomeCollectItems;
+    public static List<int> dailyQuestOpenTime;
+    public static int flyBootItemId { get; private set; }
+    public static int flyBootItemMoney { get; private set; }
+    public static int teamReadyTime { get; private set; }
+    public static int elderGodAreaAngerTotal { get; private set; }
+    public static float petRandomSpeak { get; private set; }
+    public static int[] openJobs { get; private set; }
+    public static int playerNameLength { get; private set; }
+    public static int guardDungeonCageNPCID { get; private set; }
+    public static float guardBubbleInterval { get; private set; }
+    public static List<int> autoOnHookMap { get; private set; }
+    public static float autoRideHorse { get; private set; }
+    public static Dictionary<int, string> equipPlaceNameDict { get; private set; }
+    public static Dictionary<int, int> moneyDisplayIds { get; private set; }
+    public static int expDisplayId { get; private set; }
+    public static float xpGuideDelay { get; private set; }
+    public static float xpGuideDuration { get; private set; }
+    public static Dictionary<int, string> trailBossHeadIcons { get; private set; }
+    public static Dictionary<int, string> godWeaponMobs { get; private set; }
+    public static float ResetComAtkTime { get; private set; }
+    public static int RotateSpeed { get; private set; }
+    public static float CloseNpcDist { get; private set; }
+    public static float FarawayNpcDist { get; private set; }
+    public static List<int> SpecialNpcIDs { get; private set; }
+    public static Dictionary<int, int> wingEquipLimits { get; private set; }
+    public static float PetDanceInterval { get; private set; }
+    public static float FuncNpcDanceInterval { get; private set; }
+    public static float audioScaleWhenFullScreenOn { get; private set; }
+    public static int ruinsTranscriptMapId { get; private set; }
+    public static List<int> GuardianPickUpID { get; private set; }
+    public static List<int> EarlierGetTreasure { get; private set; }
+    public static int BossSound { get; private set; }
+    public static Dictionary<int, int> iceCrystalMonsterScores { get; private set; }
+    public static float PlayBossHurtInterval { get; private set; }
+    public static List<int> NoXpDungeons { get; private set; }
+    public static List<int> RandomJobs { get; private set; }
+    public static int elderGodTalkingTime { get; private set; }
+    public static int elderGodBigBoss { get; private set; }
+    public static List<int> PassiveSkillShow { get; private set; }
+    public static List<int> bossShuntMaps { get; private set; }
+    public static int bossShuntDays { get; private set; }
+    public static Dictionary<int, int[]> itemDropEffect = new Dictionary<int, int[]>();
+    public static Dictionary<int, int[]> xllyDropEffect = new Dictionary<int, int[]>();
+    public static Dictionary<int, int[]> xqryDropEffect = new Dictionary<int, int[]>();
+    public static Dictionary<int, List<int[]>> customDropEffect = new Dictionary<int, List<int[]>>();
+    public static Dictionary<int, int> dropEffectQuality = new Dictionary<int, int>();
+    public static Dictionary<int, int> BuffToHitEffect = new Dictionary<int, int>();
+
+    //鍙傛暟int锛宨nt 锛宻tring 鍒嗗埆琛ㄧず鑱屼笟锛岃浆鐢熺瓑绾э紝icon
+    static Dictionary<int, Dictionary<int, string>> jobHeadPortrait = new Dictionary<int, Dictionary<int, string>>();
+    static Dictionary<int, Dictionary<int, string>> otherjobHeadPortrait = new Dictionary<int, Dictionary<int, string>>();
+    public static Dictionary<int, int> bossWearyValues = new Dictionary<int, int>();
+    public static Dictionary<int, Vector3> NpcPosOffset = new Dictionary<int, Vector3>();
+    public static Dictionary<int, string> propertyIconDict = new Dictionary<int, string>();
+
+    public static int demonJarHintLevelLimit { get; private set; }
+    public static int demonJarHintLineId { get; private set; }
+    public static int skillPanelUnLock { get; private set; }
+    public static int dailyQuestRedpointLevelLimit { get; private set; }
+    public static int lowHpRemind { get; private set; }
+    public static int munekadolockLimit { get; private set; }
+    public static int maxItemDropEffectCount { get; private set; }
+
+    public static int[] autoBuyItemIds;
+    public static int[] autoBuyItemPrices;
+
+    public static List<int> neutralMaps = new List<int>();
+    public static List<int> neutralBossMaps = new List<int>();
+
+    public static int demonJarRedPoint { get; private set; }
+    public static string LoadLV { get; private set; }
+    public static int MasteryLoadingLevelLimit1 { get; private set; }
+    public static int MasteryLoadingLevelLimit2 { get; private set; }
+
+    public static float mainWinSkillResetTime { get; private set; }
+    public static Vector3 heroDialogueOffset { get; private set; }
+    public static Vector3 heroDialogueRotation { get; private set; }
+    public static float heroDialogueScale { get; private set; }
+
+    public static List<int> ancientGrandTotalAchievements { get; private set; }
+    public static List<int> ancientContinueKillAchievements { get; private set; }
+
+    public static int trialDungeonGroupChallengeTipLv { get; private set; }
+    public static int prayerRedpointLimitLv { get; private set; }
+
+    public static int demonJarLevelLimit { get; private set; }
+
+    public static int fairyLandGuideId = 82;
+
+    public static int specialGuide41Mission { get; private set; }
+    public static int specialGuide41Achievement { get; private set; }
+
+    public static int supremeRechargeVipLv { get; private set; }
+
+    public static int rechargeRedpointLv { get; private set; }
+    public static int rechargeRedpointMinLv { get; private set; }
+
+    public static int runeTowerSweepBuyTimes { get; private set; }
+    public static int runeTowerSweepBuyPrice { get; private set; }
+
+    public static int teamMatchingTimeOut { get; private set; }
+    public static List<int> inGameDownLoadLevelCheckPoints = null;
+    public static List<int> inGameDownLoadTaskCheckPoints = null;
+    public static int inGameDownLoadHighLevel { get; private set; }
+    public static List<int> worldBossNoRebornRemindMaps = null;
+    public static List<int> bossHomeNoRebornRemindMaps = null;
+    public static List<int> elderGodNoRebornRemindMaps = null;
+    public static List<int> demonJarNoRebornRemindMaps = null;
+    public static List<int> dogzNoRebornRemindMaps = null;
+
+    public static string[][] ModeDefaultConfig { get; private set; }
+    public static int[][] PreloadSkillEffect { get; private set; }
+    public static int[] RealmGroup { get; private set; }
+    public static float PrefightAtkRange { get; private set; }
+
+    public static Dictionary<int, string> multipleRealmImgDict { get; private set; }
+    public static int[] ImportantItemType { get; private set; }
+    public static int[] ImportantItemID { get; private set; }
+
+    public static int inGameDownLoadHighestLevelPoint { get; private set; }
+
+    public static List<int> dungeonCanUseMoneyIds { get; private set; }
+    public static int dogzBoxLimit { get; private set; }
+
+    public static Dictionary<int, int> dungeonRebornClientTimes { get; private set; }
+    public static int[] CompareEquipPlaces { get; private set; }
+    public static Dictionary<int, int> fairyGrabBossMapLines { get; private set; }
+
+    public static Dictionary<int, List<int>> DropItemEffectMapID { get; private set; }
+    public static Dictionary<int, List<int>> itemPutInPackDict { get; private set; }
+    public static List<int> RebornAutoFightMapID { get; private set; }
+
+    public static string teamWorldCall;
+    public static int teamWorldCallInviteCount;
+
+    // public static List<Item> ancientKingAwards = new List<Item>();
+
+    public static int lowQualityEffectCount { get; private set; }
+    public static int medQualityEffectCount { get; private set; }
+    public static int highQualityEffectCount { get; private set; }
+    public static int lowQualityPetCount { get; private set; }
+    public static int medQualityPetCount { get; private set; }
+    public static int highQualityPetCount { get; private set; }
+    public static int lowQualityGuardCount { get; private set; }
+    public static int medQualityGuardCount { get; private set; }
+    public static int highQualityGuardCount { get; private set; }
+    public static int lowQualityPetEffectCount { get; private set; }
+    public static int medQualityPetEffectCount { get; private set; }
+    public static int highQualityPetEffectCount { get; private set; }
+    public static int lowQualityHorseEffectCount { get; private set; }
+    public static int medQualityHorseEffectCount { get; private set; }
+    public static int highQualityHorseEffectCount { get; private set; }
+
+    public static int GatherSoulDZ { get; private set; }
+
+    public static int fairyLandBuffCondition { get; private set; }
+    public static int fairyLandBuffId { get; private set; }
+    public static int achievementEarlierStageLevel { get; private set; }
+    public static int demonJarAutoTime { get; private set; }
+    // public static Dictionary<int, Dictionary<int, GA_NpcFightSgzcZZ.EquipRandomInfo>> SgzzRobotEquipDict { get; private set; }
+    public static Dictionary<int, int> SgzcRealm { get; private set; }
+
+    public static int crossServerOneVsOneOpenDay { get; set; }
+    public static int crossServerBattleFieldOpenDay { get; private set; }
+    public static int UISpringDecorate { get; private set; }
+    public static Dictionary<int, List<int>> skillAttrIDDict { get; private set; }
+    public static int mixServerCustomDays { get; private set; }
+    public static float ClientPvpAttributePer { get; private set; }
+    public static int openServerCustomDays { get; private set; }
+
+    public static int mysteryShopRefreshItem { get; private set; }
+    public static Dictionary<int, int> mysteryShopRefreshItemCount { get; private set; }
+    public static int mysteryShopRefreshItemValue { get; private set; }
+    public static int mysteryShopRefreshInterval { get; private set; }
+    public static Dictionary<int, Dictionary<int, int>> equipStarLimit { get; private set; }
+    public static int equipTrainMustItemId { get; private set; }
+    public static int acutionItemHour { get; private set; }
+
+    public static int mainWinTopCloseTime { get; private set; }
+    public static List<int> equipDecomposeScreen = new List<int>();
+    public static Dictionary<int, float> AtkTypeIncreasePushDis = new Dictionary<int, float>();
+    // public static Dictionary<int, CameraController.LookAtData> NpcDieSetCamera = new Dictionary<int, CameraController.LookAtData>();
+    public static int BlueEquipJumpLevel { get; private set; }
+    public static int[] defenseGetWays { get; private set; }
+    public static Dictionary<int, int> skillYinjis { get; private set; }
+    public static List<int> onlyUsedAtBackpackItems { get; private set; }
+    public static List<int> signInPromoteSkills = new List<int>();
+    public static List<int> chestDisplayItems = new List<int>();
+
+    public static int equipStarUpAmendFactor { get; private set; }
+    public static int equipStarDownAmendFactor { get; private set; }
+
+    public static int normalEquipStarUpgradeRateCeiling { get; private set; }
+    public static int normalEquipStarUpgradeRateFloor { get; private set; }
+
+    public static int suitEquipStarUpgradeRateCeiling { get; private set; }
+    public static int suitEquipStarUpgradeRateFloor { get; private set; }
+
+    public static Dictionary<int, List<int>> BossAssistAward { get; private set; }
+    public static Dictionary<int, List<int>> FBAssistAward { get; private set; }
+
+    //妫�娴嬫槸鍚﹀湪systemsetwin prefab鏄剧ず鍒囨崲鍖烘湇鍜屽垏鎹㈣处鍙�
+    public static List<string> checkShowSwitchAccount = new List<string>();
+    //绔炴妧鍦� 鍒濆绉垎|鏈�楂樼Н鍒�
+    public static List<int> ArenaSetList { get; private set; }
+    //鍩瑰吇瀵瑰簲鐗╁搧鍒楄〃 1.鍩瑰吇涓�2.鍏荤鐭�3.鐗规畩鍩瑰吇
+    public static int[] HorseTrainIDList { get; private set; }
+    public static int[] PetTrainIDList { get; private set; }
+    public static Dictionary<int, List<int>> LingQiTrainIDList { get; private set; }
+
+    //鏁板��1锛氬彲瀵规晫鏂逛娇鐢ㄧ殑闄勫姞鎶�鑳藉垪琛�
+    //鏁板��2锛氬彲瀵硅嚜宸变娇鐢ㄧ殑闄勫姞鎶�鑳藉垪琛�
+    //鏁板��3锛氫笉鍙噴鏀剧殑鎶�鑳�
+    public static int[] WorkForEnemySkills { get; private set; }
+    public static int[] WorkForMeSkills { get; private set; }
+    public static int[] WorkNotSkills { get; private set; }
+    public static Dictionary<int, List<int>> ZhanLingCtgIdDict { get; private set; }
+    public static Dictionary<int, List<int>> ZhanLingCtgIdHDict { get; private set; }
+    public static Dictionary<int, int> OldZhanLingCtgIdDict { get; private set; }
+
+    public static float fightPowerMore; //鎴樺姏瓒呰繃姣斾緥鎵嶅彲蹇�熸寫鎴�
+    public static int[] flashOpenArr; //寮�鍚浄璇涘眰 [澶╂槦濉旓紝澧冪晫濉旓紝绗﹀嵃濉旓紙鎸夌鍑犱釜濉旂畻锛塢
+    public static int[] flashCntMoreArr; //闆疯瘺鏇村娆℃暟灞傞渶姹� [澶╂槦濉旓紝澧冪晫濉旓紝绗﹀嵃濉旓紙鎸夌鍑犱釜濉旂畻锛塢
+    public static int flashKillMaxCount; //闆疯瘺鏈�澶ф鏁�
+
+    public static void Init()
+    {
+        try
+        {
+            equipStarUpAmendFactor = GetIntArray("EquipStarRate")[0];
+            equipStarDownAmendFactor = GetIntArray("EquipStarRate")[1];
+
+            normalEquipStarUpgradeRateFloor = GetIntArray("EquipStarRate", 2)[0];
+            normalEquipStarUpgradeRateCeiling = GetIntArray("EquipStarRate", 2)[1];
+
+            suitEquipStarUpgradeRateFloor = GetIntArray("EquipStarRate", 3)[0];
+            suitEquipStarUpgradeRateCeiling = GetIntArray("EquipStarRate", 3)[1];
+
+            BlueEquipJumpLevel = GetInt("BlueEquipJumpLevel");
+            initDepotGridCount = GetInt("InitDepotCellCount");
+            maxDepotGridCount = GetInt("MaxDepotCellCount");
+            initBagGridCount = GetInt("InitBagCellCount");
+            maxBagGridCount = GetInt("MaxBagCellCount");
+            maxXBGridCount = GetInt("TreasureSet", 3);
+
+            CompareEquipPlaces = GetIntArray("EquipUpType");
+            playerMaxLevel = GetInt("PlayerMaxLV");
+            kylinHomeCollectItems = GetIntArray("KirinNpc", 2);
+            dailyQuestOpenTime = GetTimeArray("ActionTime", 1);
+            flyBootItemId = GetInt("TransportPay");
+            flyBootItemMoney = GetInt("TransportPay", 2);
+            teamReadyTime = GetInt("TeamReadyTime");
+            playerNameLength = GetInt("RoleNameLength");
+            elderGodAreaAngerTotal = GetInt("AngryAdd", 4);
+            petRandomSpeak = GetFloat("PetRandomSpeak");
+            guardDungeonCageNPCID = GetInt("GuardFBCageNPCID");
+            guardBubbleInterval = GetFloat("GuardFBCageNPCID", 3);
+            autoRideHorse = GetFloat("AutoRideHorseTime") * Constants.F_DELTA;
+            moneyDisplayIds = ConfigParse.GetDic<int, int>(GetInputString("MoneyDisplayModel", 1));
+            expDisplayId = GetInt("MoneyDisplayModel", 2);
+            openJobs = GetIntArray("OpenJob");
+            xpGuideDelay = GetFloat("GuideConfig");
+            xpGuideDuration = GetFloat("GuideConfig", 2);
+            ResetComAtkTime = GetFloat("AtkWaitingTime");
+            autoOnHookMap = new List<int>(GetIntArray("AutoOnHookMap"));
+            GuardianPickUpID = new List<int>(GetIntArray("GuardianPickUpID"));
+            ArenaSetList = new List<int>(GetIntArray("ArenaSet"));
+            RotateSpeed = GetInt("RoleTurnedAngle");
+            CloseNpcDist = GetFloat("ConversationDistanc", 2);
+            FarawayNpcDist = GetFloat("ConversationDistanc");
+            SpecialNpcIDs = new List<int>(GetIntArray("SpecialCollectNpcs", 1));
+            PetDanceInterval = GetInt("PetDanceInterval") * Constants.F_GAMMA;
+            FuncNpcDanceInterval = GetInt("PetDanceInterval", 2) * Constants.F_GAMMA;
+            ruinsTranscriptMapId = GetInt("SpRewardMapID");
+            EarlierGetTreasure = new List<int>(GetIntArray("EarlierGetTreasure"));
+            BossSound = GetInt("BossSound");
+            PlayBossHurtInterval = GetFloat("BossSound", 2);
+            var jobHeadPortraitConfig1 = FuncConfigConfig.Get("Job1Head");
+            jobHeadPortrait[1] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig1.Numerical1);
+            otherjobHeadPortrait[1] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig1.Numerical2);
+
+            var jobHeadPortraitConfig2 = FuncConfigConfig.Get("Job2Head");
+            jobHeadPortrait[2] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig2.Numerical1);
+            otherjobHeadPortrait[2] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig2.Numerical2);
+
+            var jobHeadPortraitConfig3 = FuncConfigConfig.Get("Job3Head");
+            jobHeadPortrait[3] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig3.Numerical1);
+            otherjobHeadPortrait[3] = ConfigParse.GetDic<int, string>(jobHeadPortraitConfig3.Numerical2);
+
+            bossWearyValues = ConfigParse.GetDic<int, int>(GetInputString("KillBossCntLimit", 2));
+            wingEquipLimits = ConfigParse.GetDic<int, int>(GetInputString("WingRealmLimit", 1));
+            int i = 0;
+            int[] equipPlaces = GetIntArray("EquipArea", 1);
+            string[] equipPlacesNames = GetStringArray("EquipArea", 2);
+            equipPlaceNameDict = new Dictionary<int, string>();
+            for (i = 0; i < equipPlaces.Length; i++)
+            {
+                if (!equipPlaceNameDict.ContainsKey(equipPlaces[i]))
+                {
+                    equipPlaceNameDict.Add(equipPlaces[i], equipPlacesNames[i]);
+                }
+                else
+                {
+                    DebugEx.LogError("EquipArea : 瑁呭浣嶇疆閲嶅");
+                }
+            }
+            var _trailBossJson = LitJson.JsonMapper.ToObject(GetInputString("MuneKadoTrialBossHead", 1));
+            trailBossHeadIcons = new Dictionary<int, string>();
+            foreach (var _key in _trailBossJson.Keys)
+            {
+                var _npcId = int.Parse(_key);
+                if (!trailBossHeadIcons.ContainsKey(_npcId))
+                {
+                    trailBossHeadIcons.Add(_npcId, _trailBossJson[_key].ToString());
+                }
+            }
+            FuncConfigConfig HorseTrainConfig = FuncConfigConfig.Get("HorseTrain");
+            HorseTrainIDList = LitJson.JsonMapper.ToObject<int[]>(HorseTrainConfig.Numerical1);
+            FuncConfigConfig PetTrainConfig = FuncConfigConfig.Get("PetUpItem");
+            PetTrainIDList = LitJson.JsonMapper.ToObject<int[]>(PetTrainConfig.Numerical3);
+            FuncConfigConfig LingQiTrainConfig = FuncConfigConfig.Get("HorseTrain");
+            var LingQiTrainJson = LitJson.JsonMapper.ToObject(GetInputString("LingQiTrain", 1));
+            LingQiTrainIDList = new Dictionary<int, List<int>>();
+            foreach (var key in LingQiTrainJson.Keys)
+            {
+                int attrId = int.Parse(key);
+                var skillIds = LingQiTrainJson[key];
+                foreach (var skillId in skillIds)
+                {
+                    int id = int.Parse(skillId.ToString());
+                    if (!LingQiTrainIDList.ContainsKey(attrId))
+                    {
+                        List<int> list = new List<int>();
+                        list.Add(id);
+                        LingQiTrainIDList.Add(attrId, list);
+                    }
+                    else
+                    {
+                        LingQiTrainIDList[attrId].Add(id);
+                    }
+                }
+
+            }
+
+            var skillPlusAttrIDJson = LitJson.JsonMapper.ToObject(GetInputString("SkillPlusAttrID", 2));
+            skillAttrIDDict = new Dictionary<int, List<int>>();
+            foreach (var key in skillPlusAttrIDJson.Keys)
+            {
+                int attrId = int.Parse(key);
+                var skillIds = skillPlusAttrIDJson[key];
+                foreach (var skillId in skillIds)
+                {
+                    int id = int.Parse(skillId.ToString());
+                    if (!skillAttrIDDict.ContainsKey(id))
+                    {
+                        List<int> list = new List<int>();
+                        list.Add(attrId);
+                        skillAttrIDDict.Add(id, list);
+                    }
+                    else
+                    {
+                        skillAttrIDDict[id].Add(attrId);
+                    }
+                }
+
+            }
+            
+            var BossAssistAwardJson = LitJson.JsonMapper.ToObject(GetInputString("AssistAward", 1));
+            BossAssistAward = new Dictionary<int, List<int>>();
+            foreach (var key in BossAssistAwardJson.Keys)
+            {
+                int bossID = int.Parse(key);
+                var awards = BossAssistAwardJson[key];
+                if (!BossAssistAward.ContainsKey(bossID))
+                {
+                    BossAssistAward[bossID] = new List<int>();
+                }
+                foreach (var award in awards)
+                {
+                    BossAssistAward[bossID].Add(int.Parse(award.ToString()));
+                }
+
+            }
+
+            var FBAssistAwardJson = LitJson.JsonMapper.ToObject(GetInputString("AssistAward", 2));
+            FBAssistAward = new Dictionary<int, List<int>>();
+            foreach (var key in FBAssistAwardJson.Keys)
+            {
+                int mapID = int.Parse(key);
+                var awards = FBAssistAwardJson[key];
+                if (!FBAssistAward.ContainsKey(mapID))
+                {
+                    FBAssistAward[mapID] = new List<int>();
+                }
+                foreach (var award in awards)
+                {
+                    FBAssistAward[mapID].Add(int.Parse(award.ToString()));
+                }
+
+            }
+
+            var _godWeaponJson = LitJson.JsonMapper.ToObject(GetInputString("GodModel", 1));
+            godWeaponMobs = new Dictionary<int, string>();
+            foreach (var _key in _godWeaponJson.Keys)
+            {
+                var _godWeaponType = int.Parse(_key);
+                if (!godWeaponMobs.ContainsKey(_godWeaponType))
+                {
+                    godWeaponMobs.Add(_godWeaponType, _godWeaponJson[_key].ToString());
+                }
+            }
+
+            audioScaleWhenFullScreenOn = GetFloat("AudioSound");
+
+            iceCrystalMonsterScores = ConfigParse.GetDic<int, int>(GetInputString("IceLodeNeedPoint", 2));
+
+            NoXpDungeons = new List<int>(GetIntArray("XpNoUseDungeon"));
+            RandomJobs = new List<int>(GetIntArray("RandomJob"));
+            elderGodTalkingTime = GetInt("ElderGodTalkingTime");
+            elderGodBigBoss = GetInt("ElderGodBigBoss");
+            PassiveSkillShow = new List<int>(GetIntArray("PassiveSkillShow"));
+
+            FuncConfigConfig func = FuncConfigConfig.Get("NpcPosOffset");
+            LitJson.JsonData _data = LitJson.JsonMapper.ToObject(func.Numerical1);
+            foreach (var _key in _data.Keys)
+            {
+                int _npcID = int.Parse(_key);
+                double[] _pos = new double[2];
+                _pos[0] = (double)_data[_key][0];
+                _pos[1] = (double)_data[_key][1];
+                NpcPosOffset.Add(_npcID, new Vector3((float)_pos[0], 0, (float)_pos[1]));
+            }
+            //checkShowSwitchAccount
+            var showSwitchAccount = FuncConfigConfig.Get("ShowSwitchAccount");
+            LitJson.JsonData itemShowSwitchAccount = LitJson.JsonMapper.ToObject(showSwitchAccount.Numerical1);
+            checkShowSwitchAccount = new List<string>();
+            foreach(var item in itemShowSwitchAccount)
+            {
+                checkShowSwitchAccount.Add(item.ToString());
+            }
+
+            var putInItemPack = FuncConfigConfig.Get("PutInItemPack");
+            LitJson.JsonData itemPutInData = LitJson.JsonMapper.ToObject(putInItemPack.Numerical1);
+            itemPutInPackDict = new Dictionary<int, List<int>>();
+            foreach (var _key in itemPutInData.Keys)
+            {
+                var itemTypeData = itemPutInData[_key];
+                int packType = int.Parse(_key);
+                List<int> itemTypes = new List<int>();
+                itemPutInPackDict.Add(packType, itemTypes);
+                if (itemTypeData.IsArray)
+                {
+                    for (i = 0; i < itemTypeData.Count; i++)
+                    {
+                        int itemType = int.Parse(itemTypeData[i].ToString());
+                        itemTypes.Add(itemType);
+                    }
+                }
+            }
+
+            //鎷惧彇璐甸噸鐗╁搧
+            FuncConfigConfig importantItemType = FuncConfigConfig.Get("AutoBuyDrug");
+            ImportantItemType = LitJson.JsonMapper.ToObject<int[]>(importantItemType.Numerical2);
+            ImportantItemID = LitJson.JsonMapper.ToObject<int[]>(importantItemType.Numerical3);
+
+            FuncConfigConfig nxxdImg = FuncConfigConfig.Get("NXXDPicture");
+            LitJson.JsonData nxxdData = LitJson.JsonMapper.ToObject(nxxdImg.Numerical1);
+            multipleRealmImgDict = new Dictionary<int, string>();
+            if (nxxdData.IsArray)
+            {
+                for (i = 0; i < nxxdData.Count; i++)
+                {
+                    if (nxxdData[i].IsArray)
+                    {
+                        multipleRealmImgDict.Add(int.Parse(nxxdData[i][0].ToString()), nxxdData[i][1].ToString());
+                    }
+                }
+            }
+
+            bossShuntMaps = new List<int>(GetIntArray("BossShunt"));
+            bossShuntDays = GetInt("BossShunt", 3);
+
+            itemDropEffect.Clear();
+            func = FuncConfigConfig.Get("ItemEquipmentEffect");
+            _data = LitJson.JsonMapper.ToObject(func.Numerical1);
+            List<string> _keys = new List<string>(_data.Keys);
+            for (i = 0; i < _keys.Count; ++i)
+            {
+                int[] _props = new int[3];
+                for (int j = 0; j < 3; ++j)
+                {
+                    _props[j] = (int)_data[_keys[i]][j];
+                }
+                itemDropEffect[int.Parse(_keys[i])] = _props;
+            }
+
+            xllyDropEffect.Clear();
+            _data = LitJson.JsonMapper.ToObject(func.Numerical2);
+            _keys.Clear();
+            _keys.AddRange(_data.Keys);
+            for (i = 0; i < _keys.Count; ++i)
+            {
+                int[] _props = new int[3];
+                for (int j = 0; j < 3; ++j)
+                {
+                    _props[j] = (int)_data[_keys[i]][j];
+                }
+                xllyDropEffect[int.Parse(_keys[i])] = _props;
+            }
+
+            xqryDropEffect.Clear();
+            _data = LitJson.JsonMapper.ToObject(func.Numerical3);
+            _keys.Clear();
+            _keys.AddRange(_data.Keys);
+            for (i = 0; i < _keys.Count; ++i)
+            {
+                int[] _props = new int[3];
+                for (int j = 0; j < 3; ++j)
+                {
+                    _props[j] = (int)_data[_keys[i]][j];
+                }
+                xqryDropEffect[int.Parse(_keys[i])] = _props;
+            }
+
+            dropEffectQuality.Clear();
+            func = FuncConfigConfig.Get("IeemEquipmentEffectQuality");
+            _data = LitJson.JsonMapper.ToObject(func.Numerical1);
+            _keys.Clear();
+            _keys.AddRange(_data.Keys);
+            for (i = 0; i < _keys.Count; ++i)
+            {
+                dropEffectQuality[int.Parse(_keys[i])] = (int)_data[_keys[i]];
+            }
+
+            customDropEffect.Clear();
+            func = FuncConfigConfig.Get("ItemEquipmentEffectItem");
+            _data = LitJson.JsonMapper.ToObject(func.Numerical1);
+            _keys.Clear();
+            _keys.AddRange(_data.Keys);
+            int[] _tmp = null;
+            List<int[]> _content = null;
+            for (i = 0; i < _keys.Count; ++i)
+            {
+                _content = new List<int[]>();
+                foreach (LitJson.JsonData _values in _data[_keys[i]])
+                {
+                    if (_values.IsArray)
+                    {
+                        _tmp = new int[2];
+                        _tmp[0] = (int)_values[0];
+                        _tmp[1] = (int)_values[1];
+                    }
+                    else
+                    {
+                        _tmp = new int[1];
+                        _tmp[0] = (int)_values;
+                    }
+                    _content.Add(_tmp);
+                }
+                customDropEffect.Add(int.Parse(_keys[i]), _content);
+            }
+
+            BuffToHitEffect.Clear();
+            func = FuncConfigConfig.Get("BuffToHitEffect");
+            if (!string.IsNullOrEmpty(func.Numerical1) && !string.IsNullOrEmpty(func.Numerical2))
+            {
+                string[] _buffs = func.Numerical1.Split('|');
+                string[] _effects = func.Numerical2.Split('|');
+                for (i = 0; i < _buffs.Length; ++i)
+                {
+                    BuffToHitEffect[int.Parse(_buffs[i])] = int.Parse(_effects[i]);
+                }
+            }
+
+            demonJarHintLevelLimit = GetInt("DemonJarFirstRemin");
+            demonJarHintLineId = GetInt("DemonJarFirstRemin", 2);
+            skillPanelUnLock = GetInt("SkillPanelUnlock");
+            dailyQuestRedpointLevelLimit = GetInt("DailyQuestRedPoint");
+            lowHpRemind = GetInt("LowHpRemind");
+            autoBuyItemIds = GetIntArray("BuyItemPrice", 1);
+            autoBuyItemPrices = GetIntArray("BuyItemPrice", 2);
+            neutralMaps.AddRange(GetIntArray("MapLine", 4));
+            neutralBossMaps.AddRange(GetIntArray("BossListMapID"));
+
+            var _propertyIconCfg = FuncConfigConfig.Get("PropertyIcon");
+            var _propertyIconJson = LitJson.JsonMapper.ToObject(_propertyIconCfg.Numerical1);
+            foreach (var _key in _propertyIconJson.Keys)
+            {
+                var _property = int.Parse(_key);
+                propertyIconDict.Add(_property, _propertyIconJson[_key].ToString());
+            }
+
+            munekadolockLimit = GetInt("MunekadoLockLimit");
+            demonJarRedPoint = GetInt("DemonJarRedPoint");
+            LoadLV = GetInputString("LoadLV");
+
+            mainWinSkillResetTime = GetFloat("AutomaticSwitch");
+            heroDialogueOffset = GetInputString("NpcHalfLength", 1).Vector3Parse();
+            heroDialogueRotation = GetInputString("NpcHalfLength", 2).Vector3Parse();
+            heroDialogueScale = GetFloat("NpcHalfLength", 3);
+
+            var ancientConfig = FuncConfigConfig.Get("ElderBattleTarget");
+            ancientGrandTotalAchievements = new List<int>();
+            ancientGrandTotalAchievements.AddRange(ConfigParse.GetMultipleStr<int>(ancientConfig.Numerical1));
+            ancientContinueKillAchievements = new List<int>();
+            ancientContinueKillAchievements.AddRange(ConfigParse.GetMultipleStr<int>(ancientConfig.Numerical2));
+
+            trialDungeonGroupChallengeTipLv = GetInt("SingleIntoFB");
+            prayerRedpointLimitLv = GetInt("PrayRedPoint");
+            demonJarLevelLimit = GetInt("DemonJarLevelLimit");
+            maxItemDropEffectCount = GetInt("ItemMaskEffect");
+
+            specialGuide41Mission = GetInt("SpecialGuide41", 1);
+            specialGuide41Achievement = GetInt("SpecialGuide41", 2);
+
+            supremeRechargeVipLv = GetInt("SupremeCTGVipLimit", 1);
+
+            rechargeRedpointLv = GetInt("FirstPayRedPoint", 1);
+            rechargeRedpointMinLv = GetInt("FirstPayRedPoint", 2);
+            runeTowerSweepBuyTimes = GetInt("RuneTowerSweepBuy");
+            runeTowerSweepBuyPrice = GetInt("RuneTowerSweepBuy", 2);
+            teamMatchingTimeOut = GetInt("TeamMatchingTimeOut");
+            inGameDownLoadLevelCheckPoints = new List<int>(GetIntArray("InGameDownLoad"));
+            inGameDownLoadTaskCheckPoints = new List<int>(GetIntArray("InGameDownLoad", 2));
+            inGameDownLoadHighLevel = GetInt("InGameDownLoad", 3);
+
+            worldBossNoRebornRemindMaps = new List<int>(GetIntArray("NoRebornRemindMap", 1));
+            bossHomeNoRebornRemindMaps = new List<int>(GetIntArray("NoRebornRemindMap", 2));
+            elderGodNoRebornRemindMaps = new List<int>(GetIntArray("NoRebornRemindMap", 3));
+            demonJarNoRebornRemindMaps = new List<int>(GetIntArray("NoRebornRemindMap", 4));
+            dogzNoRebornRemindMaps = new List<int>(GetIntArray("NoRebornRemindMap", 5));
+
+            if (ModeDefaultConfig == null)
+            {
+                func = FuncConfigConfig.Get("ModeDefault");
+
+                string[] _funcNpc = func.Numerical1.Split('|');
+                string[] _fightNpc = func.Numerical2.Split('|');
+                string[] _pet = func.Numerical3.Split('|');
+                string[] _horse = func.Numerical4.Split('|');
+
+                ModeDefaultConfig = new string[4][];
+                ModeDefaultConfig[0] = _funcNpc;
+                ModeDefaultConfig[1] = _fightNpc;
+                ModeDefaultConfig[2] = _pet;
+                ModeDefaultConfig[3] = _horse;
+            }
+
+            if (RealmGroup == null)
+            {
+                func = FuncConfigConfig.Get("RealmGroup");
+                string[] _group = func.Numerical1.Split('|');
+                RealmGroup = new int[_group.Length];
+                for (int j = 0; j < _group.Length; ++j)
+                {
+                    int.TryParse(_group[j], out RealmGroup[j]);
+                }
+            }
+
+            func = FuncConfigConfig.Get("PrefightAtkRange");
+            PrefightAtkRange = float.Parse(func.Numerical1);
+            inGameDownLoadHighestLevelPoint = GetInt("DownReward", 2);
+
+            dungeonCanUseMoneyIds = new List<int>(GetIntArray("FBEnterTickeyAuto", 1));
+            dungeonRebornClientTimes = ConfigParse.GetDic<int, int>(GetInputString("DuplicatesRebornTime", 2));
+            dogzBoxLimit = GetInt("DogzBoxLimit");
+
+            fairyGrabBossMapLines = ConfigParse.GetDic<int, int>(GetInputString("MapLine", 2));
+            var grabBossMaps = fairyGrabBossMapLines.Keys.ToList();
+            foreach (var _key in grabBossMaps)
+            {
+                fairyGrabBossMapLines[_key] = fairyGrabBossMapLines[_key] - 1;
+            }
+
+            if (DropItemEffectMapID == null)
+            {
+                DropItemEffectMapID = new Dictionary<int, List<int>>();
+            }
+            DropItemEffectMapID.Clear();
+            func = FuncConfigConfig.Get("DropItemEffectMapID");
+            _data = LitJson.JsonMapper.ToObject(func.Numerical1);
+            int _itemID;
+            _keys.Clear();
+            _keys.AddRange(_data.Keys);
+            for (int j = 0; j < _keys.Count; ++j)
+            {
+                if (int.TryParse(_keys[j].ToString(), out _itemID))
+                {
+                    if (!DropItemEffectMapID.ContainsKey(_itemID))
+                    {
+                        DropItemEffectMapID.Add(_itemID, new List<int>());
+                    }
+                    var _jsonMapIDs = _data[_keys[j]];
+                    foreach (var _jsonMapID in _jsonMapIDs)
+                    {
+                        var _mapID = ((LitJson.IJsonWrapper)_jsonMapID).GetInt();
+                        if (!DropItemEffectMapID[_itemID].Contains(_mapID))
+                        {
+                            DropItemEffectMapID[_itemID].Add(_mapID);
+                        }
+                    }
+                }
+            }
+
+            int[] mapIDs = GetIntArray("RebornAutoFightDungeon");
+            RebornAutoFightMapID = new List<int>(mapIDs);
+
+            teamWorldCall = GetInputString("TeamWorldCall");
+            teamWorldCallInviteCount = GetInt("TeamWorldCall", 2);
+
+            var ancientKingAwradConfig = FuncConfigConfig.Get("ElderBattlefieldTopAward");
+            if (ancientKingAwradConfig != null)
+            {
+                var itemArray = LitJson.JsonMapper.ToObject<int[][]>(ancientKingAwradConfig.Numerical1);
+                for (int k = 0; k < itemArray.Length; k++)
+                {
+                    ancientKingAwards.Add(new Item()
+                    {
+                        id = itemArray[k][0],
+                        count = itemArray[k][1],
+                    });
+                }
+            }
+
+            func = FuncConfigConfig.Get("QualityEffectConfig");
+            lowQualityEffectCount = int.Parse(func.Numerical1);
+            medQualityEffectCount = int.Parse(func.Numerical2);
+            highQualityEffectCount = int.Parse(func.Numerical3);
+
+            func = FuncConfigConfig.Get("QualityPetCountConfig");
+            lowQualityPetCount = int.Parse(func.Numerical1);
+            medQualityPetCount = int.Parse(func.Numerical2);
+            highQualityPetCount = int.Parse(func.Numerical3);
+
+            func = FuncConfigConfig.Get("QualityGuardCountConfig");
+            lowQualityGuardCount = int.Parse(func.Numerical1);
+            medQualityGuardCount = int.Parse(func.Numerical2);
+            highQualityGuardCount = int.Parse(func.Numerical3);
+
+            func = FuncConfigConfig.Get("QualityPetEffectCount");
+            lowQualityPetEffectCount = int.Parse(func.Numerical1);
+            medQualityPetEffectCount = int.Parse(func.Numerical2);
+            highQualityPetEffectCount = int.Parse(func.Numerical3);
+
+            func = FuncConfigConfig.Get("QualityHorseEffectCount");
+            lowQualityHorseEffectCount = int.Parse(func.Numerical1);
+            medQualityHorseEffectCount = int.Parse(func.Numerical2);
+            highQualityHorseEffectCount = int.Parse(func.Numerical3);
+
+            fairyLandBuffCondition = GetInt("XjmjAddHarm", 1);
+            fairyLandBuffId = GetInt("XjmjAddHarm", 2);
+            achievementEarlierStageLevel = GetInt("AchieveLV");
+
+            func = FuncConfigConfig.Get("PreloadSkillEffect");
+            PreloadSkillEffect = new int[2][];
+            PreloadSkillEffect[0] = GetIntArray("PreloadSkillEffect");
+            PreloadSkillEffect[1] = GetIntArray("PreloadSkillEffect", 2);
+            demonJarAutoTime = GetInt("DemonJarAutoTime");
+
+            if (SgzzRobotEquipDict == null)
+            {
+                SgzzRobotEquipDict = new Dictionary<int, Dictionary<int, GA_NpcFightSgzcZZ.EquipRandomInfo>>();
+
+                for (int job = 1; job <= 3; ++job)
+                {
+                    string _jsonString = GetInputString("SGZCHelpBattleEquip", job);
+
+                    if (string.IsNullOrEmpty(_jsonString))
+                    {
+                        continue;
+                    }
+
+                    var _jsonData = LitJson.JsonMapper.ToObject(_jsonString);
+                    var _jobDict = new Dictionary<int, GA_NpcFightSgzcZZ.EquipRandomInfo>();
+
+                    for (i = 0; i < _jsonData.Count; ++i)
+                    {
+                        var _lvJson = _jsonData[i];
+                        var _lv = (int)_lvJson["LV"];
+                        if (!_jobDict.ContainsKey(_lv))
+                        {
+                            var _equips = _lvJson["Equips"];
+
+                            var _randEquip = new GA_NpcFightSgzcZZ.EquipRandomInfo();
+
+                            _randEquip.randClothesItemIDs = new int[_equips[0].Count];
+                            for (int j = 0; j < _equips[0].Count; ++j)
+                            {
+                                _randEquip.randClothesItemIDs[j] = (int)_equips[0][j];
+                            }
+
+                            _randEquip.randWeaponItemIDs = new int[_equips[1].Count];
+                            for (int j = 0; j < _equips[1].Count; ++j)
+                            {
+                                _randEquip.randWeaponItemIDs[j] = (int)_equips[1][j];
+                            }
+
+                            _randEquip.randSecondaryItemIDs = new int[_equips[2].Count];
+                            for (int j = 0; j < _equips[2].Count; ++j)
+                            {
+                                _randEquip.randSecondaryItemIDs[j] = (int)_equips[2][j];
+                            }
+
+                            _randEquip.randWingItemIDs = new int[_equips[3].Count];
+                            for (int j = 0; j < _equips[3].Count; ++j)
+                            {
+                                _randEquip.randWingItemIDs[j] = (int)_equips[3][j];
+                            }
+
+                            _randEquip.godWeaponIDs = new int[_equips[4].Count];
+                            for (int j = 0; j < _equips[4].Count; ++j)
+                            {
+                                _randEquip.godWeaponIDs[j] = (int)_equips[4][j];
+                            }
+
+                            _jobDict.Add(_lv, _randEquip);
+                        }
+                    }
+
+                    SgzzRobotEquipDict.Add(job, _jobDict);
+
+                }
+            }
+
+
+            if (SgzcRealm == null)
+            {
+                SgzcRealm = new Dictionary<int, int>();
+
+                var _lvArr = GetInputString("SGZCRobotRealm", 1).Split('|');
+                var _rLvArr = GetInputString("SGZCRobotRealm", 2).Split('|');
+
+                for (int j = 0; j < _lvArr.Length; ++j)
+                {
+                    SgzcRealm[int.Parse(_lvArr[j])] = int.Parse(_rLvArr[j]);
+                }
+            }
+
+            crossServerBattleFieldOpenDay = GetInt("CrossRealmCfg", 2);
+            UISpringDecorate = GetInt("UISpringDecorate");
+
+            mixServerCustomDays = GetInt("MixServer");
+            openServerCustomDays = GetInt("OperationAction");
+            ClientPvpAttributePer = GetInt("ClientPvPAttributePer") * Constants.F_DELTA;
+
+            mysteryShopRefreshItem = GetInt("MysteryShopRefresh");
+            mysteryShopRefreshItemCount = new Dictionary<int, int>();
+            var mysteryShopJson = JsonMapper.ToObject(GetInputString("MysteryShopRefresh", 2));
+            foreach (var key in mysteryShopJson.Keys)
+            {
+                var time = int.Parse(key);
+                mysteryShopRefreshItemCount[time] = (int)mysteryShopJson[key];
+            }
+
+            mysteryShopRefreshItemValue = GetInt("MysteryShopRefresh", 3);
+            mysteryShopRefreshInterval = GetInt("MysteryShopRefresh", 4);
+
+            var equipStarConfig = FuncConfigConfig.Get("EquipPartStar");
+            var equipStarJson = LitJson.JsonMapper.ToObject(equipStarConfig.Numerical1);
+            equipStarLimit = new Dictionary<int, Dictionary<int, int>>();
+            foreach (var itemColorKey in equipStarJson.Keys)
+            {
+                var itemColor = int.Parse(itemColorKey);
+                Dictionary<int, int> dict = new Dictionary<int, int>();
+                foreach (var itemLevelKey in equipStarJson[itemColorKey].Keys)
+                {
+                    var itemLevel = int.Parse(itemLevelKey);
+                    var starLimit = int.Parse(equipStarJson[itemColorKey][itemLevelKey].ToString());
+                    dict.Add(itemLevel, starLimit);
+                }
+                equipStarLimit.Add(itemColor, dict);
+            }
+
+            equipTrainMustItemId = GetInt("EquipWashMustID");
+            acutionItemHour = GetInt("AuctionItem");
+            mainWinTopCloseTime = GetInt("AutomaticSwitch");
+
+            equipDecomposeScreen.AddRange(GetIntArray("EquipDecomposeScreen", 2));
+
+            func = FuncConfigConfig.Get("AtkTypeIncreasePushDis");
+            var _ks = func.Numerical1.Split('|');
+            var _vs = func.Numerical2.Split('|');
+            for (i = 0; i < _ks.Length; ++i)
+            {
+                AtkTypeIncreasePushDis[int.Parse(_ks[i])] = int.Parse(_vs[i]) * Constants.F_DELTA;
+            }
+
+            func = FuncConfigConfig.Get("NpcDieSetCamera");
+            if (func != null)
+            {
+                var _jsonData = LitJson.JsonMapper.ToObject(func.Numerical1);
+                for (i = 0; i < _jsonData.Count; ++i)
+                {
+                    var _child = _jsonData[i];
+                    var _lookAtData = new CameraController.LookAtData();
+                    _lookAtData.position = new Vector3(MathUtility.GetFloatFromLitJson(_child[1][0]),
+                                                       MathUtility.GetFloatFromLitJson(_child[1][1]),
+                                                       MathUtility.GetFloatFromLitJson(_child[1][2]));
+                    _lookAtData.rotX = (int)_child[2];
+                    _lookAtData.rotY = (int)_child[3];
+                    _lookAtData.lastTime = MathUtility.GetFloatFromLitJson(_child[4]);
+
+                    NpcDieSetCamera[(int)_child[0]] = _lookAtData;
+                }
+            }
+            WorkForEnemySkills = GetIntArray("ArenaSetSkills", 1);
+            WorkForMeSkills = GetIntArray("ArenaSetSkills", 2);
+            WorkNotSkills = GetIntArray("ArenaSetSkills", 3);
+            defenseGetWays = GetIntArray("DefenseGetWays", 1);
+            skillYinjis = ConfigParse.GetDic<int, int>(GetInputString("SkillYinji", 1));
+            onlyUsedAtBackpackItems = new List<int>(GetIntArray("ItemPush", 2));
+
+            var signInSkillArray = GetIntArray("SignInPromoteSkill", 1);
+            if (signInSkillArray != null)
+            {
+                signInPromoteSkills.AddRange(signInSkillArray);
+            }
+
+            MasteryLoadingLevelLimit1 = GetInt("MasteryLoadingLevelLimit");
+            MasteryLoadingLevelLimit2 = GetInt("MasteryLoadingLevelLimit", 2);
+
+            chestDisplayItems = new List<int>(GetIntArray("ChestShowItems"));
+
+            func = FuncConfigConfig.Get("Zhanling");
+            if (func != null)
+            {
+                OldZhanLingCtgIdDict = new Dictionary<int, int>();
+                ZhanLingCtgIdDict = new Dictionary<int, List<int>>();
+                var tempDict = JsonMapper.ToObject(func.Numerical1);
+                var keyList = tempDict.Keys.ToList();
+                for (int j = 0; j < keyList.Count; j++)
+                {
+                    OldZhanLingCtgIdDict[int.Parse(keyList[j])] = JsonMapper.ToObject<List<int>>(tempDict[keyList[j]].ToJson())[0];
+                    ZhanLingCtgIdDict[int.Parse(keyList[j])] = JsonMapper.ToObject<List<int>>(tempDict[keyList[j]].ToJson());
+                }
+
+                ZhanLingCtgIdHDict = new Dictionary<int, List<int>>();
+                tempDict = JsonMapper.ToObject(func.Numerical3);
+                keyList = tempDict.Keys.ToList();
+                for (int k = 0; k < keyList.Count; k++)
+                {
+                    ZhanLingCtgIdHDict[int.Parse(keyList[k])] = JsonMapper.ToObject<List<int>>(tempDict[keyList[k]].ToJson());
+                }
+            }
+
+            func = FuncConfigConfig.Get("FBQuickPass");
+            fightPowerMore = float.Parse(func.Numerical1) + 0.01f; //鐤戜技鐜╁鏃犳硶闆疯瘺鏄疌/S璁$畻涓嶅绛夐棶棰橈紝鎵�浠ュ姞0.01f
+            flashOpenArr = JsonMapper.ToObject<int[]>(func.Numerical2);
+            flashCntMoreArr = JsonMapper.ToObject<int[]>(func.Numerical3);
+            flashKillMaxCount = int.Parse(func.Numerical4);
+
+        }
+        catch (Exception ex)
+        {
+            Debug.LogError(ex);
+        }
+
+    }
+
+    public static string GetJobHeadPortrait(int _job, int _ReincarnationLv)
+    {
+        if (jobHeadPortrait.ContainsKey(_job) && jobHeadPortrait[_job].ContainsKey(_ReincarnationLv))
+        {
+            return jobHeadPortrait[_job][_ReincarnationLv];
+        }
+        else
+        {
+            return string.Empty;
+        }
+    }
+
+    public static List<int> GetAttrIdsBySkill(int _skillId)
+    {
+        if (skillAttrIDDict.ContainsKey(_skillId))
+        {
+            return skillAttrIDDict[_skillId];
+        }
+        return null;
+    }
+
+    public static string GetOtherJobHeadPortrait(int _job, int _ReincarnationLv)
+    {
+        if (otherjobHeadPortrait.ContainsKey(_job) && otherjobHeadPortrait[_job].ContainsKey(_ReincarnationLv))
+        {
+            return otherjobHeadPortrait[_job][_ReincarnationLv];
+        }
+        else
+        {
+            return string.Empty;
+        }
+    }
+
+    public static PackType GetPackTypeByItemType(int itemType)
+    {
+        foreach (var key in itemPutInPackDict.Keys)
+        {
+            var types = itemPutInPackDict[key];
+            if (types.Contains(itemType))
+            {
+                return (PackType)key;
+            }
+        }
+        return PackType.Item;
+    }
+
+    public static int GetInt(string _key, int _index = 1)
+    {
+        var result = 0;
+        int.TryParse(GetInputString(_key, _index), out result);
+        return result;
+    }
+
+    public static float GetFloat(string _key, int _index = 1)
+    {
+        var result = 0f;
+        float.TryParse(GetInputString(_key, _index), out result);
+        return result;
+    }
+
+    public static bool GetBool(string _key, int _index = 1)
+    {
+        var result = false;
+        bool.TryParse(GetInputString(_key, _index), out result);
+        return result;
+    }
+
+    public static int[] GetIntArray(string _key, int _index = 1)
+    {
+        var inputString = GetInputString(_key, _index);
+        var stringArray = inputString.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+        if (stringArray.Length == 0)
+        {
+            return null;
+        }
+
+        var result = new int[stringArray.Length];
+        for (int i = 0; i < stringArray.Length; i++)
+        {
+            int.TryParse(stringArray[i], out result[i]);
+        }
+
+        return result;
+    }
+
+    public static string[] GetStringArray(string _key, int _index = 1)
+    {
+        var inputString = GetInputString(_key, _index);
+        var stringArray = inputString.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+        if (stringArray.Length == 0)
+        {
+            return null;
+        }
+
+        var result = new string[stringArray.Length];
+        for (int i = 0; i < stringArray.Length; i++)
+        {
+            result[i] = stringArray[i];
+        }
+
+        return result;
+    }
+
+
+    public static float[] GetFloatArray(string _key, int _index = 1)
+    {
+        var inputString = GetInputString(_key, _index);
+        var stringArray = inputString.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+        if (stringArray.Length == 0)
+        {
+            return null;
+        }
+
+        var result = new float[stringArray.Length];
+        for (int i = 0; i < stringArray.Length; i++)
+        {
+            float.TryParse(stringArray[i], out result[i]);
+        }
+
+        return result;
+    }
+
+    public static bool[] GetBoolArray(string _key, int _index = 1)
+    {
+        var inputString = GetInputString(_key, _index);
+        var stringArray = inputString.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+        if (stringArray.Length == 0)
+        {
+            return null;
+        }
+
+        var result = new bool[stringArray.Length];
+        for (int i = 0; i < stringArray.Length; i++)
+        {
+            bool.TryParse(stringArray[i], out result[i]);
+        }
+
+        return result;
+    }
+
+    public static List<int> GetTimeArray(string _key, int _index = 1)
+    {
+        var configContent = GetInputString(_key, _index);
+        var stringArray = configContent.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);
+        var timeList = new List<int>();
+        for (int i = 0; i < stringArray.Length; i++)
+        {
+            var input = stringArray[i];
+            var matches = Regex.Matches(input, "[0-9]{1,2}");
+            var hour = matches.Count > 0 ? int.Parse(matches[0].Value) : 0;
+            var minute = matches.Count > 1 ? int.Parse(matches[1].Value) : 0;
+            timeList.Add(hour * 60 + minute);
+        }
+
+        return timeList;
+    }
+
+    public static string GetInputString(string _key, int _index = 1)
+    {
+        var config = FuncConfigConfig.Get(_key);
+        var inputString = string.Empty;
+
+        switch (_index)
+        {
+            case 1:
+                inputString = config.Numerical1;
+                break;
+            case 2:
+                inputString = config.Numerical2;
+                break;
+            case 3:
+                inputString = config.Numerical3;
+                break;
+            case 4:
+                inputString = config.Numerical4;
+                break;
+            case 5:
+                inputString = config.Numerical5;
+                break;
+        }
+
+        return inputString;
+    }
+
+
+}
diff --git a/Main/System/GeneralConfig/GeneralDefine.cs.meta b/Main/System/GeneralConfig/GeneralDefine.cs.meta
new file mode 100644
index 0000000..7801c34
--- /dev/null
+++ b/Main/System/GeneralConfig/GeneralDefine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2ac15afa197bd78438ca0c855b4c7d60
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Language.meta b/Main/System/Language.meta
new file mode 100644
index 0000000..4574ed5
--- /dev/null
+++ b/Main/System/Language.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5c707d5196a425a4f8287eb5a2d9442c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Language/Language.cs b/Main/System/Language/Language.cs
new file mode 100644
index 0000000..3afb1f0
--- /dev/null
+++ b/Main/System/Language/Language.cs
@@ -0,0 +1,161 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+
+
+public static class Language
+{
+    public static int languageNumber
+    {
+        get;
+        set;
+    }
+
+    public static event Action languageChangeEvent;
+
+    public static void ChangeLanguage(int _number)
+    {
+        if (languageChangeEvent != null)
+        {
+            languageChangeEvent();
+        }
+    }
+
+
+    /// <summary>
+    /// 鏍规嵁绯荤粺璇█鑷姩璁剧疆榛樿璇█
+    /// </summary>
+    public static void InitDefaultLanguage()
+    {
+        var config = InitialFunctionConfig.Get("Language").Numerical1;
+        Debug.LogFormat("绯荤粺璇█锛歿0} {1}", Application.systemLanguage, config);
+        if (string.IsNullOrEmpty(config))
+            return;
+        var id = LocalSave.GetString("LANGUAGE_ID1");
+        if (!string.IsNullOrEmpty(id))
+            return;
+
+        switch (Application.systemLanguage)
+        {
+            case SystemLanguage.Chinese:
+            case SystemLanguage.ChineseSimplified:
+            case SystemLanguage.ChineseTraditional:
+                {
+                    id = "zh";
+                    break;
+                }
+        }
+        var json = LitJson.JsonMapper.ToObject(config);
+        if (json.Keys.Contains(id))
+            Id = id;
+        else
+        {
+            //寮�鍚殑鎯呭喌涓嬪繀椤昏鏈変釜榛樿鍊�
+            Id = InitialFunctionConfig.Get("Language").Numerical2;
+        }
+    }
+
+    /// <summary>
+    /// 璇█鐨処D锛岀敤浜庡尯鍒嗕笅杞借祫婧�
+    /// </summary>
+    /// <value></value>
+    public static string Id
+    {
+        get
+        {
+            var config = InitialFunctionConfig.Get("Language").Numerical1;
+            if (string.IsNullOrEmpty(config))
+                return "";
+            return LocalSave.GetString("LANGUAGE_ID1");
+        }
+        set
+        {
+            LocalSave.SetString("LANGUAGE_ID1", value);
+        }
+    }
+
+    //榛樿璺緞涓嶉檮鍔犲湴鍧�锛孖d涓嶄负绌烘椂闄勫姞Id
+    public static string fixPath
+    {
+        get
+        {
+            if (string.IsNullOrEmpty(Id))
+                return "";
+            return string.Format("/{0}", Id);
+        }
+    }
+
+    public static string Get(string _id)
+    {
+        //  TODO YYL
+        return string.Empty;
+//         var languageInfo = LanguageConfig.Get(_id);
+//         if (languageInfo == null)
+//         {
+// #if UNITY_EDITOR
+//             if (_id.StartsWith(NewBieGuideScriptableObject.GuidesPrefixNewBie) ||
+//                 _id.StartsWith(NewBieGuideScriptableObject.GuidesPrefixFun))
+//                 return string.Empty;
+//             Debug.LogFormat("缂哄皯璇█琛ㄩ厤缃�,id: {0}", _id);
+// #endif
+//             return string.Empty;
+//         }
+
+//         if (string.IsNullOrEmpty(languageInfo.content))
+//         {
+//             Debug.LogFormat("璇█鍐呭涓虹┖,id: {0}", _id);
+//         }
+
+//         return languageInfo.content;
+    }
+
+    public static string Get(string _id, params object[] _objects)
+    {
+        var content = Get(_id);
+        try
+        {
+            return string.Format(content, _objects);
+        }
+        catch (Exception ex)
+        {
+            Debug.LogFormat("璇█鍐呭鏍煎紡閿欒,id: {0}", _id);
+            return content;
+        }
+    }
+
+    public static string GetFromLocal(int _id)
+    {
+        return string.Empty;
+        //  TODO YYL
+        // var languageInfo = PriorLanguageConfig.Get(_id);
+        // if (languageInfo == null)
+        // {
+        //     Debug.LogFormat("缂哄皯璇█琛ㄩ厤缃�,id: {0}", _id);
+        //     return string.Empty;
+        // }
+
+        // if (string.IsNullOrEmpty(languageInfo.Content))
+        // {
+        //     Debug.LogFormat("璇█鍐呭涓虹┖,id: {0}", _id);
+        // }
+
+        // return languageInfo.Content;
+    }
+
+    public static string GetFromLocal(int _id, params object[] _objects)
+    {
+        var content = GetFromLocal(_id);
+        try
+        {
+            return string.Format(content, _objects);
+        }
+        catch (Exception ex)
+        {
+            Debug.LogFormat("璇█鍐呭鏍煎紡閿欒,id: {0}", _id);
+            return content;
+        }
+    }
+
+
+}
diff --git a/Main/System/Language/Language.cs.meta b/Main/System/Language/Language.cs.meta
new file mode 100644
index 0000000..2f9c0c7
--- /dev/null
+++ b/Main/System/Language/Language.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 40bd19ad08eb67941b172e37040f3ce0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Redpoint.meta b/Main/System/Redpoint.meta
new file mode 100644
index 0000000..1a3c949
--- /dev/null
+++ b/Main/System/Redpoint.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6d39ce8c530f7134f8a3f4df2c37e4e7
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Redpoint/Redpoint.cs b/Main/System/Redpoint/Redpoint.cs
new file mode 100644
index 0000000..ccafa20
--- /dev/null
+++ b/Main/System/Redpoint/Redpoint.cs
@@ -0,0 +1,64 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+    
+    public class Redpoint
+    {
+        int m_Id = 0;
+        public int id {
+            get { return m_Id; }
+            private set { m_Id = value; }
+        }
+
+        int m_Parent = 0;
+        public int parent {
+            get { return m_Parent; }
+            private set { m_Parent = value; }
+        }
+
+        RedPointState m_State = RedPointState.None;
+        public RedPointState state {
+            get { return m_State; }
+            set {
+                if (m_State != value)
+                {
+                    m_State = value;
+                    RedpointCenter.Instance.Report(this);
+                }
+            }
+        }
+
+        int m_Count = 0;
+        public int count {
+            get { return m_Count; }
+            set {
+                if (m_Count != value)
+                {
+                    m_Count = value;
+                    RedpointCenter.Instance.ReportWithoutParent(this);
+                }
+            }
+        }
+
+        public Redpoint(int _id)
+        {
+            id = _id;
+            RedpointCenter.Instance.Register(this);
+        }
+
+        public Redpoint(int _parent, int _id)
+        {
+            if (_parent <= 0)
+            {
+                Debug.Log("鏃犳晥鐨勭埗瀵硅薄Id锛�");
+                return;
+            }
+           
+            parent = _parent;
+            id = _id;
+            RedpointCenter.Instance.Register(this);
+        }
+
+        public int RedpoindId { get; internal set; }
+    }
\ No newline at end of file
diff --git a/Main/System/Redpoint/Redpoint.cs.meta b/Main/System/Redpoint/Redpoint.cs.meta
new file mode 100644
index 0000000..0e25799
--- /dev/null
+++ b/Main/System/Redpoint/Redpoint.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 197dd29377e81c947badf6c3948ec100
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Redpoint/RedpointCenter.cs b/Main/System/Redpoint/RedpointCenter.cs
new file mode 100644
index 0000000..89cf2b9
--- /dev/null
+++ b/Main/System/Redpoint/RedpointCenter.cs
@@ -0,0 +1,130 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+    
+    public class RedpointCenter : Singleton<RedpointCenter>
+    {
+        public event Action<int> redpointValueChangeEvent;
+
+        Dictionary<int, Redpoint> redpoints = new Dictionary<int, Redpoint>();
+        Dictionary<int, List<int>> parentChildren = new Dictionary<int, List<int>>();
+
+        public RedpointCenter()
+        {
+
+        }
+
+        public void ResetAllRedpointState()
+        {
+            foreach (var redpoint in redpoints.Values)
+            {
+                redpoint.state = RedPointState.None;
+            }
+        }
+
+        public void Register(Redpoint _redpoint)
+        {
+            var id = _redpoint.id;
+            if (redpoints.ContainsKey(id))
+            {
+                Debug.LogErrorFormat("閲嶅娉ㄥ唽绾㈢偣锛歩d->{0}", id);
+            }
+
+            redpoints[id] = _redpoint;
+
+            var parentId = _redpoint.parent;
+            if (parentId > 0)
+            {
+                List<int> children = null;
+                if (!parentChildren.TryGetValue(parentId, out children))
+                {
+                    parentChildren[parentId] = children = new List<int>();
+                }
+
+                if (!children.Contains(id))
+                {
+                    children.Add(id);
+                }
+            }
+        }
+
+        public void Report(Redpoint _redpoint)
+        {
+            var parentId = _redpoint.parent;
+
+            if (redpointValueChangeEvent != null)
+            {
+                redpointValueChangeEvent(_redpoint.id);
+            }
+
+            if (parentId > 0)
+            {
+                TestParentValue(_redpoint.parent);
+            }
+        }
+
+        public void ReportWithoutParent(Redpoint _redpoint)
+        {
+            if (redpointValueChangeEvent != null)
+            {
+                redpointValueChangeEvent(_redpoint.id);
+            }
+        }
+
+        public RedPointState GetRedpointState(int _id)
+        {
+            Redpoint redpoint = null;
+            if (this.redpoints.TryGetValue(_id, out redpoint))
+            {
+                return redpoint.state;
+            }
+            else
+            {
+                return RedPointState.None;
+            }
+        }
+
+        public int GetRedpointCount(int _id)
+        {
+            Redpoint redpoint = null;
+            if (this.redpoints.TryGetValue(_id, out redpoint))
+            {
+                return redpoint.count;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+
+        void TestParentValue(int _parentId)
+        {
+            List<int> children = null;
+            Redpoint parent = null;
+            if (redpoints.TryGetValue(_parentId, out parent) && parentChildren.TryGetValue(_parentId, out children))
+            {
+                var parentState = RedPointState.None;
+                for (int i = 0; i < children.Count; i++)
+                {
+                    Redpoint child = null;
+                    if (redpoints.TryGetValue(children[i], out child))
+                    {
+                        if (child.state > parentState)
+                        {
+                            parentState = child.state;
+                        }
+                    }
+
+                    if (parentState == RedPointState.Full)
+                    {
+                        break;
+                    }
+
+                }
+                parent.state = parentState;
+            }
+        }
+
+    }
\ No newline at end of file
diff --git a/Main/System/Redpoint/RedpointCenter.cs.meta b/Main/System/Redpoint/RedpointCenter.cs.meta
new file mode 100644
index 0000000..1039d21
--- /dev/null
+++ b/Main/System/Redpoint/RedpointCenter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3a14d208a8eaf094eb603ae04a77f661
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/UI/Login/LoginWin.cs b/Main/UI/Login/LoginWin.cs
index 3df7acb..62796b5 100644
--- a/Main/UI/Login/LoginWin.cs
+++ b/Main/UI/Login/LoginWin.cs
@@ -29,7 +29,6 @@
     {
         base.HandleOpen();
         Debug.Log("鎵撳紑鐧诲綍绐楀彛");
-        ResManager.Instance.PrewarmResources();
         Refresh();
     }
 
diff --git a/Main/UI/UIBase.cs b/Main/UI/UIBase.cs
index cf514ea..52b4fc7 100644
--- a/Main/UI/UIBase.cs
+++ b/Main/UI/UIBase.cs
@@ -269,7 +269,7 @@
         if (parent == null) parent = transform;
         
         // 鍔犺浇鐗规晥璧勬簮
-        GameObject effectPrefab = await ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
+        GameObject effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
         if (effectPrefab == null)
         {
             Debug.LogError($"鍔犺浇UI鐗规晥澶辫触: {effectName}");
@@ -319,7 +319,7 @@
         }
         
         // 鍔犺浇鐗规晥璧勬簮
-        GameObject effectPrefab = await ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
+        GameObject effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
         if (effectPrefab == null)
         {
             Debug.LogError($"鍔犺浇UI鐗规晥澶辫触: {effectName}");
diff --git a/Main/UI/UIManager.cs b/Main/UI/UIManager.cs
index cf10141..d603d13 100644
--- a/Main/UI/UIManager.cs
+++ b/Main/UI/UIManager.cs
@@ -367,7 +367,7 @@
     private T LoadUIResource<T>(string uiName) where T : UIBase
     {
         // 浠庤祫婧愮鐞嗗櫒鍔犺浇UI棰勫埗浣�
-        GameObject prefab = ResManager.Instance.LoadUI(uiName);
+        GameObject prefab = ResManager.Instance.LoadAsset<GameObject>("UI", uiName);
 
         // 妫�鏌ラ鍒朵綋鏄惁鍔犺浇鎴愬姛
         if (prefab == null)
diff --git a/Main/Utility/ComponentExtersion.cs b/Main/Utility/ComponentExtersion.cs
index 6e55ccf..59b3c8f 100644
--- a/Main/Utility/ComponentExtersion.cs
+++ b/Main/Utility/ComponentExtersion.cs
@@ -26,7 +26,7 @@
         }
         catch (Exception ex)
         {
-            Debug.Log(ex);
+            DebugEx.Log(ex);
             return null;
         }
 
@@ -216,6 +216,84 @@
         dropdown.onValueChanged.AddListener(action);
     }
 
+    // public static void SetEnable(this Button _btn, Text _btnTxt, bool _enable, EnableButtonConfig.EnableButtonType _type =
+    //     EnableButtonConfig.EnableButtonType.Default)
+    // {
+    //     EnableButtonConfig.SetEnable(_btn, _btnTxt, _enable, _type);
+    // }
+
+    
+    public static void SetColorful(this Button _btn, Text _btnTxt, bool _colorful, int pattern = 0)
+    {
+        if (_btn != null)
+        {
+            var imageEx = _btn.image as ImageEx;
+            if (imageEx != null)
+            {
+                imageEx.gray = !_colorful;
+            }
+        }
+        if (_btnTxt != null)
+        {
+            switch (pattern)
+            {
+                case 1:
+                    _btnTxt.color = UIHelper.GetUIColor(_colorful ? TextColType.LightYellow : TextColType.White);
+                    break;
+                case 2:
+                    _btnTxt.color = UIHelper.GetUIColor(_colorful ? TextColType.Green : TextColType.White);
+                    break;
+                default:
+                    _btnTxt.color = UIHelper.GetUIColor(_colorful ? TextColType.NavyBrown : TextColType.White);
+                    break;
+            }
+        }
+    }
+
+    
+    public static void SetInteractable(this Button _btn, Text _btnText, bool _interactable)
+    {
+        if (_btn != null)
+        {
+            _btn.interactable = _interactable;
+            var imageEx = _btn.image as ImageEx;
+            if (imageEx != null)
+            {
+                imageEx.gray = !_interactable;
+            }
+        }
+        if (_btnText != null)
+        {
+            _btnText.color = UIHelper.GetUIColor(_interactable ? TextColType.NavyBrown : TextColType.White);
+            //_btnText.color = _btnText.color.SetA(_interactable ? 1 : 0.5f);
+        }
+    }
+
+    
+    public static void SetSprite(this Image _image, string _id)
+    {
+        if (_image == null)
+        {
+            return;
+        }
+
+        var sprite = UILoader.LoadSprite(_id);
+        _image.overrideSprite = sprite;
+    }
+
+    
+    public static void SetSprite(this TextImage _textImage, string _id)
+    {
+        if (_textImage == null)
+        {
+            return;
+        }
+
+        var sprite = UILoader.LoadSprite(_id);
+        _textImage.sprite = sprite;
+    }
+
+
     public static void SetActive(this Component compoent, bool active)
     {
         if (compoent != null)
diff --git a/Main/Utility/Constants.cs b/Main/Utility/Constants.cs
new file mode 100644
index 0000000..4a51e20
--- /dev/null
+++ b/Main/Utility/Constants.cs
@@ -0,0 +1,52 @@
+锘縰sing UnityEngine;
+using System.Collections;
+
+public class Constants
+{
+    public static readonly string baseURL =
+#if UNITY_ANDROID
+    "jar:file://" + Application.dataPath + "!/assets/";
+#elif UNITY_IPHONE
+    Application.dataPath + "/Raw/";
+#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
+    "file://" + Application.dataPath + "/StreamingAssets/";
+#else
+        string.Empty;
+#endif
+
+    public enum E_LoadFrom
+    {
+        Local,
+        AssetBundle,
+    }
+
+    public static readonly Vector3 MainCity_Stage_LeftDown = new Vector3(5, -5.4f, 0);
+    public static readonly Vector3 MainCity_Stage_RightUp = new Vector3(41, 31, 0);
+
+    public const float GRAVITY_RATE = 10f;   //涓轰簡鏄撲簬璁$畻锛屼篃濂界悊瑙o紝瀹氫箟涓�10
+
+    public const char STR_TAB = '\t';
+
+    public static E_LoadFrom LoadFromType = E_LoadFrom.Local;
+
+    public const int PriorityStand = 51;
+    public const int PriorityMove = 50;
+
+    public const float F_BETA = 0.01f;
+    public const float F_GAMMA = 0.001f;
+    public const float F_DELTA = 0.0001f;
+    public const float F_EPSILON = 0.00001f;
+
+    //鏈嶅姟绔殑澶ф暟鍊奸�氳繃涓や釜瀛楁琛ㄧず锛屽ぇ鏁板瓧浣嶅崟浣嶄负浜�
+    public const ulong ExpPointValue = 100000000;
+
+    public static readonly Vector3 Special_Hide_Position = new Vector3(10000, -10000, 10000);
+    public readonly static Vector2 DESIGN_RESOLUTION = new Vector2(1334, 750);
+
+    public static int UnUsedRes_Unload_Delay = 300;
+
+    // public static AnimationCurveConfig deadAniCurve = BuiltInLoader.LoadScriptableObject<AnimationCurveConfig>("Anim_Curve_DeadFly");
+    // public static AnimationCurveConfig hurtAniCurve = BuiltInLoader.LoadScriptableObject<AnimationCurveConfig>("Anim_Curve_HurtFlash");
+    // public static AnimationCurveConfig zoomAniCurve = BuiltInLoader.LoadScriptableObject<AnimationCurveConfig>("Anim_Curve_Zoom");
+    // public static AnimationCurveConfig shakeAniCurve = BuiltInLoader.LoadScriptableObject<AnimationCurveConfig>("Anim_Curve_Shake");
+}
diff --git a/Main/Utility/Constants.cs.meta b/Main/Utility/Constants.cs.meta
new file mode 100644
index 0000000..dcaa0c6
--- /dev/null
+++ b/Main/Utility/Constants.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b9f7af19999139642bd8ad1b05d8745e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Utility/LocalSave.cs b/Main/Utility/LocalSave.cs
deleted file mode 100644
index dc0e396..0000000
--- a/Main/Utility/LocalSave.cs
+++ /dev/null
@@ -1,225 +0,0 @@
-锘�//--------------------------------------------------------
-//    [Author]:                   Wu Xijin
-//    [Date]   :           Sunday, May 08, 2016
-//--------------------------------------------------------
-using UnityEngine;
-using System.Text;
-using System;
-
-
-public static class LocalSave
-{
-
-    public static void DeleteAll()
-    {
-        PlayerPrefs.DeleteAll();
-    }
-
-    public static void DeleteKey(string _key)
-    {
-        PlayerPrefs.DeleteKey(_key);
-    }
-
-    public static bool HasKey(string _key)
-    {
-        return PlayerPrefs.HasKey(_key);
-    }
-
-    public static void SetInt(string key, int value)
-    {
-        PlayerPrefs.SetInt(key, value);
-    }
-
-    public static int GetInt(string key, int _default = 0)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return _default;
-        }
-        else
-        {
-            return PlayerPrefs.GetInt(key);
-        }
-    }
-
-    public static void SetFloat(string key, float value)
-    {
-
-        PlayerPrefs.SetFloat(key, value);
-    }
-
-    public static float GetFloat(string key, float _default = 0f)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return _default;
-        }
-        else
-        {
-            return PlayerPrefs.GetFloat(key);
-        }
-    }
-
-    public static void SetBool(string key, bool value)
-    {
-
-        PlayerPrefs.SetInt(key, value ? 1 : 0);
-    }
-
-    public static bool GetBool(string key, bool _default = false)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return _default;
-        }
-        else
-        {
-            return PlayerPrefs.GetInt(key) == 1;
-        }
-    }
-
-    public static void SetString(string key, string value)
-    {
-
-        PlayerPrefs.SetString(key, value);
-    }
-
-    public static string GetString(string key)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return string.Empty;
-        }
-        else
-        {
-            return PlayerPrefs.GetString(key);
-        }
-    }
-
-    public static void SetVector3(string key, Vector3 value)
-    {
-        var sb = new StringBuilder();
-        sb.Append(value.x);
-        sb.Append(";");
-        sb.Append(value.y);
-        sb.Append(";");
-        sb.Append(value.z);
-
-        PlayerPrefs.SetString(key, sb.ToString());
-    }
-
-    public static Vector3 GetVector3(string key)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return Vector3.zero;
-        }
-        else
-        {
-            var v = new Vector3();
-            var strArray = PlayerPrefs.GetString(key).Split(';');
-            v.x = float.Parse(strArray[0]);
-            v.y = float.Parse(strArray[2]);
-            v.z = float.Parse(strArray[4]);
-
-            return v;
-        }
-    }
-
-    public static void SetIntArray(string key, int[] value)
-    {
-        if (value != null && value.Length > 0)
-        {
-            var sb = new StringBuilder();
-            for (var i = 0; i < value.Length; i++)
-            {
-                sb.Append(value[i]);
-                sb.Append(';');
-            }
-
-            sb.Remove(sb.Length - 1, 1);
-            PlayerPrefs.SetString(key, sb.ToString());
-        }
-        else
-        {
-            PlayerPrefs.DeleteKey(key);
-        }
-    }
-
-    public static int[] GetIntArray(string key)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return null;
-        }
-        else
-        {
-            var value = PlayerPrefs.GetString(key);
-
-            var strArray = value.Split(';');
-            var intArray = new int[strArray.Length];
-            for (var i = 0; i < strArray.Length; i++)
-            {
-                int.TryParse(strArray[i], out intArray[i]);
-            }
-
-            return intArray;
-        }
-    }
-
-    public static void SetFloatArray(string key, float[] value)
-    {
-        var sb = new StringBuilder();
-        for (var i = 0; i < value.Length; i++)
-        {
-            sb.Append(value[i]);
-            sb.Append(";");
-        }
-
-        sb.Remove(sb.Length - 1, 1);
-        PlayerPrefs.SetString(key, sb.ToString());
-    }
-
-    public static float[] GetFloatArray(string key)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return null;
-        }
-        else
-        {
-            var value = PlayerPrefs.GetString(key);
-            var strArray = value.Split(';');
-            var array = new float[strArray.Length];
-            for (var i = 0; i < strArray.Length; i++)
-            {
-                float.TryParse(strArray[i], out array[i]);
-            }
-
-            return array;
-        }
-
-    }
-
-    public static void SetStringArray(string key, string[] value)
-    {
-        var valueGroup = string.Join(";", value);
-        PlayerPrefs.SetString(key, valueGroup);
-    }
-
-    public static string[] GeStringArray(string key)
-    {
-        if (!PlayerPrefs.HasKey(key))
-        {
-            return null;
-        }
-        else
-        {
-            var value = PlayerPrefs.GetString(key);
-            return value.Split(';');
-        }
-    }
-}
-
-
-
diff --git a/Main/Utility/LocalSave.cs.meta b/Main/Utility/LocalSave.cs.meta
deleted file mode 100644
index 4cac676..0000000
--- a/Main/Utility/LocalSave.cs.meta
+++ /dev/null
@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: bec7a4c05d7689a41ac542acb6406b34
-timeCreated: 1500865329
-licenseType: Free
-MonoImporter:
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 
diff --git a/Main/Utility/RunTimeABLoadLog.cs b/Main/Utility/RunTimeABLoadLog.cs
new file mode 100644
index 0000000..a6c033d
--- /dev/null
+++ b/Main/Utility/RunTimeABLoadLog.cs
@@ -0,0 +1,28 @@
+锘�#if UNITY_EDITOR
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using System.IO;
+using UnityEditor;
+
+public class RunTimeABLoadLog
+{
+    static List<string> assetBundleLoadLogs = new List<string>();
+
+    public static void AddLog(string _abName, string _asset, string _scene)
+    {
+        var log = StringUtility.Contact(_scene, "\t", _abName, "\t", _asset, "\t", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
+        assetBundleLoadLogs.Add(log);
+    }
+
+    [MenuItem("绋嬪簭/鎵撳嵃璧勬簮鍖呭姞杞芥棩蹇�")]
+    public static void Print()
+    {
+        var tile = StringUtility.Contact("鍦烘櫙鍚�", "\t", "璧勬簮鍖呭悕", "\t", "璧勬簮鍚�", "\t", "鏃堕棿");
+        assetBundleLoadLogs.Insert(0, tile);
+        File.WriteAllLines(Application.dataPath + "/RunTimeABLoadLog.txt", assetBundleLoadLogs.ToArray());
+    }
+
+}
+#endif
diff --git a/Main/Utility/RunTimeABLoadLog.cs.meta b/Main/Utility/RunTimeABLoadLog.cs.meta
new file mode 100644
index 0000000..6b6f99b
--- /dev/null
+++ b/Main/Utility/RunTimeABLoadLog.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9dd6297f319b62741b366e4d75586fa7
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Utility/RunTimeExceptionUtility.cs b/Main/Utility/RunTimeExceptionUtility.cs
new file mode 100644
index 0000000..c83d552
--- /dev/null
+++ b/Main/Utility/RunTimeExceptionUtility.cs
@@ -0,0 +1,76 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using System.IO;
+using System.Threading;
+
+
+public class RunTimeExceptionUtility : Singleton<RunTimeExceptionUtility>
+
+{
+
+    List<string> logWriteToFileTemp = new List<string>();
+    DateTime nextWriteFileTime = DateTime.Now;
+    string logFileRoot = string.Empty;
+
+    public void Init()
+    {
+        GlobalTimeEvent.Instance.secondEvent -= OnPerSecond;
+        Application.logMessageReceivedThreaded -= AddLogRenderer;
+
+        if (!DebugUtility.Instance.debugAccount)
+        {
+            return;
+        }
+
+        if (Application.platform == RuntimePlatform.Android)
+        {
+            logFileRoot = Path.GetDirectoryName(Application.persistentDataPath);
+        }
+        else if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.OSXEditor)
+        {
+            logFileRoot = Path.GetDirectoryName(Application.dataPath) + "/RunTimeLog";
+        }
+        else
+        {
+            return;
+        }
+
+        nextWriteFileTime = DateTime.Now + new TimeSpan(300 * TimeSpan.TicksPerSecond);
+
+        GlobalTimeEvent.Instance.secondEvent += OnPerSecond;
+        Application.logMessageReceivedThreaded += AddLogRenderer;
+    }
+
+    public void UnInit()
+    {
+        GlobalTimeEvent.Instance.secondEvent -= OnPerSecond;
+        Application.logMessageReceivedThreaded -= AddLogRenderer;
+    }
+
+    private void AddLogRenderer(string _log, string _callStack, LogType _type)
+    {
+        logWriteToFileTemp.Add(string.Format("{0}--{1}:Thread:{2}-{3};{4}{5}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), _type, Thread.CurrentThread.ManagedThreadId, _log, _callStack, "\r\n"));
+    }
+
+    private void OnPerSecond()
+    {
+        if (DateTime.Now > nextWriteFileTime)
+        {
+            nextWriteFileTime = DateTime.Now + new TimeSpan(300 * TimeSpan.TicksPerSecond);
+            if (logWriteToFileTemp.Count > 0)
+            {
+                if (!Directory.Exists(logFileRoot))
+                {
+                    Directory.CreateDirectory(logFileRoot);
+                }
+                var path = logFileRoot + "/" + "RunTimeLog_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm") + ".txt";
+                File.WriteAllLines(path, logWriteToFileTemp.ToArray());
+                logWriteToFileTemp.Clear();
+            }
+        }
+    }
+
+
+}
diff --git a/Main/Utility/RunTimeExceptionUtility.cs.meta b/Main/Utility/RunTimeExceptionUtility.cs.meta
new file mode 100644
index 0000000..20efcba
--- /dev/null
+++ b/Main/Utility/RunTimeExceptionUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d96e3cb32993ff44cb7886b656d10da2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Utility/TimeUtility.cs b/Main/Utility/TimeUtility.cs
new file mode 100644
index 0000000..22333df
--- /dev/null
+++ b/Main/Utility/TimeUtility.cs
@@ -0,0 +1,442 @@
+锘縰sing System;
+using System.Text;
+using UnityEngine;
+
+public static class TimeUtility
+{
+    private static DateTime s_ServerTime = DateTime.Now;
+
+    private static float _checkTime = 0;
+    /// <summary>
+    /// 褰撳墠鏈嶅姟鍣ㄦ椂闂�
+    /// </summary>
+    public static DateTime ServerNow
+    {
+        get
+        {
+            float tick = Time.realtimeSinceStartup - _checkTime;
+            DateTime real = s_ServerTime.AddSeconds(tick);
+            return real;
+        }
+        private set
+        {
+            s_ServerTime = value;
+        }
+    }
+
+    ////A0 04 鍚屾瀹㈡埛绔椂闂� #tagServerDateTime 涓殑 CrossServerTime 涓虹帺瀹跺湪瀛愭湇涓敹鍒扮殑璺ㄦ湇鏃堕棿
+    //CrossServerNow涓虹帺瀹剁櫥褰曞湪璺ㄦ湇鏈嶅姟鍣ㄩ噷鐨勯�氱煡鏃堕棿, 涓嶪LTimeUtility.ServerCrossNow锛堢帺瀹跺湪瀛愭湇鏀跺埌璺ㄦ湇鐨勬椂闂撮�氱煡锛変笉鍚�
+    static DateTime s_CrossServerTime = DateTime.Now;
+    static float _crossCheckTime = 0;
+    public static DateTime CrossServerNow
+    {
+        get
+        {
+            float tick = Time.realtimeSinceStartup - _crossCheckTime;
+            DateTime real = s_CrossServerTime.AddSeconds(tick);
+            return real;
+        }
+        private set { s_CrossServerTime = value; }
+    }
+
+    /// <summary>
+    /// 骞翠唤
+    /// </summary>
+    public static int Year
+    {
+        get { return ServerNow.Year; }
+    }
+    /// <summary>
+    /// 鏈堜唤
+    /// </summary>
+    public static int Month
+    {
+        get { return ServerNow.Month; }
+    }
+    /// <summary>
+    /// 澶�
+    /// </summary>
+    public static int Day
+    {
+        get { return ServerNow.Day; }
+    }
+    /// <summary>
+    /// 灏忔椂
+    /// </summary>
+    public static int Hour
+    {
+        get { return ServerNow.Hour; }
+    }
+    /// <summary>
+    /// 鍒嗛挓
+    /// </summary>
+    public static int Minute
+    {
+        get { return ServerNow.Minute; }
+    }
+    /// <summary>
+    /// 绉�
+    /// </summary>
+    public static int Second
+    {
+        get { return ServerNow.Second; }
+    }
+
+    // 椋庨櫓鐐�1 System.TimeZone.CurrentTimeZone.ToLocalTime 涓烘湰鏈�, ServerNow涓烘湇鍔″櫒,濡傛灉涓嶅瓨鍦ㄥ悓涓�涓椂鍖轰細閫犳垚鏃堕棿宸�
+    // 椋庨櫓鐐�2 OriginalTime鍥哄畾鍐欐涓浗鏃跺尯,鍙牴鎹畊tc璁$畻鍑烘椂鍖�,鏂逛究娴峰鍚勪釜鐗堟湰浣跨敤
+    /// <summary>
+    /// 鏈嶅姟鍣ㄨ捣濮嬫椂闂�
+    /// </summary>
+    public static readonly DateTime OriginalTime = new DateTime(1970, 1, 1, 8, 0, 0);
+    public static readonly DateTime ClientOriginalTime = new DateTime(1, 1, 1, 0, 0, 0);
+    /// <summary>
+    /// 鏈嶅姟鍣ㄦ椂闂寸浉姣旇捣濮嬫椂闂寸殑绉掓暟(涓昏鏂逛究姣旇緝)
+    /// </summary>
+    public static int AllSeconds
+    {
+        get
+        {
+            TimeSpan t = ServerNow - OriginalTime;
+            return (int)t.TotalSeconds;
+        }
+    }
+
+    //1骞翠腑鐨勭鍑犲懆锛屼互鏈嶅姟绔负鍑嗭紝python鍜宑#绠楀嚭鏉ヤ笉涓�鏍�
+    public static int WeekOfYear
+    {
+        get; private set;
+    }
+    //寮�鏈嶇鍑犲ぉ 浠�0寮�濮� 
+    public static int OpenDay
+    {
+        get; private set;
+    }
+
+    public static bool IsMixServer
+    {
+        get; private set;
+    }
+
+    public static int MixOpenDay
+    {
+        get; private set;
+    }
+
+    public static DayOfWeek openServerDayOfWeek;
+
+    public static int OpenWeekCnt
+    {
+        get
+        {
+            var _openDay = ServerNow.AddDays(-OpenDay);
+            var _opendayOfWeek = _openDay.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)_openDay.DayOfWeek;
+            _openDay = _openDay.AddDays(7 - _opendayOfWeek + 1);
+            var _openTime = new DateTime(_openDay.Year, _openDay.Month, _openDay.Day, 0, 0, 0);
+            var _total = Mathf.Max(0, (float)ServerNow.Subtract(_openTime).TotalDays);
+            return Mathf.CeilToInt((float)_total / 7);
+        }
+    }
+
+    static StringBuilder stringBuilder = new StringBuilder();
+
+    public static DateTime createRoleTime { get; private set; }
+    private static DateTime createRoleTimeTail = DateTime.Now;
+
+    //浠�1寮�濮�
+    public static int CreateDays
+    {
+        get
+        {
+            return Mathf.CeilToInt((float)(ServerNow - createRoleTimeTail).TotalDays);
+        }
+    }
+
+    public static int CreateSeconds
+    {
+        get
+        {
+            return (int)(createRoleTime - OriginalTime).TotalSeconds;
+        }
+    }
+
+    public static event Action OnCreateRoleTimeRefresh;
+    // public static void OnRefreshCreateRoleTime(HA124_tagMCPlayerInfo _package)
+    // {
+    //     if (_package.socketType == ServerType.CrossSever)
+    //     {
+    //         return;
+    //     }
+
+    //     createRoleTime = Convert.ToDateTime(UIHelper.GetTime(_package.CreateRoleTime));
+    //     createRoleTimeTail = new DateTime(createRoleTime.Year, createRoleTime.Month, createRoleTime.Day);
+    //     if (OnCreateRoleTimeRefresh != null)
+    //     {
+    //         OnCreateRoleTimeRefresh();
+    //     }
+    //     DebugEx.LogFormat("CreateRoleTime {0}  CreateDays {1}", createRoleTimeTail, CreateDays);
+    // }
+
+    public static event Action OnServerTimeRefresh;
+    // public static void OnRefreshServerTime(HA004_tagServerDateTime vNetData)
+    // {
+    //     var dateTime = new DateTime(vNetData.Year, vNetData.Month, vNetData.Day, vNetData.Hour, vNetData.Minute, vNetData.Second);
+    //     if (vNetData.socketType == ServerType.CrossSever)
+    //     {
+    //         s_CrossServerTime = dateTime;
+    //         _crossCheckTime = Time.realtimeSinceStartup;
+    //     }
+    //     else
+    //     {
+    //         s_ServerTime = dateTime;
+    //         _checkTime = Time.realtimeSinceStartup;
+    //         if (OnServerTimeRefresh != null)
+    //         {
+    //             OnServerTimeRefresh();
+    //         }
+    //     }
+
+    //     TimeDownMgr.Instance.Begin(TimeDownMgr.CoolTimeType.SyncServerTime, 60, (float tick) =>
+    //     {
+    //         SyncServerTime();
+    //     }, 60);
+    // }
+
+    public static event Action OnServerOpenDayRefresh;
+    // public static void OnRefreshServerOpenDay(HA005_tagOpenServerDay package)
+    // {
+    //     if (package.socketType != ServerType.CrossSever)
+    //     {
+    //         OpenDay = package.Day;
+    //         IsMixServer = package.IsMixServer == 1;
+    //         MixOpenDay = package.MixDay;
+    //         openServerDayOfWeek = package.OpenWeekday == 7 ? DayOfWeek.Sunday : (DayOfWeek)package.OpenWeekday;
+    //         WeekOfYear = package.WeekOfYear;
+    //     }
+
+    //     OnRefreshServerTime(new HA004_tagServerDateTime()
+    //     {
+    //         Year = package.NowYear,
+    //         Month = package.NowMonth,
+    //         Day = package.NowDay,
+    //         Hour = package.NowHour,
+    //         Minute = package.NowMinute,
+    //         Second = package.NowSecond,
+    //         MicSecond = package.NowMicSecond,
+    //         socketType = package.socketType,
+    //     });
+
+
+    //     if (package.socketType != ServerType.CrossSever
+    //         && OnServerOpenDayRefresh != null)
+    //     {
+    //         OnServerOpenDayRefresh();
+    //     }
+    // }
+
+    // public static void SyncServerTime()
+    // {
+    //     CA002_tagClientRequestServerTime pak = new CA002_tagClientRequestServerTime();
+    //     GameNetSystem.Instance.SendInfo(pak);
+    //     if (GameNetSystem.Instance.crossServerSocketConnected)
+    //     {
+    //         GameNetSystem.Instance.SendToCrossServer(pak);
+    //     }
+    // }
+    /// <summary>
+    /// 鏍规嵁鏈嶅姟鍣ㄤ笅鍙戠殑绉掓暟鑾峰彇鏃堕棿
+    /// </summary>
+    /// <param name="seconds"></param>
+    /// <returns></returns>
+    public static DateTime GetTime(uint seconds)
+    {
+        DateTime d = OriginalTime.AddTicks(seconds * TimeSpan.TicksPerSecond);
+        return d;
+    }
+
+    //鏃讹細鍒嗭細绉�
+    //渚嬪瓙
+    //xx:xx:xx
+    public static string SecondsToHMS(int _seconds)
+    {
+        int hours = _seconds / 3600;
+        int mins = _seconds % 3600 / 60;
+        int seconds = _seconds % 60;
+        return StringUtility.Contact(hours.ToString("D2"), ":", mins.ToString("D2"), ":", seconds.ToString("D2"));
+    }
+
+    //渚嬪瓙锛涘垎锛氱
+    //xx:xx
+    public static string SecondsToMS(int _seconds)
+    {
+        int mins = _seconds % 3600 / 60;
+        int seconds = _seconds % 60;
+        return StringUtility.Contact(mins.ToString("D2"), ":", seconds.ToString("D2"));
+    }
+
+    //渚嬪瓙锛涗笉瓒崇殑涓嶆樉绀� 濡�0澶�0:xx:xx:,鏄剧ず涓簒x:xx
+    //x澶﹛x:xx:xx绉�
+    public static string SecondsToDHMSCHS(int _seconds)
+    {
+        int days = _seconds / 86400;
+        int hours = _seconds % 86400 / 3600;
+        int mins = _seconds % 3600 / 60;
+        int seconds = _seconds % 60;
+        return StringUtility.Contact(days > 0 ? days.ToString() : string.Empty,
+            days > 0 ? Language.Get("L1074") + " " : string.Empty, hours > 0 ? hours.ToString() : string.Empty,
+            hours > 0 ? ":" : string.Empty, mins >= 0 ? mins.ToString("D2") : string.Empty,
+            mins >= 0 ? ":" : string.Empty, seconds >= 0 ? seconds.ToString("D2") : string.Empty,
+            seconds >= 0 ? string.Empty : string.Empty);
+    }
+
+
+    //渚嬪瓙
+    //x澶�
+    //x鏃�
+    //x鍒� 鏈�灏�1鍒�
+    public static string SecondsToTitleDHMS(int _seconds)
+    {
+        int days = _seconds / 86400;
+        if (days > 0)
+        {
+            return StringUtility.Contact(days, Language.Get("L1074"));
+        }
+        int hours = _seconds % 86400 / 3600;
+        if (hours > 0)
+        {
+            return StringUtility.Contact(hours, Language.Get("Hour"));
+        }
+        int mins = Mathf.CeilToInt(_seconds % 3600 / 60.0f);
+        if (mins > 0)
+        {
+            return StringUtility.Contact(mins, Language.Get("Minute"));
+        }
+        return StringUtility.Contact(1, Language.Get("Minute"));
+    }
+
+
+    //渚嬪瓙锛�
+    //xx:xx:xx
+    public static string SecondsToHMSCHSRetain(int _seconds, bool _hour = true, bool _min = true, bool _sec = true)
+    {
+        stringBuilder.Length = 0;
+        int hours = _seconds / 3600;
+        int mins = _seconds % 3600 / 60;
+        int seconds = _seconds % 60;
+        if (hours > 0 || _hour)
+        {
+            stringBuilder.Append(hours);
+            stringBuilder.Append(":");
+        }
+        if (mins > 0 || _min)
+        {
+            stringBuilder.Append(mins);
+            stringBuilder.Append(":");
+        }
+        if (seconds > 0 || _sec)
+        {
+            stringBuilder.Append(seconds);
+            //stringBuilder.Append(":");
+        }
+        return stringBuilder.ToString();
+    }
+
+    //渚嬪瓙
+    //澶т簬1澶╃殑鏄剧ず锛歺澶﹛x:xx:xx
+    //xx:xx:xx
+    public static string SecondsToDHMS(int _seconds)
+    {
+        int days = _seconds / 86400;
+        int hours = _seconds % 86400 / 3600;
+        int mins = _seconds % 3600 / 60;
+        int seconds = _seconds % 60;
+        if (days > 0)
+        {
+            return StringUtility.Contact(days, Language.Get("L1074"), " ", hours.ToString("D2"), ":", mins.ToString("D2"), ":", seconds.ToString("D2"));
+        }
+        return StringUtility.Contact(hours.ToString("D2"), ":", mins.ToString("D2"), ":", seconds.ToString("D2"));
+    }
+
+    //渚嬪瓙
+    //x澶�
+    //x鏃�
+    //x鍒唜绉�
+    //x绉�
+    public static string SecondsToConsumeRebate(int _seconds)
+    {
+        float days = (float)_seconds / 86400;
+        float hours = (float)_seconds % 86400 / 3600;
+        int mins = _seconds % 3600 / 60;
+        float seconds = (float)_seconds % 60;
+        if (days >= 1)
+        {
+            return StringUtility.Contact(Mathf.CeilToInt(days), Language.Get("L1074"));
+        }
+        else if (hours >= 1)
+        {
+            return StringUtility.Contact(Mathf.CeilToInt(hours), Language.Get("Hour"));
+        }
+        else if (mins >= 1)
+        {
+            return StringUtility.Contact(mins, Language.Get("Minute"), seconds, Language.Get("RealmWin_Bewrite_35"));
+        }
+        else
+        {
+            return StringUtility.Contact(seconds, Language.Get("RealmWin_Bewrite_35"));
+        }
+    }
+
+    /// <summary>
+    /// 鑾峰彇涓�澶╃殑0鐐规椂闂�
+    /// </summary>
+    /// <param name="now"></param>
+    /// <returns></returns>
+    public static DateTime GetDayStartTime(int year, int month, int day)
+    {
+        return new DateTime(year, month, day);
+    }
+
+    /// <summary>
+    /// 鑾峰彇褰撳ぉ鐨�0鐐规椂闂�
+    /// </summary>
+    /// <returns></returns>
+    public static DateTime GetTodayStartTime()
+    {
+        var now = ServerNow;
+        return new DateTime(now.Year, now.Month, now.Day);
+    }
+
+    /// <summary>
+    /// 鑾峰彇涓嬩竴涓噷鏅�5鐐圭殑鏃堕棿
+    /// </summary>
+    /// <returns></returns>
+    public static DateTime GetNext5Time()
+    {
+        var now = ServerNow;
+        if (now.Hour < 5)
+        {
+            return new DateTime(now.Year, now.Month, now.Day, 5, 0, 0);
+        }
+        return new DateTime(now.Year, now.Month, now.Day, 5, 0, 0).AddDays(1);
+
+    }
+
+    //寮�鏈嶅ぉ缁撴潫鍊掕鏃讹紱鍗曚綅绉�
+    public static int GetRemindTimeByOpenDay(int days)
+    {
+        if (days <= OpenDay)
+            return 0;
+
+        return (days - OpenDay) * 86400 - (int)(ServerNow - GetTodayStartTime()).TotalSeconds;
+
+    }
+
+    //鑾峰緱宸茶繃浜嗗灏戝ぉ锛�0鐐硅繃澶╂暣鏁帮紝绗竴澶╀负0锛�
+    // seconds 涓烘椂闂存埑
+    public static int GetPassDays(int seconds)
+    {
+        DateTime d = OriginalTime.AddTicks(seconds * TimeSpan.TicksPerSecond);
+        DateTime startTime = new DateTime(d.Year, d.Month, d.Day);
+
+        return (ServerNow - startTime).Days;
+    }
+}
diff --git a/Main/Utility/TimeUtility.cs.meta b/Main/Utility/TimeUtility.cs.meta
new file mode 100644
index 0000000..e18b4e0
--- /dev/null
+++ b/Main/Utility/TimeUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 857cbc2eea83bf545b45ecaea843ee74
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Utility/UIHelper.cs b/Main/Utility/UIHelper.cs
new file mode 100644
index 0000000..064aa5e
--- /dev/null
+++ b/Main/Utility/UIHelper.cs
@@ -0,0 +1,1320 @@
+锘縰sing System;
+using System.Text;
+using UnityEngine;
+using System.Linq;
+using System.Xml.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine.UI;
+
+using System.Text.RegularExpressions;
+using System.IO;
+using LitJson;
+
+/// <summary>
+/// UI杈呭姪绫�
+/// </summary>
+
+public static class UIHelper
+{
+
+    public static readonly string no_breaking_space = "\u00A0"; //Text鏂囨湰妗嗚緭鍏ョ┖鏍艰嚜鍔ㄦ崲琛岄棶棰� 鏇挎崲缂栫爜
+
+
+    //涓嶉渶瑕佹彁鍙栫炕璇戠殑鏂囨湰
+    private static readonly string[] numbers = new string[] { "闆�", "涓�", "浜�", "涓�", "鍥�", "浜�", "鍏�", "涓�", "鍏�", "涔�" };
+    private static readonly string[] units = new string[] { "鍗�", "鐧�", "鍗�", "涓�" };
+
+    //鏁板瓧杞腑鏂�(鍙仛灏忔暟瀛�)锛屾捣澶栫増鏈皟鐢ㄦ敼鍑芥暟鍒囨崲鐗堟湰璇风洿鎺ヨ繑鍥炴暟瀛�
+    public static string ChineseNumber(int number)
+    {
+        if (number == 0)
+            return numbers[0];
+
+        string result = "";
+        int unitPlace = 1; // 浣嶆暟锛�1 琛ㄧず鍗佷綅锛�2 琛ㄧず鐧句綅锛�3 琛ㄧず鍗冧綅锛�4 琛ㄧず涓囦綅
+        bool needZero = false; // 鏄惁闇�瑕佹坊鍔� '闆�'
+
+        while (number > 0)
+        {
+            int part = number % 10;
+            if (part != 0)
+            {
+                if (needZero)
+                    result = StringUtility.Contact(numbers[0] + result);
+
+                result = numbers[part] + (unitPlace == 1 ? "" : units[unitPlace - 2]) + result; // 鍗曚綅鍙湪鍗併�佺櫨銆佸崈銆佷竾鍐呴儴浣跨敤
+                needZero = false;
+            }
+            else
+            {
+                needZero = true;
+            }
+
+            number /= 10;
+            unitPlace++;
+        }
+        if (result.StartsWith("涓�鍗�"))
+        {
+            result = result.Substring(1);
+        }
+        if (result.EndsWith("闆�"))
+        {
+            result = result.Replace("闆�", "");
+        }
+
+        return result;
+    }
+
+
+    #region UI閫氱敤
+    public static void SetIconWithMoneyType(this Image _image, int moneyType)
+    {
+        if (_image == null) return;
+        string iconKey = StringUtility.Contact("Money_Type_", moneyType);
+        _image.SetSprite(iconKey);
+    }
+
+    public static void SetSmallIconWithMoneyType(this Image _image, int moneyType)
+    {
+        if (_image == null) return;
+        string iconKey = StringUtility.Contact("SmallMoney", moneyType);
+        _image.SetSprite(iconKey);
+    }
+
+    /// <summary>
+    /// 鍒嗙瀛楃涓叉彃鍏ョ┖鏍�
+    /// </summary>
+    public static string GetSuitNameByName(string attrName)
+    {
+        string suitStr = "";
+        for (int i = 0; i < attrName.Length; i++)
+        {
+            if (i != attrName.Length - 1)
+            {
+                if (attrName.Length == 2)
+                {
+                    suitStr = StringUtility.Contact(suitStr, attrName[i], "        ");
+                }
+                else if (attrName.Length == 3)
+                {
+                    suitStr = StringUtility.Contact(suitStr, attrName[i], "  ");
+                }
+                else
+                {
+                    suitStr = StringUtility.Contact(suitStr, attrName[i]);
+                }
+            }
+            else
+            {
+                suitStr = StringUtility.Contact(suitStr, attrName[i]);
+            }
+        }
+        return suitStr;
+
+    }
+
+    // 鍩轰簬itemColor 涓嬶紝ColorEx鍋氫簩绾у尯鍒�
+    public static void SetItemBackGround(this Image _image, int itemColor, int ColorEx = 0)
+    {
+        if (_image == null)
+        {
+            return;
+        }
+        _image.SetSprite(string.Format("Common_Public_ItemColor{0}{1}", itemColor, ColorEx));
+    }
+    /// <summary>
+    /// 鍓╀綑鏃堕棿
+    /// </summary>
+    /// <param name="startTime">鏍煎紡 骞�-鏈�-鏃� 灏忔椂:鍒嗛挓:绉�</param>
+    /// <param name="ownTime">姣</param>
+    /// <returns></returns>
+    private static Regex TimeRegex = new Regex(@"([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)", RegexOptions.Singleline);
+    public static int GetSurplusSeconds(string startTime, int seconds)
+    {
+        string start = GetTime(startTime);
+        if (start.Equals(string.Empty))
+        {
+            return 0;
+        }
+        DateTime s = Convert.ToDateTime(start);
+        DateTime t = s.AddTicks(seconds * TimeSpan.TicksPerSecond);
+        DateTime n = TimeUtility.ServerNow;
+        TimeSpan span = t - n;
+        return Mathf.Max(0, (int)span.TotalSeconds);
+    }
+
+    public static string GetTime(string startTime)
+    {
+        if (!TimeRegex.IsMatch(startTime))
+        {
+            return string.Empty;
+        }
+        Match match = TimeRegex.Match(startTime);
+        int year = int.Parse(match.Groups[1].Value);
+        int month = int.Parse(match.Groups[2].Value);
+        int day = int.Parse(match.Groups[3].Value);
+        int h = int.Parse(match.Groups[4].Value);
+        int mi = int.Parse(match.Groups[5].Value);
+        int sc = int.Parse(match.Groups[6].Value);
+
+        return string.Format("{0}-{1}-{2} {3}:{4}:{5}", year, month, day, h, mi, sc);
+
+    }
+    /// <summary>
+    /// 鑾峰彇娑堥�濈殑鏃堕棿
+    /// </summary>
+    /// <param name="lastTime"></param>
+    /// <returns></returns>
+    public static string GetFadeTime(uint lastTime)
+    {
+        DateTime n = TimeUtility.ServerNow;
+        TimeSpan span = n - TimeUtility.GetTime(lastTime);
+        if (span.TotalDays > 1) return Math.Floor(span.TotalDays) + Language.Get("L1074");
+        else if (span.TotalHours > 1) return Math.Floor(span.TotalHours) + Language.Get("L1072");
+        else if (span.TotalMinutes > 1) return Math.Floor(span.TotalMinutes) + Language.Get("L1073");
+        else return 1 + Language.Get("L1073");
+    }
+    /// <summary>
+    /// 鏍规嵁灞炴�ц幏鍙栫帺瀹舵暟鎹�
+    /// </summary>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static ulong GetPropertyValue(PropertyType type)
+    {
+        switch (type)
+        {
+            case PropertyType.LV:
+                return PlayerDatas.Instance.baseData.LV;
+            case PropertyType.POWER:
+                return (ulong)PlayerDatas.Instance.baseData.STR;
+            case PropertyType.AGILITY:
+                return (ulong)PlayerDatas.Instance.baseData.PHY;
+            case PropertyType.PHYSIQUE:
+                return (ulong)PlayerDatas.Instance.baseData.CON;
+            case PropertyType.MENTALITY:
+                return (ulong)PlayerDatas.Instance.baseData.PNE;
+            case PropertyType.HP:
+                return PlayerDatas.Instance.extersion.MaxHP;
+            case PropertyType.ATK:
+                return (ulong)PlayerDatas.Instance.extersion.MAXATK;
+            case PropertyType.DEF:
+                return (ulong)PlayerDatas.Instance.extersion.DEF;
+            case PropertyType.HIT:
+                return (ulong)PlayerDatas.Instance.extersion.HIT;
+            case PropertyType.MISS:
+                return (ulong)PlayerDatas.Instance.extersion.Miss;
+            case PropertyType.ATKSPEED:
+                return (ulong)PlayerDatas.Instance.extersion.battleValEx1;
+            case PropertyType.CritChance:
+                return (ulong)PlayerDatas.Instance.extersion.SuperHitRate;
+            case PropertyType.CritHurt:
+                return (ulong)PlayerDatas.Instance.extersion.SuperHit;
+            case PropertyType.CritResis:
+                return (ulong)PlayerDatas.Instance.extersion.SuperHitReduce;
+            case PropertyType.HeartHit:
+                return (ulong)PlayerDatas.Instance.extersion.luckHitRate;
+            case PropertyType.HeartHurt:
+                return (ulong)PlayerDatas.Instance.extersion.luckHitVal;
+            case PropertyType.HeartResis:
+                return (ulong)PlayerDatas.Instance.extersion.LuckyHitRateReduce;
+            case PropertyType.SkillHurt:
+                return (ulong)PlayerDatas.Instance.extersion.SkillAtkRate;
+            case PropertyType.PVPAddHurt:
+                return (ulong)PlayerDatas.Instance.extersion.DamagePVP;
+            case PropertyType.PVPReduceHurt:
+                return PlayerDatas.Instance.GetPlayerDataByType((PlayerDataType)191);
+            case PropertyType.LifeReply:
+                return (ulong)PlayerDatas.Instance.extersion.HPRestorePer;
+            case PropertyType.HurtReflect:
+                return (ulong)PlayerDatas.Instance.extersion.DamageBackRate;
+            case PropertyType.MoveSpeed:
+                return (ulong)PlayerDatas.Instance.extersion.SpeedValue;
+            case PropertyType.PetAddHurt:
+                return (ulong)PlayerDatas.Instance.extersion.PetDamPer;
+            case PropertyType.RealHurt:
+                return (ulong)PlayerDatas.Instance.extersion.realATK;
+            case PropertyType.RealResis:
+                return (ulong)PlayerDatas.Instance.extersion.realDEF;
+            case PropertyType.DefyDef:
+                return (ulong)PlayerDatas.Instance.extersion.IgnoreDefRate;
+            case PropertyType.DefyDefResis:
+                return (ulong)PlayerDatas.Instance.extersion.IgnoreDefRateReduce;
+            case PropertyType.DefChance:
+                return (ulong)PlayerDatas.Instance.extersion.DamChanceDef;
+            case PropertyType.BloodHurt:
+                return (ulong)PlayerDatas.Instance.extersion.BleedDamage;
+            case PropertyType.AktReplyBlood:
+                return (ulong)PlayerDatas.Instance.extersion.BattleValEx2;
+            case PropertyType.Stun:
+                return (ulong)PlayerDatas.Instance.extersion.FaintRate;
+            case PropertyType.CtrlResis:
+                return (ulong)PlayerDatas.Instance.extersion.FaintDefRate;
+            case PropertyType.AddFinalHurt:
+                return (ulong)PlayerDatas.Instance.extersion.FinalHurt;
+            case PropertyType.ReduceFinalHurt:
+                return (ulong)PlayerDatas.Instance.extersion.FinalHurtReduce;
+            case PropertyType.PVPAddHurtPer:
+                return (ulong)PlayerDatas.Instance.extersion.DamagePerPVP;
+            case PropertyType.PVPReduceHurtPer:
+                return (ulong)PlayerDatas.Instance.extersion.DamagePerPVPReduce;
+            case PropertyType.DleHitChance:
+                return (ulong)PlayerDatas.Instance.extersion.ComboDamPerRate;
+            case PropertyType.DleHurt:
+                return (ulong)PlayerDatas.Instance.extersion.ComboDamPer;
+            case PropertyType.ReduceSkillHurtPercent:
+                return (ulong)PlayerDatas.Instance.extersion.skillAtkRateReduce;
+            case PropertyType.NpcHurtAddPer:
+                return (ulong)PlayerDatas.Instance.extersion.NpcHurtAddPer;
+            case PropertyType.Luck:
+                return (ulong)PlayerDatas.Instance.extersion.luckValue;
+            case PropertyType.Mater:
+                return (ulong)PlayerDatas.Instance.baseData.mater;
+            case PropertyType.Wood:
+                return (ulong)PlayerDatas.Instance.baseData.wood;
+            case PropertyType.Water:
+                return (ulong)PlayerDatas.Instance.baseData.water;
+            case PropertyType.Fire:
+                return (ulong)PlayerDatas.Instance.baseData.fire;
+            case PropertyType.Earth:
+                return (ulong)PlayerDatas.Instance.baseData.earth;
+            case PropertyType.ReduceCrit:
+                return (ulong)PlayerDatas.Instance.baseData.reduceCrit;
+            case PropertyType.ReduceHeartHurtPer:
+                return (ulong)PlayerDatas.Instance.baseData.reduceHeartHurt;
+            case PropertyType.ReduceFinalHurtPer:
+                return (ulong)PlayerDatas.Instance.baseData.reduceFinalHurt;
+            case PropertyType.AtkPercent:
+            case PropertyType.CritHurtPercent:
+            case PropertyType.DodgePercent:
+                return (ulong)ModelCenter.Instance.GetModel<ReikiRootModel>().GetReikiPropertyValue((int)type);
+
+            case PropertyType.SkillAddPerA:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerA;
+            case PropertyType.SkillAddPerB:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerB;
+            case PropertyType.SkillAddPerC:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerC;
+            case PropertyType.SkillAddPerD:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerD;
+            case PropertyType.SkillAddPerE:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerE;
+            case PropertyType.SkillAddPerF:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerF;
+            case PropertyType.SkillAddPerG:
+                return (ulong)PlayerDatas.Instance.baseData.skillAddPerG;
+            case PropertyType.SkillReducePerA:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerA;
+            case PropertyType.SkillReducePerB:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerB;
+            case PropertyType.SkillReducePerC:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerC;
+            case PropertyType.SkillReducePerD:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerD;
+            case PropertyType.SkillReducePerE:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerE;
+            case PropertyType.SkillReducePerF:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerF;
+            case PropertyType.SkillReducePerG:
+                return (ulong)PlayerDatas.Instance.baseData.skillReducePerG;
+            case PropertyType.ReduceSkillCDPer:
+                return (ulong)PlayerDatas.Instance.extersion.battleValEx3;
+            case PropertyType.AddFinalHurtPer:
+                return (ulong)PlayerDatas.Instance.extersion.FunalHurtPer;
+            case PropertyType.AddNormalHurt:
+                return (ulong)PlayerDatas.Instance.baseData.NormalHurt;
+            case PropertyType.AddNormalHurtPer:
+                return (ulong)PlayerDatas.Instance.baseData.NormalHurtPer;
+            case PropertyType.AddSkillHurt:
+                return (ulong)PlayerDatas.Instance.baseData.FabaoHurt;
+            case PropertyType.AddSkillHurtPer:
+                return (ulong)PlayerDatas.Instance.baseData.FabaoHurtPer;
+            case PropertyType.AddPVEHurt:
+                return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.DamagePVE);
+        }
+        return 0;
+    }
+
+
+    /// <summary>
+    /// 鎹㈣
+    /// </summary>
+    /// <param name="val"></param>
+    /// <returns></returns>
+    private static Regex NewLineRegex = new Regex(@"</r>", RegexOptions.Singleline);
+    public static string ReplaceNewLine(string val)
+    {
+        return val.Replace(@"</r>", "\n");
+    }
+
+    public static double numto2Decimals(double value)
+    {
+        //涓轰粈涔堣value * 1000/10 杩欎箞鍐欙紝鐗规畩鐨勬暟瀛椾細鏈夐棶棰橈紝姣斿36.80000锛屼細(int)(value * 100)琚绠椾负3679
+        //娴嬭瘯涓嬪彧鏈�30鍑犵偣8000鐨勬墠浼氳繖鏍�
+        return (int)(value * 1000 / 10) / 100.00;
+    }
+
+    /// <summary>
+    /// 澶ф暟鍊艰浆鍖� 鏍煎紡 鏈�澶氫袱涓皬鏁�
+    /// K -鍗冿紝M -鐧捐惉锛孊-鍗佸剟锛孴 -钀剟
+    /// 涓嶅洓鑸嶄簲鍏ワ紝涓嶇敤Math.Round锛屽洜涓哄綋鐜╁鍙湁23.3456,浣嗘槸Math.Round浼氭樉绀�23.35, 褰撹喘涔颁环鏍间负23.35鏃舵棤娉曡喘涔扮殑
+    /// </summary>
+    public static string ReplaceLargeNum(double num)
+    {
+        const long K = 10000;    //鍥藉唴涓轰竾锛屾捣澶栦负鍗�
+        const long M = K * 10000;
+        const long B = M * 10000;
+        const long T = B * 10000;
+
+        if (num >= T)
+        {
+            return  StringUtility.Contact(numto2Decimals(num / T).ToString("0.##"), Language.Get("L1070_0"));
+        }
+        else if (num >= B)
+        {
+            return StringUtility.Contact(numto2Decimals(num / B).ToString("0.##"), Language.Get("L1070_1"));
+        }
+        else if (num >= M)
+        {
+            return StringUtility.Contact(numto2Decimals(num / M).ToString("0.##"), Language.Get("L1070"));
+        }
+        else if (num >= K)
+        {
+            return StringUtility.Contact(numto2Decimals(num / K).ToString("0.##"), Language.Get("L1071"));
+        }
+        else
+        {
+            return numto2Decimals(num).ToString("0.##");
+        }
+    }
+
+    //鐢ㄤ簬缇庢湳瀛� 缁熶竴鐢ㄥ瓧姣岾MBT浠h〃浣跨敤锛屽皬鏁扮偣鐢�.
+    public static string ReplaceLargeArtNum(double num)
+    {
+        const long K = 10000;    //鍥藉唴涓轰竾锛屾捣澶栦负鍗�
+        const long M = K * 10000;
+        const long B = M * 10000;
+        const long T = B * 10000;
+
+        if (num >= T)
+        {
+            return StringUtility.Contact(numto2Decimals(num / T).ToString("0.##"), "t");
+        }
+        else if (num >= B)
+        {
+            return StringUtility.Contact(numto2Decimals(num / B).ToString("0.##"), "b");
+        }
+        else if (num >= M)
+        {
+            return StringUtility.Contact(numto2Decimals(num / M).ToString("0.##"),"m");
+        }
+        else if (num >= K)
+        {
+            return StringUtility.Contact(numto2Decimals(num / K).ToString("0.##"), "k");
+        }
+        else
+        {
+            return numto2Decimals(num).ToString("0.##");
+        }
+    }
+
+    // 杞寲澶ф暟鍊煎甫鍗曚綅鐨勬樉绀猴紝濡傛灉灏忎簬200000鍒欐樉绀哄師鍊硷紝鍚﹀垯鏄剧ず澶ф暟鍊�
+    public static string ReplaceLargeNumEx(double num)
+    {
+        if (num < 200000)
+        {
+            //鏍规嵁鐣岄潰鐨勬樉绀哄亣瀹氬�� 200000锛屽彲鏍规嵁瀹為檯鎯呭喌璋冩暣
+            return GetNumFormat(num);
+        }
+        else
+        {
+            return ReplaceLargeNum(num);
+        }
+    }
+
+    //鏄剧ず鏈�澶氫袱浣嶅皬鏁帮紝骞舵寜鍦板尯鏄剧ず鏍煎紡
+    // 濡備腑鏂囩敤F2 鏄剧ず 1111.34锛岃嫳鏂囩敤N2 鏄剧ず 1,111.34锛堝甫閫楀彿锛�
+    public static string GetNumFormat(double num)
+    {
+        if (num == (int)num)
+        {
+            return num.ToString("F0");
+        }
+        return num.ToString("F2").TrimEnd('0').TrimEnd('.');
+    }
+
+
+    public static float ReplacePercentage(float num, int isPer, int decimals = 1)
+    {
+        if (isPer == 1 || isPer == 2)
+        {
+            return (float)Math.Round(num / 100, decimals);
+        }
+        else
+        {
+            return (int)num;
+        }
+    }
+
+    static Regex s_SpecialCharacterRegex = new Regex("[()锛堬級@!#$%^&*[]|_]");
+    static Regex s_AsciiCharacterRegex = new Regex("[\x00-\x1F]|[\x21-\x2F]|[\x3A-\x40]|[\x5B-\x60]|[\x7B-\x7E]");
+    public static bool HasSpecialCharac(string str)
+    {
+        if (s_SpecialCharacterRegex.IsMatch(str))
+        {
+            return true;
+        }
+        if (s_AsciiCharacterRegex.IsMatch(str))
+        {
+            return true;
+        }
+        return false;
+    }
+
+    public static string GetColorNameByItemColor(int itemColor)
+    {
+        switch (itemColor)
+        {
+            case 1:
+                return Language.Get("Market_Text_42");
+            case 2:
+                return Language.Get("Market_Text_43");
+            case 3:
+                return Language.Get("Market_Text_44");
+            case 4:
+                return Language.Get("Market_Text_45");
+            case 5:
+                return Language.Get("Market_Text_46");
+            case 6:
+            case 7:
+            case 8:
+                return Language.Get("Market_Text_47");
+            case 9:
+                return Language.Get("Market_Text_471");
+        }
+        return "";
+    }
+
+    #endregion
+
+    #region 鏂囧瓧鑹插��
+    public static readonly Color s_BrightPinkColor = new Color32(246, 64, 141, 255);
+    public static readonly Color s_BrightRedColor = new Color32(255, 3, 3, 255);
+    public static readonly Color s_BrightPurpleColor = new Color32(218, 72, 213, 255);
+    public static readonly Color s_BrightBlueColor = new Color32(0, 107, 227, 255); //006BE3FF
+    public static readonly Color s_BrightOrangeColor = new Color32(255, 103, 1, 255); //FF6701FF
+    public static readonly Color s_BrightWhiteColor = new Color32(104, 104, 104, 255); //686868
+    public static readonly Color s_BrightGreenColor = new Color32(16, 157, 6, 255); //109d06
+
+    public static readonly Color s_DarkPinkColor = new Color32(255, 124, 124, 255);
+    public static readonly Color s_DarkRedColor = new Color32(250, 1, 1, 255);
+    public static readonly Color s_DarkPurpleColor = new Color32(236, 75, 246, 255);
+    public static readonly Color s_DarkBlueColor = new Color32(49, 206, 251, 255);//31cefb
+    public static readonly Color s_DarkOrangeColor = new Color32(248, 152, 59, 255);
+    public static readonly Color s_DarkWhiteColor = new Color32(247, 247, 247, 255);
+    public static readonly Color s_DarkGreenColor = new Color32(53, 225, 34, 255); //35e122
+
+    public static readonly Color s_NavyBrown = new Color32(64, 28, 6, 255);//401c06
+    public static readonly Color s_Black = new Color32(0, 0, 0, 255);
+    public static readonly Color s_NavyYellow = new Color32(255, 239, 71, 255);
+    public static readonly Color s_LightGreen = new Color32(141, 220, 17, 255);//8ddc11
+    public static readonly Color s_LightYellow = new Color32(255, 244, 205, 255); //fff4cd
+    public static readonly Color s_Gray = new Color32(204, 204, 204, 255);
+    public static readonly Color s_Gold = new Color32(255, 239, 71, 255);//ffef47
+    public static readonly Color s_EarthYellow = new Color32(248, 152, 59, 255);//f8983b
+
+    public static readonly Color s_BrightDanLV0 = new Color32(102, 102, 102, 255); //666666
+    public static readonly Color s_BrightDanLV1 = new Color32(148, 96, 255, 255); //9460ff
+    public static readonly Color s_BrightDanLV2 = new Color32(0, 102, 255, 255); //0066ff
+    public static readonly Color s_BrightDanLV3 = new Color32(0, 179, 55, 255); //00b337
+    public static readonly Color s_BrightDanLV4 = new Color32(255, 102, 0, 255); //ff6600
+    public static readonly Color s_BrightDanLV5 = new Color32(255, 0, 0, 255); //ff0000
+    public static readonly Color s_BrightDanLV6 = new Color32(255, 0, 246, 255); //ff00f6
+
+    public static readonly Color s_GrayDanLV0 = new Color32(221, 221, 221, 255); //dddddd
+    public static readonly Color s_GrayDanLV1 = new Color32(121, 153, 255, 255); //7999ff
+    public static readonly Color s_GrayDanLV2 = new Color32(0, 198, 255, 255); //00c6ff
+    public static readonly Color s_GrayDanLV3 = new Color32(102, 255, 0, 255); //66ff00
+    public static readonly Color s_GrayDanLV4 = new Color32(255, 144, 0, 255); //ff9000
+    public static readonly Color s_GrayDanLV5 = new Color32(255, 0, 0, 255); //ff0000
+    public static readonly Color s_GrayDanLV6 = new Color32(240, 0, 255, 255); //f000ff
+
+    public static Color GetDanLVColor(int danLv, bool bright = false)
+    {
+        var crossDanLVConfig = CrossServerArenaConfig.Get(danLv);
+        if (crossDanLVConfig != null)
+        {
+            switch (crossDanLVConfig.DanType)
+            {
+                case 0:
+                    return bright ? s_BrightDanLV0 : s_GrayDanLV0;
+                case 1:
+                    return bright ? s_BrightDanLV1 : s_GrayDanLV1;
+                case 2:
+                    return bright ? s_BrightDanLV2 : s_GrayDanLV2;
+                case 3:
+                    return bright ? s_BrightDanLV3 : s_GrayDanLV3;
+                case 4:
+                    return bright ? s_BrightDanLV4 : s_GrayDanLV4;
+                case 5:
+                    return bright ? s_BrightDanLV5 : s_GrayDanLV5;
+                case 6:
+                    return bright ? s_BrightDanLV6 : s_GrayDanLV6;
+            }
+        }
+        return Color.white;
+    }
+
+    public static string AppendDanLVNameColor(int danLv, bool bright = false)
+    {
+        var crossDanLVConfig = CrossServerArenaConfig.Get(danLv);
+        if (crossDanLVConfig == null)
+        {
+            return string.Empty;
+        }
+        var name = crossDanLVConfig.Name;
+        switch (crossDanLVConfig.DanType)
+        {
+            case 0:
+                return StringUtility.Contact("<color=#", bright ? "666666" : "dddddd", ">", name, "</color>");
+            case 1:
+                return StringUtility.Contact("<color=#", bright ? "9460ff" : "7999ff", ">", name, "</color>");
+            case 2:
+                return StringUtility.Contact("<color=#", bright ? "0066ff" : "00c6ff", ">", name, "</color>");
+            case 3:
+                return StringUtility.Contact("<color=#", bright ? "00b337" : "66ff00", ">", name, "</color>");
+            case 4:
+                return StringUtility.Contact("<color=#", bright ? "ff6600" : "ff9000", ">", name, "</color>");
+            case 5:
+                return StringUtility.Contact("<color=#", bright ? "ff0000" : "ff0000", ">", name, "</color>");
+            case 6:
+                return StringUtility.Contact("<color=#", bright ? "ff00f6" : "f000ff", ">", name, "</color>");
+        }
+        return name;
+    }
+
+    public static Color GetUIColor(int itemColor, bool bright = false)
+    {
+        switch (itemColor)
+        {
+            case 0:
+                return GetUIColor(TextColType.White, bright);
+            case 1:
+                return GetUIColor(TextColType.White, bright);
+            case 2:
+                return GetUIColor(TextColType.Blue, bright);
+            case 3:
+                return GetUIColor(TextColType.Purple, bright);
+            case 4:
+                return GetUIColor(TextColType.Orange, bright);
+            case 5:
+                return GetUIColor(TextColType.Red, bright);
+            case 6:
+            case 7:
+            case 8:
+                return GetUIColor(TextColType.Pink, bright);
+            case 9:
+                return GetUIColor(TextColType.Green, bright);
+        }
+        return GetUIColor(TextColType.White, bright);
+    }
+
+    public static Color GetUIColor(TextColType type, bool bright = false)
+    {
+        switch (type)
+        {
+            case TextColType.None:
+            case TextColType.White:
+                return bright ? s_BrightWhiteColor : s_DarkWhiteColor;  // s_BrightWhiteColor 鏄寒搴曠伆鑹�
+            case TextColType.Blue:
+                return bright ? s_BrightBlueColor : s_DarkBlueColor;
+            case TextColType.Purple:
+                return bright ? s_BrightPurpleColor : s_DarkPurpleColor;
+            case TextColType.Orange:
+                return bright ? s_BrightOrangeColor : s_DarkOrangeColor;
+            case TextColType.Red:
+                return bright ? s_BrightRedColor : s_DarkRedColor;
+            case TextColType.Pink:
+                return bright ? s_BrightPinkColor : s_DarkPinkColor;
+            case TextColType.Green:
+                return bright ? s_BrightGreenColor : s_DarkGreenColor;
+            case TextColType.NavyBrown:
+                return s_NavyBrown;
+            case TextColType.DarkGreen:
+                return s_BrightGreenColor;
+            case TextColType.Black:
+                return s_Black;
+            case TextColType.NavyYellow:
+                return s_NavyYellow;
+            case TextColType.LightGreen:
+                return s_LightGreen;
+            case TextColType.LightYellow:
+                return s_LightYellow;
+            case TextColType.Gray:
+                return s_Gray;
+        }
+        return bright ? s_BrightWhiteColor : s_DarkWhiteColor;
+    }
+
+    private static Regex m_TextColorRegex = new Regex("<color=#[0-9a-zA-Z]+>(.*)</color>", RegexOptions.Singleline);
+
+    public static string AppendColor(TextColType type, string msg, bool bright = false)
+    {
+        if (m_TextColorRegex.IsMatch(msg) && msg.ToLower().StartsWith("<color=#")
+            && msg.ToLower().EndsWith("</color>"))
+        {
+            Match match = m_TextColorRegex.Match(msg);
+            msg = match.Groups[1].Value;
+        }
+        switch (type)
+        {
+            case TextColType.None:
+            case TextColType.White:
+                return StringUtility.Contact("<color=#", bright ? "686868" : "f7f7f7", ">", msg, "</color>");
+            case TextColType.Blue:
+                return StringUtility.Contact("<color=#", bright ? "006be3" : "31cefb", ">", msg, "</color>");
+            case TextColType.Purple:
+                return StringUtility.Contact("<color=#", bright ? "da48d5" : "ec4bf6", ">", msg, "</color>");
+            case TextColType.Orange:
+                return StringUtility.Contact("<color=#", bright ? "ff6701" : "f8983b", ">", msg, "</color>");
+            case TextColType.Red:
+                return StringUtility.Contact("<color=#", bright ? "ff0303" : "ff0101", ">", msg, "</color>");
+            case TextColType.Pink:
+                return StringUtility.Contact("<color=#", bright ? "f6408d" : "ff7c7c", ">", msg, "</color>");
+            case TextColType.Green:
+                return StringUtility.Contact("<color=#", bright ? "109d06" : "35e122", ">", msg, "</color>");
+            case TextColType.NavyBrown:
+                return StringUtility.Contact("<color=#", "401c06", ">", msg, "</color>");
+            case TextColType.DarkGreen:
+                return StringUtility.Contact("<color=#", "109d06", ">", msg, "</color>");
+            case TextColType.Black:
+                return StringUtility.Contact("<color=#", "000000", ">", msg, "</color>");
+            case TextColType.LightYellow:
+                return StringUtility.Contact("<color=#", "fff4cd", ">", msg, "</color>");
+            case TextColType.LightGreen:
+                return StringUtility.Contact("<color=#", "8ddc11", ">", msg, "</color>");
+            case TextColType.Gray:
+                return StringUtility.Contact("<color=#", "686868", ">", msg, "</color>");
+        }
+        return msg;
+    }
+
+    //needName 鎸囧鐣�0鏄惁闇�瑕佸悕绉�
+    public static string GetRealmName(int realmLv, bool bright = false, bool needName = false)
+    {
+        if (realmLv <= 0 && !needName)
+        {
+            return string.Empty;
+        }
+        var config = RealmConfig.Get(realmLv);
+        if (config == null)
+        {
+            return string.Empty;
+        }
+        return GetRealmColorByLv(realmLv, config.Name, bright);
+    }
+
+    //strFormat闄勫姞 澧冪晫鍚嶄互澶栫殑鏂囧瓧
+    //needName 鎸囧鐣�0鏄惁闇�瑕佸悕绉�
+    public static string GetRealmNameEx(int realmLv, string strFormat, bool bright = false, bool needName = false)
+    {
+        if (realmLv <= 0 && !needName)
+        {
+            return string.Empty;
+        }
+        var config = RealmConfig.Get(realmLv);
+        if (config == null)
+        {
+            return string.Empty;
+        }
+        return GetRealmColorByLv(realmLv, string.Format(strFormat, config.Name), bright);
+    }
+
+    public static string GetRealmColorByLv(int realmLv, string msg, bool bright = false)
+    {
+        var config = RealmConfig.Get(realmLv);
+        if (config == null)
+        {
+            return string.Empty;
+        }
+        switch (config.Quality)
+        {
+            case 1:
+                return StringUtility.Contact("<color=#", bright ? "666666" : "dddddd", ">", msg, "</color>");
+            case 2:
+                return StringUtility.Contact("<color=#", bright ? "00b337" : "66ff00", ">", msg, "</color>");
+            case 3:
+                return StringUtility.Contact("<color=#", bright ? "0066ff" : "00c6ff", ">", msg, "</color>");
+            case 4:
+                return StringUtility.Contact("<color=#", bright ? "ff00f6" : "f000ff", ">", msg, "</color>");
+            case 5:
+                return StringUtility.Contact("<color=#", bright ? "ff6600" : "ff9000", ">", msg, "</color>");
+            case 6:
+                return StringUtility.Contact("<color=#", bright ? "ff0000" : "ff0000", ">", msg, "</color>");
+            default:
+                return msg;
+        }
+    }
+
+    public static string AppendColor(int itemColor, string msg, bool bright = false)
+    {
+        switch (itemColor)
+        {
+            case 0:
+            case 1:
+                return AppendColor(TextColType.White, msg, bright);
+            case 2:
+                return AppendColor(TextColType.Blue, msg, bright);
+            case 3:
+                return AppendColor(TextColType.Purple, msg, bright);
+            case 4:
+                return AppendColor(TextColType.Orange, msg, bright);
+            case 5:
+                return AppendColor(TextColType.Red, msg, bright);
+            case 6:
+            case 7:
+            case 8:
+                return AppendColor(TextColType.Pink, msg, bright);
+            case 9:
+                return AppendColor(TextColType.Green, msg, bright);
+        }
+        return msg;
+    }
+
+    public static int GetItemColor(int _id, Dictionary<int, List<int>> _dict = null)
+    {
+        int _itemColor = 0;
+        var _itemCfg = ItemConfig.Get(_id);
+        if (_itemCfg != null)
+        {
+            _itemColor = _itemCfg.ItemColor;
+            if (_itemCfg.Type == 113 && _dict != null)
+            {
+                _itemColor = ItemLogicUtility.Instance.GetItemQuality(_itemCfg.ID, _dict);
+            }
+        }
+        return _itemColor;
+    }
+
+    public static Color GetPropertyColor(int property)
+    {
+        switch ((PropertyType)property)
+        {
+            case PropertyType.Mater:
+                return s_Gold;
+            case PropertyType.Wood:
+                return s_LightGreen;
+            case PropertyType.Water:
+                return s_DarkBlueColor;
+            case PropertyType.Fire:
+                return s_GrayDanLV5;
+            case PropertyType.Earth:
+                return s_EarthYellow;
+        }
+        return s_NavyBrown;
+    }
+    #endregion
+
+    #region 璁$畻鎴樻枟鍔�
+    public static readonly string FightPowerFormula = "FightpowerFormula";
+
+    public static int GetFightPower(Dictionary<int, int> _propertyDict)
+    {
+        Equation.Instance.Clear();
+        if (_propertyDict == null || _propertyDict.Count == 0)
+        {
+            return 0;
+        }
+
+        foreach (var _key in _propertyDict.Keys)
+        {
+            PlayerPropertyConfig cfg = PlayerPropertyConfig.Get(_key);
+            if (cfg != null)
+            {
+                if (_key == 7)
+                {
+                    Equation.Instance.AddKeyValue("MinAtk", _propertyDict[_key]);
+                    Equation.Instance.AddKeyValue("MaxAtk", _propertyDict[_key]);
+                }
+                else if (_key == 24)
+                {
+                    Equation.Instance.AddKeyValue("PetMinAtk", _propertyDict[_key]);
+                    Equation.Instance.AddKeyValue("PetMaxAtk", _propertyDict[_key]);
+                }
+                else
+                {
+                    ulong attrValue = (ulong)_propertyDict[_key];
+                    var fightParm = GetFightPowerParmByAttrId(_key);
+                    if (_key == 11)
+                    {
+                        var playerLv = PlayerDatas.Instance.baseData.LV;
+                        var paramConfig = FightPowerParamConfig.Get(playerLv);
+                        Equation.Instance.AddKeyValue("AtkSpeedParameter", paramConfig.AtkSpeedParameter);
+                    }
+                    else
+                    {
+                        if (fightParm != 0)
+                        {
+                            attrValue = attrValue * (ulong)fightParm;
+                        }
+                    }
+                    Equation.Instance.AddKeyValue(cfg.Parameter, attrValue);
+                }
+            }
+
+        }
+        FuncConfigConfig funcCfg = FuncConfigConfig.Get(FightPowerFormula);
+        return Equation.Instance.Eval<int>(funcCfg.Numerical1);
+    }
+
+    public static int GetFightPowerParmByAttrId(int attrId)
+    {
+        int playerLv = PlayerDatas.Instance.baseData.LV;
+        FightPowerParamConfig paramConfig = FightPowerParamConfig.Get(playerLv);
+        PlayerPropertyConfig cfg = PlayerPropertyConfig.Get(attrId);
+        if (paramConfig == null || cfg == null) return 0;
+
+        switch (cfg.Parameter)
+        {
+            case "Hit":
+                return paramConfig.Hit;
+            case "Miss":
+                return paramConfig.Miss;
+            case "IgnoreDefRate":
+                return paramConfig.IgnoreDefRate;
+            case "DamChanceDef":
+                return paramConfig.DamChanceDef;
+            case "FaintRate":
+                return paramConfig.FaintRate;
+            case "LuckyHitRateReduce":
+                return paramConfig.LuckyHitRateReduce;
+            case "SkillAtkRate":
+                return paramConfig.SkillAtkRate;
+            case "SkillAtkRateReduce":
+                return paramConfig.SkillAtkRateReduce;
+            case "DamagePerPVP":
+                return paramConfig.DamagePerPVP;
+            case "DamagePerPVPReduce":
+                return paramConfig.DamagePerPVPReduce;
+            case "DamBackPer":
+                return paramConfig.DamBackPer;
+            case "IgnoreDefRateReduce":
+                return paramConfig.IgnoreDefRateReduce;
+            case "FaintDefRate":
+                return paramConfig.FaintDefRate;
+            case "AtkSpeedParameter":
+                return paramConfig.AtkSpeedParameter;
+            case "JobAHurtAddPer":
+                return paramConfig.JobAHurtAddPer;
+            case "JobBHurtAddPer":
+                return paramConfig.JobBHurtAddPer;
+            case "JobCHurtAddPer":
+                return paramConfig.JobCHurtAddPer;
+            case "JobAAtkReducePer":
+                return paramConfig.JobAAtkReducePer;
+            case "JobBAtkReducePer":
+                return paramConfig.JobBAtkReducePer;
+            case "JobCAtkReducePer":
+                return paramConfig.JobCAtkReducePer;
+            case "SuperHitRate":
+                return paramConfig.SuperHitRate;
+            case "LuckyHitRate":
+                return paramConfig.LuckyHitRate;
+            case "SuperHitRateReduce":
+                return paramConfig.SuperHitRateReduce;
+            case "FinalHurtPer":
+                return paramConfig.FinalHurtPer;
+            case "FinalHurtReducePer":
+                return paramConfig.FinalHurtReducePer;
+            case "NPCHurtAddPer":
+                return paramConfig.NPCHurtAddPer;
+            case "NormalHurtPer":
+                return paramConfig.NormalHurtPer;
+            case "FabaoHurtPer":
+                return paramConfig.FabaoHurtPer;
+            case "AffairSpeedPer":
+                return paramConfig.AffairSpeedPer;
+            case "FamilyBossHurtPer":
+                return paramConfig.FamilyBossHurtPer;
+            case "FamilyWarHPPer":
+                return paramConfig.FamilyWarHPPer;
+            case "FamilyWarAtkPer":
+                return paramConfig.FamilyWarAtkPer;
+            case "FamilySitExpPer":
+                return paramConfig.FamilySitExpPer;
+            case "BossFinalHurtPer":
+                return paramConfig.BossFinalHurtPer;
+        }
+
+        return 0;
+    }
+
+    #endregion
+
+    #region 寰楀埌閲戦挶鏁伴噺鏍规嵁閲戦挶绫诲瀷
+
+
+    //璐у竵鍗曚綅鐨勬樉绀猴紝娴峰鏄剧ず閫楀彿, 鍥藉唴涓嶅姞閫楀彿
+    public static string GetMoneyFormat(double money)
+    {
+        if (money == (int)money)
+        {
+            return money.ToString("F0");
+        }
+        return money.ToString("F2").TrimEnd('0').TrimEnd('.');
+        //return money.ToString();
+    }
+
+    //浠呯敤浜庢樉绀� 浠欑帀鍜岀伒鐭崇殑鐗规畩澶勭悊锛屽瓨鍦ㄨ礋鏁版儏鍐碉紝濡侴M鎯╃綒鎵i櫎璐у竵
+    public static int GetMoneyCntEx(int moneyType)
+    {
+        switch (moneyType)
+        {
+            case 1:
+                {
+                    return (int)(PlayerDatas.Instance.baseData.diamond - PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default5));
+                }
+            case 2:
+                {
+                    return (int)(PlayerDatas.Instance.baseData.bindDiamond - PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default6));
+                }
+        }
+        return 0;
+    }
+
+
+    public static ulong GetMoneyCnt(int moneyType)
+    {
+        switch (moneyType)
+        {
+            case 1:
+                {
+                    return PlayerDatas.Instance.baseData.diamond;
+                }
+            case 2:
+                {
+                    return PlayerDatas.Instance.baseData.bindDiamond;
+                }
+            case 3:
+                {
+                    return PlayerDatas.Instance.baseData.allCopper;
+                }
+            case 18:
+                {
+                    return (ulong)PlayerDatas.Instance.extersion.honorValue;
+                }
+            case 25:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.CDBPlayerRefresh_TreasureScore);
+                    //return (ulong)ModelCenter.Instance.GetModel<StoreModel>().GetTCBPlayerData(PlayerDataType.CDBPlayerRefresh_TreasureScore);
+                }
+            case 24:
+                {
+                    return (ulong)PlayerDatas.Instance.extersion.runeChip;
+                }
+            case 15:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.UnionLiven);
+                    //return (ulong)ModelCenter.Instance.GetModel<StoreModel>().GetTCBPlayerData(PlayerDataType.UnionLiven);
+                }
+            case 17:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.FBHelpPoint);
+                    //return (ulong)ModelCenter.Instance.GetModel<StoreModel>().GetTCBPlayerData(PlayerDataType.FBHelpPoint);
+                }
+            case 27:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.CDBPlayerRefresh_Danjing);
+                    //return (ulong)ModelCenter.Instance.GetModel<StoreModel>().GetTCBPlayerData(PlayerDataType.CDBPlayerRefresh_Danjing);
+                }
+            case 28:
+                {
+                    return PlayerDatas.Instance.extersion.soulDust; //搴熷純浜嗙敤44
+                }
+            case 29:
+                {
+                    return PlayerDatas.Instance.extersion.soulSplinters;
+                }
+            case 30:
+                {
+                    return PlayerDatas.Instance.extersion.soulCore;
+                }
+            case 32:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default4);
+                }
+            case 34:
+                {
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default13);
+                }
+            case 35:
+                {
+                    //鍔熷痉鐐�
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default14);
+                }
+            case 37:
+                {
+                    //鏈虹紭鐐�
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default17);
+                }
+            case 39:
+                {
+                    //鎴愬氨绉垎
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default19);
+                }
+            case 40:
+                {
+                    //涓囩晫绉垎
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default20);
+                }
+            case 41:
+                {
+                    //绗﹀嵃绮惧崕
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.RuneSplinters);
+                }
+            case 43:
+                {
+                    //鍑瘉绉垎
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default34);
+                }
+            case 44:
+                {
+                    //鑱氶瓊绮惧崕
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default35);
+                }
+            case 45:
+                {
+                    //楠戝疇绉垎
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default37);
+                }
+            case 46:
+                {
+                    //鍙ゅ疂鍏绘垚璐у竵
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default38);
+                }
+            case 47:
+                {
+                    //澶╅亾甯�
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default39);
+                }
+            case 49:
+                {
+                    //浠欑紭绉垎
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default42);
+                }
+            case 50:
+                {
+                    //骞诲闃佺Н鍒�
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default43);
+                }
+            case 98:
+                {
+                    //杩囨湡鍨嬩唬閲戝埜
+                    return PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.default41);
+                }
+            case 99:
+                {
+                    //浠i噾鍒�
+                    return PlayerDatas.Instance.baseData.ExAttr11;
+                }
+        }
+        return 0;
+    }
+
+    public static int GetAllVourcher()
+    {
+        return (int)GetMoneyCnt(98) + (int)GetMoneyCnt(99);
+    }
+
+    #endregion
+
+    #region 寰楀埌瑁呭浣嶅搴旂殑閮ㄤ綅鍚嶇О
+    public static string GetEquipPlaceName(int place)
+    {
+        if (GeneralDefine.equipPlaceNameDict.ContainsKey(place))
+        {
+            return GeneralDefine.equipPlaceNameDict[place];
+        }
+        return "";
+    }
+    #endregion
+
+    #region 鏈嶅姟绔彂杩囨潵鏂囧瓧鏄剧ず涓嶅嚭鏉ラ棶棰�
+    public static string ServerStringTrim(string str)
+    {
+        if (!string.IsNullOrEmpty(str))
+        {
+            str = str.Replace("\0", "");
+            str = str.Replace("\x00", "");
+            return str;
+        }
+        else
+        {
+            return string.Empty;
+        }
+    }
+    #endregion
+
+    //璐﹀彿锛�706907@1@hyyngame@s30锛屾湇鍔″櫒ID锛�30
+    public static int GetServerIDByAccount(string account)
+    {
+        string[] strArray = account.Split('@');
+        if (strArray.Length < 2)
+        {
+            //鍒ゆ柇闀垮害2涓嶆槸涓�涓疄闄呴暱搴︼紝涓�鑸兘鏄ぇ浜�2
+            return 0;
+        }
+        if (strArray[strArray.Length - 1].Length < 2)
+            return 0;
+        int id = 0;
+        int.TryParse(strArray[strArray.Length - 1].Substring(1), out id);
+        return id;
+    }
+
+
+    #region 鑾峰彇闂撮殧濂栧姳
+    public static int GetIntervalAward(ICollection<int> _keys, int _present)
+    {
+        foreach (var _key in _keys)
+        {
+            if (_present <= _key)
+            {
+                return _key;
+            }
+        }
+        return _keys.Last();
+    }
+    #endregion
+
+    public static string GetGrade(int _star)
+    {
+        switch (_star)
+        {
+            case 5:
+                return "S";
+            case 4:
+                return "A";
+            case 3:
+                return "B";
+            case 2:
+                return "C";
+            case 1:
+                return "D";
+        }
+        return "D";
+    }
+
+    public static string TrimContentToServer(string content)
+    {
+        content = WordAnalysis.Color_Start_Regex.Replace(content, string.Empty);
+        content = WordAnalysis.Color_End_Regex.Replace(content, string.Empty);
+        content = content.Replace("=", string.Empty);
+        content = content.Replace(" ", string.Empty);
+        return content;
+    }
+
+    public static bool SatisfyNameLength(string name, out int error)
+    {
+        error = 0;
+        //bool pureChinese = Regex.IsMatch(name, "^[\u4e00-\u9fa5]+$");
+        //var chsCount = GetChsCount(name);
+        int length = Encoding.Default.GetBytes(name).Length;
+        var maxlength = 20;
+        var minlength = 3;
+        if (length > maxlength)
+        {
+            error = 1;
+        }
+        else if (length < minlength)
+        {
+            error = 2;
+        }
+        return error == 0;
+    }
+
+    public static int GetChsCount(string name)
+    {
+        var count = 0;
+        for (int i = 0; i < name.Length; i++)
+        {
+            if (Regex.IsMatch(name[i].ToString(), "[\u4e00-\u9fa5]"))
+            {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    public static string GetEquipSuitName(int itemId, bool bright = false)
+    {
+        if (ItemLogicUtility.Instance.IsSuitEquip(itemId))
+        {
+            var itemConfig = ItemConfig.Get(itemId);
+            return AppendColor(TextColType.Green, EquipModel.GetSuitName(itemConfig.LV), bright);
+        }
+        return string.Empty;
+    }
+
+    public static string GetItemName(int itmeId, bool bright = false)
+    {
+        var itemConfig = ItemConfig.Get(itmeId);
+        if (itemConfig == null)
+        {
+            return string.Empty;
+        }
+        return StringUtility.Contact(GetEquipSuitName(itmeId, bright), itemConfig.ItemName);
+    }
+
+    public static string GetStar(int star)
+    {
+        switch (star)
+        {
+            case 5:
+                return "S";
+            case 4:
+                return "A";
+            case 3:
+                return "B";
+            case 2:
+                return "C";
+            case 1:
+                return "D";
+        }
+        return string.Empty;
+    }
+
+
+    //杞负s1,s2,s3鏍煎紡
+    public static string GetServers(string serverIDRangeInfo)
+    {
+        var serverList = new List<string>();
+        if (string.IsNullOrEmpty(serverIDRangeInfo) || serverIDRangeInfo == "[]")
+        {
+            return "all";
+        }
+
+        var serverArray = JsonMapper.ToObject<int[][]>(serverIDRangeInfo);
+
+        for (int i = 0; i < serverArray.Length; i++)
+        {
+            int startID = serverArray[i][0];
+            int endID = serverArray[i][1];
+            for (int j = startID; j <= endID; j++)
+            {
+                var serverName = ServerListCenter.Instance.GetServerName(j);
+                serverList.Add(serverName);
+                //澶暱浼氬鑷寸晫闈㈤《鐐规暟瓒呰繃65000
+                if (serverList.Count > 1000)
+                    return string.Join(", ", serverList.ToArray());
+            }
+        }
+        return string.Join(", ", serverList.ToArray());
+    }
+
+    //涓嶅悓鐗堟湰鐜伴噾鐨勫崟浣嶄笉涓�鏍凤紝姣斿瓒婂崡鐩炬槸鏁存暟锛屼笅鍙戞槸鍘熷�硷紱缇庡厓鍜孯MB鏄皬鏁帮紝涓嬪彂鏄師鍊肩殑100
+    public static float GetRealCoin(int money, float scale = 100.0f)
+    {
+        return money / scale;
+    }
+
+}
diff --git a/Main/Utility/UIHelper.cs.meta b/Main/Utility/UIHelper.cs.meta
new file mode 100644
index 0000000..c5ffa1c
--- /dev/null
+++ b/Main/Utility/UIHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6c2107ad216c0b246a40cc2d8657d608
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

--
Gitblit v1.8.0