UI系统组件

This commit is contained in:
2026-06-06 09:00:11 +08:00
parent fe4fd60083
commit d794b83ebe
107 changed files with 25690 additions and 476 deletions

View File

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: 9ce5c865a2d3a0840aabdd8ccb3fd4b1 m_DefaultGroup: 9ce5c865a2d3a0840aabdd8ccb3fd4b1
m_currentHash: m_currentHash:
serializedVersion: 2 serializedVersion: 2
Hash: 15c2855dcd9c0ee51e3ef23e37c6e24d Hash: 31691697811707650999fb9a02054009
m_OptimizeCatalogSize: 0 m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0 m_BuildRemoteCatalog: 0
m_BundleLocalCatalog: 0 m_BundleLocalCatalog: 0

View File

@@ -21,7 +21,7 @@ MonoBehaviour:
m_GetFontFeaturesAtRuntime: 1 m_GetFontFeaturesAtRuntime: 1
m_missingGlyphCharacter: 0 m_missingGlyphCharacter: 0
m_warningsDisabled: 0 m_warningsDisabled: 0
m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_defaultFontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_defaultFontAssetPath: Fonts & Materials/ m_defaultFontAssetPath: Fonts & Materials/
m_defaultFontSize: 36 m_defaultFontSize: 36
m_defaultAutoSizeMinRatio: 0.5 m_defaultAutoSizeMinRatio: 0.5
@@ -29,18 +29,17 @@ MonoBehaviour:
m_defaultTextMeshProTextContainerSize: {x: 20, y: 5} m_defaultTextMeshProTextContainerSize: {x: 20, y: 5}
m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50} m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50}
m_autoSizeTextContainer: 0 m_autoSizeTextContainer: 0
m_fallbackFontAssets: [] m_IsTextObjectScaleStatic: 0
m_fallbackFontAssets:
- {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_matchMaterialPreset: 1 m_matchMaterialPreset: 1
m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, type: 2}
type: 2}
m_defaultSpriteAssetPath: Sprite Assets/ m_defaultSpriteAssetPath: Sprite Assets/
m_enableEmojiSupport: 1 m_enableEmojiSupport: 1
m_MissingCharacterSpriteUnicode: 0 m_MissingCharacterSpriteUnicode: 0
m_defaultColorGradientPresetsPath: Color Gradient Presets/ m_defaultColorGradientPresetsPath: Color Gradient Presets/
m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, type: 2}
type: 2}
m_StyleSheetsResourcePath: m_StyleSheetsResourcePath:
m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3} m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3}
m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, type: 3}
type: 3}
m_UseModernHangulLineBreakingRules: 0 m_UseModernHangulLineBreakingRules: 0

View File

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

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

View File

@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 028abe651ad4d13458a11b7b8fc8c0ff
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Noto Sans SC
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,14 +1,244 @@
{ {
"entries": [ "entries": [
{ "key": "TOAST_ACHIEVEMENT_TITLE", "value": "成就解锁" }, {
{ "key": "TOAST_ABILITY_TITLE", "value": "能力获得" }, "key": "BADGE_STEELSOUL",
{ "key": "REBIND_WAITING_PROMPT", "value": "按下新按键…" }, "value": "钢魂"
{ "key": "MAP_PROGRESS_GLOBAL", "value": "已探索 {0:P0}" }, },
{ "key": "MAP_PROGRESS_REGION", "value": "{1}{0:P0}" }, {
{ "key": "MAP_CLOSE_HINT", "value": "关闭地图" }, "key": "BTN_BACK",
{ "key": "TELEPORT_CONFIRM_TITLE", "value": "快速传送" }, "value": "返回"
{ "key": "TELEPORT_CONFIRM_BODY", "value": "传送到:" }, },
{ "key": "CONFIRM_YES", "value": "确认" }, {
{ "key": "CONFIRM_NO", "value": "取消" } "key": "CONFIRM_DELETE_BODY",
"value": "确定删除该存档槽的所有进度吗?此操作不可撤销。"
},
{
"key": "CONFIRM_DELETE_TITLE",
"value": "删除存档"
},
{
"key": "CONFIRM_NO",
"value": "取消"
},
{
"key": "CONFIRM_OVERWRITE_BODY",
"value": "该存档槽已有进度,确定覆盖并开始新游戏吗?"
},
{
"key": "CONFIRM_OVERWRITE_TITLE",
"value": "覆盖存档"
},
{
"key": "CONFIRM_YES",
"value": "确认"
},
{
"key": "CREDITS_BODY",
"value": "ZELING\n\n一段 2D 动作冒险\n\n制作 · Joywayer\n\n感谢游玩。"
},
{
"key": "CREDITS_TITLE",
"value": "制作团队"
},
{
"key": "MAP_CLOSE_HINT",
"value": "关闭地图"
},
{
"key": "MAP_PROGRESS_GLOBAL",
"value": "已探索 {0:P0}"
},
{
"key": "MAP_PROGRESS_REGION",
"value": "{1}{0:P0}"
},
{
"key": "MENU_CONTINUE",
"value": "继续"
},
{
"key": "MENU_CREDITS",
"value": "制作团队"
},
{
"key": "MENU_NEW_GAME",
"value": "新游戏"
},
{
"key": "MENU_QUIT",
"value": "退出"
},
{
"key": "MENU_SETTINGS",
"value": "设置"
},
{
"key": "MENU_SUBTITLE",
"value": "一段 2D 动作冒险"
},
{
"key": "MODE_NORMAL",
"value": "普通"
},
{
"key": "MODE_SELECT_TITLE",
"value": "选择模式"
},
{
"key": "MODE_STEELSOUL",
"value": "钢铁之魂"
},
{
"key": "MODE_STEELSOUL_DESC",
"value": "钢铁之魂:一命模式,死亡即清空存档。"
},
{
"key": "REBIND_WAITING_PROMPT",
"value": "按下新按键…"
},
{
"key": "SAVESLOT_EMPTY",
"value": "空槽 · 开始新游戏"
},
{
"key": "SAVESLOT_TITLE",
"value": "选择存档"
},
{
"key": "SETTINGS_AMBIENT_VOLUME",
"value": "环境音量"
},
{
"key": "SETTINGS_BGM_VOLUME",
"value": "音乐音量"
},
{
"key": "SETTINGS_COLORBLIND",
"value": "色盲模式"
},
{
"key": "SETTINGS_FPS",
"value": "帧率上限"
},
{
"key": "SETTINGS_LANGUAGE",
"value": "语言"
},
{
"key": "SETTINGS_MASTER_VOLUME",
"value": "主音量"
},
{
"key": "SETTINGS_SCREEN_SHAKE",
"value": "屏幕震动"
},
{
"key": "SETTINGS_SFX_VOLUME",
"value": "音效音量"
},
{
"key": "SETTINGS_TITLE",
"value": "设置"
},
{
"key": "SETTINGS_UI_SCALE",
"value": "界面缩放"
},
{
"key": "SETTINGS_VSYNC",
"value": "垂直同步"
},
{
"key": "SET_AMBIENT_VOLUME",
"value": "环境音"
},
{
"key": "SET_BGM_VOLUME",
"value": "音乐"
},
{
"key": "SET_COLORBLIND",
"value": "色盲模式"
},
{
"key": "SET_COLORBLIND_0",
"value": "关闭"
},
{
"key": "SET_COLORBLIND_1",
"value": "红色弱Protanopia"
},
{
"key": "SET_COLORBLIND_2",
"value": "绿色弱Deuteranopia"
},
{
"key": "SET_COLORBLIND_3",
"value": "蓝色弱Tritanopia"
},
{
"key": "SET_FPS_UNLIMITED",
"value": "无限"
},
{
"key": "SET_LANGUAGE",
"value": "语言"
},
{
"key": "SET_MASTER_VOLUME",
"value": "主音量"
},
{
"key": "SET_SCREEN_SHAKE",
"value": "屏幕震动"
},
{
"key": "SET_SECTION_ACCESS",
"value": "辅助功能"
},
{
"key": "SET_SECTION_AUDIO",
"value": "音频"
},
{
"key": "SET_SECTION_DISPLAY",
"value": "画面"
},
{
"key": "SET_SECTION_LANGUAGE",
"value": "语言"
},
{
"key": "SET_SFX_VOLUME",
"value": "音效"
},
{
"key": "SET_TARGET_FPS",
"value": "目标帧率"
},
{
"key": "SET_UI_SCALE",
"value": "界面缩放"
},
{
"key": "SET_VSYNC",
"value": "垂直同步"
},
{
"key": "TELEPORT_CONFIRM_BODY",
"value": "传送到:"
},
{
"key": "TELEPORT_CONFIRM_TITLE",
"value": "快速传送"
},
{
"key": "TOAST_ABILITY_TITLE",
"value": "能力获得"
},
{
"key": "TOAST_ACHIEVEMENT_TITLE",
"value": "成就解锁"
}
] ]
} }

View File

@@ -1,14 +1,244 @@
{ {
"entries": [ "entries": [
{ "key": "TOAST_ACHIEVEMENT_TITLE", "value": "Achievement Unlocked" }, {
{ "key": "TOAST_ABILITY_TITLE", "value": "Ability Acquired" }, "key": "BADGE_STEELSOUL",
{ "key": "REBIND_WAITING_PROMPT", "value": "Press New Key…" }, "value": "STEEL"
{ "key": "MAP_PROGRESS_GLOBAL", "value": "Explored {0:P0}" }, },
{ "key": "MAP_PROGRESS_REGION", "value": "{1}: {0:P0}" }, {
{ "key": "MAP_CLOSE_HINT", "value": "Close Map" }, "key": "BTN_BACK",
{ "key": "TELEPORT_CONFIRM_TITLE", "value": "Fast Travel" }, "value": "Back"
{ "key": "TELEPORT_CONFIRM_BODY", "value": "Travel to: " }, },
{ "key": "CONFIRM_YES", "value": "Confirm" }, {
{ "key": "CONFIRM_NO", "value": "Cancel" } "key": "CONFIRM_DELETE_BODY",
"value": "Delete all progress in this slot? This cannot be undone."
},
{
"key": "CONFIRM_DELETE_TITLE",
"value": "Delete Save"
},
{
"key": "CONFIRM_NO",
"value": "Cancel"
},
{
"key": "CONFIRM_OVERWRITE_BODY",
"value": "This slot already has progress. Overwrite it and start a new game?"
},
{
"key": "CONFIRM_OVERWRITE_TITLE",
"value": "Overwrite Save"
},
{
"key": "CONFIRM_YES",
"value": "Confirm"
},
{
"key": "CREDITS_BODY",
"value": "ZELING\n\nA 2D Action Adventure\n\nMade by Joywayer\n\nThanks for playing."
},
{
"key": "CREDITS_TITLE",
"value": "Credits"
},
{
"key": "MAP_CLOSE_HINT",
"value": "Close Map"
},
{
"key": "MAP_PROGRESS_GLOBAL",
"value": "Explored {0:P0}"
},
{
"key": "MAP_PROGRESS_REGION",
"value": "{1}: {0:P0}"
},
{
"key": "MENU_CONTINUE",
"value": "Continue"
},
{
"key": "MENU_CREDITS",
"value": "Credits"
},
{
"key": "MENU_NEW_GAME",
"value": "New Game"
},
{
"key": "MENU_QUIT",
"value": "Quit"
},
{
"key": "MENU_SETTINGS",
"value": "Settings"
},
{
"key": "MENU_SUBTITLE",
"value": "A 2D Action Adventure"
},
{
"key": "MODE_NORMAL",
"value": "Normal"
},
{
"key": "MODE_SELECT_TITLE",
"value": "Select Mode"
},
{
"key": "MODE_STEELSOUL",
"value": "Steel Soul"
},
{
"key": "MODE_STEELSOUL_DESC",
"value": "Steel Soul: one life. Death wipes the save."
},
{
"key": "REBIND_WAITING_PROMPT",
"value": "Press New Key…"
},
{
"key": "SAVESLOT_EMPTY",
"value": "Empty Slot · New Game"
},
{
"key": "SAVESLOT_TITLE",
"value": "Select Save"
},
{
"key": "SETTINGS_AMBIENT_VOLUME",
"value": "Ambient Volume"
},
{
"key": "SETTINGS_BGM_VOLUME",
"value": "Music Volume"
},
{
"key": "SETTINGS_COLORBLIND",
"value": "Colorblind Mode"
},
{
"key": "SETTINGS_FPS",
"value": "Frame Rate"
},
{
"key": "SETTINGS_LANGUAGE",
"value": "Language"
},
{
"key": "SETTINGS_MASTER_VOLUME",
"value": "Master Volume"
},
{
"key": "SETTINGS_SCREEN_SHAKE",
"value": "Screen Shake"
},
{
"key": "SETTINGS_SFX_VOLUME",
"value": "SFX Volume"
},
{
"key": "SETTINGS_TITLE",
"value": "Settings"
},
{
"key": "SETTINGS_UI_SCALE",
"value": "UI Scale"
},
{
"key": "SETTINGS_VSYNC",
"value": "V-Sync"
},
{
"key": "SET_AMBIENT_VOLUME",
"value": "Ambience"
},
{
"key": "SET_BGM_VOLUME",
"value": "Music"
},
{
"key": "SET_COLORBLIND",
"value": "Colorblind Mode"
},
{
"key": "SET_COLORBLIND_0",
"value": "Off"
},
{
"key": "SET_COLORBLIND_1",
"value": "Protanopia"
},
{
"key": "SET_COLORBLIND_2",
"value": "Deuteranopia"
},
{
"key": "SET_COLORBLIND_3",
"value": "Tritanopia"
},
{
"key": "SET_FPS_UNLIMITED",
"value": "Unlimited"
},
{
"key": "SET_LANGUAGE",
"value": "Language"
},
{
"key": "SET_MASTER_VOLUME",
"value": "Master Volume"
},
{
"key": "SET_SCREEN_SHAKE",
"value": "Screen Shake"
},
{
"key": "SET_SECTION_ACCESS",
"value": "Accessibility"
},
{
"key": "SET_SECTION_AUDIO",
"value": "Audio"
},
{
"key": "SET_SECTION_DISPLAY",
"value": "Display"
},
{
"key": "SET_SECTION_LANGUAGE",
"value": "Language"
},
{
"key": "SET_SFX_VOLUME",
"value": "Sound Effects"
},
{
"key": "SET_TARGET_FPS",
"value": "Target FPS"
},
{
"key": "SET_UI_SCALE",
"value": "UI Scale"
},
{
"key": "SET_VSYNC",
"value": "V-Sync"
},
{
"key": "TELEPORT_CONFIRM_BODY",
"value": "Travel to: "
},
{
"key": "TELEPORT_CONFIRM_TITLE",
"value": "Fast Travel"
},
{
"key": "TOAST_ABILITY_TITLE",
"value": "Ability Acquired"
},
{
"key": "TOAST_ACHIEVEMENT_TITLE",
"value": "Achievement Unlocked"
}
] ]
} }

View File

@@ -0,0 +1,24 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b31f31378d72a8e42b454d4af01e51ab, type: 3}
m_Name: FontConfig
m_EditorClassIdentifier:
entries:
- language: 0
fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
fontMaterial: {fileID: 0}
- language: 2
fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
fontMaterial: {fileID: 0}
- language: 3
fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
fontMaterial: {fileID: 0}

View File

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

View File

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

View File

@@ -0,0 +1,35 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e1d97086a1337cc47a5d2ee9c85a944d, type: 3}
m_Name: UI_Theme_Default
m_EditorClassIdentifier:
Primary: {r: 0.1, g: 0.55, b: 0.95, a: 1}
Secondary: {r: 0.2, g: 0.2, b: 0.25, a: 1}
Accent: {r: 1, g: 0.78, b: 0.2, a: 1}
Background: {r: 0.06, g: 0.07, b: 0.1, a: 1}
TextPrimary: {r: 1, g: 1, b: 1, a: 1}
TextSecondary: {r: 0.75, g: 0.78, b: 0.82, a: 1}
TextDisabled: {r: 0.4, g: 0.42, b: 0.45, a: 1}
Success: {r: 0.3, g: 0.85, b: 0.45, a: 1}
Warning: {r: 0.95, g: 0.7, b: 0.1, a: 1}
Danger: {r: 0.95, g: 0.3, b: 0.3, a: 1}
HeaderFont: {fileID: 0}
BodyFont: {fileID: 0}
HeaderFontSize: 36
BodyFontSize: 20
SmallFontSize: 14
ButtonNormal: {r: 0.1, g: 0.55, b: 0.95, a: 1}
ButtonHighlighted: {r: 0.2, g: 0.65, b: 1, a: 1}
ButtonPressed: {r: 0.05, g: 0.4, b: 0.8, a: 1}
ButtonDisabled: {r: 0.3, g: 0.3, b: 0.32, a: 1}
ClickSound: {fileID: 0}
HoverSound: {fileID: 0}

View File

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

View File

@@ -0,0 +1,45 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d78ee6af5c2b0344ea105452f496e85c, type: 3}
m_Name: UI_MainMenuConfig
m_EditorClassIdentifier:
_items:
- labelKey: MENU_NEW_GAME
icon: {fileID: 0}
action: 0
requiresSave: 0
sceneKey:
eventChannel: {fileID: 0}
- labelKey: MENU_CONTINUE
icon: {fileID: 0}
action: 1
requiresSave: 1
sceneKey:
eventChannel: {fileID: 0}
- labelKey: MENU_SETTINGS
icon: {fileID: 0}
action: 2
requiresSave: 0
sceneKey:
eventChannel: {fileID: 0}
- labelKey: MENU_CREDITS
icon: {fileID: 0}
action: 3
requiresSave: 0
sceneKey:
eventChannel: {fileID: 0}
- labelKey: MENU_QUIT
icon: {fileID: 0}
action: 5
requiresSave: 0
sceneKey:
eventChannel: {fileID: 0}

View File

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

View File

@@ -0,0 +1,57 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0edaa79306d53d74da12f1f0cb03ea48, type: 3}
m_Name: UI_SettingsSchema
m_EditorClassIdentifier:
_items:
- isHeader: 1
labelKey: SET_SECTION_AUDIO
key: 0
- isHeader: 0
labelKey: SET_MASTER_VOLUME
key: 0
- isHeader: 0
labelKey: SET_BGM_VOLUME
key: 1
- isHeader: 0
labelKey: SET_SFX_VOLUME
key: 2
- isHeader: 0
labelKey: SET_AMBIENT_VOLUME
key: 3
- isHeader: 1
labelKey: SET_SECTION_DISPLAY
key: 0
- isHeader: 0
labelKey: SET_VSYNC
key: 4
- isHeader: 0
labelKey: SET_TARGET_FPS
key: 5
- isHeader: 1
labelKey: SET_SECTION_ACCESS
key: 0
- isHeader: 0
labelKey: SET_UI_SCALE
key: 6
- isHeader: 0
labelKey: SET_COLORBLIND
key: 7
- isHeader: 0
labelKey: SET_SCREEN_SHAKE
key: 8
- isHeader: 1
labelKey: SET_SECTION_LANGUAGE
key: 0
- isHeader: 0
labelKey: SET_LANGUAGE
key: 9

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,54 @@
key,ChineseSimplified,English,Japanese,Korean
BADGE_STEELSOUL,钢魂,STEEL,,
BTN_BACK,返回,Back,,
CONFIRM_DELETE_BODY,确定删除该存档槽的所有进度吗?此操作不可撤销。,Delete all progress in this slot? This cannot be undone.,,
CONFIRM_DELETE_TITLE,删除存档,Delete Save,,
CONFIRM_NO,取消,Cancel,,
CONFIRM_OVERWRITE_BODY,该存档槽已有进度,确定覆盖并开始新游戏吗?,This slot already has progress. Overwrite it and start a new game?,,
CONFIRM_OVERWRITE_TITLE,覆盖存档,Overwrite Save,,
CONFIRM_YES,确认,Confirm,,
CREDITS_BODY,"ZELING
一段 2D 动作冒险
制作 · Joywayer
感谢游玩。","ZELING
A 2D Action Adventure
Made by Joywayer
Thanks for playing.",,
CREDITS_TITLE,制作团队,Credits,,
MAP_CLOSE_HINT,关闭地图,Close Map,,
MAP_PROGRESS_GLOBAL,已探索 {0:P0},Explored {0:P0},,
MAP_PROGRESS_REGION,{1}{0:P0},{1}: {0:P0},,
MENU_CONTINUE,继续,Continue,,
MENU_CREDITS,制作团队,Credits,,
MENU_NEW_GAME,新游戏,New Game,,
MENU_QUIT,退出,Quit,,
MENU_SETTINGS,设置,Settings,,
MENU_SUBTITLE,一段 2D 动作冒险,A 2D Action Adventure,,
MODE_NORMAL,普通,Normal,,
MODE_SELECT_TITLE,选择模式,Select Mode,,
MODE_STEELSOUL,钢铁之魂,Steel Soul,,
MODE_STEELSOUL_DESC,钢铁之魂:一命模式,死亡即清空存档。,Steel Soul: one life. Death wipes the save.,,
REBIND_WAITING_PROMPT,按下新按键…,Press New Key…,新しいキーを押してください…,새 키를 누르세요…
SAVESLOT_EMPTY,空槽 · 开始新游戏,Empty Slot · New Game,,
SAVESLOT_TITLE,选择存档,Select Save,,
SETTINGS_AMBIENT_VOLUME,环境音量,Ambient Volume,,
SETTINGS_BGM_VOLUME,音乐音量,Music Volume,,
SETTINGS_COLORBLIND,色盲模式,Colorblind Mode,,
SETTINGS_FPS,帧率上限,Frame Rate,,
SETTINGS_LANGUAGE,语言,Language,,
SETTINGS_MASTER_VOLUME,主音量,Master Volume,,
SETTINGS_SCREEN_SHAKE,屏幕震动,Screen Shake,,
SETTINGS_SFX_VOLUME,音效音量,SFX Volume,,
SETTINGS_TITLE,设置,Settings,,
SETTINGS_UI_SCALE,界面缩放,UI Scale,,
SETTINGS_VSYNC,垂直同步,V-Sync,,
TELEPORT_CONFIRM_BODY,传送到:,Travel to: ,,
TELEPORT_CONFIRM_TITLE,快速传送,Fast Travel,,
TOAST_ABILITY_TITLE,能力获得,Ability Acquired,アビリティ獲得,능력 획득
TOAST_ACHIEVEMENT_TITLE,成就解锁,Achievement Unlocked,実績アンロック,업적 잊금
1 key ChineseSimplified English Japanese Korean
2 BADGE_STEELSOUL 钢魂 STEEL
3 BTN_BACK 返回 Back
4 CONFIRM_DELETE_BODY 确定删除该存档槽的所有进度吗?此操作不可撤销。 Delete all progress in this slot? This cannot be undone.
5 CONFIRM_DELETE_TITLE 删除存档 Delete Save
6 CONFIRM_NO 取消 Cancel
7 CONFIRM_OVERWRITE_BODY 该存档槽已有进度,确定覆盖并开始新游戏吗? This slot already has progress. Overwrite it and start a new game?
8 CONFIRM_OVERWRITE_TITLE 覆盖存档 Overwrite Save
9 CONFIRM_YES 确认 Confirm
10 CREDITS_BODY ZELING 一段 2D 动作冒险 制作 · Joywayer 感谢游玩。 ZELING A 2D Action Adventure Made by Joywayer Thanks for playing.
11 CREDITS_TITLE 制作团队 Credits
12 MAP_CLOSE_HINT 关闭地图 Close Map
13 MAP_PROGRESS_GLOBAL 已探索 {0:P0} Explored {0:P0}
14 MAP_PROGRESS_REGION {1}:{0:P0} {1}: {0:P0}
15 MENU_CONTINUE 继续 Continue
16 MENU_CREDITS 制作团队 Credits
17 MENU_NEW_GAME 新游戏 New Game
18 MENU_QUIT 退出 Quit
19 MENU_SETTINGS 设置 Settings
20 MENU_SUBTITLE 一段 2D 动作冒险 A 2D Action Adventure
21 MODE_NORMAL 普通 Normal
22 MODE_SELECT_TITLE 选择模式 Select Mode
23 MODE_STEELSOUL 钢铁之魂 Steel Soul
24 MODE_STEELSOUL_DESC 钢铁之魂:一命模式,死亡即清空存档。 Steel Soul: one life. Death wipes the save.
25 REBIND_WAITING_PROMPT 按下新按键… Press New Key… 新しいキーを押してください… 새 키를 누르세요…
26 SAVESLOT_EMPTY 空槽 · 开始新游戏 Empty Slot · New Game
27 SAVESLOT_TITLE 选择存档 Select Save
28 SETTINGS_AMBIENT_VOLUME 环境音量 Ambient Volume
29 SETTINGS_BGM_VOLUME 音乐音量 Music Volume
30 SETTINGS_COLORBLIND 色盲模式 Colorblind Mode
31 SETTINGS_FPS 帧率上限 Frame Rate
32 SETTINGS_LANGUAGE 语言 Language
33 SETTINGS_MASTER_VOLUME 主音量 Master Volume
34 SETTINGS_SCREEN_SHAKE 屏幕震动 Screen Shake
35 SETTINGS_SFX_VOLUME 音效音量 SFX Volume
36 SETTINGS_TITLE 设置 Settings
37 SETTINGS_UI_SCALE 界面缩放 UI Scale
38 SETTINGS_VSYNC 垂直同步 V-Sync
39 TELEPORT_CONFIRM_BODY 传送到: Travel to:
40 TELEPORT_CONFIRM_TITLE 快速传送 Fast Travel
41 TOAST_ABILITY_TITLE 能力获得 Ability Acquired アビリティ獲得 능력 획득
42 TOAST_ACHIEVEMENT_TITLE 成就解锁 Achievement Unlocked 実績アンロック 업적 잊금

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 766b94c478152f347a7245501116f2e8
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,307 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4648993278565750863
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7434669335039776586}
- component: {fileID: 4989798412556107440}
- component: {fileID: 1446889652086510839}
- component: {fileID: 4780358684561283937}
m_Layer: 0
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7434669335039776586
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4648993278565750863}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7145670357572348738}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4989798412556107440
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4648993278565750863}
m_CullTransparentMesh: 1
--- !u!114 &1446889652086510839
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4648993278565750863}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Button
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 14
m_fontSizeBase: 14
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &4780358684561283937
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4648993278565750863}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 7
_overrideFontSize: 0
--- !u!1 &4798970077294940872
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7145670357572348738}
- component: {fileID: 4133336030444025929}
- component: {fileID: 5784682159282604535}
- component: {fileID: 2876723545713027670}
- component: {fileID: 2961568203053643187}
- component: {fileID: 4023577034128914888}
m_Layer: 0
m_Name: UI_Control_Button
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7145670357572348738
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7434669335039776586}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 48}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4133336030444025929
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_CullTransparentMesh: 1
--- !u!114 &5784682159282604535
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &2876723545713027670
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 0.1, g: 0.55, b: 0.95, a: 1}
m_HighlightedColor: {r: 0.208, g: 0.60400003, b: 0.956, a: 1}
m_PressedColor: {r: 0.085, g: 0.4675, b: 0.8075, a: 1}
m_SelectedColor: {r: 0.208, g: 0.60400003, b: 0.956, a: 1}
m_DisabledColor: {r: 0.3, g: 0.3, b: 0.32, a: 1}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 5784682159282604535}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2961568203053643187
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 270b0a121b06dfc4587c060335f18432, type: 3}
m_Name:
m_EditorClassIdentifier:
_variant: 0
_theme: {fileID: 11400000, guid: 88bab5495f6103f4d9d69fa043d4c3e1, type: 2}
_scaleFeedback: 1
_selectedScale: 1.06
_scaleDuration: 0.08
_onClickSfx: {fileID: 0}
_onHoverSfx: {fileID: 0}
--- !u!114 &4023577034128914888
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798970077294940872}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 11
_overrideFontSize: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: af94b3795e225b54985a0c4d6a2f4aa9
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c96b1f39a48501e48954175108c896c0
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,287 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7491264101481992626
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1404081159922799881}
- component: {fileID: 6930878104455828636}
- component: {fileID: 6084647886258874521}
- component: {fileID: 6384349683107319821}
m_Layer: 0
m_Name: Title
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1404081159922799881
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7491264101481992626}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2078232494173195539}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: -16}
m_SizeDelta: {x: -32, y: 40}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &6930878104455828636
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7491264101481992626}
m_CullTransparentMesh: 1
--- !u!114 &6084647886258874521
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7491264101481992626}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Panel
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 28
m_fontSizeBase: 28
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &6384349683107319821
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7491264101481992626}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 9
_overrideFontSize: 0
--- !u!1 &8217544468495105350
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2078232494173195539}
- component: {fileID: 7015213363194495042}
- component: {fileID: 2221117938118938275}
- component: {fileID: 1182987514380032191}
- component: {fileID: 7022297426914789910}
- component: {fileID: 1174997407675126460}
- component: {fileID: 8682268969386925379}
m_Layer: 0
m_Name: UI_Control_Panel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2078232494173195539
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1404081159922799881}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 480, y: 320}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7015213363194495042
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_CullTransparentMesh: 1
--- !u!114 &2221117938118938275
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.06, g: 0.07, b: 0.1, a: 0.96}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &1182987514380032191
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 3
_overrideFontSize: 0
--- !u!225 &7022297426914789910
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!114 &1174997407675126460
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 50572ad108fd3354da04ea8fba66370b, type: 3}
m_Name:
m_EditorClassIdentifier:
_theme: {fileID: 11400000, guid: 88bab5495f6103f4d9d69fa043d4c3e1, type: 2}
_applyOnEnable: 1
--- !u!114 &8682268969386925379
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8217544468495105350}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c6fa4cf81d2fd2e46b0d922f7b55097c, type: 3}
m_Name:
m_EditorClassIdentifier:
_firstSelected: {fileID: 0}
_canvasGroup: {fileID: 7022297426914789910}
_fadeInDuration: 0.15
_selectFirstOnEnable: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9f0d13c44b1b5484b86746e3d696bb79
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,456 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &477095832022680696
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2056370201300175144}
- component: {fileID: 9132335891156628336}
- component: {fileID: 5198911377577739583}
- component: {fileID: 5619472571537383739}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2056370201300175144
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 477095832022680696}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3293627937247209068}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 20, y: 0}
m_SizeDelta: {x: -64, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9132335891156628336
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 477095832022680696}
m_CullTransparentMesh: 1
--- !u!114 &5198911377577739583
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 477095832022680696}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Row
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 20
m_fontSizeBase: 20
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &5619472571537383739
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 477095832022680696}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 7
_overrideFontSize: 0
--- !u!1 &526907397050529052
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 805913492557441718}
- component: {fileID: 5420200537658845125}
- component: {fileID: 1739625167890660215}
m_Layer: 0
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &805913492557441718
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526907397050529052}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3293627937247209068}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: 10, y: 0}
m_SizeDelta: {x: 32, y: 32}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &5420200537658845125
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526907397050529052}
m_CullTransparentMesh: 1
--- !u!114 &1739625167890660215
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526907397050529052}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3831138589626733696
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4051871124872751768}
- component: {fileID: 7168122679137864546}
- component: {fileID: 5561835652314978329}
- component: {fileID: 7120742326677395016}
m_Layer: 0
m_Name: SelectedHighlight
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &4051871124872751768
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3831138589626733696}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3293627937247209068}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7168122679137864546
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3831138589626733696}
m_CullTransparentMesh: 1
--- !u!114 &5561835652314978329
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3831138589626733696}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.2, g: 0.65, b: 1, a: 0.35}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7120742326677395016
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3831138589626733696}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 2
_overrideFontSize: 0
--- !u!1 &6596140938478677270
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3293627937247209068}
- component: {fileID: 2266986535621667995}
- component: {fileID: 4173014312274757759}
- component: {fileID: 9054154986878635174}
- component: {fileID: 2527815508985184034}
m_Layer: 0
m_Name: UI_Control_SelectableRow
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3293627937247209068
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6596140938478677270}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4051871124872751768}
- {fileID: 805913492557441718}
- {fileID: 2056370201300175144}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 320, y: 48}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2266986535621667995
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6596140938478677270}
m_CullTransparentMesh: 1
--- !u!114 &4173014312274757759
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6596140938478677270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0.06}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &9054154986878635174
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6596140938478677270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 4173014312274757759}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2527815508985184034
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6596140938478677270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 64037ec2ca4c93d40908480eb137ccf3, type: 3}
m_Name:
m_EditorClassIdentifier:
_button: {fileID: 9054154986878635174}
_label: {fileID: 5198911377577739583}
_icon: {fileID: 1739625167890660215}
_selectedHighlight: {fileID: 3831138589626733696}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6885ddbf2204e1e49a91ac277cad4e90
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,555 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2892246082093230636
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6777873855412127507}
- component: {fileID: 7943591468316354171}
- component: {fileID: 6718276243346542542}
m_Layer: 0
m_Name: Fill
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6777873855412127507
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2892246082093230636}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2856380859823679016}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 10, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7943591468316354171
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2892246082093230636}
m_CullTransparentMesh: 1
--- !u!114 &6718276243346542542
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2892246082093230636}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2955367232293863162
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2856380859823679016}
m_Layer: 0
m_Name: Fill Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2856380859823679016
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2955367232293863162}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6777873855412127507}
m_Father: {fileID: 4890485910657195775}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: -5, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &3036624611908829816
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4890485910657195775}
- component: {fileID: 6009437737723481310}
- component: {fileID: 5243221914320319692}
m_Layer: 0
m_Name: UI_Control_Slider
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4890485910657195775
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3036624611908829816}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6906943864500586170}
- {fileID: 2856380859823679016}
- {fileID: 3504415066853500042}
- {fileID: 3560607011362116889}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 240, y: 24}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6009437737723481310
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3036624611908829816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 3074083777787071048}
m_FillRect: {fileID: 6777873855412127507}
m_HandleRect: {fileID: 8095715524730652885}
m_Direction: 0
m_MinValue: 0
m_MaxValue: 1
m_WholeNumbers: 0
m_Value: 0
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
--- !u!114 &5243221914320319692
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3036624611908829816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a1743e750e4f79c43b64e07a1c1a7270, type: 3}
m_Name:
m_EditorClassIdentifier:
_slider: {fileID: 6009437737723481310}
_valueLabel: {fileID: 5727754088110451924}
_format: '{0:0}'
--- !u!1 &3158898647431107578
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3560607011362116889}
- component: {fileID: 6883055686052382372}
- component: {fileID: 5727754088110451924}
- component: {fileID: 8457252421405363693}
m_Layer: 0
m_Name: ValueLabel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3560607011362116889
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3158898647431107578}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4890485910657195775}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: 8, y: 0}
m_SizeDelta: {x: 48, y: 24}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &6883055686052382372
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3158898647431107578}
m_CullTransparentMesh: 1
--- !u!114 &5727754088110451924
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3158898647431107578}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: 0
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 18
m_fontSizeBase: 18
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &8457252421405363693
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3158898647431107578}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 8
_overrideFontSize: 0
--- !u!1 &6664664133928497365
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6906943864500586170}
- component: {fileID: 1618532266414389766}
- component: {fileID: 5860135118569899921}
m_Layer: 0
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6906943864500586170
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6664664133928497365}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4890485910657195775}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1618532266414389766
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6664664133928497365}
m_CullTransparentMesh: 1
--- !u!114 &5860135118569899921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6664664133928497365}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7693947586556550140
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8095715524730652885}
- component: {fileID: 3392477586643606721}
- component: {fileID: 3074083777787071048}
m_Layer: 0
m_Name: Handle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8095715524730652885
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7693947586556550140}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3504415066853500042}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3392477586643606721
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7693947586556550140}
m_CullTransparentMesh: 1
--- !u!114 &3074083777787071048
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7693947586556550140}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &9211551707266728646
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3504415066853500042}
m_Layer: 0
m_Name: Handle Slide Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3504415066853500042
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9211551707266728646}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8095715524730652885}
m_Father: {fileID: 4890485910657195775}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 535b57c53e471bb4c9a2d7940b5ad20a
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 728889ae05c256f4ca5669ec31fa5be6
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,400 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &157705238739733498
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7174374360084985875}
- component: {fileID: 1331274105184499728}
- component: {fileID: 3042592292942350693}
- component: {fileID: 3321591285440411207}
- component: {fileID: 1171217503679730641}
- component: {fileID: 6247134819645328346}
m_Layer: 0
m_Name: UI_MainMenu_Button
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7174374360084985875
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 813307877032466524}
- {fileID: 2269043522301662760}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 300, y: 56}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1331274105184499728
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_CullTransparentMesh: 1
--- !u!114 &3042592292942350693
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0.06}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &3321591285440411207
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 0.1, g: 0.55, b: 0.95, a: 1}
m_HighlightedColor: {r: 0.208, g: 0.60400003, b: 0.956, a: 1}
m_PressedColor: {r: 0.085, g: 0.4675, b: 0.8075, a: 1}
m_SelectedColor: {r: 0.208, g: 0.60400003, b: 0.956, a: 1}
m_DisabledColor: {r: 0.3, g: 0.3, b: 0.32, a: 1}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 3042592292942350693}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &1171217503679730641
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 270b0a121b06dfc4587c060335f18432, type: 3}
m_Name:
m_EditorClassIdentifier:
_variant: 0
_theme: {fileID: 11400000, guid: 88bab5495f6103f4d9d69fa043d4c3e1, type: 2}
_scaleFeedback: 1
_selectedScale: 1.06
_scaleDuration: 0.08
_onClickSfx: {fileID: 0}
_onHoverSfx: {fileID: 0}
--- !u!114 &6247134819645328346
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 157705238739733498}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: aa83d8ead83f78b428cdd2b0d1a89aa7, type: 3}
m_Name:
m_EditorClassIdentifier:
_button: {fileID: 3321591285440411207}
_label: {fileID: 5199662468546267514}
_icon: {fileID: 3358762196943047451}
--- !u!1 &1456531517881710782
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 813307877032466524}
- component: {fileID: 6811148169943758410}
- component: {fileID: 3358762196943047451}
m_Layer: 0
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &813307877032466524
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1456531517881710782}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7174374360084985875}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: 14, y: 0}
m_SizeDelta: {x: 32, y: 32}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &6811148169943758410
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1456531517881710782}
m_CullTransparentMesh: 1
--- !u!114 &3358762196943047451
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1456531517881710782}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6871540172822531622
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2269043522301662760}
- component: {fileID: 9060446448532800869}
- component: {fileID: 1310292088589468557}
- component: {fileID: 5199662468546267514}
- component: {fileID: 4564880767979808658}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2269043522301662760
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6871540172822531622}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7174374360084985875}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 22, y: 0}
m_SizeDelta: {x: -68, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9060446448532800869
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6871540172822531622}
m_CullTransparentMesh: 1
--- !u!114 &1310292088589468557
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6871540172822531622}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Menu Item
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 24
m_fontSizeBase: 24
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &5199662468546267514
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6871540172822531622}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 964e3a3ab86805244bbde47d5f54950b, type: 3}
m_Name:
m_EditorClassIdentifier:
_key:
_table: UI
_fontConfig: {fileID: 0}
--- !u!114 &4564880767979808658
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6871540172822531622}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 7
_overrideFontSize: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e2fb1298d0d8c754e9329131507a17ee
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ddba9af2988598d4fa913c21792ed775
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,203 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &289442062472622113
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1188174262370179090}
m_Layer: 0
m_Name: UI_Setting_Header
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1188174262370179090
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 289442062472622113}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5268560256912078874}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 480, y: 32}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &6990715320569207602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5268560256912078874}
- component: {fileID: 9164091955681480904}
- component: {fileID: 3435145567134533558}
- component: {fileID: 7268257288245050301}
- component: {fileID: 7398263746022830265}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5268560256912078874
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6990715320569207602}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1188174262370179090}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9164091955681480904
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6990715320569207602}
m_CullTransparentMesh: 1
--- !u!114 &3435145567134533558
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6990715320569207602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Section
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 22
m_fontSizeBase: 22
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &7268257288245050301
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6990715320569207602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 964e3a3ab86805244bbde47d5f54950b, type: 3}
m_Name:
m_EditorClassIdentifier:
_key:
_table: UI
_fontConfig: {fileID: 0}
--- !u!114 &7398263746022830265
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6990715320569207602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 9
_overrideFontSize: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1fc36ce46442d804189dcff0e57157e8
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,847 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1070957217287351926
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3792209296828831907}
- component: {fileID: 1959550421015514039}
- component: {fileID: 9051068453793032797}
m_Layer: 0
m_Name: Fill
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3792209296828831907
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1070957217287351926}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2658611266293307845}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 10, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1959550421015514039
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1070957217287351926}
m_CullTransparentMesh: 1
--- !u!114 &9051068453793032797
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1070957217287351926}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2702037931686343815
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3542422590775939441}
- component: {fileID: 4479914283644628608}
- component: {fileID: 6067219681297384585}
m_Layer: 0
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3542422590775939441
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2702037931686343815}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3284263899435988708}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4479914283644628608
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2702037931686343815}
m_CullTransparentMesh: 1
--- !u!114 &6067219681297384585
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2702037931686343815}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5544342181587606156
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7336571758001316545}
m_Layer: 0
m_Name: Handle Slide Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7336571758001316545
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5544342181587606156}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3732250768482148382}
m_Father: {fileID: 3284263899435988708}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &6130680863292913750
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3284263899435988708}
- component: {fileID: 6020905755306608269}
- component: {fileID: 7951912803875530729}
- component: {fileID: 4658929192453894749}
m_Layer: 0
m_Name: Slider
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3284263899435988708
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6130680863292913750}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3542422590775939441}
- {fileID: 2658611266293307845}
- {fileID: 7336571758001316545}
m_Father: {fileID: 534764500401432470}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 160, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6020905755306608269
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6130680863292913750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 2099364674220670182}
m_FillRect: {fileID: 3792209296828831907}
m_HandleRect: {fileID: 3732250768482148382}
m_Direction: 0
m_MinValue: 0
m_MaxValue: 1
m_WholeNumbers: 0
m_Value: 0
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
--- !u!114 &7951912803875530729
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6130680863292913750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: 20
m_FlexibleWidth: 1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &4658929192453894749
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6130680863292913750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a1743e750e4f79c43b64e07a1c1a7270, type: 3}
m_Name:
m_EditorClassIdentifier:
_slider: {fileID: 6020905755306608269}
_valueLabel: {fileID: 4351432712411767913}
_format: '{0:0}'
--- !u!1 &6513111251415266017
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 685461569274276067}
- component: {fileID: 2028758860801033200}
- component: {fileID: 8112916051202351531}
- component: {fileID: 4375017972804521103}
- component: {fileID: 6653917221928333869}
- component: {fileID: 2065978793198596394}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &685461569274276067
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 534764500401432470}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2028758860801033200
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_CullTransparentMesh: 1
--- !u!114 &8112916051202351531
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Label
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 20
m_fontSizeBase: 20
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &4375017972804521103
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 200
m_PreferredHeight: -1
m_FlexibleWidth: 0
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &6653917221928333869
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 964e3a3ab86805244bbde47d5f54950b, type: 3}
m_Name:
m_EditorClassIdentifier:
_key:
_table: UI
_fontConfig: {fileID: 0}
--- !u!114 &2065978793198596394
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6513111251415266017}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 7
_overrideFontSize: 0
--- !u!1 &7479472690954379399
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3732250768482148382}
- component: {fileID: 3467825019843033312}
- component: {fileID: 2099364674220670182}
m_Layer: 0
m_Name: Handle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3732250768482148382
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7479472690954379399}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7336571758001316545}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3467825019843033312
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7479472690954379399}
m_CullTransparentMesh: 1
--- !u!114 &2099364674220670182
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7479472690954379399}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7890162411181439519
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3800851516441515564}
- component: {fileID: 1697561054443252004}
- component: {fileID: 4351432712411767913}
- component: {fileID: 6893262776634421921}
- component: {fileID: 1140659565093859435}
m_Layer: 0
m_Name: Value
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3800851516441515564
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7890162411181439519}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 534764500401432470}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1697561054443252004
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7890162411181439519}
m_CullTransparentMesh: 1
--- !u!114 &4351432712411767913
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7890162411181439519}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: 0
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 18
m_fontSizeBase: 18
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 4
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &6893262776634421921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7890162411181439519}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 56
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &1140659565093859435
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7890162411181439519}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 8
_overrideFontSize: 0
--- !u!1 &8494921200535570368
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2658611266293307845}
m_Layer: 0
m_Name: Fill Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2658611266293307845
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8494921200535570368}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3792209296828831907}
m_Father: {fileID: 3284263899435988708}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: -5, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &8959349832593751440
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 534764500401432470}
- component: {fileID: 1763515077177812284}
m_Layer: 0
m_Name: UI_Setting_SliderRow
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &534764500401432470
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8959349832593751440}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 685461569274276067}
- {fileID: 3284263899435988708}
- {fileID: 3800851516441515564}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 480, y: 44}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1763515077177812284
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8959349832593751440}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 8
m_Right: 8
m_Top: 4
m_Bottom: 4
m_ChildAlignment: 3
m_Spacing: 12
m_ChildForceExpandWidth: 0
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b4d11fea678bb244c961f838a48b8d8a
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,589 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3995405466752322
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8196243737921290128}
- component: {fileID: 8800226531137800996}
- component: {fileID: 942878399107994917}
m_Layer: 0
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8196243737921290128
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3995405466752322}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2656612968632289128}
m_Father: {fileID: 6473902974054121827}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 10, y: -10}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8800226531137800996
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3995405466752322}
m_CullTransparentMesh: 1
--- !u!114 &942878399107994917
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3995405466752322}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2451954446105504201
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1673254917135424496}
- component: {fileID: 4659366053795274176}
- component: {fileID: 95609837900800165}
- component: {fileID: 1304675786351196457}
- component: {fileID: 301319037677175097}
- component: {fileID: 3999780911325784356}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1673254917135424496
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1428818964736103486}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4659366053795274176
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_CullTransparentMesh: 1
--- !u!114 &95609837900800165
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Label
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_sharedMaterial: {fileID: 1445647621079294416, guid: c9ebf78286d2b6345b16575012502acc, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 20
m_fontSizeBase: 20
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 4096
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &1304675786351196457
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 200
m_PreferredHeight: -1
m_FlexibleWidth: 0
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &301319037677175097
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 964e3a3ab86805244bbde47d5f54950b, type: 3}
m_Name:
m_EditorClassIdentifier:
_key:
_table: UI
_fontConfig: {fileID: 0}
--- !u!114 &3999780911325784356
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2451954446105504201}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 7
_overrideFontSize: 0
--- !u!1 &3055060066778635686
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1428818964736103486}
- component: {fileID: 4398321019914005696}
m_Layer: 0
m_Name: UI_Setting_ToggleRow
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1428818964736103486
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3055060066778635686}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1673254917135424496}
- {fileID: 6473902974054121827}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 480, y: 44}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &4398321019914005696
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3055060066778635686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 8
m_Right: 8
m_Top: 4
m_Bottom: 4
m_ChildAlignment: 3
m_Spacing: 12
m_ChildForceExpandWidth: 0
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &4266586670429411161
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7493993138355221773}
- component: {fileID: 7236726997102272855}
- component: {fileID: 5058325138044312319}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7493993138355221773
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4266586670429411161}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6473902974054121827}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 9, y: -0.5}
m_SizeDelta: {x: -28, y: -3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7236726997102272855
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4266586670429411161}
m_CullTransparentMesh: 1
--- !u!114 &5058325138044312319
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4266586670429411161}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: Toggle
--- !u!1 &8258555473425308654
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2656612968632289128}
- component: {fileID: 9027761644858669518}
- component: {fileID: 6035592076729699155}
m_Layer: 0
m_Name: Checkmark
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2656612968632289128
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8258555473425308654}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8196243737921290128}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9027761644858669518
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8258555473425308654}
m_CullTransparentMesh: 1
--- !u!114 &6035592076729699155
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8258555473425308654}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &9090532220244762198
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6473902974054121827}
- component: {fileID: 6356272649930288434}
- component: {fileID: 3779328636036996330}
m_Layer: 0
m_Name: Toggle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6473902974054121827
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9090532220244762198}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8196243737921290128}
- {fileID: 7493993138355221773}
m_Father: {fileID: 1428818964736103486}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 160, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6356272649930288434
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9090532220244762198}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 942878399107994917}
toggleTransition: 1
graphic: {fileID: 6035592076729699155}
m_Group: {fileID: 0}
onValueChanged:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
--- !u!114 &3779328636036996330
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9090532220244762198}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 30
m_PreferredHeight: 30
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f8f9f3d7a98b3e5498882a7d28c4cfe5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2223001114492423287
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 917245127540703404}
- component: {fileID: 4391685559759235234}
- component: {fileID: 4856692938931279967}
- component: {fileID: 3408593224840790089}
- component: {fileID: 1073301951202894995}
- component: {fileID: 7181543472462533001}
m_Layer: 0
m_Name: UI_SettingsPanel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &917245127540703404
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4833472193421351787}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 540, y: 640}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4391685559759235234
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_CullTransparentMesh: 1
--- !u!114 &4856692938931279967
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.06, g: 0.07, b: 0.1, a: 0.96}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &3408593224840790089
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1fa7f5f3910b010489199ef7ddee773e, type: 3}
m_Name:
m_EditorClassIdentifier:
_kind: 3
_overrideFontSize: 0
--- !u!114 &1073301951202894995
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 50572ad108fd3354da04ea8fba66370b, type: 3}
m_Name:
m_EditorClassIdentifier:
_theme: {fileID: 11400000, guid: 88bab5495f6103f4d9d69fa043d4c3e1, type: 2}
_applyOnEnable: 1
--- !u!114 &7181543472462533001
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2223001114492423287}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a7cf26a2f7cc5bb49b573bbe9f5614b5, type: 3}
m_Name:
m_EditorClassIdentifier:
_firstSelected: {fileID: 0}
_canvasGroup: {fileID: 0}
_fadeInDuration: 0.15
_selectFirstOnEnable: 1
_schema: {fileID: 11400000, guid: e4755a1ee888ca14ab8889635a7d547c, type: 2}
_container: {fileID: 4833472193421351787}
_headerPrefab: {fileID: 289442062472622113, guid: 1fc36ce46442d804189dcff0e57157e8, type: 3}
_sliderRowPrefab: {fileID: 8959349832593751440, guid: b4d11fea678bb244c961f838a48b8d8a, type: 3}
_toggleRowPrefab: {fileID: 3055060066778635686, guid: f8f9f3d7a98b3e5498882a7d28c4cfe5, type: 3}
_dropdownRowPrefab: {fileID: 2833855665454200082, guid: ddba9af2988598d4fa913c21792ed775, type: 3}
--- !u!1 &4104686635909379854
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4833472193421351787}
- component: {fileID: 7986706200646771626}
m_Layer: 0
m_Name: Content
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4833472193421351787
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4104686635909379854}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 917245127540703404}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -32, y: -32}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &7986706200646771626
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4104686635909379854}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 1
m_Spacing: 6
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: af91076953b254749b310d9184a34d49
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -2013,6 +2013,7 @@ GameObject:
- component: {fileID: 359293281} - component: {fileID: 359293281}
- component: {fileID: 359293283} - component: {fileID: 359293283}
- component: {fileID: 359293282} - component: {fileID: 359293282}
- component: {fileID: 359293284}
m_Layer: 0 m_Layer: 0
m_Name: EventSystem m_Name: EventSystem
m_TagString: Untagged m_TagString: Untagged
@@ -2081,6 +2082,18 @@ MonoBehaviour:
m_FirstSelected: {fileID: 0} m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1 m_sendNavigationEvents: 1
m_DragThreshold: 10 m_DragThreshold: 10
--- !u!114 &359293284
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 359293280}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a95115526c2b68e469f425df962742e4, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &377842515 --- !u!1 &377842515
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -4010,9 +4023,6 @@ MonoBehaviour:
m_Script: {fileID: 1136785156} m_Script: {fileID: 1136785156}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_mode: 0
_actionName:
_bindingPath:
--- !u!114 &639737772 --- !u!114 &639737772
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -5000,6 +5010,7 @@ GameObject:
- component: {fileID: 814710354} - component: {fileID: 814710354}
- component: {fileID: 814710353} - component: {fileID: 814710353}
- component: {fileID: 814710352} - component: {fileID: 814710352}
- component: {fileID: 814710356}
m_Layer: 0 m_Layer: 0
m_Name: Main Camera m_Name: Main Camera
m_TagString: MainCamera m_TagString: MainCamera
@@ -5113,6 +5124,50 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 1800597369} m_Father: {fileID: 1800597369}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &814710356
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 814710351}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_RenderShadows: 1
m_RequiresDepthTextureOption: 2
m_RequiresOpaqueTextureOption: 2
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_AllowHDROutput: 1
m_UseScreenCoordOverride: 0
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
m_TaaSettings:
m_Quality: 3
m_FrameInfluence: 0.1
m_JitterScale: 1
m_MipBias: 0
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
--- !u!1 &825595902 --- !u!1 &825595902
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -1,6 +1,7 @@
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using BaseGames.Dialogue; using BaseGames.Dialogue;
using BaseGames.Editor.Localization;
namespace BaseGames.Editor.Dialogue namespace BaseGames.Editor.Dialogue
{ {
@@ -78,30 +79,10 @@ namespace BaseGames.Editor.Dialogue
} }
/// <summary> /// <summary>
/// 在 Project 窗口中 Ping 指定表名对应的本地化 JSON 文件Resources/Localization/…/{tableName}.json /// 在 Project 窗口中 Ping 指定表名对应的本地化 JSON 文件
/// 遍历所有语言目录,以第一个找到的文件为准 /// Assets/_Game/Data/Localization/…/{tableName}.json优先简体中文 → 英文)
/// </summary> /// </summary>
private static void PingLocalizationFile(string tableName) private static void PingLocalizationFile(string tableName)
{ => LocalizationFileIO.PingAny(tableName);
string[] guids = AssetDatabase.FindAssets(
$"t:TextAsset {tableName}",
new[] { "Assets/Resources/Localization" });
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
// 文件名(不含扩展名)必须完全匹配 tableName
if (!path.EndsWith($"/{tableName}.json", System.StringComparison.OrdinalIgnoreCase)) continue;
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
if (asset == null) continue;
EditorGUIUtility.PingObject(asset);
Selection.activeObject = asset;
return;
}
Debug.LogWarning($"[NpcSOEditor] 未找到本地化表文件Resources/Localization/…/{tableName}.json");
}
} }
} }

View File

@@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using BaseGames.Localization;
namespace BaseGames.Editor.Localization
{
/// <summary>
/// 本地化 CSVExcel 往返)读写共享工具。
///
/// CSV 约定:
/// - 列顺序:<c>key, ChineseSimplified, English, Japanese, Korean</c>(表头用 <see cref="Language"/> 枚举名)。
/// - 以 <b>UTF-8 BOM</b> 写出,使 Excel 双击打开时中日韩文不乱码。
/// - 解析遵循 RFC 4180带引号字段可含逗号 / 换行 / 双引号转义),并自动剥离前导 BOM。
/// - 导入语义:合并(覆盖已有 key、追加新 key、不删除多余 key
/// </summary>
public static class LocalizationCsv
{
/// <summary>导出列顺序(与导入表头解析共用)。</summary>
public static readonly Language[] Columns = LocalizationFileIO.AllLanguages;
// 带 BOM 的 UTF-8Excel 友好)
private static readonly Encoding Utf8Bom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
// ── 高层:表 ⇄ CSV 文件 ─────────────────────────────────────────────────
/// <summary>
/// 将给定的"语言→字典"导出为该表的 CSV 文件(含 BOM。返回写出的资产路径。
/// </summary>
public static string ExportToFile(string table,
IReadOnlyDictionary<Language, Dictionary<string, string>> langDicts)
{
// 汇总所有语言出现过的 key排序保证稳定 diff
var allKeys = new SortedSet<string>(StringComparer.Ordinal);
foreach (var lang in Columns)
if (langDicts.TryGetValue(lang, out var d) && d != null)
foreach (var k in d.Keys) allKeys.Add(k);
string csvText = BuildCsvText(allKeys, langDicts);
EditorScaffoldUtils.EnsureFolder(LocalizationPaths.ExportRoot);
string assetPath = LocalizationPaths.CsvPath(table);
File.WriteAllText(ToFullPath(assetPath), csvText, Utf8Bom);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
return assetPath;
}
/// <summary>
/// 读取该表的 CSV 文件并解析为"语言→字典"(仅含表头出现的语言列)。
/// CSV 文件不存在时返回 null。
/// </summary>
public static Dictionary<Language, Dictionary<string, string>> ParseFile(string table)
{
string assetPath = LocalizationPaths.CsvPath(table);
string fullPath = ToFullPath(assetPath);
if (!File.Exists(fullPath)) return null;
return ParseText(File.ReadAllText(fullPath, Encoding.UTF8));
}
/// <summary>
/// 将该表的 CSV 合并写回磁盘 JSON供批处理工具用
/// 对 CSV 表头出现的每个语言,读现有 JSON → 合并 CSV → <see cref="LocalizationFileIO.Write"/>。
/// 返回受影响的语言数CSV 不存在时返回 0。
/// </summary>
public static int ImportFileToJson(string table)
{
var parsed = ParseFile(table);
if (parsed == null) return 0;
foreach (var (lang, csvDict) in parsed)
{
var merged = LocalizationFileIO.Read(lang, table); // 现有 JSON 副本
foreach (var kv in csvDict) merged[kv.Key] = kv.Value;
LocalizationFileIO.Write(lang, table, merged);
}
return parsed.Count;
}
// ── 低层:文本 ⇄ 行 ─────────────────────────────────────────────────────
/// <summary>构造 CSV 文本(表头 + 数据行,按 allKeys 顺序)。</summary>
public static string BuildCsvText(IEnumerable<string> orderedKeys,
IReadOnlyDictionary<Language, Dictionary<string, string>> langDicts)
{
var sb = new StringBuilder();
sb.Append("key");
foreach (var lang in Columns) sb.Append(',').Append(lang);
sb.Append('\n');
foreach (var key in orderedKeys)
{
sb.Append(Escape(key));
foreach (var lang in Columns)
{
string val = "";
if (langDicts.TryGetValue(lang, out var d) && d != null)
d.TryGetValue(key, out val);
sb.Append(',').Append(Escape(val ?? ""));
}
sb.Append('\n');
}
return sb.ToString();
}
/// <summary>解析 CSV 文本为"语言→字典"(仅表头识别出的 Language 列)。</summary>
public static Dictionary<Language, Dictionary<string, string>> ParseText(string text)
{
var rows = ParseRows(text);
var result = new Dictionary<Language, Dictionary<string, string>>();
if (rows.Count < 2) return result;
// 表头:列号 → Language
var header = rows[0];
var langCols = new List<(int col, Language lang)>();
for (int col = 1; col < header.Count; col++)
if (Enum.TryParse<Language>(header[col].Trim(), out var lang))
{
langCols.Add((col, lang));
result[lang] = new Dictionary<string, string>(StringComparer.Ordinal);
}
for (int row = 1; row < rows.Count; row++)
{
var cells = rows[row];
if (cells.Count == 0 || string.IsNullOrWhiteSpace(cells[0])) continue;
string key = cells[0];
foreach (var (col, lang) in langCols)
result[lang][key] = col < cells.Count ? cells[col] : "";
}
return result;
}
/// <summary>按 RFC 4180 规范转义单元格(含逗号 / 引号 / 换行时用双引号包裹)。</summary>
public static string Escape(string value)
{
if (value == null) return "";
bool needsQuote = value.IndexOf(',') >= 0 || value.IndexOf('"') >= 0
|| value.IndexOf('\n') >= 0 || value.IndexOf('\r') >= 0;
if (!needsQuote) return value;
return "\"" + value.Replace("\"", "\"\"") + "\"";
}
/// <summary>RFC 4180 CSV 解析器,支持带引号字段(含换行),并剥离前导 UTF-8 BOM。</summary>
public static List<List<string>> ParseRows(string text)
{
var rows = new List<List<string>>();
if (string.IsNullOrEmpty(text)) return rows;
// 剥离前导 BOMFile.ReadAllText 以 UTF8 读时若文件带 BOM 会保留为 U+FEFF
if (text[0] == '') text = text.Substring(1);
var row = new List<string>();
var cell = new StringBuilder();
bool inQuote = false;
int i = 0;
while (i < text.Length)
{
char c = text[i];
if (inQuote)
{
if (c == '"')
{
if (i + 1 < text.Length && text[i + 1] == '"') { cell.Append('"'); i += 2; }
else { inQuote = false; i++; }
}
else { cell.Append(c); i++; }
}
else
{
if (c == '"') { inQuote = true; i++; }
else if (c == ',') { row.Add(cell.ToString()); cell.Clear(); i++; }
else if (c == '\r')
{
row.Add(cell.ToString()); cell.Clear();
rows.Add(row); row = new List<string>();
if (i + 1 < text.Length && text[i + 1] == '\n') i++;
i++;
}
else if (c == '\n')
{ row.Add(cell.ToString()); cell.Clear(); rows.Add(row); row = new List<string>(); i++; }
else { cell.Append(c); i++; }
}
}
if (cell.Length > 0 || row.Count > 0)
{
row.Add(cell.ToString());
rows.Add(row);
}
return rows;
}
private static string ToFullPath(string assetPath)
{
string projectRoot = Path.GetDirectoryName(Application.dataPath)!;
return Path.Combine(projectRoot, assetPath.Replace('/', Path.DirectorySeparatorChar));
}
}
}

View File

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

View File

@@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using BaseGames.Localization; using BaseGames.Localization;
@@ -11,11 +9,12 @@ namespace BaseGames.Editor.Localization
/// <summary> /// <summary>
/// 本地化 CSV 导入/导出工具。 /// 本地化 CSV 导入/导出工具。
/// ///
/// 每个表导出为独立 CSV列顺序key, ChineseSimplified, English, Japanese, Korean。 /// 每个表导出为独立 CSV(含 UTF-8 BOMExcel 中文不乱码)列顺序key, ChineseSimplified, English, Japanese, Korean。
/// 文件存放路径Assets/_Game/Localization/Export/{TableName}.csv /// 文件存放路径Assets/_Game/Localization/Export/{TableName}.csv
/// ///
/// 导入:读取 CSV → 回写 Resources/Localization/{Language}/{TableName}.json /// 导入:读取 CSV → 合并回写 Assets/_Game/Data/Localization/{Language}/{TableName}.json(经 LocalizationFileIO
/// ///
/// 注日常单表编辑请用「BaseGames / Localization / 表格编辑器」,此窗口用于批量多表导入导出。
/// 菜单BaseGames / Localization / CSV 导入导出工具 /// 菜单BaseGames / Localization / CSV 导入导出工具
/// </summary> /// </summary>
public class LocalizationCsvTool : EditorWindow public class LocalizationCsvTool : EditorWindow
@@ -29,9 +28,6 @@ namespace BaseGames.Editor.Localization
// ── 状态 ───────────────────────────────────────────────────────────── // ── 状态 ─────────────────────────────────────────────────────────────
private static readonly Language[] s_allLanguages =
(Language[])Enum.GetValues(typeof(Language));
private static readonly string[] s_allTables = private static readonly string[] s_allTables =
{ {
LocalizationTable.UI, LocalizationTable.UI,
@@ -45,6 +41,7 @@ namespace BaseGames.Editor.Localization
}; };
private const string ExportDir = "Assets/_Game/Localization/Export"; private const string ExportDir = "Assets/_Game/Localization/Export";
private const string DataDir = LocalizationPaths.DataRoot;
private readonly bool[] _exportSelected = new bool[s_allTables.Length]; private readonly bool[] _exportSelected = new bool[s_allTables.Length];
private readonly bool[] _importSelected = new bool[s_allTables.Length]; private readonly bool[] _importSelected = new bool[s_allTables.Length];
@@ -61,7 +58,7 @@ namespace BaseGames.Editor.Localization
EditorGUILayout.Space(6); EditorGUILayout.Space(6);
GUILayout.Label("📤 导出 → CSV", EditorStyles.boldLabel); GUILayout.Label("📤 导出 → CSV", EditorStyles.boldLabel);
EditorGUILayout.HelpBox( EditorGUILayout.HelpBox(
$"将 Resources/Localization/ 中的 JSON 表导出为 CSV 文件。\n" + $"将 {DataDir}/ 中的 JSON 表导出为 CSV 文件UTF-8 BOMExcel 可直接打开)。\n" +
$"目标目录:{ExportDir}/", $"目标目录:{ExportDir}/",
MessageType.Info); MessageType.Info);
@@ -84,7 +81,7 @@ namespace BaseGames.Editor.Localization
GUILayout.Label("📥 导入 ← CSV", EditorStyles.boldLabel); GUILayout.Label("📥 导入 ← CSV", EditorStyles.boldLabel);
EditorGUILayout.HelpBox( EditorGUILayout.HelpBox(
$"读取 {ExportDir}/ 中的 CSV回写至 Resources/Localization/ JSON 文件。\n" + $"读取 {ExportDir}/ 中的 CSV合并回写至 {DataDir}/ JSON 文件。\n" +
"已有 Key 覆盖,新增 Key 追加,不删除多余 Key。", "已有 Key 覆盖,新增 Key 追加,不删除多余 Key。",
MessageType.Info); MessageType.Info);
@@ -114,7 +111,7 @@ namespace BaseGames.Editor.Localization
private void RunExport() private void RunExport()
{ {
EnsureDirectory(ExportDir); LocalizationManager.ClearEditorPreviewCache();
int exported = 0; int exported = 0;
try try
@@ -126,50 +123,23 @@ namespace BaseGames.Editor.Localization
EditorUtility.DisplayProgressBar("导出 CSV", $"导出 {tableName}…", (float)ti / s_allTables.Length); EditorUtility.DisplayProgressBar("导出 CSV", $"导出 {tableName}…", (float)ti / s_allTables.Length);
// 收集所有语言字典(以第一个语言的 Key 集合为主键集 // 经统一门面读取各语言字典(正确路径),交给 LocalizationCsv 写出(含 BOM
var langDicts = new Dictionary<Language, Dictionary<string, string>>(); var langDicts = new Dictionary<Language, Dictionary<string, string>>();
var allKeys = new SortedSet<string>(StringComparer.Ordinal); bool any = false;
foreach (var lang in LocalizationFileIO.AllLanguages)
foreach (var lang in s_allLanguages)
{
LocalizationManager.ClearEditorPreviewCache();
var dict = LocalizationManager.GetEditorTable(lang, tableName);
if (dict != null)
{ {
var dict = LocalizationFileIO.Read(lang, tableName);
langDicts[lang] = dict; langDicts[lang] = dict;
foreach (var k in dict.Keys) allKeys.Add(k); if (dict.Count > 0) any = true;
}
} }
if (allKeys.Count == 0) if (!any)
{ {
Debug.LogWarning($"[CsvTool] 表「{tableName}」无数据,跳过导出。"); Debug.LogWarning($"[CsvTool] 表「{tableName}」无数据,跳过导出。");
continue; continue;
} }
var sb = new StringBuilder(); LocalizationCsv.ExportToFile(tableName, langDicts);
// 表头
sb.Append("key");
foreach (var lang in s_allLanguages)
sb.Append(',').Append(lang);
sb.AppendLine();
// 数据行
foreach (var key in allKeys)
{
sb.Append(CsvEscape(key));
foreach (var lang in s_allLanguages)
{
string val = "";
if (langDicts.TryGetValue(lang, out var d))
d.TryGetValue(key, out val);
sb.Append(',').Append(CsvEscape(val ?? ""));
}
sb.AppendLine();
}
string csvPath = $"{ExportDir}/{tableName}.csv";
File.WriteAllText(csvPath, sb.ToString(), Encoding.UTF8);
exported++; exported++;
} }
} }
@@ -195,61 +165,18 @@ namespace BaseGames.Editor.Localization
{ {
if (!_importSelected[ti]) continue; if (!_importSelected[ti]) continue;
string tableName = s_allTables[ti]; string tableName = s_allTables[ti];
string csvPath = Path.Combine(Path.GetDirectoryName(Application.dataPath)!, $"{ExportDir}/{tableName}.csv");
EditorUtility.DisplayProgressBar("导入 CSV", $"导入 {tableName}…", (float)ti / s_allTables.Length); EditorUtility.DisplayProgressBar("导入 CSV", $"导入 {tableName}…", (float)ti / s_allTables.Length);
if (!File.Exists(csvPath))
{
Debug.LogWarning($"[CsvTool] CSV 文件不存在,跳过:{ExportDir}/{tableName}.csv");
continue;
}
try try
{ {
var rows = ParseCsv(File.ReadAllText(csvPath, Encoding.UTF8)); // 合并语义 + 正确格式/目录/Addressable 注册,全部由统一门面处理
if (rows.Count < 2) continue; int affected = LocalizationCsv.ImportFileToJson(tableName);
if (affected == 0)
// 表头行解析出列对应的语言
var header = rows[0];
var langCols = new List<(int col, Language lang)>();
for (int col = 1; col < header.Count; col++)
{ {
if (Enum.TryParse<Language>(header[col].Trim(), out var lang)) Debug.LogWarning($"[CsvTool] CSV 文件不存在或为空,跳过:{ExportDir}/{tableName}.csv");
langCols.Add((col, lang)); continue;
} }
// 为每个语言准备合并后的字典
var mergedDicts = new Dictionary<Language, Dictionary<string, string>>();
foreach (var (_, lang) in langCols)
{
LocalizationManager.ClearEditorPreviewCache();
var existing = LocalizationManager.GetEditorTable(lang, tableName)
?? new Dictionary<string, string>(StringComparer.Ordinal);
mergedDicts[lang] = new Dictionary<string, string>(existing, StringComparer.Ordinal);
}
// 用 CSV 数据覆盖/追加
for (int row = 1; row < rows.Count; row++)
{
var cells = rows[row];
if (cells.Count == 0 || string.IsNullOrWhiteSpace(cells[0])) continue;
string key = cells[0];
foreach (var (col, lang) in langCols)
{
string val = col < cells.Count ? cells[col] : "";
mergedDicts[lang][key] = val;
}
}
// 写回 JSON
foreach (var (lang, dict) in mergedDicts)
{
string jsonPath = GetJsonPath(lang, tableName);
EnsureDirectory(Path.GetDirectoryName(jsonPath));
File.WriteAllText(jsonPath, DictToJson(dict), Encoding.UTF8);
}
imported++; imported++;
} }
catch (Exception ex) catch (Exception ex)
@@ -275,104 +202,6 @@ namespace BaseGames.Editor.Localization
// ── 工具函数 ───────────────────────────────────────────────────────── // ── 工具函数 ─────────────────────────────────────────────────────────
/// <summary>将 value 按 RFC 4180 规范包裹(含逗号/双引号/换行时用双引号包裹,内部双引号转义为 "")。</summary>
private static string CsvEscape(string value)
{
if (value == null) return "";
bool needsQuote = value.Contains(',') || value.Contains('"') || value.Contains('\n') || value.Contains('\r');
if (!needsQuote) return value;
return "\"" + value.Replace("\"", "\"\"") + "\"";
}
/// <summary>简单 CSV 解析器,支持 RFC 4180 带引号字段(含换行)。</summary>
private static List<List<string>> ParseCsv(string text)
{
var rows = new List<List<string>>();
var row = new List<string>();
var cell = new StringBuilder();
bool inQuote = false;
int i = 0;
while (i < text.Length)
{
char c = text[i];
if (inQuote)
{
if (c == '"')
{
if (i + 1 < text.Length && text[i + 1] == '"')
{ cell.Append('"'); i += 2; }
else
{ inQuote = false; i++; }
}
else
{ cell.Append(c); i++; }
}
else
{
if (c == '"')
{ inQuote = true; i++; }
else if (c == ',')
{ row.Add(cell.ToString()); cell.Clear(); i++; }
else if (c == '\r')
{
row.Add(cell.ToString()); cell.Clear();
rows.Add(row); row = new List<string>();
if (i + 1 < text.Length && text[i + 1] == '\n') i++;
i++;
}
else if (c == '\n')
{ row.Add(cell.ToString()); cell.Clear(); rows.Add(row); row = new List<string>(); i++; }
else
{ cell.Append(c); i++; }
}
}
if (cell.Length > 0 || row.Count > 0)
{
row.Add(cell.ToString());
rows.Add(row);
}
return rows;
}
/// <summary>将字符串字典序列化为最小 JSON 对象UTF-8适合直接写入 Resources JSON。</summary>
private static string DictToJson(Dictionary<string, string> dict)
{
var sb = new StringBuilder();
sb.AppendLine("{");
int written = 0;
foreach (var kv in dict)
{
sb.Append(" ").Append(JsonString(kv.Key)).Append(": ").Append(JsonString(kv.Value));
if (++written < dict.Count) sb.Append(',');
sb.AppendLine();
}
sb.Append('}');
return sb.ToString();
}
private static string JsonString(string s)
{
if (s == null) return "\"\"";
s = s.Replace("\\", "\\\\")
.Replace("\"", "\\\"")
.Replace("\n", "\\n")
.Replace("\r", "\\r")
.Replace("\t", "\\t");
return $"\"{s}\"";
}
private static string GetJsonPath(Language lang, string tableName)
=> $"Assets/Resources/Localization/{lang}/{tableName}.json";
private static void EnsureDirectory(string dir)
{
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
}
private static void SetAll(bool[] arr, bool v) private static void SetAll(bool[] arr, bool v)
{ {
for (int i = 0; i < arr.Length; i++) arr[i] = v; for (int i = 0; i < arr.Length; i++) arr[i] = v;

View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using BaseGames.Localization;
namespace BaseGames.Editor.Localization
{
/// <summary>
/// 本地化 JSON 表的编辑器侧磁盘读写门面(唯一入口)。
///
/// 所有编辑器工具表格编辑器、CSV 工具、审计模块、各 Inspector读写本地化文件
/// 都必须经此类,统一:路径(<see cref="LocalizationPaths"/>)、格式
/// <see cref="LocalizationSerializer"/>、Addressable 注册、编辑器缓存刷新。
///
/// 这样运行时加载与编辑器写盘永不脱节——杜绝"编辑器看着正常、Play 加载不到"的隐藏 bug。
/// </summary>
public static class LocalizationFileIO
{
/// <summary>所有受支持语言(枚举顺序)。</summary>
public static readonly Language[] AllLanguages =
(Language[])Enum.GetValues(typeof(Language));
// ── 读 ───────────────────────────────────────────────────────────────
/// <summary>
/// 读取指定语言 + 表的 key→value 字典(返回可安全修改的副本,不存在时返回空字典)。
/// 内部走 <see cref="LocalizationManager.GetEditorTable"/> 复用其静态缓存。
/// </summary>
public static Dictionary<string, string> Read(Language language, string table)
{
var src = LocalizationManager.GetEditorTable(language, table);
return src == null
? new Dictionary<string, string>(StringComparer.Ordinal)
: new Dictionary<string, string>(src, StringComparer.Ordinal);
}
/// <summary>该表的 JSON 文件是否已存在于磁盘。</summary>
public static bool TableExists(Language language, string table)
=> AssetDatabase.LoadAssetAtPath<TextAsset>(LocalizationPaths.AssetPath(language, table)) != null;
/// <summary>扫描数据根目录,返回磁盘上实际存在子目录的语言。</summary>
public static List<Language> DiscoverLanguages()
{
var result = new List<Language>();
if (!AssetDatabase.IsValidFolder(LocalizationPaths.DataRoot)) return result;
foreach (var langFolder in AssetDatabase.GetSubFolders(LocalizationPaths.DataRoot))
{
string langName = Path.GetFileName(langFolder);
if (Enum.TryParse<Language>(langName, out var lang))
result.Add(lang);
}
return result;
}
// ── 写 ───────────────────────────────────────────────────────────────
/// <summary>
/// 将字典写回指定语言 + 表的 JSON 文件(正确的 <c>{entries:[…]}</c> 格式 + 正确目录)。
/// 新文件会自动注册到 Addressables地址 <see cref="LocalizationPaths.Address"/>
/// 写盘后清除编辑器预览缓存。
/// </summary>
/// <param name="language">目标语言。</param>
/// <param name="table">目标表名(<see cref="LocalizationTable"/> 常量)。</param>
/// <param name="dict">key→value 字典。</param>
/// <param name="registerAddressable">是否确保 Addressable 注册(默认 true。</param>
public static void Write(Language language, string table,
IReadOnlyDictionary<string, string> dict, bool registerAddressable = true)
{
string assetPath = LocalizationPaths.AssetPath(language, table);
EditorScaffoldUtils.EnsureFolder(LocalizationPaths.LanguageFolder(language));
// JSON 文件不写 BOMAddressables/TextAsset 解析期望纯 UTF-8
string json = LocalizationSerializer.Serialize(dict, sortKeys: true);
string fullPath = ToFullPath(assetPath);
File.WriteAllText(fullPath, json, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
if (registerAddressable)
EnsureAddressable(language, table, assetPath);
LocalizationManager.ClearEditorPreviewCache();
}
// ── Ping ───────────────────────────────────────────────────────────────
/// <summary>在 Project 窗口中定位指定语言 + 表的 JSON 文件。</summary>
public static TextAsset Ping(Language language, string table)
{
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(LocalizationPaths.AssetPath(language, table));
if (asset != null) EditorScaffoldUtils.PingAndSelect(asset);
return asset;
}
/// <summary>在 Project 窗口中定位指定表的任一存在语言文件(优先简体中文 → 英文 → 其余)。</summary>
public static TextAsset PingAny(string table)
{
foreach (var lang in OrderedForPing())
{
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(LocalizationPaths.AssetPath(lang, table));
if (asset != null) { EditorScaffoldUtils.PingAndSelect(asset); return asset; }
}
Debug.LogWarning($"[LocalizationFileIO] 未找到本地化表文件:{LocalizationPaths.DataRoot}/…/{table}.json");
return null;
}
// ── 内部 ───────────────────────────────────────────────────────────────
private static IEnumerable<Language> OrderedForPing()
{
yield return Language.ChineseSimplified;
yield return Language.English;
foreach (var lang in AllLanguages)
if (lang != Language.ChineseSimplified && lang != Language.English)
yield return lang;
}
/// <summary>
/// 确保该 JSON 文件已注册为对应 Addressable 地址。
/// 复用 <see cref="BaseGames.Editor.Addressables.CoreSceneRegistrar"/> 的 FindEntry-or-Create 幂等范式。
/// </summary>
private static void EnsureAddressable(Language language, string table, string assetPath)
{
var settings = AddressableAssetSettingsDefaultObject.Settings;
if (settings == null)
{
Debug.LogWarning(
$"[LocalizationFileIO] Addressable Settings 未初始化,未能注册 " +
$"{LocalizationPaths.Address(language, table)}。运行时可能加载不到该表。");
return;
}
string guid = AssetDatabase.AssetPathToGUID(assetPath);
if (string.IsNullOrEmpty(guid)) return;
string address = LocalizationPaths.Address(language, table);
var entry = settings.FindAssetEntry(guid)
?? settings.CreateOrMoveEntry(guid, settings.DefaultGroup, false, false);
// 已注册且地址正确则无需改动(避免无意义的 SetDirty
if (entry.address == address) return;
entry.address = address;
EditorUtility.SetDirty(settings);
AssetDatabase.SaveAssets();
}
private static string ToFullPath(string assetPath)
{
string projectRoot = Path.GetDirectoryName(Application.dataPath)!;
return Path.Combine(projectRoot, assetPath.Replace('/', Path.DirectorySeparatorChar));
}
}
}

View File

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

View File

@@ -60,7 +60,7 @@ namespace BaseGames.Editor.Localization
{ {
EditorUtility.DisplayDialog("Key 选择器", EditorUtility.DisplayDialog("Key 选择器",
$"表「{table}」尚无可用 Key。\n" + $"表「{table}」尚无可用 Key。\n" +
$"请先在 Resources/Localization/{{语言}}/{table}.json 中添加条目。", $"请先用「BaseGames / Localization / 表格编辑器」或在 {LocalizationPaths.DataRoot}/{{语言}}/{table}.json 中添加条目。",
"确定"); "确定");
return; return;
} }

View File

@@ -0,0 +1,463 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using BaseGames.Localization;
namespace BaseGames.Editor.Localization
{
/// <summary>
/// 本地化表格编辑器(策划录入中心)。
///
/// 以 (Key × 语言) 网格直接编辑一张本地化表,无需手改 JSON
/// - 表切换、搜索过滤、"仅显示缺失"。
/// - 新增 / 重命名 / 删除 Key跨所有语言同步
/// - 缺失单元格红底高亮。
/// - 保存:经 <see cref="LocalizationFileIO"/> 写回所有语言 JSON正确 entries 格式 + 自动注册 Addressables
/// - 工具栏内置 Excel/CSV 双向:导出 CSVUTF-8 BOM、导入 CSV合并后即时刷新网格
/// - 1000+ 行虚拟化渲染(仅绘制可见行)。
///
/// 菜单BaseGames / Localization / 表格编辑器
/// </summary>
public class LocalizationTableEditorWindow : EditorWindow
{
[MenuItem("BaseGames/Localization/表格编辑器")]
private static void Open()
{
var win = GetWindow<LocalizationTableEditorWindow>("本地化表格编辑器");
win.minSize = new Vector2(720, 480);
}
// ── 常量 ─────────────────────────────────────────────────────────────
private static readonly Language[] s_langs = LocalizationFileIO.AllLanguages;
private const float RowHeight = 22f;
private const float KeyColWidth = 240f;
private const float MinLangCol = 140f;
private const float Scrollbar = 16f;
// ── 状态 ─────────────────────────────────────────────────────────────
private string[] _tables;
private int _tableIndex;
private string _currentTable;
// 工作副本:语言 → (key → value)
private readonly Dictionary<Language, Dictionary<string, string>> _data = new();
private readonly List<string> _keys = new(); // 全部 key已排序
private readonly List<string> _filtered = new(); // 过滤后用于显示
private string _search = "";
private bool _onlyMissing;
private bool _dirty;
private Vector2 _scroll;
// 行内输入状态机(新增 / 重命名 Key
private enum InputMode { None, AddKey, RenameKey }
private InputMode _inputMode = InputMode.None;
private string _inputText = "";
private string _renameTarget;
private GUIStyle _keyBtnStyle;
// ── 生命周期 ──────────────────────────────────────────────────────────
private void OnEnable()
{
_tables = LocalizationTable.All;
_tableIndex = 0;
LoadTable(_tables[_tableIndex]);
}
// ── 数据加载 / 保存 ───────────────────────────────────────────────────
private void LoadTable(string table)
{
_currentTable = table;
_data.Clear();
LocalizationManager.ClearEditorPreviewCache();
var union = new SortedSet<string>(StringComparer.Ordinal);
foreach (var lang in s_langs)
{
var dict = LocalizationFileIO.Read(lang, table);
_data[lang] = dict;
foreach (var k in dict.Keys) union.Add(k);
}
_keys.Clear();
_keys.AddRange(union);
_dirty = false;
_inputMode = InputMode.None;
ApplyFilter();
}
private void Save()
{
foreach (var lang in s_langs)
LocalizationFileIO.Write(lang, _currentTable, _data[lang]);
AssetDatabase.SaveAssets();
_dirty = false;
ShowNotification(new GUIContent($"已保存 {_currentTable}{_keys.Count} 个 Key × {s_langs.Length} 语言)"));
}
/// <summary>切换表 / 关闭前:若有未保存改动,询问保存。返回 false 表示用户取消操作。</summary>
private bool ConfirmDiscardIfDirty(string actionDesc)
{
if (!_dirty) return true;
int choice = EditorUtility.DisplayDialogComplex(
"有未保存的改动",
$"表「{_currentTable}」有未保存的改动。{actionDesc}前要保存吗?",
"保存", "取消", "丢弃");
switch (choice)
{
case 0: Save(); return true; // 保存
case 2: return true; // 丢弃
default: return false; // 取消
}
}
// ── GUI ───────────────────────────────────────────────────────────────
private void OnGUI()
{
EnsureStyles();
DrawToolbar();
if (_inputMode != InputMode.None) DrawInputBar();
DrawHeader();
DrawGrid();
}
private void DrawToolbar()
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
// 表切换
EditorGUI.BeginChangeCheck();
int newIndex = EditorGUILayout.Popup(_tableIndex, _tables, EditorStyles.toolbarPopup, GUILayout.Width(160));
if (EditorGUI.EndChangeCheck() && newIndex != _tableIndex)
{
if (ConfirmDiscardIfDirty("切换表"))
{
_tableIndex = newIndex;
LoadTable(_tables[_tableIndex]);
}
}
// 搜索
EditorGUI.BeginChangeCheck();
_search = EditorGUILayout.TextField(_search, EditorStyles.toolbarSearchField, GUILayout.MinWidth(120));
if (EditorGUI.EndChangeCheck()) ApplyFilter();
bool prevOnlyMissing = _onlyMissing;
_onlyMissing = GUILayout.Toggle(_onlyMissing, "仅显示缺失", EditorStyles.toolbarButton, GUILayout.Width(80));
if (_onlyMissing != prevOnlyMissing) ApplyFilter();
GUILayout.FlexibleSpace();
if (GUILayout.Button(" 新增 Key", EditorStyles.toolbarButton, GUILayout.Width(80)))
BeginAddKey();
if (GUILayout.Button("导出 CSV", EditorStyles.toolbarButton, GUILayout.Width(64)))
ExportCsv();
if (GUILayout.Button("导入 CSV", EditorStyles.toolbarButton, GUILayout.Width(64)))
ImportCsv();
using (new EditorGUI.DisabledScope(!_dirty))
{
var saveContent = new GUIContent(_dirty ? "● 保存" : "保存");
if (GUILayout.Button(saveContent, EditorStyles.toolbarButton, GUILayout.Width(64)))
Save();
}
if (GUILayout.Button("刷新", EditorStyles.toolbarButton, GUILayout.Width(44)))
{
if (ConfirmDiscardIfDirty("刷新")) LoadTable(_currentTable);
}
EditorGUILayout.EndHorizontal();
}
private void DrawInputBar()
{
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
GUILayout.Label(_inputMode == InputMode.AddKey ? "新增 Key" : $"重命名「{_renameTarget}」为:",
GUILayout.Width(_inputMode == InputMode.AddKey ? 70 : 200));
GUI.SetNextControlName("LocInputField");
_inputText = EditorGUILayout.TextField(_inputText);
bool submit = false;
var e = Event.current;
if (e.type == EventType.KeyDown && (e.keyCode == KeyCode.Return || e.keyCode == KeyCode.KeypadEnter)
&& GUI.GetNameOfFocusedControl() == "LocInputField")
{ submit = true; e.Use(); }
if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Escape) { CancelInput(); e.Use(); }
if (GUILayout.Button("确认", GUILayout.Width(48)) || submit) CommitInput();
if (GUILayout.Button("取消", GUILayout.Width(48))) CancelInput();
EditorGUILayout.EndHorizontal();
// 命名提示
if (!string.IsNullOrEmpty(_inputText) && !IsValidKey(_inputText))
EditorGUILayout.HelpBox("建议使用 UPPER_SNAKE_CASE大写字母开头大写字母/数字/下划线)。", MessageType.Warning);
}
private void DrawHeader()
{
float langW = LangColWidth();
var rect = GUILayoutUtility.GetRect(0, RowHeight, GUILayout.ExpandWidth(true));
EditorGUI.DrawRect(rect, new Color(0.18f, 0.18f, 0.18f, 1f));
var keyRect = new Rect(rect.x + 4, rect.y + 3, KeyColWidth - 6, RowHeight - 4);
EditorGUI.LabelField(keyRect, $"Key{_filtered.Count}/{_keys.Count}", EditorStyles.boldLabel);
for (int c = 0; c < s_langs.Length; c++)
{
var lr = new Rect(rect.x + KeyColWidth + c * langW + 4, rect.y + 3, langW - 6, RowHeight - 4);
int missing = CountMissing(s_langs[c]);
string label = missing > 0 ? $"{s_langs[c]} (缺{missing})" : s_langs[c].ToString();
EditorGUI.LabelField(lr, label, EditorStyles.boldLabel);
}
}
private void DrawGrid()
{
float langW = LangColWidth();
float viewH = position.height - GUILayoutUtility.GetLastRect().yMax;
float contentH = _filtered.Count * RowHeight;
_scroll = GUI.BeginScrollView(
new Rect(0, GUILayoutUtility.GetLastRect().yMax, position.width, viewH),
_scroll,
new Rect(0, 0, position.width - Scrollbar, contentH));
int first = Mathf.Max(0, (int)(_scroll.y / RowHeight) - 1);
int last = Mathf.Min(_filtered.Count - 1, (int)((_scroll.y + viewH) / RowHeight) + 1);
for (int i = first; i <= last && i < _filtered.Count; i++)
DrawRow(i, _filtered[i], langW);
GUI.EndScrollView();
}
private void DrawRow(int index, string key, float langW)
{
float y = index * RowHeight;
var rowRect = new Rect(0, y, position.width - Scrollbar, RowHeight);
if (index % 2 == 0)
EditorGUI.DrawRect(rowRect, new Color(1f, 1f, 1f, 0.025f));
// Key 列(点击弹出 重命名/删除/复制 菜单)
var keyRect = new Rect(2, y + 1, KeyColWidth - 4, RowHeight - 2);
if (GUI.Button(keyRect, key, _keyBtnStyle))
ShowKeyContextMenu(key);
// 各语言可编辑单元格
for (int c = 0; c < s_langs.Length; c++)
{
var lang = s_langs[c];
var cellRect = new Rect(KeyColWidth + c * langW + 1, y + 1, langW - 2, RowHeight - 2);
_data[lang].TryGetValue(key, out var val);
if (string.IsNullOrEmpty(val))
EditorGUI.DrawRect(cellRect, new Color(0.5f, 0.15f, 0.1f, 0.28f)); // 缺失高亮
EditorGUI.BeginChangeCheck();
string newVal = EditorGUI.DelayedTextField(cellRect, val ?? "");
if (EditorGUI.EndChangeCheck())
{
_data[lang][key] = newVal;
MarkDirty();
if (_onlyMissing) ApplyFilter(); // 填上后可能从"缺失"列表消失
}
}
}
// ── Key 增删改 ────────────────────────────────────────────────────────
private void ShowKeyContextMenu(string key)
{
var menu = new GenericMenu();
menu.AddItem(new GUIContent("重命名"), false, () => BeginRename(key));
menu.AddItem(new GUIContent("删除"), false, () => DeleteKey(key));
menu.AddItem(new GUIContent("复制 Key"), false, () => EditorGUIUtility.systemCopyBuffer = key);
menu.ShowAsContext();
}
private void BeginAddKey()
{
_inputMode = InputMode.AddKey;
_inputText = "";
_renameTarget = null;
EditorGUI.FocusTextInControl("LocInputField");
}
private void BeginRename(string key)
{
_inputMode = InputMode.RenameKey;
_inputText = key;
_renameTarget = key;
EditorGUI.FocusTextInControl("LocInputField");
}
private void CommitInput()
{
string newKey = _inputText?.Trim();
if (string.IsNullOrEmpty(newKey)) { CancelInput(); return; }
if (_inputMode == InputMode.AddKey)
{
if (_keys.Contains(newKey))
{
EditorUtility.DisplayDialog("新增 Key", $"Key「{newKey}」已存在。", "确定");
return;
}
foreach (var lang in s_langs) _data[lang][newKey] = "";
_keys.Add(newKey);
_keys.Sort(StringComparer.Ordinal);
MarkDirty();
}
else if (_inputMode == InputMode.RenameKey && _renameTarget != null)
{
if (newKey == _renameTarget) { CancelInput(); return; }
if (_keys.Contains(newKey))
{
EditorUtility.DisplayDialog("重命名", $"Key「{newKey}」已存在。", "确定");
return;
}
foreach (var lang in s_langs)
{
_data[lang].TryGetValue(_renameTarget, out var v);
_data[lang].Remove(_renameTarget);
_data[lang][newKey] = v ?? "";
}
_keys.Remove(_renameTarget);
_keys.Add(newKey);
_keys.Sort(StringComparer.Ordinal);
MarkDirty();
}
_inputMode = InputMode.None;
ApplyFilter();
}
private void CancelInput()
{
_inputMode = InputMode.None;
_inputText = "";
_renameTarget = null;
GUI.FocusControl(null);
}
private void DeleteKey(string key)
{
if (!EditorUtility.DisplayDialog("删除 Key", $"确定删除「{key}」(所有语言)?", "删除", "取消"))
return;
foreach (var lang in s_langs) _data[lang].Remove(key);
_keys.Remove(key);
MarkDirty();
ApplyFilter();
}
// ── CSV 双向 ─────────────────────────────────────────────────────────
private void ExportCsv()
{
string path = LocalizationCsv.ExportToFile(_currentTable, _data);
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
if (asset != null) EditorGUIUtility.PingObject(asset);
ShowNotification(new GUIContent($"已导出 {path}"));
}
private void ImportCsv()
{
var parsed = LocalizationCsv.ParseFile(_currentTable);
if (parsed == null)
{
EditorUtility.DisplayDialog("导入 CSV",
$"未找到 CSV 文件:\n{LocalizationPaths.CsvPath(_currentTable)}\n\n请先「导出 CSV」或将文件放到该路径。",
"确定");
return;
}
// 合并进内存网格(覆盖已有 key、追加新 key、不删多余随后置脏待保存
int added = 0, updated = 0;
foreach (var (lang, csvDict) in parsed)
{
if (!_data.ContainsKey(lang)) _data[lang] = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (var kv in csvDict)
{
bool isNew = !_keys.Contains(kv.Key);
if (isNew && !_data[lang].ContainsKey(kv.Key)) added++;
else updated++;
_data[lang][kv.Key] = kv.Value;
if (!_keys.Contains(kv.Key)) _keys.Add(kv.Key);
}
}
_keys.Sort(StringComparer.Ordinal);
MarkDirty();
ApplyFilter();
ShowNotification(new GUIContent($"已导入并刷新网格(新增 {added}、更新 {updated})。记得点「保存」写回。"));
}
// ── 过滤 / 工具 ───────────────────────────────────────────────────────
private void ApplyFilter()
{
_filtered.Clear();
foreach (var key in _keys)
{
if (_onlyMissing && !HasMissing(key)) continue;
if (!string.IsNullOrEmpty(_search) && !MatchesSearch(key)) continue;
_filtered.Add(key);
}
Repaint();
}
private bool MatchesSearch(string key)
{
if (key.IndexOf(_search, StringComparison.OrdinalIgnoreCase) >= 0) return true;
foreach (var lang in s_langs)
if (_data[lang].TryGetValue(key, out var v) && !string.IsNullOrEmpty(v)
&& v.IndexOf(_search, StringComparison.OrdinalIgnoreCase) >= 0)
return true;
return false;
}
private bool HasMissing(string key)
{
foreach (var lang in s_langs)
if (!_data[lang].TryGetValue(key, out var v) || string.IsNullOrEmpty(v)) return true;
return false;
}
private int CountMissing(Language lang)
{
int n = 0;
foreach (var key in _keys)
if (!_data[lang].TryGetValue(key, out var v) || string.IsNullOrEmpty(v)) n++;
return n;
}
private float LangColWidth()
{
float avail = position.width - KeyColWidth - Scrollbar;
return Mathf.Max(MinLangCol, avail / s_langs.Length);
}
private static bool IsValidKey(string key)
{
if (string.IsNullOrEmpty(key) || !char.IsUpper(key[0])) return false;
foreach (char c in key)
if (!(char.IsUpper(c) || char.IsDigit(c) || c == '_')) return false;
return true;
}
private void MarkDirty() => _dirty = true;
private void EnsureStyles()
{
_keyBtnStyle ??= new GUIStyle(EditorStyles.label)
{
alignment = TextAnchor.MiddleLeft,
padding = new RectOffset(4, 2, 0, 0),
fontSize = 11,
};
}
}
}

View File

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

View File

@@ -64,7 +64,7 @@ namespace BaseGames.Editor.Localization
{ {
EditorGUILayout.HelpBox( EditorGUILayout.HelpBox(
$"Key「{key}」在表「{table}」中未找到(简体中文表与英文表均未命中)。\n" + $"Key「{key}」在表「{table}」中未找到(简体中文表与英文表均未命中)。\n" +
$"请检查 Resources/Localization/{{Language}}/{table}.json 文件。", $"请检查 {LocalizationPaths.DataRoot}/{{Language}}/{table}.json 文件。",
MessageType.Warning); MessageType.Warning);
} }
else else
@@ -101,7 +101,7 @@ namespace BaseGames.Editor.Localization
Repaint(); Repaint();
} }
if (GUILayout.Button($"跳转到表文件({table}", GUILayout.Width(160))) if (GUILayout.Button($"跳转到表文件({table}", GUILayout.Width(160)))
PingLocalizationFile(table); LocalizationFileIO.PingAny(table);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
} }
@@ -120,24 +120,5 @@ namespace BaseGames.Editor.Localization
catch { return template; } catch { return template; }
} }
private static void PingLocalizationFile(string tableName)
{
string[] guids = AssetDatabase.FindAssets(
$"t:TextAsset {tableName}",
new[] { "Assets/Resources/Localization" });
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (!path.EndsWith($"/{tableName}.json", System.StringComparison.OrdinalIgnoreCase)) continue;
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
if (asset == null) continue;
EditorGUIUtility.PingObject(asset);
Selection.activeObject = asset;
return;
}
Debug.LogWarning($"[LocalizedTextEditor] 未找到本地化表文件Resources/Localization/…/{tableName}.json");
}
} }
} }

View File

@@ -7,13 +7,14 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
using BaseGames.Localization; using BaseGames.Localization;
using BaseGames.Editor.Localization;
namespace BaseGames.Editor.Modules namespace BaseGames.Editor.Modules
{ {
/// <summary> /// <summary>
/// DataHub 本地化审计模块。 /// DataHub 本地化审计模块。
/// 通过 <see cref="ILocalizableAsset"/> 接口扫描项目中所有 ScriptableObject 的本地化 Key /// 通过 <see cref="ILocalizableAsset"/> 接口扫描项目中所有 ScriptableObject 的本地化 Key
/// 与 Resources/Localization/ JSON 表比对,列出缺失条目和命名不规范条目。 /// 与 Assets/_Game/Data/Localization/ JSON 表比对,列出缺失条目和命名不规范条目。
/// ///
/// 菜单入口DataHub → "本地化审计" /// 菜单入口DataHub → "本地化审计"
/// </summary> /// </summary>
@@ -168,15 +169,8 @@ namespace BaseGames.Editor.Modules
private void DiscoverLanguages() private void DiscoverLanguages()
{ {
string root = "Assets/Resources/Localization"; // 统一经 LocalizationFileIO 扫描真相源目录Assets/_Game/Data/Localization
if (!AssetDatabase.IsValidFolder(root)) return; _availableLanguages.AddRange(LocalizationFileIO.DiscoverLanguages());
foreach (var langFolder in AssetDatabase.GetSubFolders(root))
{
string langName = Path.GetFileName(langFolder);
if (Enum.TryParse<Language>(langName, out var lang))
_availableLanguages.Add(lang);
}
} }
// ── 通用 ILocalizableAsset 扫描 ─────────────────────────────────────── // ── 通用 ILocalizableAsset 扫描 ───────────────────────────────────────
@@ -556,16 +550,14 @@ namespace BaseGames.Editor.Modules
private static void PingTableFile(string language, string tableName) private static void PingTableFile(string language, string tableName)
{ {
string path = $"Assets/Resources/Localization/{language}/{tableName}.json"; if (Enum.TryParse<Language>(language, out var lang))
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
if (asset != null)
{ {
EditorGUIUtility.PingObject(asset); if (LocalizationFileIO.Ping(lang, tableName) == null)
Selection.activeObject = asset; Debug.LogWarning($"[LocalizationAudit] 未找到表文件:{LocalizationPaths.AssetPath(lang, tableName)}");
} }
else else
{ {
Debug.LogWarning($"[LocalizationAudit] 未找到表文件:{path}"); LocalizationFileIO.PingAny(tableName);
} }
} }
} }

View File

@@ -313,9 +313,25 @@ namespace BaseGames.Editor
// ── 流式加载系统 ────────────────────────────────────────────────── // ── 流式加载系统 ──────────────────────────────────────────────────
ScaffoldStreamingSystem(services, report); ScaffoldStreamingSystem(services, report);
// ── 多设备 UI 焦点守护EventSystem 上挂 UISelectionRestorer──────────
EnsureUISelectionRestorer(report);
MarkDirtyAndLog("Persistent 场景脚手架", root, report); MarkDirtyAndLog("Persistent 场景脚手架", root, report);
} }
/// <summary>确保场景中的 EventSystem 挂有 <see cref="BaseGames.UI.UISelectionRestorer"/>(多设备焦点守护,幂等)。</summary>
private static void EnsureUISelectionRestorer(List<string> report)
{
var es = Object.FindObjectOfType<UnityEngine.EventSystems.EventSystem>();
if (es == null)
{
report.Add("未找到 EventSystemUISelectionRestorer 未挂载(键盘/手柄丢失焦点后无法自动恢复)。请确认 Persistent 场景含 EventSystem + InputSystemUIInputModule。");
return;
}
if (es.GetComponent<BaseGames.UI.UISelectionRestorer>() == null)
Undo.AddComponent<BaseGames.UI.UISelectionRestorer>(es.gameObject);
}
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────
// Scaffold Main Menu Scene // Scaffold Main Menu Scene
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────
@@ -357,6 +373,7 @@ namespace BaseGames.Editor
var subTmp = GetOrAddComponent<TextMeshProUGUI>(subtitleRt.gameObject); var subTmp = GetOrAddComponent<TextMeshProUGUI>(subtitleRt.gameObject);
subTmp.text = "A 2D Action Adventure"; subTmp.fontSize = 40f; subTmp.alignment = TextAlignmentOptions.Center; subTmp.text = "A 2D Action Adventure"; subTmp.fontSize = 40f; subTmp.alignment = TextAlignmentOptions.Center;
subTmp.color = new Color(0.7f, 0.66f, 0.55f, 0.9f); subTmp.raycastTarget = false; subTmp.characterSpacing = 8f; subTmp.color = new Color(0.7f, 0.66f, 0.55f, 0.9f); subTmp.raycastTarget = false; subTmp.characterSpacing = 8f;
BindLocalizedText(subtitleRt.gameObject, "MENU_SUBTITLE");
// ── 主菜单控制器 ────────────────────────────────────────────────── // ── 主菜单控制器 ──────────────────────────────────────────────────
MainMenuController menuCtrl = GetOrAddComponent<MainMenuController>(canvasGo); MainMenuController menuCtrl = GetOrAddComponent<MainMenuController>(canvasGo);
@@ -386,6 +403,11 @@ namespace BaseGames.Editor
var le = GetOrAddComponent<LayoutElement>(b); var le = GetOrAddComponent<LayoutElement>(b);
le.preferredHeight = 64f; le.minHeight = 56f; le.preferredHeight = 64f; le.minHeight = 56f;
} }
BindLocalizedButton(btnNewGameGo, "MENU_NEW_GAME");
BindLocalizedButton(btnContinueGo, "MENU_CONTINUE");
BindLocalizedButton(btnSettingsGo, "MENU_SETTINGS");
BindLocalizedButton(btnCreditsGo, "MENU_CREDITS");
BindLocalizedButton(btnQuitGo, "MENU_QUIT");
AssignReference(menuCtrl, "_btnNewGame", btnNewGameGo.GetComponent<Button>()); AssignReference(menuCtrl, "_btnNewGame", btnNewGameGo.GetComponent<Button>());
AssignReference(menuCtrl, "_btnContinue", btnContinueGo.GetComponent<Button>()); AssignReference(menuCtrl, "_btnContinue", btnContinueGo.GetComponent<Button>());
@@ -416,6 +438,7 @@ namespace BaseGames.Editor
var slotTitleTmp = GetOrAddComponent<TextMeshProUGUI>(slotTitleRt.gameObject); var slotTitleTmp = GetOrAddComponent<TextMeshProUGUI>(slotTitleRt.gameObject);
slotTitleTmp.text = "Select Save"; slotTitleTmp.fontSize = 56f; slotTitleTmp.fontStyle = FontStyles.Bold; slotTitleTmp.text = "Select Save"; slotTitleTmp.fontSize = 56f; slotTitleTmp.fontStyle = FontStyles.Bold;
slotTitleTmp.alignment = TextAlignmentOptions.Center; slotTitleTmp.color = GoldText; slotTitleTmp.raycastTarget = false; slotTitleTmp.alignment = TextAlignmentOptions.Center; slotTitleTmp.color = GoldText; slotTitleTmp.raycastTarget = false;
BindLocalizedText(slotTitleRt.gameObject, "SAVESLOT_TITLE");
// 卡片容器(居中竖排) // 卡片容器(居中竖排)
var slotsContainerRt = GetOrCreateUIChild(saveSlotPanelGo.transform, "SlotsContainer"); var slotsContainerRt = GetOrCreateUIChild(saveSlotPanelGo.transform, "SlotsContainer");
@@ -450,6 +473,7 @@ namespace BaseGames.Editor
SetRect(slotBackRt, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), SetRect(slotBackRt, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f),
new Vector2(0f, 70f), new Vector2(260f, 64f)); new Vector2(0f, 70f), new Vector2(260f, 64f));
StyleAsTextButton(slotBackGo, 30f); StyleAsTextButton(slotBackGo, 30f);
BindLocalizedButton(slotBackGo, "BTN_BACK");
AssignReference(menuCtrl, "_btnCloseSaveSlot", slotBackGo.GetComponent<Button>()); AssignReference(menuCtrl, "_btnCloseSaveSlot", slotBackGo.GetComponent<Button>());
// ── ConfirmDialog覆盖 / 删除确认)───────────────────── // ── ConfirmDialog覆盖 / 删除确认)─────────────────────
@@ -460,15 +484,17 @@ namespace BaseGames.Editor
NewGameModeController modeCtrl = BuildNewGameMode(saveSlotPanelGo.transform); NewGameModeController modeCtrl = BuildNewGameMode(saveSlotPanelGo.transform);
AssignReference(saveSlotCtrl, "_modeSelect", modeCtrl); AssignReference(saveSlotCtrl, "_modeSelect", modeCtrl);
// ── SettingsPanel ───────────────────────────────────────────────── // ── SettingsPanel(音量 / 画面 / 可访问性 / 语言)──────────────────
var settingsPanelRt = GetOrCreateUIChild(canvasGo.transform, "SettingsPanel"); var settingsPanelRt = GetOrCreateUIChild(canvasGo.transform, "SettingsPanel");
StretchFull(settingsPanelRt); StretchFull(settingsPanelRt);
BuildSettingsPanel(settingsPanelRt.gameObject, menuCtrl, report);
settingsPanelRt.gameObject.SetActive(false); settingsPanelRt.gameObject.SetActive(false);
AssignReference(menuCtrl, "_settingsPanel", settingsPanelRt.gameObject); AssignReference(menuCtrl, "_settingsPanel", settingsPanelRt.gameObject);
// ── CreditsPanel ────────────────────────────────────────────────── // ── CreditsPanel(制作团队)────────────────────────────────────────
var creditsPanelRt = GetOrCreateUIChild(canvasGo.transform, "CreditsPanel"); var creditsPanelRt = GetOrCreateUIChild(canvasGo.transform, "CreditsPanel");
StretchFull(creditsPanelRt); StretchFull(creditsPanelRt);
BuildCreditsPanel(creditsPanelRt.gameObject, menuCtrl, report);
creditsPanelRt.gameObject.SetActive(false); creditsPanelRt.gameObject.SetActive(false);
AssignReference(menuCtrl, "_creditsPanel", creditsPanelRt.gameObject); AssignReference(menuCtrl, "_creditsPanel", creditsPanelRt.gameObject);
@@ -505,20 +531,38 @@ namespace BaseGames.Editor
bgImg.type = Image.Type.Simple; bgImg.preserveAspect = true; bgImg.enabled = false; bgImg.type = Image.Type.Simple; bgImg.preserveAspect = true; bgImg.enabled = false;
bgImg.transform.SetSiblingIndex(1); bgImg.transform.SetSiblingIndex(1);
// 全覆盖选择按钮(透明,金色高亮;位于信息层之下,靠 raycast 接收点击 // 选中/悬停高亮叠加(基色白不透明;显隐由按钮 ColorBlock 的 alpha 控制 → 可见的选中反馈
var hlImg = GetOrCreateImage(slotGo.transform, "Highlight", Color.white, false);
hlImg.transform.SetSiblingIndex(2);
// 全覆盖选择按钮(透明,靠 raycast 接收点击;着色目标为 Highlight 叠加图)
GameObject selectGo = GetOrCreateButtonChild(slotGo.transform, "SelectButton", ""); GameObject selectGo = GetOrCreateButtonChild(slotGo.transform, "SelectButton", "");
StretchFull((RectTransform)selectGo.transform); StretchFull((RectTransform)selectGo.transform);
var selImg = selectGo.GetComponent<Image>(); var selImg = selectGo.GetComponent<Image>();
if (selImg != null) selImg.color = new Color(1f, 1f, 1f, 0f); if (selImg != null) selImg.color = new Color(1f, 1f, 1f, 0f);
var selLabel = GetButtonLabel(selectGo); var selLabel = GetButtonLabel(selectGo);
if (selLabel != null) selLabel.gameObject.SetActive(false); if (selLabel != null) selLabel.gameObject.SetActive(false);
var selBtn = selectGo.GetComponent<Button>();
if (selBtn != null)
{
selBtn.targetGraphic = hlImg;
var cc = selBtn.colors;
cc.normalColor = new Color(1f, 0.85f, 0.45f, 0f); // 静态:透明
cc.highlightedColor = new Color(1f, 0.86f, 0.5f, 0.08f); // 悬停:极淡金
cc.selectedColor = new Color(1f, 0.86f, 0.5f, 0.13f); // 键盘/手柄选中:淡金叠加
cc.pressedColor = new Color(1f, 0.86f, 0.5f, 0.22f);
cc.disabledColor = new Color(1f, 1f, 1f, 0f);
cc.colorMultiplier = 1f; cc.fadeDuration = 0.1f;
selBtn.colors = cc;
}
// 空槽提示 // 空槽提示
var emptyRt = GetOrCreateUIChild(slotGo.transform, "EmptyIndicator"); var emptyRt = GetOrCreateUIChild(slotGo.transform, "EmptyIndicator");
StretchFull(emptyRt); StretchFull(emptyRt);
GameObject emptyGo = emptyRt.gameObject; GameObject emptyGo = emptyRt.gameObject;
GetOrCreateText(emptyGo.transform, "EmptyText", "Empty Slot · New Game", 34f, var emptyText = GetOrCreateText(emptyGo.transform, "EmptyText", "Empty Slot · New Game", 34f,
new Color(0.7f, 0.66f, 0.55f, 0.85f), TextAlignmentOptions.Center); new Color(0.7f, 0.66f, 0.55f, 0.85f), TextAlignmentOptions.Center);
BindLocalizedText(emptyText.gameObject, "SAVESLOT_EMPTY");
// 有档信息区(左侧竖排:区域 / 时长 / 时间)+ 右侧(灵珠 / 生命 / 钢魂) // 有档信息区(左侧竖排:区域 / 时长 / 时间)+ 右侧(灵珠 / 生命 / 钢魂)
var dataRt = GetOrCreateUIChild(slotGo.transform, "DataIndicator"); var dataRt = GetOrCreateUIChild(slotGo.transform, "DataIndicator");
@@ -540,7 +584,8 @@ namespace BaseGames.Editor
var badgeRt = GetOrCreateUIChild(dataGo.transform, "SteelSoulBadge"); var badgeRt = GetOrCreateUIChild(dataGo.transform, "SteelSoulBadge");
SetRect(badgeRt, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 4f), new Vector2(120f, 40f)); SetRect(badgeRt, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 4f), new Vector2(120f, 40f));
GetOrAddComponent<Image>(badgeRt.gameObject).color = new Color(0.5f, 0.55f, 0.6f, 0.5f); GetOrAddComponent<Image>(badgeRt.gameObject).color = new Color(0.5f, 0.55f, 0.6f, 0.5f);
GetOrCreateText(badgeRt.transform, "BadgeText", "STEEL", 22f, new Color(0.85f,0.9f,1f,1f), TextAlignmentOptions.Center); var badgeText = GetOrCreateText(badgeRt.transform, "BadgeText", "STEEL", 22f, new Color(0.85f,0.9f,1f,1f), TextAlignmentOptions.Center);
BindLocalizedText(badgeText.gameObject, "BADGE_STEELSOUL");
GameObject badgeGo = badgeRt.gameObject; GameObject badgeGo = badgeRt.gameObject;
// 删除按钮(右上角小 × // 删除按钮(右上角小 ×
@@ -597,6 +642,8 @@ namespace BaseGames.Editor
yesGo.GetComponent<Image>().color = new Color(0.45f, 0.12f, 0.12f, 0.85f); yesGo.GetComponent<Image>().color = new Color(0.45f, 0.12f, 0.12f, 0.85f);
GameObject noGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Cancel", "Cancel"); GameObject noGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Cancel", "Cancel");
SetRect((RectTransform)noGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(150f,40f), new Vector2(220f,64f)); SetRect((RectTransform)noGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(150f,40f), new Vector2(220f,64f));
BindLocalizedButton(yesGo, "CONFIRM_YES");
BindLocalizedButton(noGo, "CONFIRM_NO");
AssignReference(confirmCtrl, "_root", confirmGo); AssignReference(confirmCtrl, "_root", confirmGo);
AssignReference(confirmCtrl, "_titleText", titleTmp); AssignReference(confirmCtrl, "_titleText", titleTmp);
@@ -638,6 +685,10 @@ namespace BaseGames.Editor
GameObject backGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Back", "Back"); GameObject backGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Back", "Back");
SetRect((RectTransform)backGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0f,46f), new Vector2(260f,60f)); SetRect((RectTransform)backGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0f,46f), new Vector2(260f,60f));
StyleAsTextButton(backGo, 28f); StyleAsTextButton(backGo, 28f);
BindLocalizedText(modeTitle.gameObject, "MODE_SELECT_TITLE");
BindLocalizedButton(normalGo, "MODE_NORMAL");
BindLocalizedButton(steelGo, "MODE_STEELSOUL");
BindLocalizedButton(backGo, "BTN_BACK");
AssignReference(modeCtrl, "_root", modeGo); AssignReference(modeCtrl, "_root", modeGo);
AssignReference(modeCtrl, "_btnNormal", normalGo.GetComponent<Button>()); AssignReference(modeCtrl, "_btnNormal", normalGo.GetComponent<Button>());
@@ -1073,18 +1124,273 @@ namespace BaseGames.Editor
return t != null ? t.GetComponent<TextMeshProUGUI>() : null; return t != null ? t.GetComponent<TextMeshProUGUI>() : null;
} }
/// <summary>将按钮改造为"纯文字"风格(透明底,仅金色高亮),用于主菜单主按钮列表。</summary> /// <summary>
/// 将按钮改造为"纯文字"风格(透明底)。关键:把 Button 的 targetGraphic 指向文字 Label
/// 这样鼠标悬停Highlighted与键盘/手柄选中Selected会直接给文字着色 → 导航有可见反馈。
/// Label 基色设为白,由 ColorBlock 决定静态/高亮/选中的可见色。
/// </summary>
private static void StyleAsTextButton(GameObject buttonGo, float fontSize = 34f) private static void StyleAsTextButton(GameObject buttonGo, float fontSize = 34f)
{ {
var img = buttonGo.GetComponent<Image>(); var img = buttonGo.GetComponent<Image>();
if (img != null) img.color = new Color(1f, 1f, 1f, 0f); // 透明底,仍可作 raycast target if (img != null) { img.color = new Color(1f, 1f, 1f, 0f); img.raycastTarget = true; } // 透明底作 raycast target
var label = GetButtonLabel(buttonGo); var label = GetButtonLabel(buttonGo);
if (label != null) if (label == null) return;
{
label.fontSize = fontSize; label.fontSize = fontSize;
label.fontStyle = FontStyles.Normal; label.fontStyle = FontStyles.Normal;
label.color = GoldText; label.color = Color.white; // 基色白,实际可见色由 ColorBlock × 该色得到
var btn = buttonGo.GetComponent<Button>();
if (btn == null) return;
btn.targetGraphic = label; // 文字作为着色目标 → 选中/悬停可见
var c = btn.colors;
c.normalColor = new Color(0.60f, 0.56f, 0.42f, 1f); // 静态:暗金
c.highlightedColor = new Color(1f, 0.95f, 0.72f, 1f); // 鼠标悬停:亮金
c.selectedColor = new Color(1f, 0.95f, 0.72f, 1f); // 键盘/手柄选中:亮金
c.pressedColor = new Color(1f, 0.82f, 0.38f, 1f);
c.disabledColor = new Color(0.4f, 0.4f, 0.4f, 0.5f);
c.colorMultiplier = 1f; c.fadeDuration = 0.1f;
btn.colors = c;
} }
/// <summary>
/// 给含 TMP_Text 的节点挂上 <see cref="BaseGames.Localization.LocalizedText"/> 并绑定本地化 keyUI 表)。
/// 自动绑定 FontConfig语言切换时换 CJK 字体),并立即刷新编辑器预览(显示当前语言文本)。
/// </summary>
private static void BindLocalizedText(GameObject textGo, string key)
{
if (textGo == null || textGo.GetComponent<TMP_Text>() == null) return;
var loc = GetOrAddComponent<BaseGames.Localization.LocalizedText>(textGo);
var so = new SerializedObject(loc);
so.FindProperty("_key").stringValue = key;
var fontCfg = FindFirstAssetByType<BaseGames.Localization.LanguageFontConfigSO>("FontConfig");
if (fontCfg != null) so.FindProperty("_fontConfig").objectReferenceValue = fontCfg;
so.ApplyModifiedPropertiesWithoutUndo();
loc.UpdateEditorPreview();
}
/// <summary>给 GetOrCreateButtonChild 生成的按钮的 "Label" 子节点绑定本地化 key。</summary>
private static void BindLocalizedButton(GameObject buttonGo, string key)
{
var label = GetButtonLabel(buttonGo);
if (label != null) BindLocalizedText(label.gameObject, key);
}
// ─────────────────────────────────────────────────────────────────────
// 设置控件辅助(复用 Unity DefaultControls / TMP_DefaultControls 标准控件层级)
// ─────────────────────────────────────────────────────────────────────
private static UnityEngine.UI.DefaultControls.Resources _uiRes;
private static UnityEngine.UI.DefaultControls.Resources UIRes()
{
if (_uiRes.standard == null)
_uiRes = new UnityEngine.UI.DefaultControls.Resources
{
standard = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd"),
background = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd"),
inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/InputFieldBackground.psd"),
knob = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd"),
checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd"),
dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd"),
mask = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd"),
};
return _uiRes;
}
private static TMPro.TMP_DefaultControls.Resources _tmpRes;
private static TMPro.TMP_DefaultControls.Resources TMPRes()
{
if (_tmpRes.standard == null)
_tmpRes = new TMPro.TMP_DefaultControls.Resources
{
standard = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd"),
background = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd"),
inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/InputFieldBackground.psd"),
knob = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd"),
checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd"),
dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd"),
mask = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd"),
};
return _tmpRes;
}
/// <summary>将控件 RectTransform 放到行的右半区(横向拉伸、固定高度、垂直居中)。</summary>
private static void PlaceRightHalf(RectTransform rt, float height, float rightInset = 12f)
{
rt.anchorMin = new Vector2(0.5f, 0.5f);
rt.anchorMax = new Vector2(1f, 0.5f);
rt.pivot = new Vector2(0.5f, 0.5f);
rt.offsetMin = new Vector2(8f, -height / 2f);
rt.offsetMax = new Vector2(-rightInset, height / 2f);
}
/// <summary>创建/获取一行设置项(左侧本地化标签 + 右半区控件,由调用方填充),返回行 RectTransform。</summary>
private static RectTransform CreateSettingRow(Transform content, string name, string labelKey)
{
var row = GetOrCreateUIChild(content, name);
var le = GetOrAddComponent<LayoutElement>(row.gameObject);
le.preferredHeight = 56f; le.minHeight = 50f;
var label = GetOrCreateText(row, "Label", labelKey, 26f, GoldText, TextAlignmentOptions.MidlineLeft);
SetRect((RectTransform)label.transform, new Vector2(0f, 0f), new Vector2(0.5f, 1f), new Vector2(0f, 0.5f), new Vector2(12f, 0f), Vector2.zero);
((RectTransform)label.transform).offsetMin = new Vector2(12f, 0f);
((RectTransform)label.transform).offsetMax = new Vector2(0f, 0f);
BindLocalizedText(label.gameObject, labelKey);
return row;
}
private static Slider GetOrCreateSliderInRow(RectTransform row, float min, float max, float val, float rightInset = 12f)
{
var existing = row.Find("Slider");
GameObject go;
if (existing != null && existing.GetComponent<Slider>() != null) go = existing.gameObject;
else
{
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
go = UnityEngine.UI.DefaultControls.CreateSlider(UIRes());
go.name = "Slider";
Undo.RegisterCreatedObjectUndo(go, "Create Slider");
go.transform.SetParent(row, false);
}
PlaceRightHalf((RectTransform)go.transform, 20f, rightInset);
var s = go.GetComponent<Slider>();
s.minValue = min; s.maxValue = max; s.value = val;
return s;
}
private static Toggle GetOrCreateToggleInRow(RectTransform row)
{
var existing = row.Find("Toggle");
GameObject go;
if (existing != null && existing.GetComponent<Toggle>() != null) go = existing.gameObject;
else
{
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
go = UnityEngine.UI.DefaultControls.CreateToggle(UIRes());
go.name = "Toggle";
Undo.RegisterCreatedObjectUndo(go, "Create Toggle");
go.transform.SetParent(row, false);
}
// 隐藏勾选框自带的 Label设置项标签由行左侧统一提供
var lbl = go.transform.Find("Label");
if (lbl != null) lbl.gameObject.SetActive(false);
PlaceRightHalf((RectTransform)go.transform, 28f);
return go.GetComponent<Toggle>();
}
private static TMPro.TMP_Dropdown GetOrCreateDropdownInRow(RectTransform row, string[] options)
{
var existing = row.Find("Dropdown");
GameObject go;
if (existing != null && existing.GetComponent<TMPro.TMP_Dropdown>() != null) go = existing.gameObject;
else
{
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
go = TMPro.TMP_DefaultControls.CreateDropdown(TMPRes());
go.name = "Dropdown";
Undo.RegisterCreatedObjectUndo(go, "Create Dropdown");
go.transform.SetParent(row, false);
}
PlaceRightHalf((RectTransform)go.transform, 36f);
var dd = go.GetComponent<TMPro.TMP_Dropdown>();
dd.options.Clear();
foreach (var o in options) dd.options.Add(new TMPro.TMP_Dropdown.OptionData(o));
dd.value = 0;
dd.RefreshShownValue();
return dd;
}
// ─────────────────────────────────────────────────────────────────────
// 设置面板 / 制作团队面板构建器
// ─────────────────────────────────────────────────────────────────────
/// <summary>构建设置面板内容(音量 / 画面 / 可访问性 / 语言)并绑定 SettingsPanelController 全部字段。</summary>
private static void BuildSettingsPanel(GameObject panelGo, MainMenuController menuCtrl, List<string> report)
{
var ctrl = GetOrAddComponent<BaseGames.UI.SettingsPanelController>(panelGo);
GetOrCreateImage(panelGo.transform, "Overlay", new Color(0.04f, 0.05f, 0.08f, 0.97f), true).transform.SetAsFirstSibling();
var titleTmp = GetOrCreateText(panelGo.transform, "PanelTitle", "Settings", 56f, GoldText, TextAlignmentOptions.Center);
titleTmp.fontStyle = FontStyles.Bold;
SetRect((RectTransform)titleTmp.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -70f), new Vector2(900f, 80f));
BindLocalizedText(titleTmp.gameObject, "SETTINGS_TITLE");
var content = GetOrCreateUIChild(panelGo.transform, "Content");
SetRect(content, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -10f), new Vector2(860f, 720f));
var vlg = GetOrAddComponent<VerticalLayoutGroup>(content.gameObject);
vlg.spacing = 8f; vlg.childAlignment = TextAnchor.UpperCenter;
vlg.childControlWidth = true; vlg.childControlHeight = true;
vlg.childForceExpandWidth = true; vlg.childForceExpandHeight = false;
// 音量
var rMaster = CreateSettingRow(content, "Row_Master", "SETTINGS_MASTER_VOLUME");
var rBgm = CreateSettingRow(content, "Row_BGM", "SETTINGS_BGM_VOLUME");
var rSfx = CreateSettingRow(content, "Row_SFX", "SETTINGS_SFX_VOLUME");
var rAmbient = CreateSettingRow(content, "Row_Ambient", "SETTINGS_AMBIENT_VOLUME");
var sMaster = GetOrCreateSliderInRow(rMaster, 0f, 1f, 1f);
var sBgm = GetOrCreateSliderInRow(rBgm, 0f, 1f, 0.8f);
var sSfx = GetOrCreateSliderInRow(rSfx, 0f, 1f, 1f);
var sAmbient = GetOrCreateSliderInRow(rAmbient, 0f, 1f, 0.8f);
// 画面
var rVsync = CreateSettingRow(content, "Row_VSync", "SETTINGS_VSYNC");
var tVsync = GetOrCreateToggleInRow(rVsync);
var rFps = CreateSettingRow(content, "Row_FPS", "SETTINGS_FPS");
var dFps = GetOrCreateDropdownInRow(rFps, new[] { "30", "60", "120", "∞" });
// 可访问性
var rUiScale = CreateSettingRow(content, "Row_UIScale", "SETTINGS_UI_SCALE");
var sUiScale = GetOrCreateSliderInRow(rUiScale, 0.8f, 1.5f, 1f, 76f);
var uiScaleVal = GetOrCreateText(rUiScale, "ValueText", "100%", 22f, new Color(0.8f,0.78f,0.7f,1f), TextAlignmentOptions.MidlineRight);
SetRect((RectTransform)uiScaleVal.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-12f, 0f), new Vector2(64f, 36f));
var rColorblind = CreateSettingRow(content, "Row_Colorblind", "SETTINGS_COLORBLIND");
var dColorblind = GetOrCreateDropdownInRow(rColorblind, new[] { "关闭", "红色盲", "绿色盲", "蓝黄色盲" });
var rShake = CreateSettingRow(content, "Row_ScreenShake", "SETTINGS_SCREEN_SHAKE");
var tShake = GetOrCreateToggleInRow(rShake);
// 语言
var rLang = CreateSettingRow(content, "Row_Language", "SETTINGS_LANGUAGE");
var dLang = GetOrCreateDropdownInRow(rLang, new[] { "中文", "English", "日本語", "한국어" });
// 绑定 SettingsPanelController 字段
AssignReference(ctrl, "_masterVolume", sMaster);
AssignReference(ctrl, "_bgmVolume", sBgm);
AssignReference(ctrl, "_sfxVolume", sSfx);
AssignReference(ctrl, "_ambientVolume", sAmbient);
AssignReference(ctrl, "_vSyncToggle", tVsync);
AssignReference(ctrl, "_fpsDropdown", dFps);
AssignReference(ctrl, "_uiScaleSlider", sUiScale);
AssignReference(ctrl, "_uiScaleValueText", uiScaleVal);
AssignReference(ctrl, "_colorblindDropdown", dColorblind);
AssignReference(ctrl, "_screenShakeToggle", tShake);
AssignReference(ctrl, "_languageDropdown", dLang);
// 返回按钮
GameObject backGo = GetOrCreateButtonChild(panelGo.transform, "BackButton", "Back");
SetRect((RectTransform)backGo.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 60f), new Vector2(260f, 64f));
StyleAsTextButton(backGo, 30f);
BindLocalizedButton(backGo, "BTN_BACK");
AssignReference(menuCtrl, "_btnCloseSettings", backGo.GetComponent<Button>());
}
/// <summary>构建制作团队面板(标题 + 滚动正文 + 返回)。</summary>
private static void BuildCreditsPanel(GameObject panelGo, MainMenuController menuCtrl, List<string> report)
{
GetOrCreateImage(panelGo.transform, "Overlay", new Color(0.04f, 0.05f, 0.08f, 0.97f), true).transform.SetAsFirstSibling();
var titleTmp = GetOrCreateText(panelGo.transform, "PanelTitle", "Credits", 56f, GoldText, TextAlignmentOptions.Center);
titleTmp.fontStyle = FontStyles.Bold;
SetRect((RectTransform)titleTmp.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -70f), new Vector2(900f, 80f));
BindLocalizedText(titleTmp.gameObject, "CREDITS_TITLE");
var body = GetOrCreateText(panelGo.transform, "Body", "Credits", 30f, new Color(0.82f, 0.8f, 0.74f, 1f), TextAlignmentOptions.Top);
SetRect((RectTransform)body.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(900f, 600f));
BindLocalizedText(body.gameObject, "CREDITS_BODY");
GameObject backGo = GetOrCreateButtonChild(panelGo.transform, "BackButton", "Back");
SetRect((RectTransform)backGo.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 60f), new Vector2(260f, 64f));
StyleAsTextButton(backGo, 30f);
BindLocalizedButton(backGo, "BTN_BACK");
AssignReference(menuCtrl, "_btnCloseCredits", backGo.GetComponent<Button>());
} }
private static void AssignReference(Object target, string propertyName, Object value) private static void AssignReference(Object target, string propertyName, Object value)

View File

@@ -0,0 +1,759 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using BaseGames.UI;
using BaseGames.UI.Settings;
using BaseGames.UI.MainMenu;
using BaseGames.UI.Theme;
using BaseGames.Localization;
using BaseGames.Editor.Localization;
namespace BaseGames.Editor.UI
{
/// <summary>
/// UI 通用控件库脚手架。
///
/// 一键生成 / 更新 themed 控件预制件UIButton / UISelectableRow / UISlider / UIDropdown /
/// UISimplePanel / UITabGroup并提供"向选中节点放置控件"菜单,使策划可拖拽即用。
///
/// 预制件输出目录Assets/_Game/Prefabs/UI/Controls/(命名前缀 UI_符合 AssetFolderSpec
/// 构建方式复用 Unity/TMP 的 DefaultControls 标准层级,再挂上本项目的封装组件与 UIThemeRole 标记。
///
/// 菜单BaseGames/UI/控件库/...
/// </summary>
public static class UIControlLibraryScaffold
{
private const string ControlsDir = "Assets/_Game/Prefabs/UI/Controls";
private const string ThemeDir = "Assets/_Game/Data/UI/Themes";
private const string ThemeName = "UI_Theme_Default";
// 生成期间的默认主题GenerateAll 开头确保存在;各 Build 方法读取)
private static UIThemeSO s_theme;
// 预制件文件名
private const string PfButton = "UI_Control_Button";
private const string PfRow = "UI_Control_SelectableRow";
private const string PfSlider = "UI_Control_Slider";
private const string PfDropdown = "UI_Control_Dropdown";
private const string PfPanel = "UI_Control_Panel";
private const string PfTabBar = "UI_Control_TabBar";
// ── 生成 ─────────────────────────────────────────────────────────────
[MenuItem("BaseGames/UI/控件库/生成或更新控件预制件")]
public static void GenerateAll()
{
EnsureFolder(ControlsDir);
var report = new List<string>();
s_theme = EnsureDefaultTheme(report);
BuildButton(report);
BuildSelectableRow(report);
BuildSlider(report);
BuildDropdown(report);
BuildPanel(report);
BuildTabBar(report);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
var sb = new System.Text.StringBuilder("[UIControlLibrary] 控件预制件已生成/更新:\n");
foreach (var r in report) sb.AppendLine(" • " + r);
sb.AppendLine($"目录:{ControlsDir}/(占位配色,可挂 UIThemeApplier + UIThemeSO 统一主题)");
Debug.Log(sb.ToString());
}
// ── 放置 ─────────────────────────────────────────────────────────────
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Button")]
private static void PlaceButton() => Place(PfButton);
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ SelectableRow")]
private static void PlaceRow() => Place(PfRow);
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Slider")]
private static void PlaceSlider() => Place(PfSlider);
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Dropdown")]
private static void PlaceDropdown() => Place(PfDropdown);
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Panel")]
private static void PlacePanel() => Place(PfPanel);
[MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ TabBar")]
private static void PlaceTabBar() => Place(PfTabBar);
private static void Place(string prefabName)
{
string path = $"{ControlsDir}/{prefabName}.prefab";
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab == null)
{
EditorUtility.DisplayDialog("控件库",
$"未找到预制件:{path}\n请先执行「生成或更新控件预制件」。", "确定");
return;
}
// 父节点:当前选中的 Transform否则活动场景中的第一个 Canvas
Transform parent = Selection.activeTransform;
if (parent == null)
{
var canvas = Object.FindObjectOfType<Canvas>();
parent = canvas != null ? canvas.transform : null;
}
var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, parent);
if (instance == null) return;
Undo.RegisterCreatedObjectUndo(instance, $"Place {prefabName}");
Selection.activeGameObject = instance;
EditorGUIUtility.PingObject(instance);
}
// ── 默认主题 ─────────────────────────────────────────────────────────
private static UIThemeSO EnsureDefaultTheme(List<string> report)
{
EnsureFolder(ThemeDir);
string path = $"{ThemeDir}/{ThemeName}.asset";
var theme = AssetDatabase.LoadAssetAtPath<UIThemeSO>(path);
if (theme == null)
{
theme = ScriptableObject.CreateInstance<UIThemeSO>(); // 字段含默认配色
AssetDatabase.CreateAsset(theme, path);
report.Add($"{path}(默认主题,可调色板/字体)");
}
return theme;
}
// ── 各控件构建 ───────────────────────────────────────────────────────
private static void BuildButton(List<string> report)
{
var go = TMP_DefaultControls.CreateButton(TmpResources());
go.name = PfButton;
Size(go, 200, 48);
var uiBtn = GetOrAdd<UIButton>(go);
if (s_theme != null) AssignRef(uiBtn, "_theme", s_theme);
SetEnum(GetOrAdd<UIThemeRole>(go), "_kind", (int)UIThemeRoleKind.Button);
var label = go.GetComponentInChildren<TMP_Text>();
if (label != null)
{
label.text = "Button";
SetEnum(GetOrAdd<UIThemeRole>(label.gameObject), "_kind", (int)UIThemeRoleKind.Text_Primary);
}
SaveAsPrefab(go, PfButton, report);
}
private static void BuildSelectableRow(List<string> report)
{
var go = NewUI(PfRow, 320, 48);
var bg = go.AddComponent<Image>();
bg.sprite = Standard(); bg.type = Image.Type.Sliced;
bg.color = new Color(1f, 1f, 1f, 0.06f);
var btn = go.AddComponent<Button>();
btn.targetGraphic = bg;
var row = go.AddComponent<UISelectableRow>();
// 选中高亮(铺底,置于内容之下,默认隐藏)
var highlight = NewUIChild(go.transform, "SelectedHighlight", out var hlRt);
Stretch(hlRt);
var hlImg = highlight.AddComponent<Image>();
hlImg.color = new Color(0.20f, 0.65f, 1f, 0.35f);
SetEnum(highlight.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Graphic_Accent);
highlight.SetActive(false);
// 图标
var iconGo = NewUIChild(go.transform, "Icon", out var iconRt);
iconRt.anchorMin = new Vector2(0, 0.5f); iconRt.anchorMax = new Vector2(0, 0.5f);
iconRt.pivot = new Vector2(0, 0.5f); iconRt.anchoredPosition = new Vector2(10, 0);
iconRt.sizeDelta = new Vector2(32, 32);
var icon = iconGo.AddComponent<Image>(); icon.enabled = false;
// 标签
var labelGo = NewUIChild(go.transform, "Label", out var labelRt);
labelRt.anchorMin = new Vector2(0, 0); labelRt.anchorMax = new Vector2(1, 1);
labelRt.offsetMin = new Vector2(52, 0); labelRt.offsetMax = new Vector2(-12, 0);
var label = labelGo.AddComponent<TextMeshProUGUI>();
label.text = "Row"; label.alignment = TextAlignmentOptions.MidlineLeft; label.fontSize = 20;
SetEnum(labelGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Primary);
AssignRef(row, "_button", btn);
AssignRef(row, "_label", label);
AssignRef(row, "_icon", icon);
AssignRef(row, "_selectedHighlight", highlight);
SaveAsPrefab(go, PfRow, report);
}
private static void BuildSlider(List<string> report)
{
var go = DefaultControls.CreateSlider(UiResources());
go.name = PfSlider;
Size(go, 240, 24);
var slider = go.GetComponent<Slider>();
var ui = GetOrAdd<UISlider>(go);
// 数值标签(右侧)
var labelGo = NewUIChild(go.transform, "ValueLabel", out var labelRt);
labelRt.anchorMin = new Vector2(1, 0.5f); labelRt.anchorMax = new Vector2(1, 0.5f);
labelRt.pivot = new Vector2(0, 0.5f); labelRt.anchoredPosition = new Vector2(8, 0);
labelRt.sizeDelta = new Vector2(48, 24);
var label = labelGo.AddComponent<TextMeshProUGUI>();
label.text = "0"; label.alignment = TextAlignmentOptions.MidlineLeft; label.fontSize = 18;
SetEnum(labelGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Secondary);
AssignRef(ui, "_slider", slider);
AssignRef(ui, "_valueLabel", label);
SaveAsPrefab(go, PfSlider, report);
}
private static void BuildDropdown(List<string> report)
{
var go = TMP_DefaultControls.CreateDropdown(TmpResources());
go.name = PfDropdown;
Size(go, 200, 40);
var dd = go.GetComponent<TMP_Dropdown>();
var ui = GetOrAdd<UIDropdown>(go);
AssignRef(ui, "_dropdown", dd);
SaveAsPrefab(go, PfDropdown, report);
}
private static void BuildPanel(List<string> report)
{
var go = NewUI(PfPanel, 480, 320);
var bg = go.AddComponent<Image>();
bg.sprite = Background(); bg.type = Image.Type.Sliced;
bg.color = new Color(0.06f, 0.07f, 0.10f, 0.96f);
SetEnum(go.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Graphic_Background);
go.AddComponent<CanvasGroup>();
var applier = go.AddComponent<UIThemeApplier>();
if (s_theme != null) AssignRef(applier, "_theme", s_theme);
var panel = go.AddComponent<UISimplePanel>();
AssignRef(panel, "_canvasGroup", go.GetComponent<CanvasGroup>());
// 标题
var titleGo = NewUIChild(go.transform, "Title", out var titleRt);
titleRt.anchorMin = new Vector2(0, 1); titleRt.anchorMax = new Vector2(1, 1);
titleRt.pivot = new Vector2(0.5f, 1); titleRt.anchoredPosition = new Vector2(0, -16);
titleRt.sizeDelta = new Vector2(-32, 40);
var title = titleGo.AddComponent<TextMeshProUGUI>();
title.text = "Panel"; title.alignment = TextAlignmentOptions.Top; title.fontSize = 28;
SetEnum(titleGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Header);
SaveAsPrefab(go, PfPanel, report);
}
private static void BuildTabBar(List<string> report)
{
var go = NewUI(PfTabBar, 480, 360);
var tabGroup = go.AddComponent<UITabGroup>();
// 头部按钮行
var headerGo = NewUIChild(go.transform, "Header", out var headerRt);
headerRt.anchorMin = new Vector2(0, 1); headerRt.anchorMax = new Vector2(1, 1);
headerRt.pivot = new Vector2(0.5f, 1); headerRt.anchoredPosition = Vector2.zero;
headerRt.sizeDelta = new Vector2(0, 44);
var hLayout = headerGo.AddComponent<HorizontalLayoutGroup>();
hLayout.spacing = 4; hLayout.childForceExpandWidth = true; hLayout.childForceExpandHeight = true;
// 内容容器
var contentGo = NewUIChild(go.transform, "Content", out var contentRt);
contentRt.anchorMin = Vector2.zero; contentRt.anchorMax = Vector2.one;
contentRt.offsetMin = new Vector2(0, 0); contentRt.offsetMax = new Vector2(0, -48);
var tabs = new (GameObject content, Button btn, GameObject hl)[2];
for (int i = 0; i < 2; i++)
{
var (btn, hl) = MakeTabHeader(headerGo.transform, $"Tab{i}Header", $"Tab {i + 1}");
var tabContent = NewUIChild(contentGo.transform, $"Tab{i}Content", out var tcRt);
Stretch(tcRt);
var tcImg = tabContent.AddComponent<Image>();
tcImg.color = new Color(1f, 1f, 1f, 0.03f);
var lblGo = NewUIChild(tabContent.transform, "Label", out var lblRt);
Stretch(lblRt);
var lbl = lblGo.AddComponent<TextMeshProUGUI>();
lbl.text = $"Tab {i + 1} 内容"; lbl.alignment = TextAlignmentOptions.Center; lbl.fontSize = 22;
if (i != 0) tabContent.SetActive(false);
tabs[i] = (tabContent, btn, hl);
}
WireTabGroup(tabGroup, tabs);
SaveAsPrefab(go, PfTabBar, report);
}
private static (Button btn, GameObject highlight) MakeTabHeader(Transform parent, string name, string text)
{
var go = NewUIChild(parent, name, out _);
var bg = go.AddComponent<Image>();
bg.sprite = Standard(); bg.type = Image.Type.Sliced;
bg.color = new Color(1f, 1f, 1f, 0.08f);
var btn = go.AddComponent<Button>(); btn.targetGraphic = bg;
var uiBtn = GetOrAdd<UIButton>(go);
if (s_theme != null) AssignRef(uiBtn, "_theme", s_theme);
var hl = NewUIChild(go.transform, "Highlight", out var hlRt);
Stretch(hlRt);
var hlImg = hl.AddComponent<Image>();
hlImg.color = new Color(0.20f, 0.65f, 1f, 0.30f);
hl.SetActive(false);
var lblGo = NewUIChild(go.transform, "Label", out var lblRt);
Stretch(lblRt);
var lbl = lblGo.AddComponent<TextMeshProUGUI>();
lbl.text = text; lbl.alignment = TextAlignmentOptions.Center; lbl.fontSize = 20;
SetEnum(lblGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Primary);
return (btn, hl);
}
private static void WireTabGroup(UITabGroup tabGroup, (GameObject content, Button btn, GameObject hl)[] tabs)
{
var so = new SerializedObject(tabGroup);
var prop = so.FindProperty("_tabs");
prop.arraySize = tabs.Length;
for (int i = 0; i < tabs.Length; i++)
{
var el = prop.GetArrayElementAtIndex(i);
el.FindPropertyRelative("content").objectReferenceValue = tabs[i].content;
el.FindPropertyRelative("headerButton").objectReferenceValue = tabs[i].btn;
el.FindPropertyRelative("headerHighlight").objectReferenceValue = tabs[i].hl;
}
so.ApplyModifiedPropertiesWithoutUndo();
}
// ══ 设置面板(数据驱动)════════════════════════════════════════════════
private const string SchemaDir = "Assets/_Game/Data/UI";
private const string SchemaName = "UI_SettingsSchema";
private const string PfSettingHeader = "UI_Setting_Header";
private const string PfSettingSlider = "UI_Setting_SliderRow";
private const string PfSettingToggle = "UI_Setting_ToggleRow";
private const string PfSettingDrop = "UI_Setting_DropdownRow";
private const string PfSettingsPanel = "UI_SettingsPanel";
[MenuItem("BaseGames/UI/控件库/生成设置面板(行预制件 + 默认表 + 面板)")]
public static void GenerateSettings()
{
EnsureFolder(ControlsDir);
EnsureFolder(SchemaDir);
var report = new List<string>();
s_theme = EnsureDefaultTheme(report);
var header = BuildSettingHeader(report);
var slider = BuildSettingSliderRow(report);
var toggle = BuildSettingToggleRow(report);
var dropdown = BuildSettingDropdownRow(report);
var schema = EnsureDefaultSchema(report);
BuildSettingsPanel(report, header, slider, toggle, dropdown, schema);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
var sb = new System.Text.StringBuilder("[UIControlLibrary] 数据驱动设置面板已生成:\n");
foreach (var r in report) sb.AppendLine(" • " + r);
sb.AppendLine("标签 KeySET_*请用「BaseGames/Localization/表格编辑器」补译文;改 UI_SettingsSchema 即可增删/重排设置项。");
Debug.Log(sb.ToString());
}
private static GameObject BuildSettingHeader(List<string> report)
{
var go = NewUI(PfSettingHeader, 480, 32);
var lblGo = NewUIChild(go.transform, "Label", out var rt);
Stretch(rt);
var lbl = lblGo.AddComponent<TextMeshProUGUI>();
lbl.text = "Section"; lbl.fontSize = 22; lbl.alignment = TextAlignmentOptions.MidlineLeft;
lblGo.AddComponent<BaseGames.Localization.LocalizedText>();
SetEnum(lblGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Header);
return SaveAsPrefab(go, PfSettingHeader, report);
}
private static GameObject BuildSettingSliderRow(List<string> report)
{
var go = SettingRowRoot(PfSettingSlider, out _);
var sliderGo = DefaultControls.CreateSlider(UiResources());
sliderGo.name = "Slider"; sliderGo.transform.SetParent(go.transform, false);
var sle = sliderGo.AddComponent<LayoutElement>(); sle.flexibleWidth = 1; sle.preferredHeight = 20;
var slider = sliderGo.GetComponent<Slider>();
var uiSlider = sliderGo.AddComponent<UISlider>();
var valGo = NewUIChild(go.transform, "Value", out _);
var val = valGo.AddComponent<TextMeshProUGUI>();
val.text = "0"; val.fontSize = 18; val.alignment = TextAlignmentOptions.MidlineRight;
var vle = valGo.AddComponent<LayoutElement>(); vle.preferredWidth = 56;
SetEnum(valGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Secondary);
AssignRef(uiSlider, "_slider", slider);
AssignRef(uiSlider, "_valueLabel", val);
return SaveAsPrefab(go, PfSettingSlider, report);
}
private static GameObject BuildSettingToggleRow(List<string> report)
{
var go = SettingRowRoot(PfSettingToggle, out _);
var toggleGo = DefaultControls.CreateToggle(UiResources());
toggleGo.name = "Toggle"; toggleGo.transform.SetParent(go.transform, false);
var tle = toggleGo.AddComponent<LayoutElement>(); tle.preferredWidth = 30; tle.preferredHeight = 30;
return SaveAsPrefab(go, PfSettingToggle, report);
}
private static GameObject BuildSettingDropdownRow(List<string> report)
{
var go = SettingRowRoot(PfSettingDrop, out _);
var ddGo = TMP_DefaultControls.CreateDropdown(TmpResources());
ddGo.name = "Dropdown"; ddGo.transform.SetParent(go.transform, false);
var dle = ddGo.AddComponent<LayoutElement>(); dle.flexibleWidth = 1; dle.preferredHeight = 32;
var dd = ddGo.GetComponent<TMP_Dropdown>();
var ui = ddGo.AddComponent<UIDropdown>();
AssignRef(ui, "_dropdown", dd);
return SaveAsPrefab(go, PfSettingDrop, report);
}
/// <summary>构建带左侧本地化标签的设置行根HorizontalLayout。返回根out 标签 TMP。</summary>
private static GameObject SettingRowRoot(string name, out TMP_Text label)
{
var go = NewUI(name, 480, 44);
var h = go.AddComponent<HorizontalLayoutGroup>();
h.spacing = 12; h.childAlignment = TextAnchor.MiddleLeft;
h.childForceExpandWidth = false; h.childForceExpandHeight = false;
h.childControlWidth = true; h.childControlHeight = true;
h.padding = new RectOffset(8, 8, 4, 4);
var lblGo = NewUIChild(go.transform, "Label", out _);
label = lblGo.AddComponent<TextMeshProUGUI>();
label.text = "Label"; label.fontSize = 20; label.alignment = TextAlignmentOptions.MidlineLeft;
var le = lblGo.AddComponent<LayoutElement>(); le.preferredWidth = 200; le.flexibleWidth = 0;
lblGo.AddComponent<BaseGames.Localization.LocalizedText>();
SetEnum(lblGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Primary);
return go;
}
private static SettingsSchemaSO EnsureDefaultSchema(List<string> report)
{
string path = $"{SchemaDir}/{SchemaName}.asset";
var schema = AssetDatabase.LoadAssetAtPath<SettingsSchemaSO>(path);
bool created = schema == null;
if (created) { schema = ScriptableObject.CreateInstance<SettingsSchemaSO>(); AssetDatabase.CreateAsset(schema, path); }
// 仅在新建时填充默认项,避免覆盖策划已有编辑
if (created)
{
var items = new (bool h, string key, SettingKey s)[]
{
(true, "SET_SECTION_AUDIO", default),
(false, "SET_MASTER_VOLUME", SettingKey.MasterVolume),
(false, "SET_BGM_VOLUME", SettingKey.BGMVolume),
(false, "SET_SFX_VOLUME", SettingKey.SFXVolume),
(false, "SET_AMBIENT_VOLUME", SettingKey.AmbientVolume),
(true, "SET_SECTION_DISPLAY", default),
(false, "SET_VSYNC", SettingKey.VSync),
(false, "SET_TARGET_FPS", SettingKey.TargetFPS),
(true, "SET_SECTION_ACCESS", default),
(false, "SET_UI_SCALE", SettingKey.UIScale),
(false, "SET_COLORBLIND", SettingKey.ColorblindMode),
(false, "SET_SCREEN_SHAKE", SettingKey.ScreenShake),
(true, "SET_SECTION_LANGUAGE", default),
(false, "SET_LANGUAGE", SettingKey.Language),
};
var so = new SerializedObject(schema);
var prop = so.FindProperty("_items");
prop.arraySize = items.Length;
for (int i = 0; i < items.Length; i++)
{
var el = prop.GetArrayElementAtIndex(i);
el.FindPropertyRelative("isHeader").boolValue = items[i].h;
el.FindPropertyRelative("labelKey").stringValue = items[i].key;
el.FindPropertyRelative("key").enumValueIndex = (int)items[i].s;
}
so.ApplyModifiedPropertiesWithoutUndo();
report.Add($"{path}(默认 {items.Length} 项,可增删/重排)");
}
return schema;
}
private static void BuildSettingsPanel(List<string> report, GameObject header, GameObject slider,
GameObject toggle, GameObject dropdown, SettingsSchemaSO schema)
{
var go = NewUI(PfSettingsPanel, 540, 640);
var bg = go.AddComponent<Image>();
bg.sprite = Background(); bg.type = Image.Type.Sliced;
bg.color = new Color(0.06f, 0.07f, 0.10f, 0.96f);
SetEnum(go.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Graphic_Background);
var applier = go.AddComponent<UIThemeApplier>();
if (s_theme != null) AssignRef(applier, "_theme", s_theme);
var panel = go.AddComponent<DataDrivenSettingsPanel>();
// 行容器(竖向布局)
var content = NewUIChild(go.transform, "Content", out var crt);
crt.anchorMin = Vector2.zero; crt.anchorMax = Vector2.one;
crt.offsetMin = new Vector2(16, 16); crt.offsetMax = new Vector2(-16, -16);
var v = content.AddComponent<VerticalLayoutGroup>();
v.spacing = 6; v.childForceExpandWidth = true; v.childForceExpandHeight = false;
v.childControlWidth = true; v.childControlHeight = true;
v.childAlignment = TextAnchor.UpperCenter;
AssignRef(panel, "_schema", schema);
AssignRef(panel, "_container", content.transform);
AssignRef(panel, "_headerPrefab", header);
AssignRef(panel, "_sliderRowPrefab", slider);
AssignRef(panel, "_toggleRowPrefab", toggle);
AssignRef(panel, "_dropdownRowPrefab", dropdown);
SaveAsPrefab(go, PfSettingsPanel, report);
}
// ══ 主菜单(数据驱动)════════════════════════════════════════════════
private const string PfMenuButton = "UI_MainMenu_Button";
private const string MenuConfigName = "UI_MainMenuConfig";
[MenuItem("BaseGames/UI/控件库/生成主菜单(按钮预制件 + 默认表)")]
public static void GenerateMainMenu()
{
EnsureFolder(ControlsDir);
EnsureFolder(SchemaDir);
var report = new List<string>();
s_theme = EnsureDefaultTheme(report);
BuildMainMenuButton(report);
EnsureDefaultMenuConfig(report);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
var sb = new System.Text.StringBuilder("[UIControlLibrary] 数据驱动主菜单已生成:\n");
foreach (var r in report) sb.AppendLine(" • " + r);
sb.AppendLine("标签 MENU_* 请补译文;改 UI_MainMenuConfig 即可增删/重排菜单项。");
sb.AppendLine("用法:在 Scene_MainMenu 挂 DataDrivenMainMenuController指定 config/container/buttonPrefab + 子面板引用。");
Debug.Log(sb.ToString());
}
private static GameObject BuildMainMenuButton(List<string> report)
{
var go = NewUI(PfMenuButton, 300, 56);
var bg = go.AddComponent<Image>();
bg.sprite = Standard(); bg.type = Image.Type.Sliced; bg.color = new Color(1f, 1f, 1f, 0.06f);
var btn = go.AddComponent<Button>(); btn.targetGraphic = bg;
var uiBtn = GetOrAdd<UIButton>(go);
if (s_theme != null) AssignRef(uiBtn, "_theme", s_theme);
var view = go.AddComponent<MainMenuButtonView>();
var iconGo = NewUIChild(go.transform, "Icon", out var irt);
irt.anchorMin = new Vector2(0, 0.5f); irt.anchorMax = new Vector2(0, 0.5f); irt.pivot = new Vector2(0, 0.5f);
irt.anchoredPosition = new Vector2(14, 0); irt.sizeDelta = new Vector2(32, 32);
var icon = iconGo.AddComponent<Image>(); icon.enabled = false;
var lblGo = NewUIChild(go.transform, "Label", out var lrt);
lrt.anchorMin = Vector2.zero; lrt.anchorMax = Vector2.one;
lrt.offsetMin = new Vector2(56, 0); lrt.offsetMax = new Vector2(-12, 0);
var lbl = lblGo.AddComponent<TextMeshProUGUI>();
lbl.text = "Menu Item"; lbl.alignment = TextAlignmentOptions.MidlineLeft; lbl.fontSize = 24;
var loc = lblGo.AddComponent<BaseGames.Localization.LocalizedText>();
SetEnum(lblGo.AddComponent<UIThemeRole>(), "_kind", (int)UIThemeRoleKind.Text_Primary);
AssignRef(view, "_button", btn);
AssignRef(view, "_label", loc);
AssignRef(view, "_icon", icon);
return SaveAsPrefab(go, PfMenuButton, report);
}
private static MainMenuConfigSO EnsureDefaultMenuConfig(List<string> report)
{
string path = $"{SchemaDir}/{MenuConfigName}.asset";
var cfg = AssetDatabase.LoadAssetAtPath<MainMenuConfigSO>(path);
bool created = cfg == null;
if (created) { cfg = ScriptableObject.CreateInstance<MainMenuConfigSO>(); AssetDatabase.CreateAsset(cfg, path); }
if (created)
{
var items = new (string key, MainMenuAction a, bool req)[]
{
("MENU_NEW_GAME", MainMenuAction.NewGame, false),
("MENU_CONTINUE", MainMenuAction.Continue, true),
("MENU_SETTINGS", MainMenuAction.OpenSettings, false),
("MENU_CREDITS", MainMenuAction.OpenCredits, false),
("MENU_QUIT", MainMenuAction.Quit, false),
};
var so = new SerializedObject(cfg);
var prop = so.FindProperty("_items");
prop.arraySize = items.Length;
for (int i = 0; i < items.Length; i++)
{
var el = prop.GetArrayElementAtIndex(i);
el.FindPropertyRelative("labelKey").stringValue = items[i].key;
el.FindPropertyRelative("action").enumValueIndex = (int)items[i].a;
el.FindPropertyRelative("requiresSave").boolValue = items[i].req;
el.FindPropertyRelative("sceneKey").stringValue = "";
}
so.ApplyModifiedPropertiesWithoutUndo();
report.Add($"{path}(默认 {items.Length} 项菜单)");
}
return cfg;
}
// ══ 本地化补全(数据驱动面板的 SET_*/MENU_* 标签)══════════════════════
[MenuItem("BaseGames/UI/控件库/补充设置与菜单本地化(中/英)")]
public static void SeedDataDrivenUILocalization()
{
var zh = new Dictionary<string, string>
{
{ "SET_SECTION_AUDIO", "音频" },
{ "SET_MASTER_VOLUME", "主音量" },
{ "SET_BGM_VOLUME", "音乐" },
{ "SET_SFX_VOLUME", "音效" },
{ "SET_AMBIENT_VOLUME", "环境音" },
{ "SET_SECTION_DISPLAY", "画面" },
{ "SET_VSYNC", "垂直同步" },
{ "SET_TARGET_FPS", "目标帧率" },
{ "SET_SECTION_ACCESS", "辅助功能" },
{ "SET_UI_SCALE", "界面缩放" },
{ "SET_COLORBLIND", "色盲模式" },
{ "SET_SCREEN_SHAKE", "屏幕震动" },
{ "SET_SECTION_LANGUAGE", "语言" },
{ "SET_LANGUAGE", "语言" },
{ "SET_FPS_UNLIMITED", "无限" },
{ "SET_COLORBLIND_0", "关闭" },
{ "SET_COLORBLIND_1", "红色弱Protanopia" },
{ "SET_COLORBLIND_2", "绿色弱Deuteranopia" },
{ "SET_COLORBLIND_3", "蓝色弱Tritanopia" },
{ "MENU_NEW_GAME", "新游戏" },
{ "MENU_CONTINUE", "继续" },
{ "MENU_SETTINGS", "设置" },
{ "MENU_CREDITS", "制作团队" },
{ "MENU_QUIT", "退出" },
};
var en = new Dictionary<string, string>
{
{ "SET_SECTION_AUDIO", "Audio" },
{ "SET_MASTER_VOLUME", "Master Volume" },
{ "SET_BGM_VOLUME", "Music" },
{ "SET_SFX_VOLUME", "Sound Effects" },
{ "SET_AMBIENT_VOLUME", "Ambience" },
{ "SET_SECTION_DISPLAY", "Display" },
{ "SET_VSYNC", "V-Sync" },
{ "SET_TARGET_FPS", "Target FPS" },
{ "SET_SECTION_ACCESS", "Accessibility" },
{ "SET_UI_SCALE", "UI Scale" },
{ "SET_COLORBLIND", "Colorblind Mode" },
{ "SET_SCREEN_SHAKE", "Screen Shake" },
{ "SET_SECTION_LANGUAGE", "Language" },
{ "SET_LANGUAGE", "Language" },
{ "SET_FPS_UNLIMITED", "Unlimited" },
{ "SET_COLORBLIND_0", "Off" },
{ "SET_COLORBLIND_1", "Protanopia" },
{ "SET_COLORBLIND_2", "Deuteranopia" },
{ "SET_COLORBLIND_3", "Tritanopia" },
{ "MENU_NEW_GAME", "New Game" },
{ "MENU_CONTINUE", "Continue" },
{ "MENU_SETTINGS", "Settings" },
{ "MENU_CREDITS", "Credits" },
{ "MENU_QUIT", "Quit" },
};
int added = MergeWriteUI(Language.ChineseSimplified, zh)
+ MergeWriteUI(Language.English, en);
Debug.Log($"[UIControlLibrary] 已补充设置/菜单本地化(新增 {added} 条,已存在的不覆盖)。" +
"日/韩缺省走英文回退可用「BaseGames/Localization/表格编辑器」补译。");
}
/// <summary>把缺失的 key 合并写入指定语言的 UI 表(已存在的保留,不覆盖)。返回新增数。</summary>
private static int MergeWriteUI(Language lang, Dictionary<string, string> kv)
{
var dict = LocalizationFileIO.Read(lang, LocalizationTable.UI);
int added = 0;
foreach (var p in kv)
if (!dict.ContainsKey(p.Key)) { dict[p.Key] = p.Value; added++; }
if (added > 0) LocalizationFileIO.Write(lang, LocalizationTable.UI, dict);
return added;
}
// ── 通用助手 ─────────────────────────────────────────────────────────
private static GameObject NewUI(string name, float w, float h)
{
var go = new GameObject(name, typeof(RectTransform));
((RectTransform)go.transform).sizeDelta = new Vector2(w, h);
return go;
}
private static GameObject NewUIChild(Transform parent, string name, out RectTransform rt)
{
var go = new GameObject(name, typeof(RectTransform));
rt = (RectTransform)go.transform;
rt.SetParent(parent, false);
return go;
}
private static void Size(GameObject go, float w, float h)
{
if (go.transform is RectTransform rt) rt.sizeDelta = new Vector2(w, h);
}
private static void Stretch(RectTransform rt)
{
rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one;
rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero;
}
private static T GetOrAdd<T>(GameObject go) where T : Component
=> go.GetComponent<T>() ?? go.AddComponent<T>();
private static void SetEnum(Component c, string prop, int value)
{
var so = new SerializedObject(c);
var p = so.FindProperty(prop);
if (p != null) { p.enumValueIndex = value; so.ApplyModifiedPropertiesWithoutUndo(); }
}
private static void AssignRef(Object target, string prop, Object value)
{
var so = new SerializedObject(target);
var p = so.FindProperty(prop);
if (p == null) { Debug.LogWarning($"[UIControlLibrary] 未找到属性 {target.GetType().Name}.{prop}"); return; }
p.objectReferenceValue = value;
so.ApplyModifiedPropertiesWithoutUndo();
}
private static GameObject SaveAsPrefab(GameObject go, string name, List<string> report)
{
string path = $"{ControlsDir}/{name}.prefab";
var asset = PrefabUtility.SaveAsPrefabAsset(go, path);
Object.DestroyImmediate(go);
report.Add(path);
return asset;
}
private static void EnsureFolder(string dir)
{
string[] parts = dir.Split('/');
string cur = parts[0]; // "Assets"
for (int i = 1; i < parts.Length; i++)
{
string next = $"{cur}/{parts[i]}";
if (!AssetDatabase.IsValidFolder(next)) AssetDatabase.CreateFolder(cur, parts[i]);
cur = next;
}
}
// ── 内建 UI 资源(默认皮肤 sprite──────────────────────────────────────
private static Sprite Standard() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd");
private static Sprite Background() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd");
private static Sprite Knob() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd");
private static Sprite Checkmark() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd");
private static Sprite DropArrow() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd");
private static Sprite Mask() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd");
private static Sprite InputBg() => AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/InputFieldBackground.psd");
private static DefaultControls.Resources UiResources() => new DefaultControls.Resources
{
standard = Standard(), background = Background(), inputField = InputBg(),
knob = Knob(), checkmark = Checkmark(), dropdown = DropArrow(), mask = Mask(),
};
private static TMP_DefaultControls.Resources TmpResources() => new TMP_DefaultControls.Resources
{
standard = Standard(), background = Background(), inputField = InputBg(),
knob = Knob(), checkmark = Checkmark(), dropdown = DropArrow(), mask = Mask(),
};
}
}

View File

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

View File

@@ -2,7 +2,8 @@ namespace BaseGames.Localization
{ {
/// <summary> /// <summary>
/// 游戏支持的语言列表。 /// 游戏支持的语言列表。
/// 添加新语言时同步在 Resources/Localization/ 下创建对应子目录和 JSON 表文件 /// 添加新语言时同步在 Assets/_Game/Data/Localization/ 下创建对应子目录和 JSON 表文件
/// 推荐用「BaseGames / Localization / 表格编辑器」新建并自动注册 Addressables
/// </summary> /// </summary>
public enum Language public enum Language
{ {

View File

@@ -1,7 +1,7 @@
// Assets/Scripts/Localization/LocalizationManager.cs // Assets/Scripts/Localization/LocalizationManager.cs
// 本地化管理器(运行时 JSON 文件驱动)。 // 本地化管理器(运行时 JSON 文件驱动)。
// //
// 数据格式(放在 Resources/Localization/{Language}/{TableName}.json // 数据格式(放在 Assets/_Game/Data/Localization/{Language}/{TableName}.json
// { // {
// "entries": [ // "entries": [
// { "key": "ui_start", "value": "开始游戏" }, // { "key": "ui_start", "value": "开始游戏" },
@@ -317,7 +317,7 @@ namespace BaseGames.Localization
return cached; return cached;
// 编辑器按资产路径读取(与运行时 Addressable 地址对应的物理位置) // 编辑器按资产路径读取(与运行时 Addressable 地址对应的物理位置)
string path = $"Assets/_Game/Data/Localization/{language}/{table}.json"; string path = LocalizationPaths.AssetPath(language, table);
var asset = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset>(path); var asset = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset>(path);
var dict = asset == null ? null : ParseTableText(asset.text); var dict = asset == null ? null : ParseTableText(asset.text);
s_editorPreviewCache[cacheKey] = dict; s_editorPreviewCache[cacheKey] = dict;
@@ -349,7 +349,7 @@ namespace BaseGames.Localization
/// </summary> /// </summary>
private static Dictionary<string, string> LoadTable(Language language, string table) private static Dictionary<string, string> LoadTable(Language language, string table)
{ {
string address = $"Localization/{language}/{table}"; string address = LocalizationPaths.Address(language, table);
// 统一经 AssetLoader 门面:缺键安全检查 + 同步加载 + 释放 // 统一经 AssetLoader 门面:缺键安全检查 + 同步加载 + 释放
if (!AssetLoader.Exists(address, typeof(TextAsset))) return null; if (!AssetLoader.Exists(address, typeof(TextAsset))) return null;
@@ -360,21 +360,12 @@ namespace BaseGames.Localization
} }
/// <summary> /// <summary>
/// 将 JSON 文本解析为 key→value 字典(内部共享解析逻辑) /// 将 JSON 文本解析为 key→value 字典。
/// 委托给 <see cref="LocalizationSerializer.Parse"/>,与编辑器写盘共用同一格式逻辑。
/// 返回 null 表示格式无效。 /// 返回 null 表示格式无效。
/// </summary> /// </summary>
private static Dictionary<string, string> ParseTableText(string jsonText) private static Dictionary<string, string> ParseTableText(string jsonText)
{ => LocalizationSerializer.Parse(jsonText);
var parsed = JsonUtility.FromJson<StringTableJson>(jsonText);
if (parsed?.entries == null) return null;
var dict = new Dictionary<string, string>(parsed.entries.Count, StringComparer.Ordinal);
foreach (var entry in parsed.entries)
if (!string.IsNullOrEmpty(entry.key))
dict[entry.key] = entry.value ?? string.Empty;
return dict;
}
// ── 缓存键(值类型,消除字符串插值 GC────────────────────────────── // ── 缓存键(值类型,消除字符串插值 GC──────────────────────────────
private readonly struct CacheKey : IEquatable<CacheKey> private readonly struct CacheKey : IEquatable<CacheKey>
@@ -398,20 +389,5 @@ namespace BaseGames.Localization
public override int GetHashCode() public override int GetHashCode()
=> HashCode.Combine((int)_language, _table); => HashCode.Combine((int)_language, _table);
} }
// ── 序列化辅助类型 ────────────────────────────────────────────────────
[Serializable]
private class StringTableJson
{
public List<StringEntry> entries;
}
[Serializable]
private class StringEntry
{
public string key;
public string value;
}
} }
} }

View File

@@ -0,0 +1,40 @@
namespace BaseGames.Localization
{
/// <summary>
/// 本地化资源路径 / Addressable 地址的唯一真相源。
///
/// 运行时与编辑器工具的所有路径、地址都必须经此类构造,禁止再硬编码
/// "Assets/_Game/Data/Localization" 或 "Localization/{lang}/{table}" 字符串。
///
/// 设计要点:
/// - 纯静态、无 UnityEditor 依赖,放运行时 asmdef<c>BaseGames.Localization</c>
/// 使运行时加载(<see cref="LocalizationManager"/>)与编辑器工具共用同一套路径逻辑。
/// - 物理 JSON 路径(<see cref="AssetPath"/>)供编辑器直读 / 写盘;
/// Addressable 地址(<see cref="Address"/>)供运行时 <c>AssetLoader</c> 加载。
/// </summary>
public static class LocalizationPaths
{
/// <summary>本地化 JSON 数据根目录(项目资产相对路径)。</summary>
public const string DataRoot = "Assets/_Game/Data/Localization";
/// <summary>CSV 导入导出目录(供 Excel 往返)。</summary>
public const string ExportRoot = "Assets/_Game/Localization/Export";
/// <summary>指定语言的子目录,如 <c>Assets/_Game/Data/Localization/English</c>。</summary>
public static string LanguageFolder(Language language) => $"{DataRoot}/{language}";
/// <summary>指定语言 + 表的 JSON 资产路径。</summary>
public static string AssetPath(Language language, string table)
=> $"{DataRoot}/{language}/{table}.json";
/// <summary>
/// 指定语言 + 表的 Addressable 地址(运行时加载用)。
/// 必须与 <see cref="AssetPath"/> 指向的文件注册的地址一致。
/// </summary>
public static string Address(Language language, string table)
=> $"Localization/{language}/{table}";
/// <summary>指定表的 CSV 导出路径。</summary>
public static string CsvPath(string table) => $"{ExportRoot}/{table}.csv";
}
}

View File

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

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace BaseGames.Localization
{
/// <summary>
/// 本地化表 JSON 的对称解析 / 序列化(唯一格式真相源)。
///
/// 表格式:<c>{ "entries": [ { "key": "...", "value": "..." } ] }</c>
///
/// 运行时加载(<see cref="LocalizationManager"/>)与编辑器写盘(<c>LocalizationFileIO</c>
/// 都经此类,确保读写格式永远一致,杜绝"格式漂移"。
/// </summary>
public static class LocalizationSerializer
{
/// <summary>
/// 将表 JSON 文本解析为 key→value 字典。
/// 返回 null 表示格式无效entries 缺失)。空 key 条目被跳过。
/// </summary>
public static Dictionary<string, string> Parse(string jsonText)
{
if (string.IsNullOrEmpty(jsonText)) return null;
StringTableJson parsed;
try { parsed = JsonUtility.FromJson<StringTableJson>(jsonText); }
catch { return null; }
if (parsed?.entries == null) return null;
var dict = new Dictionary<string, string>(parsed.entries.Count, StringComparer.Ordinal);
foreach (var entry in parsed.entries)
if (!string.IsNullOrEmpty(entry.key))
dict[entry.key] = entry.value ?? string.Empty;
return dict;
}
/// <summary>
/// 将 key→value 字典序列化为表 JSON 文本(<c>{entries:[…]}</c> 格式pretty print
/// 该输出可被 <see cref="Parse"/> 与运行时加载器无损还原。
/// </summary>
/// <param name="dict">要序列化的字典。</param>
/// <param name="sortKeys">是否按 key 的序数顺序排序(默认 true减少版本控制 diff 噪声)。</param>
public static string Serialize(IReadOnlyDictionary<string, string> dict, bool sortKeys = true)
{
var table = new StringTableJson { entries = new List<StringEntry>(dict?.Count ?? 0) };
if (dict != null)
{
IEnumerable<string> keys = dict.Keys;
if (sortKeys)
{
var sorted = new List<string>(dict.Keys);
sorted.Sort(StringComparer.Ordinal);
keys = sorted;
}
foreach (var key in keys)
table.entries.Add(new StringEntry { key = key, value = dict[key] ?? string.Empty });
}
// JsonUtility 正确转义引号/反斜杠/换行,且保留中日韩字符原文(不转 \uXXXX
return JsonUtility.ToJson(table, prettyPrint: true);
}
// ── 序列化辅助类型(运行时与编辑器共用)────────────────────────────────
[Serializable]
internal class StringTableJson
{
public List<StringEntry> entries;
}
[Serializable]
internal class StringEntry
{
public string key;
public string value;
}
}
}

View File

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

View File

@@ -5,7 +5,8 @@ namespace BaseGames.Localization
/// 所有调用 <see cref="ILocalizationService.Get"/> 或 <see cref="LocalizationManager.Get"/> 时 /// 所有调用 <see cref="ILocalizationService.Get"/> 或 <see cref="LocalizationManager.Get"/> 时
/// 必须引用此类的常量,禁止直接硬编码表名字符串。 /// 必须引用此类的常量,禁止直接硬编码表名字符串。
/// ///
/// 新增表时:在此追加常量,并在 Resources/Localization/{Language}/ 下创建同名 JSON 文件。 /// 新增表时:在此追加常量,并用「BaseGames / Localization / 表格编辑器」新建同名表
/// (自动在 Assets/_Game/Data/Localization/{Language}/ 下创建 JSON 并注册 Addressables
/// </summary> /// </summary>
public static class LocalizationTable public static class LocalizationTable
{ {

View File

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

View File

@@ -0,0 +1,91 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core;
using BaseGames.Core.Events;
namespace BaseGames.UI
{
/// <summary>
/// UI 面板基类:统一面板生命周期、焦点恢复、进场淡入与事件订阅清理。
///
/// 消除各面板控制器PauseMenu / Settings / InventoryHub 等)重复的样板:
/// - OnEnable取服务 / 订阅 / 设默认选中 / 播淡入
/// - OnDisable清理订阅<see cref="_subs"/>/ 停动画
/// - <see cref="IFocusable.OnFocusRestored"/>:关闭子面板回到栈顶时聚焦首项
///
/// 与 <see cref="UIManager"/> 面板栈完全兼容UIManager 仍以 SetActive 驱动开关,
/// 本基类只在 OnEnable/OnDisable 加钩子,不改变栈语义。
///
/// 子类用法:重写 <see cref="OnPanelOpen"/>(订阅/刷新)与可选 <see cref="OnPanelClose"/>
/// 在 Inspector 指定 <see cref="_firstSelected"/>(手柄/键盘默认焦点);可选挂 CanvasGroup 做淡入。
/// </summary>
[DisallowMultipleComponent]
public abstract class UIPanelBase : MonoBehaviour, IFocusable
{
[Header("Panel Base")]
[Tooltip("打开 / 焦点恢复时默认选中的控件(手柄/键盘导航起点)。可空。")]
[SerializeField] protected Selectable _firstSelected;
[Tooltip("进场淡入用的 CanvasGroup可空为空则不淡入。")]
[SerializeField] protected CanvasGroup _canvasGroup;
[Tooltip("进场淡入时长。0 表示无淡入。")]
[SerializeField] protected float _fadeInDuration = 0.15f;
[Tooltip("打开时是否自动把焦点设到首项。")]
[SerializeField] protected bool _selectFirstOnEnable = true;
/// <summary>事件订阅容器OnDisable 自动清理。子类订阅用 <c>channel.Subscribe(..).AddTo(_subs)</c>。</summary>
protected readonly CompositeDisposable _subs = new();
private Coroutine _fadeRoutine;
// ── 生命周期 ──────────────────────────────────────────────────────────
protected virtual void OnEnable()
{
OnPanelOpen();
if (_canvasGroup != null && _fadeInDuration > 0f) PlayFadeIn();
if (_selectFirstOnEnable) FocusFirst();
}
protected virtual void OnDisable()
{
_subs.Clear();
if (_fadeRoutine != null) { StopCoroutine(_fadeRoutine); _fadeRoutine = null; }
OnPanelClose();
}
/// <summary>面板打开时调用OnEnable。子类在此取服务、订阅事件、刷新内容。</summary>
protected virtual void OnPanelOpen() { }
/// <summary>面板关闭时调用OnDisable_subs 已清理之后)。子类在此释放非 _subs 资源。</summary>
protected virtual void OnPanelClose() { }
// ── 焦点 ──────────────────────────────────────────────────────────────
/// <summary>关闭子面板、本面板恢复为栈顶时调用(<see cref="IUIManager.CloseTopPanel"/> 触发)。</summary>
public virtual void OnFocusRestored() => FocusFirst();
/// <summary>将 EventSystem 焦点设到首项(优先 <see cref="_firstSelected"/>,否则 <see cref="ResolveFirstSelected"/>)。</summary>
protected void FocusFirst()
{
var go = _firstSelected != null ? _firstSelected.gameObject : ResolveFirstSelected();
if (go != null && EventSystem.current != null)
EventSystem.current.SetSelectedGameObject(go);
}
/// <summary>子类可重写:动态决定首个选中项(如列表第一行),当 <see cref="_firstSelected"/> 未指定时使用。</summary>
protected virtual GameObject ResolveFirstSelected() => null;
// ── 工具 ──────────────────────────────────────────────────────────────
/// <summary>从 ServiceLocator 取服务(未注册返回 null。</summary>
protected static T GetService<T>() where T : class => ServiceLocator.GetOrDefault<T>();
private void PlayFadeIn()
{
if (_fadeRoutine != null) StopCoroutine(_fadeRoutine);
_canvasGroup.alpha = 0f;
_fadeRoutine = StartCoroutine(UITween.FadeCanvasGroup(_canvasGroup, 1f, _fadeInDuration));
}
}
}

View File

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

View File

@@ -0,0 +1,11 @@
namespace BaseGames.UI
{
/// <summary>
/// 通用面板:<see cref="UIPanelBase"/> 的最简具体实现,无额外逻辑。
/// 用作脚手架生成的 themed 面板根(带 CanvasGroup 淡入 + 默认焦点 + 订阅清理),
/// 适合不需要自定义控制器的简单弹窗 / 容器。需要业务逻辑时改挂自定义 <see cref="UIPanelBase"/> 子类。
/// </summary>
public sealed class UISimplePanel : UIPanelBase
{
}
}

View File

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

View File

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

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using UnityEngine;
namespace BaseGames.UI
{
/// <summary>
/// 简单数据绑定列表项接口。视图实现后,<see cref="PooledListView{TData,TView}"/>
/// 的默认 <c>BindItem</c> 可直接调用,无需子类重写绑定逻辑。
/// </summary>
public interface IPooledItemView<in TData>
{
void Bind(TData data);
}
/// <summary>
/// 对象池数据绑定列表基类(统一 ItemInventory / CharmEquip / QuestLog 等处的手写重建模板)。
///
/// 用法:
/// 1. 子类指定 TData数据与 TView继承 <see cref="Component"/> 的列表项视图)。
/// 2. 在 Inspector 设置 <see cref="_container"/>(布局父节点)与 <see cref="_template"/>(保持 inactive 的原型)。
/// 3. 调用 <see cref="SetItems"/> 以数据集重建;视图通过 <see cref="BindItem"/> 绑定。
///
/// 默认绑定TView 实现 <see cref="IPooledItemView{TData}"/> 时无需重写 <see cref="BindItem"/>
/// 需要传回调(如 onSelect时重写 <see cref="BindItem"/>。
///
/// 非虚拟化:所有项同时存在(适合数十到上百项);超长列表后续可加虚拟化。
/// </summary>
public abstract class PooledListView<TData, TView> : MonoBehaviour
where TView : Component
{
[Header("Pooled List")]
[Tooltip("列表项的布局父节点(通常挂 Horizontal/VerticalLayoutGroup 或 GridLayoutGroup。")]
[SerializeField] protected Transform _container;
[Tooltip("列表项原型(保持 inactive作为对象池模板。")]
[SerializeField] protected TView _template;
private readonly List<TView> _active = new();
private readonly Queue<TView> _pool = new();
/// <summary>当前激活的列表项视图(只读)。</summary>
public IReadOnlyList<TView> Active => _active;
protected virtual void Awake()
{
if (_template != null) _template.gameObject.SetActive(false);
}
/// <summary>以数据集重建列表(回收旧项 → 逐项 Spawn + 绑定 → <see cref="OnRebuilt"/>)。</summary>
public void SetItems(IEnumerable<TData> items)
{
RecycleAll();
if (_container == null || _template == null || items == null) { OnRebuilt(); return; }
foreach (var data in items)
{
var view = Spawn();
BindItem(view, data);
_active.Add(view);
}
OnRebuilt();
}
/// <summary>回收所有激活项到池中(隐藏)。</summary>
public void RecycleAll()
{
foreach (var view in _active)
{
if (view == null) continue;
view.gameObject.SetActive(false);
_pool.Enqueue(view);
}
_active.Clear();
}
/// <summary>
/// 绑定单个视图。默认TView 实现 <see cref="IPooledItemView{TData}"/> 时直接调用其 Bind。
/// 需要额外参数(如选中回调)时子类重写。
/// </summary>
protected virtual void BindItem(TView view, TData data)
{
if (view is IPooledItemView<TData> bindable) bindable.Bind(data);
}
/// <summary>重建完成回调(子类可重写:默认选中首项、空态提示等)。</summary>
protected virtual void OnRebuilt() { }
private TView Spawn()
{
TView view = _pool.Count > 0 ? _pool.Dequeue() : Instantiate(_template, _container);
view.transform.SetParent(_container, false);
view.gameObject.SetActive(true);
return view;
}
}
}

View File

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

View File

@@ -0,0 +1,142 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core.Events;
using BaseGames.UI.Theme;
namespace BaseGames.UI
{
/// <summary>按钮视觉变体(驱动从主题派生的 <see cref="ColorBlock"/>)。</summary>
public enum UIButtonVariant { Primary, Secondary, Accent, Danger, Ghost }
/// <summary>
/// 主题化按钮变体 + 交互反馈。薄封装在 uGUI <see cref="Button"/> 之上:
/// - 按变体从 <see cref="UIThemeSO"/> 取基色,派生 normal/highlighted/pressed/disabled 并写入 Button.colors。
/// - 选中/悬停时缩放反馈(走 <see cref="UITween.Scale"/>)。
/// - 可选点击/悬停音效(事件频道驱动,不直接耦合 Audio 程序集)。
///
/// 主题来源:优先 Inspector 直接赋的 <see cref="_theme"/>,否则就近向上找 <see cref="UIThemeApplier"/>。
/// </summary>
[RequireComponent(typeof(Button))]
[DisallowMultipleComponent]
public class UIButton : MonoBehaviour,
ISelectHandler, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler
{
[Header("变体")]
[SerializeField] private UIButtonVariant _variant = UIButtonVariant.Primary;
[Tooltip("主题资产;为空则就近向上查找 UIThemeApplier。")]
[SerializeField] private UIThemeSO _theme;
[Header("反馈")]
[Tooltip("选中/悬停时的缩放反馈。")]
[SerializeField] private bool _scaleFeedback = true;
[SerializeField] private float _selectedScale = 1.06f;
[SerializeField] private float _scaleDuration = 0.08f;
[Header("音效(可选,事件频道驱动)")]
[SerializeField] private VoidEventChannelSO _onClickSfx;
[SerializeField] private VoidEventChannelSO _onHoverSfx;
private Button _button;
private Coroutine _scaleRoutine;
private Vector3 _baseScale = Vector3.one;
private void Awake()
{
_button = GetComponent<Button>();
_baseScale = transform.localScale;
_button.onClick.AddListener(RaiseClickSfx);
}
private void OnEnable()
{
ApplyTheme();
transform.localScale = _baseScale;
}
private void OnDisable()
{
if (_scaleRoutine != null) { StopCoroutine(_scaleRoutine); _scaleRoutine = null; }
transform.localScale = _baseScale;
}
// ── 主题应用 ──────────────────────────────────────────────────────────
/// <summary>按当前变体与主题刷新 Button 配色。</summary>
public void ApplyTheme()
{
var theme = ResolveTheme();
if (theme == null) return;
if (_button == null) _button = GetComponent<Button>();
if (_button == null) return;
Color baseColor = VariantBaseColor(theme, _variant);
var cb = _button.colors;
cb.colorMultiplier = 1f;
cb.fadeDuration = 0.1f;
cb.disabledColor = theme.ButtonDisabled;
if (_variant == UIButtonVariant.Ghost)
{
cb.normalColor = new Color(baseColor.r, baseColor.g, baseColor.b, 0f);
cb.highlightedColor = new Color(baseColor.r, baseColor.g, baseColor.b, 0.25f);
cb.pressedColor = new Color(baseColor.r, baseColor.g, baseColor.b, 0.40f);
cb.selectedColor = cb.highlightedColor;
}
else
{
cb.normalColor = baseColor;
cb.highlightedColor = Color.Lerp(baseColor, Color.white, 0.12f);
cb.pressedColor = Color.Lerp(baseColor, Color.black, 0.15f);
cb.selectedColor = cb.highlightedColor;
}
_button.colors = cb;
}
private static Color VariantBaseColor(UIThemeSO t, UIButtonVariant v) => v switch
{
UIButtonVariant.Primary => t.Primary,
UIButtonVariant.Secondary => t.Secondary,
UIButtonVariant.Accent => t.Accent,
UIButtonVariant.Danger => t.Danger,
UIButtonVariant.Ghost => t.TextPrimary,
_ => t.Primary,
};
private UIThemeSO ResolveTheme()
{
if (_theme != null) return _theme;
var applier = GetComponentInParent<UIThemeApplier>(includeInactive: true);
return applier != null ? applier.Theme : null;
}
// ── 交互反馈 ──────────────────────────────────────────────────────────
public void OnSelect(BaseEventData e) { PlayScale(_selectedScale); RaiseHoverSfx(); }
public void OnDeselect(BaseEventData e) { PlayScale(1f); }
public void OnPointerEnter(PointerEventData e) { PlayScale(_selectedScale); RaiseHoverSfx(); }
public void OnPointerExit(PointerEventData e)
{
// 仍为当前选中项则保持放大
if (EventSystem.current != null && EventSystem.current.currentSelectedGameObject == gameObject) return;
PlayScale(1f);
}
private void PlayScale(float factor)
{
if (!_scaleFeedback || !isActiveAndEnabled) return;
if (_scaleRoutine != null) StopCoroutine(_scaleRoutine);
_scaleRoutine = StartCoroutine(UITween.Scale(transform, _baseScale * factor, _scaleDuration));
}
private void RaiseClickSfx() => _onClickSfx?.Raise();
private void RaiseHoverSfx() => _onHoverSfx?.Raise();
#if UNITY_EDITOR
private void OnValidate()
{
if (Application.isPlaying) return;
_button = GetComponent<Button>();
ApplyTheme();
}
#endif
}
}

View File

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

View File

@@ -0,0 +1,44 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;
namespace BaseGames.UI
{
/// <summary>
/// 下拉控件封装TMP_Dropdown + 一行式 <see cref="Bind"/>(填充选项 / 设当前项 / 接回调),
/// 消除设置面板里重复的 ClearOptions/AddOptions/RefreshShownValue 样板。
/// 选项文本可由调用方先经本地化(<c>LocalizationManager.Get</c>)解析后传入。
/// </summary>
[DisallowMultipleComponent]
public class UIDropdown : MonoBehaviour
{
[SerializeField] private TMP_Dropdown _dropdown;
public TMP_Dropdown Dropdown => _dropdown;
public int Value => _dropdown != null ? _dropdown.value : 0;
/// <summary>填充选项、设当前选中项并接变更回调。</summary>
public void Bind(IEnumerable<string> options, int index, UnityAction<int> onChanged)
{
if (_dropdown == null) return;
_dropdown.onValueChanged.RemoveAllListeners();
_dropdown.ClearOptions();
var list = options as List<string> ?? new List<string>(options);
_dropdown.AddOptions(list);
_dropdown.value = Mathf.Clamp(index, 0, Mathf.Max(0, list.Count - 1));
_dropdown.RefreshShownValue();
_dropdown.onValueChanged.AddListener(i => onChanged?.Invoke(i));
}
/// <summary>不触发回调地设置当前选中项(用于外部状态同步)。</summary>
public void SetIndexSilent(int index)
{
if (_dropdown == null) return;
_dropdown.SetValueWithoutNotify(Mathf.Clamp(index, 0, Mathf.Max(0, _dropdown.options.Count - 1)));
_dropdown.RefreshShownValue();
}
}
}

View File

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

View File

@@ -0,0 +1,74 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
namespace BaseGames.UI
{
/// <summary>
/// 通用可选择行:图标 + 标签 + 选中高亮 + 按钮,适用于菜单项、设置行、存档槽、列表项。
///
/// 配合 <see cref="PooledListView{TData,TView}"/> 作 TView或在面板里直接布局使用。
/// 选中(手柄/键盘导航或鼠标悬停)时自动切换高亮节点。
/// </summary>
[DisallowMultipleComponent]
public class UISelectableRow : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler
{
[Header("引用")]
[SerializeField] private Button _button;
[SerializeField] private TMP_Text _label;
[Tooltip("行图标(可空)。")]
[SerializeField] private Image _icon;
[Tooltip("选中高亮节点(可空,选中时 SetActive(true))。")]
[SerializeField] private GameObject _selectedHighlight;
/// <summary>行被点击(或 Submit时触发。</summary>
public event Action Clicked;
public Button Button => _button;
public Selectable Selectable => _button;
private void Awake()
{
if (_selectedHighlight != null) _selectedHighlight.SetActive(false);
if (_button != null)
_button.onClick.AddListener(() => Clicked?.Invoke());
}
// ── 数据填充 ──────────────────────────────────────────────────────────
public void SetLabel(string text)
{
if (_label != null) _label.text = text;
}
public void SetIcon(Sprite sprite)
{
if (_icon == null) return;
_icon.sprite = sprite;
_icon.enabled = sprite != null;
}
public void SetSelected(bool selected)
{
if (_selectedHighlight != null) _selectedHighlight.SetActive(selected);
}
/// <summary>把 EventSystem 焦点设到本行。</summary>
public void Focus()
{
if (_button != null && EventSystem.current != null)
EventSystem.current.SetSelectedGameObject(_button.gameObject);
}
// ── 选中反馈 ──────────────────────────────────────────────────────────
public void OnSelect(BaseEventData e) => SetSelected(true);
public void OnDeselect(BaseEventData e) => SetSelected(false);
public void OnPointerEnter(PointerEventData e)
{
if (_button != null && _button.interactable && EventSystem.current != null)
EventSystem.current.SetSelectedGameObject(_button.gameObject);
}
}
}

View File

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

View File

@@ -0,0 +1,52 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using TMPro;
namespace BaseGames.UI
{
/// <summary>
/// 滑条控件封装Slider + 实时数值标签 + 一行式 <see cref="Bind"/>
/// 消除 <see cref="SettingsPanelController"/> 里"移除监听→设值→加监听→更新标签"的重复样板。
/// </summary>
[DisallowMultipleComponent]
public class UISlider : MonoBehaviour
{
[SerializeField] private Slider _slider;
[Tooltip("实时数值标签(可空)。")]
[SerializeField] private TMP_Text _valueLabel;
[Tooltip("数值标签格式(当未传 fmt 委托时使用)。例:\"{0:0}\"、\"{0:0}%\"。")]
[SerializeField] private string _format = "{0:0}";
private Func<float, string> _fmt;
public Slider Slider => _slider;
public float Value => _slider != null ? _slider.value : 0f;
/// <summary>
/// 绑定取值范围、初值与变更回调。<paramref name="fmt"/> 可自定义数值标签文本(优先于 <see cref="_format"/>)。
/// </summary>
public void Bind(float min, float max, float value, UnityAction<float> onChanged, Func<float, string> fmt = null)
{
if (_slider == null) return;
_slider.onValueChanged.RemoveAllListeners();
_slider.minValue = min;
_slider.maxValue = max;
_slider.value = Mathf.Clamp(value, min, max);
_fmt = fmt;
UpdateLabel(_slider.value);
_slider.onValueChanged.AddListener(v =>
{
onChanged?.Invoke(v);
UpdateLabel(v);
});
}
private void UpdateLabel(float v)
{
if (_valueLabel == null) return;
_valueLabel.text = _fmt != null ? _fmt(v) : string.Format(_format, v);
}
}
}

View File

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

View File

@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core.Events;
namespace BaseGames.UI
{
/// <summary>
/// 可复用标签组(从 <see cref="BaseGames.UI.Inventory.InventoryHubPanel"/> 的 Tab 逻辑提取)。
///
/// 职责:管理一组 Tab内容根 + 头部按钮 + 高亮),处理 Next/Prev/Select 切换、
/// 头部高亮、焦点委托(内容若实现 <see cref="IFocusable"/> 则接管,否则聚焦头部按钮),
/// 可选跨重建记忆当前 Tab并通过 C# 事件 + 可选 SO 频道广播索引。
///
/// 解耦:不引用任何具体 Tab 类型,只持有 Tab 根 <see cref="GameObject"/>。
/// 由宿主面板在 OnEnable 中调用 <see cref="Activate"/>,并把肩键频道接到 <see cref="Next"/>/<see cref="Prev"/>。
/// </summary>
public class UITabGroup : MonoBehaviour
{
[Serializable]
public struct Tab
{
[Tooltip("Tab 内容根节点(激活时 SetActive(true))。")]
public GameObject content;
[Tooltip("Tab 头部按钮(点击跳转;高亮显示当前选中)。可空。")]
public Button headerButton;
[Tooltip("Tab 头部高亮节点(选中时 SetActive(true))。可空。")]
public GameObject headerHighlight;
}
[Header("Tabs按显示顺序")]
[SerializeField] private Tab[] _tabs;
[Tooltip("默认打开的 Tab 索引。")]
[SerializeField] private int _defaultIndex = 0;
[Tooltip("是否记住上次停留的 Tab跨面板重开。")]
[SerializeField] private bool _rememberLast = true;
[Tooltip("跨重建记忆用的键;为空则只在本实例存活期间记忆。")]
[SerializeField] private string _persistKey = "";
[Header("Event Channels可选")]
[Tooltip("当前 Tab 变化时广播索引。可空。")]
[SerializeField] private IntEventChannelSO _onTabChanged;
/// <summary>当前 Tab 变化时触发(参数为新索引)。</summary>
public event Action<int> TabChanged;
public int CurrentIndex { get; private set; } = -1;
public int TabCount => _tabs?.Length ?? 0;
// 跨重建记忆(静态:面板/组件被销毁重建后仍保留)
private static readonly Dictionary<string, int> s_persist = new();
private bool _wired;
private void Awake() => EnsureWired();
private void EnsureWired()
{
if (_wired || _tabs == null) return;
for (int i = 0; i < _tabs.Length; i++)
{
int captured = i;
if (_tabs[i].headerButton != null)
{
_tabs[i].headerButton.onClick.RemoveAllListeners();
_tabs[i].headerButton.onClick.AddListener(() => Select(captured));
}
if (_tabs[i].content != null) _tabs[i].content.SetActive(false);
if (_tabs[i].headerHighlight != null) _tabs[i].headerHighlight.SetActive(false);
}
_wired = true;
}
/// <summary>激活标签组并打开起始 Tab默认或记忆。宿主面板在 OnEnable 中调用。</summary>
public void Activate()
{
EnsureWired();
if (TabCount == 0) return;
int start = _rememberLast && TryGetPersisted(out var p) ? p : _defaultIndex;
CurrentIndex = -1; // 强制 Select 执行切换
Select(Mathf.Clamp(start, 0, TabCount - 1));
}
public void Next() => Step(+1);
public void Prev() => Step(-1);
private void Step(int dir)
{
if (TabCount == 0) return;
int next = CurrentIndex;
for (int i = 0; i < _tabs.Length; i++) // 跳过未配置 content 的空槽
{
next = (next + dir + _tabs.Length) % _tabs.Length;
if (_tabs[next].content != null) break;
}
Select(next);
}
/// <summary>切换到指定 Tab无效或与当前相同则忽略。</summary>
public void Select(int index)
{
EnsureWired();
if (TabCount == 0) return;
index = Mathf.Clamp(index, 0, _tabs.Length - 1);
if (index == CurrentIndex) return;
// 关闭旧 Tab
if (CurrentIndex >= 0 && CurrentIndex < _tabs.Length)
{
if (_tabs[CurrentIndex].content != null) _tabs[CurrentIndex].content.SetActive(false);
if (_tabs[CurrentIndex].headerHighlight != null) _tabs[CurrentIndex].headerHighlight.SetActive(false);
}
CurrentIndex = index;
SetPersisted(index);
// 打开新 Tab
var tab = _tabs[index];
if (tab.content != null) tab.content.SetActive(true);
if (tab.headerHighlight != null) tab.headerHighlight.SetActive(true);
FocusCurrent();
_onTabChanged?.Raise(index);
TabChanged?.Invoke(index);
}
/// <summary>把焦点交给当前 Tab内容 IFocusable 优先,否则其头部按钮)。供宿主 OnFocusRestored 调用。</summary>
public void FocusCurrent()
{
if (CurrentIndex < 0 || CurrentIndex >= TabCount) return;
var tab = _tabs[CurrentIndex];
var focusable = tab.content != null ? tab.content.GetComponent<IFocusable>() : null;
if (focusable != null) focusable.OnFocusRestored();
else if (tab.headerButton != null && EventSystem.current != null)
EventSystem.current.SetSelectedGameObject(tab.headerButton.gameObject);
}
// ── 记忆 ──────────────────────────────────────────────────────────────
private bool TryGetPersisted(out int index)
{
if (!string.IsNullOrEmpty(_persistKey) && s_persist.TryGetValue(_persistKey, out index)) return true;
if (CurrentIndex >= 0) { index = CurrentIndex; return true; }
index = -1;
return false;
}
private void SetPersisted(int index)
{
if (!string.IsNullOrEmpty(_persistKey)) s_persist[_persistKey] = index;
}
}
}

View File

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

View File

@@ -0,0 +1,259 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core;
using BaseGames.Core.Assets;
using BaseGames.Core.Events;
namespace BaseGames.UI.MainMenu
{
/// <summary>
/// 数据驱动主菜单控制器(<see cref="MainMenuController"/> 的表驱动版,非破坏性并存)。
///
/// 按钮列表据 <see cref="MainMenuConfigSO"/> 生成(标签/图标/顺序/动作纯数据,策划改表零代码);
/// 子面板开关、存档槽流程、入场动画、状态锁定等编排仍在本控制器(场景耦合,不下放配置表)。
/// 动作派发:内置 NewGame/Continue/OpenSettings/OpenCredits/LoadScene/Quit + 事件频道 RaiseEvent。
/// </summary>
public class DataDrivenMainMenuController : MonoBehaviour
{
[Header("数据表 / 按钮列表")]
[SerializeField] private MainMenuConfigSO _config;
[Tooltip("按钮的父节点(通常挂 VerticalLayoutGroup即主按钮组。")]
[SerializeField] private Transform _container;
[SerializeField] private MainMenuButtonView _buttonPrefab;
[Header("主按钮组(入场动画)")]
[SerializeField] private CanvasGroup _mainButtonsGroup;
[SerializeField] private RectTransform _mainButtonsRect;
[Header("子面板")]
[SerializeField] private GameObject _saveSlotPanel;
[SerializeField] private BaseGames.UI.Menus.SaveSlotController _saveSlotController;
[SerializeField] private GameObject _settingsPanel;
[SerializeField] private GameObject _creditsPanel;
[Header("子面板关闭按钮(可选)")]
[SerializeField] private Button _btnCloseSaveSlot;
[SerializeField] private Button _btnCloseSettings;
[SerializeField] private Button _btnCloseCredits;
[Header("入场动画")]
[SerializeField] private float _entrySlideOffset = 80f;
[SerializeField] private float _entryDuration = 0.55f;
[Header("场景")]
[SerializeField] private string _firstGameSceneKey = AddressKeys.SceneGameChapter1;
[Header("Event Channels - Listen")]
[SerializeField] private GameStateEventChannelSO _onGameStateChanged;
[SerializeField] private IntEventChannelSO _onSlotConfirmed;
[Header("Event Channels - Raise")]
[SerializeField] private SceneLoadRequestEventChannelSO _onSceneLoadRequest;
private readonly CompositeDisposable _subs = new();
private readonly List<(MainMenuConfigSO.Item item, MainMenuButtonView view)> _buttons = new();
private Vector2 _buttonsPanelOriginalPos;
private MainMenuButtonView _firstButton;
// ── 生命周期 ──────────────────────────────────────────────────────────
private void Awake()
{
if (_buttonPrefab != null) _buttonPrefab.gameObject.SetActive(false);
_btnCloseSaveSlot?.onClick.AddListener(() => CloseSubPanel(_saveSlotPanel));
_btnCloseSettings?.onClick.AddListener(() => CloseSubPanel(_settingsPanel));
_btnCloseCredits? .onClick.AddListener(() => CloseSubPanel(_creditsPanel));
if (_mainButtonsRect != null)
_buttonsPanelOriginalPos = _mainButtonsRect.anchoredPosition;
SetPanel(_saveSlotPanel, false);
SetPanel(_settingsPanel, false);
SetPanel(_creditsPanel, false);
SetButtonsGroupVisible(false);
BuildMenu();
}
private void OnEnable()
{
_onGameStateChanged?.Subscribe(HandleGameStateChanged).AddTo(_subs);
_onSlotConfirmed? .Subscribe(HandleSlotConfirmed).AddTo(_subs);
}
private void OnDisable() => _subs.Clear();
private void Start() => StartCoroutine(PlayEntryAnimation());
// ── 据表建菜单 ────────────────────────────────────────────────────────
/// <summary>据配置重建主菜单按钮列表public 以便编辑器/测试验证)。</summary>
public void BuildMenu()
{
foreach (var (_, view) in _buttons) if (view != null) Destroy(view.gameObject);
_buttons.Clear();
_firstButton = null;
if (_config == null || _container == null || _buttonPrefab == null) return;
foreach (var item in _config.Items)
{
var view = Instantiate(_buttonPrefab, _container);
view.gameObject.SetActive(true);
var captured = item;
view.Bind(item.labelKey, item.icon, () => Dispatch(captured));
_buttons.Add((item, view));
if (_firstButton == null) _firstButton = view;
}
RefreshConditional();
}
/// <summary>根据存档存在性刷新 requiresSave 按钮的可用性(如"继续")。</summary>
public void RefreshConditional()
{
bool hasSave = HasAnySave();
foreach (var (item, view) in _buttons)
if (item.requiresSave && view != null)
view.SetInteractable(hasSave);
}
// ── 动作派发 ──────────────────────────────────────────────────────────
private void Dispatch(MainMenuConfigSO.Item item)
{
switch (item.action)
{
case MainMenuAction.NewGame:
_saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.NewGame);
OpenSubPanel(_saveSlotPanel);
break;
case MainMenuAction.Continue:
_saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.Continue);
OpenSubPanel(_saveSlotPanel);
break;
case MainMenuAction.OpenSettings:
OpenSubPanel(_settingsPanel);
break;
case MainMenuAction.OpenCredits:
OpenSubPanel(_creditsPanel);
if (_btnCloseCredits != null)
EventSystem.current?.SetSelectedGameObject(_btnCloseCredits.gameObject);
break;
case MainMenuAction.LoadScene:
_onSceneLoadRequest?.Raise(new SceneLoadRequest
{
SceneName = string.IsNullOrEmpty(item.sceneKey) ? _firstGameSceneKey : item.sceneKey,
TransitionType = TransitionType.Scene,
ShowLoadingScreen = true,
});
break;
case MainMenuAction.Quit:
Application.Quit();
break;
case MainMenuAction.RaiseEvent:
item.eventChannel?.Raise();
break;
}
}
// ── 子面板编排 ────────────────────────────────────────────────────────
private void OpenSubPanel(GameObject panel)
{
SetMainButtonsInteractable(false);
SetPanel(panel, true);
}
private void CloseSubPanel(GameObject panel)
{
SetPanel(panel, false);
SetMainButtonsInteractable(true);
if (_firstButton != null)
EventSystem.current?.SetSelectedGameObject(_firstButton.Button.gameObject);
}
private void SetMainButtonsInteractable(bool on)
{
if (_mainButtonsGroup == null) return;
_mainButtonsGroup.interactable = on;
_mainButtonsGroup.blocksRaycasts = on;
}
// ── 存档槽确认(与 MainMenuController 一致)────────────────────────────
private void HandleSlotConfirmed(int _)
{
SetPanel(_saveSlotPanel, false);
var svc = ServiceLocator.GetOrDefault<ISaveService>();
string checkpointScene = svc?.LastCheckpointScene;
bool hasCheckpoint = !string.IsNullOrEmpty(checkpointScene);
_onSceneLoadRequest?.Raise(new SceneLoadRequest
{
SceneName = hasCheckpoint ? checkpointScene : _firstGameSceneKey,
EntryTransitionId = hasCheckpoint ? svc.LastCheckpointSpawnId : null,
TransitionType = TransitionType.Scene,
ShowLoadingScreen = true,
});
}
private void HandleGameStateChanged(GameStateId state)
{
bool isMainMenu = state == GameStates.MainMenu;
if (_mainButtonsGroup != null)
{
_mainButtonsGroup.interactable = isMainMenu;
_mainButtonsGroup.blocksRaycasts = isMainMenu;
}
}
// ── 入场动画 ──────────────────────────────────────────────────────────
private IEnumerator PlayEntryAnimation()
{
if (_mainButtonsGroup == null) yield break;
Vector2 startPos = _buttonsPanelOriginalPos - new Vector2(0f, _entrySlideOffset);
if (_mainButtonsRect != null) _mainButtonsRect.anchoredPosition = startPos;
float elapsed = 0f;
while (elapsed < _entryDuration)
{
float t = Mathf.SmoothStep(0f, 1f, elapsed / _entryDuration);
_mainButtonsGroup.alpha = t;
if (_mainButtonsRect != null)
_mainButtonsRect.anchoredPosition = Vector2.Lerp(startPos, _buttonsPanelOriginalPos, t);
elapsed += Time.unscaledDeltaTime;
yield return null;
}
_mainButtonsGroup.alpha = 1f;
if (_mainButtonsRect != null) _mainButtonsRect.anchoredPosition = _buttonsPanelOriginalPos;
_mainButtonsGroup.interactable = true;
_mainButtonsGroup.blocksRaycasts = true;
if (_firstButton != null)
EventSystem.current?.SetSelectedGameObject(_firstButton.Button.gameObject);
}
// ── 工具 ──────────────────────────────────────────────────────────────
private static bool HasAnySave()
{
var s = ServiceLocator.GetOrDefault<ISaveService>();
return s != null && (s.HasSave(0) || s.HasSave(1) || s.HasSave(2));
}
private static void SetPanel(GameObject panel, bool active)
{
if (panel != null) panel.SetActive(active);
}
private void SetButtonsGroupVisible(bool visible)
{
if (_mainButtonsGroup == null) return;
_mainButtonsGroup.alpha = visible ? 1f : 0f;
_mainButtonsGroup.interactable = visible;
_mainButtonsGroup.blocksRaycasts = visible;
}
}
}

View File

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

View File

@@ -0,0 +1,44 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using BaseGames.Localization;
namespace BaseGames.UI.MainMenu
{
/// <summary>
/// 主菜单按钮视图(显式序列化绑定,对照 <see cref="BaseGames.UI.Inventory.ItemSlotView"/> 风格)。
/// 由 <see cref="DataDrivenMainMenuController"/> 据配置实例化并 <see cref="Bind"/>。
/// 标签走 <see cref="LocalizedText"/>,随语言切换自动刷新。
/// </summary>
[DisallowMultipleComponent]
public class MainMenuButtonView : MonoBehaviour
{
[SerializeField] private Button _button;
[SerializeField] private LocalizedText _label;
[Tooltip("按钮图标(可空)。")]
[SerializeField] private Image _icon;
public Button Button => _button;
/// <summary>绑定标签 Key、图标与点击回调。</summary>
public void Bind(string labelKey, Sprite icon, Action onClick)
{
if (_label != null) _label.SetKey(labelKey);
if (_icon != null)
{
_icon.sprite = icon;
_icon.enabled = icon != null;
}
if (_button != null)
{
_button.onClick.RemoveAllListeners();
if (onClick != null) _button.onClick.AddListener(() => onClick());
}
}
public void SetInteractable(bool value)
{
if (_button != null) _button.interactable = value;
}
}
}

View File

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

View File

@@ -0,0 +1,56 @@
using System;
using UnityEngine;
using BaseGames.Core.Events;
namespace BaseGames.UI.MainMenu
{
/// <summary>主菜单项动作类型。常用动作内置;任意自定义走事件频道。</summary>
public enum MainMenuAction
{
NewGame, // 打开存档槽(新游戏语境)
Continue, // 打开存档槽(继续语境)
OpenSettings, // 打开设置子面板
OpenCredits, // 打开制作团队子面板
LoadScene, // 直接发起场景加载(用 sceneKey
Quit, // 退出游戏
RaiseEvent, // 触发 eventChannel万能扩展
}
/// <summary>
/// 主菜单数据驱动表(策划编辑)。按顺序列出主菜单项;
/// <see cref="DataDrivenMainMenuController"/> 据此生成按钮并派发动作。
/// 策划可增删 / 重排 / 改标签图标 / 改动作,无需改代码。
///
/// 派发边界:动作类型固定(含 RaiseEvent 万能扩展);
/// 子面板 / 场景 / 存档流的编排在控制器,配置表不引用场景对象。
/// </summary>
[CreateAssetMenu(menuName = "BaseGames/UI/Main Menu Config", fileName = "UI_MainMenuConfig")]
public class MainMenuConfigSO : ScriptableObject
{
[Serializable]
public struct Item
{
[Tooltip("按钮标签本地化 KeyUI 表)。")]
public string labelKey;
[Tooltip("按钮图标(可空)。")]
public Sprite icon;
[Tooltip("点击动作。")]
public MainMenuAction action;
[Tooltip("勾选则需要存在有效存档才可用(如\"继续\";无存档时按钮置灰)。")]
public bool requiresSave;
[Tooltip("LoadScene 动作的目标场景 Addressable Key。")]
public string sceneKey;
[Tooltip("RaiseEvent 动作触发的事件频道。")]
public VoidEventChannelSO eventChannel;
}
[SerializeField] private Item[] _items;
public Item[] Items => _items;
}
}

View File

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

View File

@@ -93,9 +93,9 @@ namespace BaseGames.UI.MainMenu
_btnCredits? .onClick.AddListener(OnCreditsClicked); _btnCredits? .onClick.AddListener(OnCreditsClicked);
_btnQuit? .onClick.AddListener(Application.Quit); _btnQuit? .onClick.AddListener(Application.Quit);
_btnCloseSaveSlot?.onClick.AddListener(() => SetPanel(_saveSlotPanel, false)); _btnCloseSaveSlot?.onClick.AddListener(() => CloseSubPanel(_saveSlotPanel, _btnNewGame));
_btnCloseSettings?.onClick.AddListener(() => SetPanel(_settingsPanel, false)); _btnCloseSettings?.onClick.AddListener(() => CloseSubPanel(_settingsPanel, _btnSettings));
_btnCloseCredits? .onClick.AddListener(() => SetPanel(_creditsPanel, false)); _btnCloseCredits? .onClick.AddListener(() => CloseSubPanel(_creditsPanel, _btnCredits));
// 记录按钮组原始位置(供动画使用) // 记录按钮组原始位置(供动画使用)
if (_mainButtonsRect != null) if (_mainButtonsRect != null)
@@ -162,15 +162,44 @@ namespace BaseGames.UI.MainMenu
private void OnNewGameClicked() private void OnNewGameClicked()
{ {
_saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.NewGame); _saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.NewGame);
SetPanel(_saveSlotPanel, true); OpenSubPanel(_saveSlotPanel);
} }
private void OnContinueClicked() private void OnContinueClicked()
{ {
_saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.Continue); _saveSlotController?.SetMode(BaseGames.UI.Menus.SaveSlotPanelMode.Continue);
SetPanel(_saveSlotPanel, true); OpenSubPanel(_saveSlotPanel);
}
private void OnSettingsClicked() => OpenSubPanel(_settingsPanel); // SettingsPanelController 自行设焦点
private void OnCreditsClicked()
{
OpenSubPanel(_creditsPanel);
// Credits 面板无独立控制器,打开时把焦点交给返回按钮(键盘 / 手柄可直接退出)
if (_btnCloseCredits != null)
EventSystem.current?.SetSelectedGameObject(_btnCloseCredits.gameObject);
}
/// <summary>打开子面板:禁用主按钮组交互,避免键盘/手柄导航"穿透"到背后的主菜单按钮。</summary>
private void OpenSubPanel(GameObject panel)
{
SetMainButtonsInteractable(false);
SetPanel(panel, true);
}
/// <summary>关闭子面板:恢复主按钮组交互,并把焦点恢复到对应主菜单按钮(导航连续性)。</summary>
private void CloseSubPanel(GameObject panel, Button focusAfter)
{
SetPanel(panel, false);
SetMainButtonsInteractable(true);
if (focusAfter != null)
EventSystem.current?.SetSelectedGameObject(focusAfter.gameObject);
}
private void SetMainButtonsInteractable(bool on)
{
if (_mainButtonsGroup == null) return;
_mainButtonsGroup.interactable = on;
_mainButtonsGroup.blocksRaycasts = on;
} }
private void OnSettingsClicked() => SetPanel(_settingsPanel, true);
private void OnCreditsClicked() => SetPanel(_creditsPanel, true);
// ── 存档槽确认 ─────────────────────────────────────────────────────── // ── 存档槽确认 ───────────────────────────────────────────────────────

View File

@@ -1,7 +1,5 @@
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core;
using BaseGames.Core.Assets; using BaseGames.Core.Assets;
using BaseGames.Core.Events; using BaseGames.Core.Events;
@@ -10,9 +8,9 @@ namespace BaseGames.UI
/// <summary> /// <summary>
/// 暂停菜单控制器(架构 10_UIModule §5 /// 暂停菜单控制器(架构 10_UIModule §5
/// 挂载在 Canvas_Menu → PauseMenuPanel GameObject 上。 /// 挂载在 Canvas_Menu → PauseMenuPanel GameObject 上。
/// 按钮绑定在 Awake 中完成;UIManager 负责面板开关 /// 按钮绑定在 Awake 中完成;生命周期 / 焦点由 <see cref="UIPanelBase"/> 统一处理
/// </summary> /// </summary>
public class PauseMenuController : MonoBehaviour, IFocusable public class PauseMenuController : UIPanelBase
{ {
// UIManager 通过 ServiceLocator 解析,开启时自动获取,无需 Inspector 直接绑定具体类型 // UIManager 通过 ServiceLocator 解析,开启时自动获取,无需 Inspector 直接绑定具体类型
private IUIManager _uiManager; private IUIManager _uiManager;
@@ -35,18 +33,13 @@ namespace BaseGames.UI
_btnQuit?.onClick.AddListener(Application.Quit); _btnQuit?.onClick.AddListener(Application.Quit);
} }
private void OnEnable()
{
// 暂停面板由 UIManager 开启,此时 ServiceLocator 已就绪 // 暂停面板由 UIManager 开启,此时 ServiceLocator 已就绪
_uiManager = ServiceLocator.GetOrDefault<IUIManager>(); protected override void OnPanelOpen() => _uiManager = GetService<IUIManager>();
// 手柄导航:打开时将焦点置于第一个按钮 protected override void OnPanelClose() => _uiManager = null;
EventSystem.current?.SetSelectedGameObject(_btnResume?.gameObject);
}
private void OnDisable() /// <summary>默认焦点 / 焦点恢复回到"继续"按钮(基类 FocusFirst 调用)。</summary>
{ protected override GameObject ResolveFirstSelected()
_uiManager = null; => _btnResume != null ? _btnResume.gameObject : null;
}
// ── 按钮回调 ────────────────────────────────────────────────────────── // ── 按钮回调 ──────────────────────────────────────────────────────────
@@ -71,11 +64,5 @@ namespace BaseGames.UI
ShowLoadingScreen = false, ShowLoadingScreen = false,
}); });
} }
// ── IFocusable ────────────────────────────────────────────────────────
/// <summary>面板恢复为栈顶时(关闭子面板后)自动移回第一个按鈕。</summary>
public void OnFocusRestored()
=> EventSystem.current?.SetSelectedGameObject(_btnResume?.gameObject);
} }
} }

View File

@@ -83,6 +83,9 @@ namespace BaseGames.UI.Menus
if (t.IsFaulted && !(t.Exception?.InnerException is OperationCanceledException)) if (t.IsFaulted && !(t.Exception?.InnerException is OperationCanceledException))
Debug.LogException(t.Exception?.InnerException ?? t.Exception, this); Debug.LogException(t.Exception?.InnerException ?? t.Exception, this);
}, TaskScheduler.FromCurrentSynchronizationContext()); }, TaskScheduler.FromCurrentSynchronizationContext());
// 面板打开时设置初始焦点(键盘 / 手柄导航入口)
StartCoroutine(RestoreFocusNextFrame());
} }
private void OnDisable() private void OnDisable()

View File

@@ -1,16 +1,17 @@
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.EventSystems;
using BaseGames.Core; using BaseGames.Core;
using BaseGames.Localization;
namespace BaseGames.UI namespace BaseGames.UI
{ {
/// <summary> /// <summary>
/// 设置面板控制器(架构 10_UIModule §7 /// 设置面板控制器(架构 10_UIModule §7
/// 驱动 SettingsManager 的音量与画面设置,并从当前配置初始化控件值。 /// 驱动 SettingsManager 的音量与画面设置,并从当前配置初始化控件值。
/// 生命周期 / 焦点由 <see cref="UIPanelBase"/> 统一处理。
/// </summary> /// </summary>
public class SettingsPanelController : MonoBehaviour, IFocusable public class SettingsPanelController : UIPanelBase
{ {
// ISettingsService 通过 ServiceLocator 获取,无需 Inspector 直接注入具体类, // ISettingsService 通过 ServiceLocator 获取,无需 Inspector 直接注入具体类,
// 支持测试场景替换 Mock 实现。 // 支持测试场景替换 Mock 实现。
@@ -32,12 +33,19 @@ namespace BaseGames.UI
[SerializeField] private TMP_Dropdown _colorblindDropdown; // None / Prot / Deut / Trit [SerializeField] private TMP_Dropdown _colorblindDropdown; // None / Prot / Deut / Trit
[SerializeField] private Toggle _screenShakeToggle; [SerializeField] private Toggle _screenShakeToggle;
[Header("语言")]
[SerializeField] private TMP_Dropdown _languageDropdown; // 中文 / English / 日本語 / 한국어
[Header("按键重绑定")] [Header("按键重绑定")]
[SerializeField] private GameObject _rebindPanelRoot; // RebindPanel GameObject [SerializeField] private GameObject _rebindPanelRoot; // RebindPanel GameObject
private static readonly int[] FpsOptions = { 30, 60, 120, -1 }; private static readonly int[] FpsOptions = { 30, 60, 120, -1 };
private void OnEnable() // 语言下拉项顺序(与脚手架填充的显示项一一对应)
private static readonly Language[] LanguageOptions =
{ Language.ChineseSimplified, Language.English, Language.Japanese, Language.Korean };
protected override void OnPanelOpen()
{ {
_settings = ServiceLocator.GetOrDefault<ISettingsService>(); _settings = ServiceLocator.GetOrDefault<ISettingsService>();
if (_settings == null) return; if (_settings == null) return;
@@ -95,8 +103,18 @@ namespace BaseGames.UI
_screenShakeToggle.onValueChanged.AddListener(v => _settings.SetScreenShakeEnabled(v)); _screenShakeToggle.onValueChanged.AddListener(v => _settings.SetScreenShakeEnabled(v));
} }
// 手柄导航:打开设置面板时将焦点置于主音量滑条 // ── 语言 ──────────────────────────────────────────────────────────
EventSystem.current?.SetSelectedGameObject(_masterVolume?.gameObject); if (_languageDropdown != null)
{
_languageDropdown.onValueChanged.RemoveAllListeners();
var loc = ServiceLocator.GetOrDefault<ILocalizationService>();
int idx = loc != null ? System.Array.IndexOf(LanguageOptions, loc.CurrentLanguage) : 0;
_languageDropdown.value = idx >= 0 ? idx : 0;
_languageDropdown.RefreshShownValue();
_languageDropdown.onValueChanged.AddListener(i =>
ServiceLocator.GetOrDefault<ILocalizationService>()?
.SetLanguage(LanguageOptions[Mathf.Clamp(i, 0, LanguageOptions.Length - 1)]));
}
} }
private void UpdateUIScaleLabel(float v) private void UpdateUIScaleLabel(float v)
@@ -115,10 +133,10 @@ namespace BaseGames.UI
slider.onValueChanged.AddListener(onChange); slider.onValueChanged.AddListener(onChange);
} }
// ── IFocusable ──────────────────────────────────────────────────────── // ── 焦点 ──────────────────────────────────────────────────────────────
/// <summary>面板恢复为栈顶时将焦点移回主音量滑条。</summary> /// <summary>默认焦点 / 焦点恢复回到主音量滑条(基类 FocusFirst 调用)。</summary>
public void OnFocusRestored() protected override GameObject ResolveFirstSelected()
=> EventSystem.current?.SetSelectedGameObject(_masterVolume?.gameObject); => _masterVolume != null ? _masterVolume.gameObject : null;
} }
} }

View File

@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BaseGames.Core;
using BaseGames.Localization;
namespace BaseGames.UI.Settings
{
/// <summary>
/// 数据驱动设置面板:据 <see cref="SettingsSchemaSO"/> 生成控件行并绑定 <see cref="ISettingsService"/>。
///
/// 取代硬编码的 <see cref="BaseGames.UI.SettingsPanelController"/>:策划改表即可增删 / 重排 / 改标签 / 分节,
/// 无需改代码。每行据 <see cref="SettingKey"/> 自动选用 Slider / Toggle / Dropdown 行预制件,
/// 并复用通用控件 <see cref="UISlider"/> / <see cref="UIDropdown"/>。
///
/// 控件来源:行预制件由 <c>SettingsPanelScaffold</c> 生成(标签为 <see cref="LocalizedText"/>)。
/// </summary>
public class DataDrivenSettingsPanel : UIPanelBase
{
public enum ControlKind { Slider, Toggle, Dropdown }
[Header("数据表")]
[SerializeField] private SettingsSchemaSO _schema;
[Header("行布局")]
[Tooltip("生成的行的父节点(通常挂 VerticalLayoutGroup。")]
[SerializeField] private Transform _container;
[SerializeField] private GameObject _headerPrefab;
[SerializeField] private GameObject _sliderRowPrefab;
[SerializeField] private GameObject _toggleRowPrefab;
[SerializeField] private GameObject _dropdownRowPrefab;
// FPS 下拉的取值集合(与 SettingsPanelController 一致)
private static readonly int[] FpsOptions = { 30, 60, 120, -1 };
private static readonly Language[] LanguageOptions =
{ Language.ChineseSimplified, Language.English, Language.Japanese, Language.Korean };
private static readonly string[] LanguageNativeNames =
{ "简体中文", "English", "日本語", "한국어" };
private ISettingsService _settings;
private ILocalizationService _loc;
private readonly List<GameObject> _spawned = new();
// ── 生命周期 ──────────────────────────────────────────────────────────
protected override void OnPanelOpen()
{
_settings = GetService<ISettingsService>();
_loc = GetService<ILocalizationService>();
Build();
}
protected override void OnPanelClose() => Clear();
// ── 构建 ──────────────────────────────────────────────────────────────
/// <summary>据 schema 重建所有行。可在无 ISettingsService 时调用(仅生成行 + 标签,不绑定)。</summary>
public void Build()
{
Clear();
if (_schema == null || _container == null) return;
foreach (var item in _schema.Items)
{
GameObject prefab = item.isHeader ? _headerPrefab : PrefabFor(KindOf(item.key));
if (prefab == null) continue;
var go = Instantiate(prefab, _container);
_spawned.Add(go);
SetLabel(go, item.labelKey);
if (!item.isHeader && _settings != null)
BindControl(go, item.key);
}
}
private void Clear()
{
foreach (var go in _spawned) if (go != null) Destroy(go);
_spawned.Clear();
}
private GameObject PrefabFor(ControlKind kind) => kind switch
{
ControlKind.Slider => _sliderRowPrefab,
ControlKind.Toggle => _toggleRowPrefab,
ControlKind.Dropdown => _dropdownRowPrefab,
_ => null,
};
private static void SetLabel(GameObject row, string labelKey)
{
var loc = row.GetComponentInChildren<LocalizedText>(true);
if (loc != null) loc.SetKey(labelKey);
}
// ── 控件类型映射 ──────────────────────────────────────────────────────
public static ControlKind KindOf(SettingKey key) => key switch
{
SettingKey.MasterVolume or SettingKey.BGMVolume or SettingKey.SFXVolume
or SettingKey.AmbientVolume or SettingKey.UIScale => ControlKind.Slider,
SettingKey.VSync or SettingKey.ScreenShake => ControlKind.Toggle,
SettingKey.TargetFPS or SettingKey.ColorblindMode or SettingKey.Language => ControlKind.Dropdown,
_ => ControlKind.Slider,
};
// ── 绑定派发 ──────────────────────────────────────────────────────────
private void BindControl(GameObject row, SettingKey key)
{
switch (KindOf(key))
{
case ControlKind.Slider: BindSlider(row, key); break;
case ControlKind.Toggle: BindToggle(row, key); break;
case ControlKind.Dropdown: BindDropdown(row, key); break;
}
}
private void BindSlider(GameObject row, SettingKey key)
{
var ui = row.GetComponentInChildren<UISlider>(true);
if (ui == null) return;
var data = _settings.Current;
switch (key)
{
case SettingKey.MasterVolume:
ui.Bind(0f, 1f, data.MasterVolume, v => _settings.SetMasterVolume(v), Percent); break;
case SettingKey.BGMVolume:
ui.Bind(0f, 1f, data.BGMVolume, v => _settings.SetBGMVolume(v), Percent); break;
case SettingKey.SFXVolume:
ui.Bind(0f, 1f, data.SFXVolume, v => _settings.SetSFXVolume(v), Percent); break;
case SettingKey.AmbientVolume:
ui.Bind(0f, 1f, data.AmbientVolume, v => _settings.SetAmbientVolume(v), Percent); break;
case SettingKey.UIScale:
ui.Bind(0.8f, 1.5f, data.UIScale, v => _settings.SetUIScale(v), Percent); break;
}
}
private void BindToggle(GameObject row, SettingKey key)
{
var toggle = row.GetComponentInChildren<Toggle>(true);
if (toggle == null) return;
var data = _settings.Current;
toggle.onValueChanged.RemoveAllListeners();
switch (key)
{
case SettingKey.VSync:
toggle.isOn = data.VSync;
toggle.onValueChanged.AddListener(v => _settings.SetVSync(v));
break;
case SettingKey.ScreenShake:
toggle.isOn = data.ScreenShakeEnabled;
toggle.onValueChanged.AddListener(v => _settings.SetScreenShakeEnabled(v));
break;
}
}
private void BindDropdown(GameObject row, SettingKey key)
{
var ui = row.GetComponentInChildren<UIDropdown>(true);
if (ui == null) return;
var data = _settings.Current;
switch (key)
{
case SettingKey.TargetFPS:
{
var opts = new List<string> { "30", "60", "120", Loc("SET_FPS_UNLIMITED", "无限") };
int idx = Array.IndexOf(FpsOptions, data.TargetFPS); if (idx < 0) idx = 1;
ui.Bind(opts, idx, i => _settings.SetTargetFrameRate(FpsOptions[Mathf.Clamp(i, 0, FpsOptions.Length - 1)]));
break;
}
case SettingKey.ColorblindMode:
{
int count = Enum.GetValues(typeof(ColorblindMode)).Length;
var opts = new List<string>(count);
for (int i = 0; i < count; i++)
opts.Add(Loc($"SET_COLORBLIND_{i}", ((ColorblindMode)i).ToString()));
ui.Bind(opts, (int)data.ColorblindMode,
i => _settings.SetColorblindMode((ColorblindMode)Mathf.Clamp(i, 0, count - 1)));
break;
}
case SettingKey.Language:
{
var opts = new List<string>(LanguageNativeNames);
int idx = _loc != null ? Array.IndexOf(LanguageOptions, _loc.CurrentLanguage) : 0;
if (idx < 0) idx = 0;
ui.Bind(opts, idx, i =>
GetService<ILocalizationService>()?.SetLanguage(LanguageOptions[Mathf.Clamp(i, 0, LanguageOptions.Length - 1)]));
break;
}
}
}
// ── 工具 ──────────────────────────────────────────────────────────────
private static string Percent(float v) => Mathf.RoundToInt(v * 100f) + "%";
private string Loc(string key, string fallback)
{
if (_loc != null && _loc.TryGet(key, out var v, LocalizationTable.UI)) return v;
return fallback;
}
protected override GameObject ResolveFirstSelected()
{
foreach (var go in _spawned)
{
if (go == null) continue;
var sel = go.GetComponentInChildren<Selectable>(true);
if (sel != null) return sel.gameObject;
}
return null;
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More