工具修改
This commit is contained in:
parent
811527ae24
commit
74449e09a2
@ -1 +1 @@
|
||||
Subproject commit e1f7ea568b27493475d39eeef68fb4407d43928f
|
||||
Subproject commit ab2ea01d2aede712e859db9c794e14f284f3a275
|
||||
@ -1,273 +0,0 @@
|
||||
# DecorateConfigEditor 修改清单
|
||||
|
||||
## 版本更新日期:2025-12-26
|
||||
|
||||
---
|
||||
|
||||
## 📋 功能限制
|
||||
|
||||
### 1. AreaId 限制
|
||||
- **限制内容**:禁止编辑 AreaId = 1 或 2 的配置
|
||||
- **实现位置**:
|
||||
- `OnLoadConfigClicked()` - 读取配置时检查
|
||||
- `OnSaveConfigClicked()` - 保存配置时检查
|
||||
- `CreateNewAreaConfig()` - 创建新场景时检查
|
||||
- **提示信息**:"AreaId 1 和 2 包含特殊处理,不支持通过此工具编辑。如需修改请联系编辑器作者。"
|
||||
- **原因**:AreaId 1和2包含特殊处理逻辑,避免误操作
|
||||
|
||||
### 2. 步骤数量限制
|
||||
- **限制内容**:步骤数量固定为 25,不允许修改
|
||||
- **实现位置**:
|
||||
- `BindUIControls()` - UI加载时禁用步骤数量输入框
|
||||
- `OnLoadConfigClicked()` - 强制设置为25
|
||||
- `CreateNewAreaConfig()` - 新场景默认25步
|
||||
- UXML界面 - 添加提示文字:"不可修改,如需调整请联系编辑器作者"
|
||||
- **UI表现**:StepCountField 输入框禁用(灰色不可编辑)
|
||||
|
||||
### 3. 不存在的AreaId处理
|
||||
- **处理逻辑**:
|
||||
- 读取配置时,如果指定的AreaId不存在,弹出提示框
|
||||
- 提示信息:"未找到AreaId=X的配置。如需创建新场景,请点击'创建新场景'按钮。"
|
||||
- **不进行任何自动创建**,只提示用户
|
||||
- **实现位置**:`OnLoadConfigClicked()`
|
||||
|
||||
### 4. 创建新场景流程
|
||||
- **新增按钮**:"创建新场景"按钮(在配置管理区域)
|
||||
- **操作流程**:
|
||||
1. 点击"创建新场景"按钮
|
||||
2. 弹出输入对话框,要求输入AreaId
|
||||
3. 验证AreaId(不能是1或2,不能是已存在的)
|
||||
4. 创建25个默认步骤配置
|
||||
5. 自动记录bg初始状态(如果bg节点已设置)
|
||||
6. 允许用户进行编辑
|
||||
7. **此时配置未保存到文件**,需要手动点击"保存配置"
|
||||
- **新增类**:`InputDialogWindow` - 用于输入AreaId的弹窗
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Spine相关特殊处理
|
||||
|
||||
### 1. UI中隐藏Spine操作
|
||||
- **实现位置**:`ParseAndCreateActionGroups()`
|
||||
- **处理逻辑**:
|
||||
```csharp
|
||||
// 跳过所有spine相关操作,用户不可见不可编辑
|
||||
if (actionType.Contains("spine")) continue;
|
||||
```
|
||||
- **支持的spine类型**:
|
||||
- `init_spine` - 初始化spine
|
||||
- `replace_spine` - 替换spine
|
||||
- 任何包含"spine"关键字的操作
|
||||
|
||||
### 2. 保存时保留Spine配置
|
||||
- **实现位置**:`UpdateRowActionString()`
|
||||
- **处理逻辑**:
|
||||
1. 从原始Action字符串中提取所有spine操作
|
||||
2. 将spine操作放在新Action字符串的**最前面**
|
||||
3. 后面跟用户编辑的其他操作
|
||||
- **代码示例**:
|
||||
```csharp
|
||||
// 保存原有的spine操作(放在最前面)
|
||||
List<string> spineActions = new List<string>();
|
||||
if (!string.IsNullOrEmpty(row.Action))
|
||||
{
|
||||
string[] oldActions = row.Action.Split('@');
|
||||
foreach (string oldAction in oldActions)
|
||||
{
|
||||
if (oldAction.Contains("spine"))
|
||||
{
|
||||
spineActions.Add(oldAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 先添加spine操作
|
||||
actionStrings.AddRange(spineActions);
|
||||
```
|
||||
|
||||
### 3. 场景还原时跳过Spine
|
||||
- **实现位置**:
|
||||
- `ApplyInitAction()` - 跳过 init_spine
|
||||
- `ApplyStepAction()` - 跳过所有spine操作
|
||||
- **效果**:用户在预览场景时,spine相关操作不会执行,但配置保持完整
|
||||
|
||||
---
|
||||
|
||||
## ✨ 新增功能
|
||||
|
||||
### 1. reset_pos 操作支持
|
||||
- **操作格式**:`reset_pos#节点路径,x=y`
|
||||
- **示例**:`reset_pos#bg/clearObj/my_sg_2,-156=-838`
|
||||
- **功能**:重置指定GameObject的位置(RectTransform.anchoredPosition)
|
||||
|
||||
#### UI实现:
|
||||
- **类型**:固定2个字段
|
||||
- ObjectField:选择目标GameObject
|
||||
- TextField:输入位置坐标(格式:x=y,如:-156=-838)
|
||||
- **位置**:与clear、add、replace、replace_image并列
|
||||
- **添加按钮**:"+ ResetPos"
|
||||
|
||||
#### 代码实现:
|
||||
1. **CreateActionGroup()** - 创建reset_pos UI组
|
||||
```csharp
|
||||
else if (actionType == "reset_pos")
|
||||
{
|
||||
ObjectField objField = new ObjectField("目标节点:");
|
||||
TextField posField = new TextField("位置(x=y):");
|
||||
}
|
||||
```
|
||||
|
||||
2. **ParseAndCreateActionGroups()** - 解析现有reset_pos配置
|
||||
```csharp
|
||||
else if (actionType == "reset_pos")
|
||||
{
|
||||
string[] pathParts = paths.Split(',');
|
||||
// 解析节点和位置
|
||||
}
|
||||
```
|
||||
|
||||
3. **UpdateRowActionString()** - 生成reset_pos字符串
|
||||
```csharp
|
||||
else if (actionType == "reset_pos")
|
||||
{
|
||||
actionStrings.Add($"reset_pos#{targetPath},{position}");
|
||||
}
|
||||
```
|
||||
|
||||
4. **ApplyResetPosAction()** - 应用reset_pos操作
|
||||
```csharp
|
||||
private void ApplyResetPosAction(string paths)
|
||||
{
|
||||
// 解析x=y格式
|
||||
string[] posParts = positionStr.Split('=');
|
||||
rt.anchoredPosition = new Vector2(x, y);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 只读Action字符串显示
|
||||
- **位置**:每个步骤编辑区域的顶部
|
||||
- **显示内容**:当前步骤的完整Action配置字符串
|
||||
- **特性**:
|
||||
- 只读(不可编辑)
|
||||
- 灰色显示(opacity: 0.7)
|
||||
- 多行显示(multiline)
|
||||
- 实时更新:当用户编辑操作组时,自动更新显示
|
||||
- **UI元素名称**:`ActionDisplay`
|
||||
- **更新位置**:`UpdateRowActionString()` 末尾
|
||||
|
||||
---
|
||||
|
||||
## 🔧 代码结构优化
|
||||
|
||||
### 新增文件
|
||||
无新增文件,所有修改在现有文件中
|
||||
|
||||
### 新增类
|
||||
1. **InputDialogWindow**(EditorWindow)
|
||||
- 用途:创建新场景时输入AreaId
|
||||
- 包含字段:
|
||||
- `message` - 提示信息
|
||||
- `inputValue` - 用户输入的值
|
||||
- `confirmed` - 是否确认
|
||||
- 方法:`OnGUI()` - 绘制输入界面
|
||||
|
||||
### 新增方法
|
||||
1. **OnCreateNewSceneClicked()** - 处理"创建新场景"按钮点击
|
||||
2. **ShowInputDialog()** - 显示输入对话框
|
||||
3. **ApplyResetPosAction()** - 应用reset_pos操作
|
||||
|
||||
### 修改的方法
|
||||
1. **BindUIControls()** - 禁用步骤数量输入框
|
||||
2. **OnLoadConfigClicked()** - 添加AreaId和配置存在检查
|
||||
3. **OnSaveConfigClicked()** - 添加AreaId限制检查
|
||||
4. **CreateNewAreaConfig()** - 改为弹窗输入AreaId,添加验证
|
||||
5. **ParseAndCreateActionGroups()** - 跳过spine,支持reset_pos
|
||||
6. **CreateActionGroup()** - 支持reset_pos类型
|
||||
7. **UpdateRowActionString()** - 保留spine操作,支持reset_pos
|
||||
8. **ApplyStepAction()** - 跳过所有spine操作
|
||||
9. **ApplyInitAction()** - 跳过init_spine
|
||||
10. **CreateStepEditItem()** - 添加只读Action显示
|
||||
|
||||
---
|
||||
|
||||
## 📝 配置文件格式说明
|
||||
|
||||
### Action字符串格式
|
||||
```
|
||||
操作1@操作2@操作3...
|
||||
```
|
||||
|
||||
### 支持的操作类型
|
||||
| 操作类型 | 格式 | 示例 | UI编辑 |
|
||||
|---------|------|------|--------|
|
||||
| clear | `clear#路径1,路径2,...` | `clear#bg/clearObj/3,bg/clearObj/4` | ✅ 可编辑 |
|
||||
| add | `add#路径1,路径2,...` | `add#bg/addObj/5,bg/addObj/6` | ✅ 可编辑 |
|
||||
| replace | `replace#旧路径,新路径` | `replace#bg/clearObj/1,bg/addObj/1` | ✅ 可编辑 |
|
||||
| replace_image | `replace_image#节点路径,图片路径` | `replace_image#bg,BG/s3_bg_2` | ✅ 可编辑 |
|
||||
| reset_pos | `reset_pos#节点路径,x=y` | `reset_pos#bg/clearObj/2,-156=-838` | ✅ 可编辑 |
|
||||
| init_spine | `init_spine#...` | - | ❌ 自动保留 |
|
||||
| replace_spine | `replace_spine#...` | - | ❌ 自动保留 |
|
||||
|
||||
### Spine操作处理策略
|
||||
- **读取时**:spine操作不显示在UI中
|
||||
- **编辑时**:用户无法看到和修改spine操作
|
||||
- **保存时**:spine操作放在Action字符串的最前面,原样保留
|
||||
- **预览时**:spine操作不执行(避免spine加载问题)
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **AreaId限制**
|
||||
- AreaId 1和2不可通过编辑器修改
|
||||
- 如需修改,需要直接编辑配置文件或联系编辑器作者
|
||||
|
||||
2. **步骤数量固定**
|
||||
- 所有场景固定25步
|
||||
- 如需修改步骤数量,需要修改编辑器代码
|
||||
|
||||
3. **Spine无感知**
|
||||
- 用户在UI中完全看不到spine相关配置
|
||||
- 但spine配置不会丢失,保存时会自动保留
|
||||
|
||||
4. **新场景创建**
|
||||
- 创建新场景后,配置仅在内存中,需手动保存
|
||||
- 保存前可以预览场景效果
|
||||
|
||||
5. **reset_pos坐标格式**
|
||||
- 必须使用 `x=y` 格式(使用等号=分隔)
|
||||
- 示例:`-156=-838` 或 `100=200`
|
||||
- 不支持其他分隔符(如逗号或冒号)
|
||||
|
||||
6. **配置完整性**
|
||||
- 只读Action显示帮助验证配置正确性
|
||||
- 建议每次编辑后检查只读显示的内容
|
||||
|
||||
---
|
||||
|
||||
## 🐛 已知问题
|
||||
|
||||
无
|
||||
|
||||
---
|
||||
|
||||
## 📞 联系方式
|
||||
|
||||
如需对编辑器进行调整或遇到问题,请联系编辑器作者(你)。
|
||||
|
||||
---
|
||||
|
||||
## 📊 测试检查清单
|
||||
|
||||
- [ ] 尝试编辑AreaId=1,验证拒绝
|
||||
- [ ] 尝试编辑AreaId=2,验证拒绝
|
||||
- [ ] 尝试修改步骤数量,验证输入框禁用
|
||||
- [ ] 读取不存在的AreaId,验证提示正确
|
||||
- [ ] 创建新场景,输入AreaId=1,验证拒绝
|
||||
- [ ] 创建新场景,输入AreaId=3,验证成功
|
||||
- [ ] 创建新场景,输入已存在的AreaId,验证拒绝
|
||||
- [ ] 编辑包含spine的配置,验证spine不显示在UI
|
||||
- [ ] 保存包含spine的配置,验证spine保留在最前面
|
||||
- [ ] 添加reset_pos操作,验证可正常添加和编辑
|
||||
- [ ] 预览包含reset_pos的步骤,验证位置正确设置
|
||||
- [ ] 编辑操作后,验证只读Action显示实时更新
|
||||
- [ ] 新建场景不保存直接关闭,验证配置文件未改变
|
||||
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c1336f834fb30c45986701ba8b43f3e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ab35bf45404d564cb87c85fac02577f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,139 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<engine:UXML
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:engine="UnityEngine.UIElements"
|
||||
xmlns:editor="UnityEditor.UIElements"
|
||||
xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd">
|
||||
|
||||
<engine:VisualElement style="flex-grow: 1; padding: 10px;">
|
||||
<!-- 状态栏 -->
|
||||
<engine:VisualElement name="StatusBar" style="margin-bottom: 10px; padding: 8px; background-color: rgb(35, 35, 35); border-radius: 5px;">
|
||||
<engine:Label name="StatusLabel" text="⚪ 待保存状态:无修改" style="font-size: 13px; color: rgb(100, 150, 255); -unity-text-align: middle-left;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 顶部配置区域 -->
|
||||
<engine:VisualElement name="ConfigArea" style="margin-bottom: 10px; padding: 10px; border-width: 2px; border-color: rgb(50, 50, 50); border-radius: 5px;">
|
||||
<!-- 标题行:配置管理 + 核心操作按钮 + 常用工具 + 折叠按钮 -->
|
||||
<engine:VisualElement style="flex-direction: row; align-items: center; margin-bottom: 10px;">
|
||||
<engine:Label text="配置管理" style="font-size: 16px; -unity-font-style: bold; width: 100px;" />
|
||||
<engine:Button name="LoadConfigButton" text="读取配置" style="width: 90px; height: 28px; margin-right: 5px; background-color: rgb(60, 120, 180);" />
|
||||
<engine:Button name="SaveConfigButton" text="保存配置" style="width: 90px; height: 28px; margin-right: 5px; background-color: rgb(80, 140, 80);" />
|
||||
<engine:Button name="RecordInitButton" text="记录初始状态" style="width: 110px; height: 28px; margin-right: 15px; background-color: rgb(180, 100, 60);" />
|
||||
|
||||
<!-- 常用工具(高频按钮) -->
|
||||
<engine:Label text="常用工具:" style="font-size: 12px; margin-right: 5px; color: rgb(150, 200, 255);" />
|
||||
<engine:Button name="SortNamesButtonTop" text="名称排序" style="width: 85px; height: 28px; margin-right: 5px; background-color: rgb(100, 80, 140);" />
|
||||
<engine:Button name="ScaleImageButtonTop" text="图片X1.5" style="width: 80px; height: 28px; margin-right: 10px; background-color: rgb(100, 80, 140);" />
|
||||
|
||||
<engine:VisualElement style="flex-grow: 1;" />
|
||||
<engine:Button name="ToggleConfigButton" text="▲ 折叠" style="width: 80px; height: 25px;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 可折叠内容区域 -->
|
||||
<engine:VisualElement name="ConfigContent">
|
||||
<!-- 基础配置 -->
|
||||
<engine:VisualElement style="margin-bottom: 10px; padding: 8px; background-color: rgba(0, 0, 0, 0.2); border-radius: 3px;">
|
||||
<engine:VisualElement style="flex-direction: row; margin-bottom: 5px;">
|
||||
<engine:Label text="配置文件路径:" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
<engine:TextField name="ConfigPathField" style="flex-grow: 1; margin-right: 5px;" />
|
||||
<engine:Button name="BrowseConfigButton" text="浏览..." style="width: 80px;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<engine:VisualElement style="flex-direction: row; margin-bottom: 5px;">
|
||||
<engine:Label text="场景AreaId:" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
<engine:IntegerField name="AreaIdField" value="1" style="width: 100px;" />
|
||||
<engine:Label text="步骤数量(固定):" style="width: 130px; margin-left: 20px; -unity-text-align: middle-left;" />
|
||||
<engine:IntegerField name="StepCountField" value="25" style="width: 100px;" />
|
||||
<engine:Label text="不可修改,如需调整请联系编辑器作者" style="margin-left: 10px; -unity-text-align: middle-left; font-size: 10px; opacity: 0.7;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<engine:VisualElement style="flex-direction: row;">
|
||||
<engine:Label text="场景bg节点:" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
<editor:ObjectField name="BgObjectField" type="UnityEngine.Transform, UnityEngine.CoreModule" style="flex-grow: 1; margin-right: 5px;" />
|
||||
<engine:Button name="CheckBgButton" text="检测bg格式" style="width: 100px;" />
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 批量设置 -->
|
||||
<engine:Label text="批量设置" style="font-size: 13px; -unity-font-style: bold; margin-bottom: 5px; color: rgb(150, 200, 255);" />
|
||||
<engine:VisualElement style="flex-direction: row; margin-bottom: 5px;">
|
||||
<engine:Button name="AutoSetTitleButton" text="自动设置标题" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="AutoSetIconButton" text="自动设置Icon" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="BatchSetIconPosButton" text="批量Icon位置" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="AutoSetBuildButton" text="自动建造效果" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="AutoSetShineButton" text="全部闪光" style="flex-grow: 1; height: 28px;" />
|
||||
</engine:VisualElement>
|
||||
<engine:VisualElement style="flex-direction: row;">
|
||||
<engine:Button name="BatchSetCostButton" text="批量资源消耗" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="BatchSetSkipButton" text="批量设置批次" style="flex-grow: 1; margin-right: 5px; height: 28px;" />
|
||||
<engine:Button name="ClearSceneButton" text="清空场景" style="flex-grow: 1; margin-right: 5px; height: 28px; background-color: rgb(140, 60, 60);" />
|
||||
<engine:VisualElement style="flex-grow: 2;" />
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 初始状态编辑区域 -->
|
||||
<engine:VisualElement style="margin-bottom: 10px; padding: 10px; border-width: 2px; border-color: rgb(50, 50, 50); border-radius: 5px;">
|
||||
<!-- 标题行带折叠按钮 -->
|
||||
<engine:VisualElement style="flex-direction: row; align-items: center; margin-bottom: 10px;">
|
||||
<engine:Label text="初始状态编辑" style="font-size: 14px; -unity-font-style: bold; flex-grow: 1;" />
|
||||
<engine:Button name="ToggleInitEditButton" text="▲ 折叠" style="width: 80px; height: 25px;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 可折叠内容 -->
|
||||
<engine:VisualElement name="InitEditContent">
|
||||
<engine:Label text="点击【记录初始状态】后,可在此处编辑各对象的初始属性" style="font-size: 11px; color: rgb(150, 150, 150); margin-bottom: 8px;" />
|
||||
<engine:ScrollView style="max-height: 300px; border-width: 1px; border-color: rgb(60, 60, 60); border-radius: 3px; background-color: rgba(0, 0, 0, 0.2);">
|
||||
<engine:VisualElement name="InitEditContainer" style="padding: 5px;">
|
||||
<engine:Label name="InitEmptyLabel" text="暂无初始状态数据" style="margin: 20px; -unity-text-align: middle-center; color: rgb(128, 128, 128);" />
|
||||
</engine:VisualElement>
|
||||
</engine:ScrollView>
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 步骤操作和编辑区域(双栏布局)-->
|
||||
<engine:VisualElement style="flex-direction: row; flex-grow: 1; gap: 10px;">
|
||||
<!-- 左侧:步骤快速选择面板 -->
|
||||
<engine:VisualElement style="width: 220px; border-width: 2px; border-color: rgb(50, 50, 50); border-radius: 5px; padding: 10px;">
|
||||
<engine:Label text="步骤导航" style="font-size: 14px; -unity-font-style: bold; margin-bottom: 8px;" />
|
||||
|
||||
<!-- 快速跳转 -->
|
||||
<engine:VisualElement style="flex-direction: row; margin-bottom: 8px; align-items: center;">
|
||||
<engine:Label text="当前:" style="width: 35px; font-size: 11px;" />
|
||||
<engine:IntegerField name="CurrentStepField" value="0" style="width: 50px; margin-right: 3px;" />
|
||||
<engine:Button name="GotoStepButton" text="GO" style="width: 35px; height: 22px; font-size: 11px;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 导航按钮组 -->
|
||||
<engine:VisualElement style="flex-direction: row; gap: 3px; margin-bottom: 10px;">
|
||||
<engine:Button name="PrevStepButton" text="◀上步" style="flex-grow: 1; height: 24px; font-size: 11px;" />
|
||||
<engine:Button name="NextStepButton" text="下步▶" style="flex-grow: 1; height: 24px; font-size: 11px;" />
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 步骤网格(4列布局)-->
|
||||
<engine:ScrollView style="flex-grow: 1; border-width: 1px; border-color: rgb(60, 60, 60); border-radius: 3px; background-color: rgba(0, 0, 0, 0.3);">
|
||||
<engine:VisualElement name="StepGridContainer" style="padding: 5px; flex-wrap: wrap; flex-direction: row;">
|
||||
<!-- 这里会动态添加25个步骤按钮,每个按钮40x38像素,4列布局 -->
|
||||
</engine:VisualElement>
|
||||
</engine:ScrollView>
|
||||
|
||||
<!-- 预览控制 -->
|
||||
<engine:VisualElement style="margin-top: 8px; padding-top: 8px; border-top-width: 1px; border-color: rgb(60, 60, 60);">
|
||||
<engine:Label name="StepInfoLabel" text="初始状态" style="margin-bottom: 5px; -unity-text-align: middle-center; font-size: 11px; color: rgb(180, 180, 180);" />
|
||||
<engine:Button name="ShowDecorateButton" text="显示装饰按钮" style="width: 100%; height: 24px; margin-bottom: 3px; font-size: 11px;" />
|
||||
<engine:Button name="HideDecorateButton" text="隐藏装饰按钮" style="width: 100%; height: 24px; font-size: 11px;" />
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
|
||||
<!-- 右侧:步骤编辑区域 -->
|
||||
<engine:ScrollView name="StepEditScrollView" style="flex-grow: 1; border-width: 2px; border-color: rgb(50, 50, 50); border-radius: 5px;">
|
||||
<engine:VisualElement name="StepEditContainer" style="padding: 10px;">
|
||||
<engine:Label text="步骤编辑" style="font-size: 14px; -unity-font-style: bold; margin-bottom: 10px;" />
|
||||
|
||||
<!-- 这里会动态添加步骤编辑项 -->
|
||||
<engine:Label name="EmptyLabel" text="请先读取或创建配置" style="margin: 20px; -unity-text-align: middle-center; color: rgb(128, 128, 128);" />
|
||||
</engine:VisualElement>
|
||||
</engine:ScrollView>
|
||||
</engine:VisualElement>
|
||||
</engine:VisualElement>
|
||||
</engine:UXML>
|
||||
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18e43c7ee1d33164697d9fbb1076fe3d
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@ -1,234 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using OfficeOpenXml;
|
||||
|
||||
/// <summary>
|
||||
/// DecorateCost表格转换工具
|
||||
/// 用于将Icon列的完整路径转换为只保留文件名
|
||||
/// 例如: Icon/first/s1_icon_renwu_5 -> s1_icon_renwu_5
|
||||
/// </summary>
|
||||
public class DecorateCostTableConverter : EditorWindow
|
||||
{
|
||||
private string excelPath = "E:\\WorkSpace\\Docs\\config\\DecorateCost.xlsx";
|
||||
private const string SHEET_NAME = "DecorateCost";
|
||||
private Vector2 scrollPosition;
|
||||
private string logMessage = "";
|
||||
|
||||
[MenuItem("蹊径/转换DecorateCost表格")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<DecorateCostTableConverter>("DecorateCost表格转换");
|
||||
window.minSize = new Vector2(500, 400);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Label("DecorateCost表格Icon路径转换工具", EditorStyles.boldLabel);
|
||||
GUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"此工具会将Icon列的完整路径转换为只保留文件名。\n" +
|
||||
"例如: Icon/first/s1_icon_renwu_5 → s1_icon_renwu_5\n\n" +
|
||||
"转换规则:\n" +
|
||||
"• 如果Icon路径包含'/',则只保留最后一部分\n" +
|
||||
"• 如果Icon路径为空或不包含'/',则保持不变\n" +
|
||||
"• 如果Action列包含'init_spine',则跳过该行(不转换)\n" +
|
||||
"• 会自动备份原文件(添加.backup扩展名)",
|
||||
MessageType.Info);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Excel文件路径
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("Excel路径:", GUILayout.Width(80));
|
||||
excelPath = EditorGUILayout.TextField(excelPath);
|
||||
if (GUILayout.Button("浏览", GUILayout.Width(60)))
|
||||
{
|
||||
string path = EditorUtility.OpenFilePanel("选择DecorateCost.xlsx", "", "xlsx");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
excelPath = path;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// 转换按钮
|
||||
if (GUILayout.Button("开始转换", GUILayout.Height(30)))
|
||||
{
|
||||
ConvertTable();
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// 日志显示区域
|
||||
if (!string.IsNullOrEmpty(logMessage))
|
||||
{
|
||||
EditorGUILayout.LabelField("转换日志:", EditorStyles.boldLabel);
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(200));
|
||||
EditorGUILayout.TextArea(logMessage, GUILayout.ExpandHeight(true));
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConvertTable()
|
||||
{
|
||||
logMessage = "";
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!File.Exists(excelPath))
|
||||
{
|
||||
logMessage = $"❌ 错误: 文件不存在\n路径: {excelPath}";
|
||||
Debug.LogError(logMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 设置EPPlus许可证
|
||||
|
||||
// 备份原文件
|
||||
string backupPath = excelPath + ".backup";
|
||||
File.Copy(excelPath, backupPath, true);
|
||||
logMessage += $"✓ 已备份原文件到: {backupPath}\n\n";
|
||||
|
||||
// 读取Excel
|
||||
using (var package = new ExcelPackage(new FileInfo(excelPath)))
|
||||
{
|
||||
var worksheet = package.Workbook.Worksheets[SHEET_NAME];
|
||||
if (worksheet == null)
|
||||
{
|
||||
logMessage += $"❌ 错误: 找不到工作表 '{SHEET_NAME}'\n";
|
||||
Debug.LogError(logMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找Icon列的索引(假设第一行是标题行)
|
||||
int iconColIndex = -1;
|
||||
int sortIdColIndex = -1;
|
||||
int actionColIndex = -1;
|
||||
int totalCols = worksheet.Dimension.End.Column;
|
||||
|
||||
for (int col = 1; col <= totalCols; col++)
|
||||
{
|
||||
var cellValue = worksheet.Cells[1, col].Text.Trim();
|
||||
if (cellValue == "Icon" || cellValue == "图标")
|
||||
{
|
||||
iconColIndex = col;
|
||||
}
|
||||
else if (cellValue == "SortId" || cellValue == "排序Id")
|
||||
{
|
||||
sortIdColIndex = col;
|
||||
}
|
||||
else if (cellValue == "Action" || cellValue == "行为")
|
||||
{
|
||||
actionColIndex = col;
|
||||
}
|
||||
}
|
||||
|
||||
if (iconColIndex == -1)
|
||||
{
|
||||
logMessage += "❌ 错误: 找不到Icon列\n";
|
||||
Debug.LogError(logMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
logMessage += $"✓ 找到Icon列: 第{iconColIndex}列\n";
|
||||
if (sortIdColIndex != -1)
|
||||
{
|
||||
logMessage += $"✓ 找到SortId列: 第{sortIdColIndex}列\n";
|
||||
}
|
||||
if (actionColIndex != -1)
|
||||
{
|
||||
logMessage += $"✓ 找到Action列: 第{actionColIndex}列\n";
|
||||
}
|
||||
logMessage += "\n开始转换...\n\n";
|
||||
|
||||
int totalRows = worksheet.Dimension.End.Row;
|
||||
int convertedCount = 0;
|
||||
int skippedCount = 0;
|
||||
int emptyCount = 0;
|
||||
int spineSkippedCount = 0;
|
||||
|
||||
// 从第3行开始处理(第1行是英文标题,第2行是中文标题)
|
||||
for (int row = 3; row <= totalRows; row++)
|
||||
{
|
||||
var iconCell = worksheet.Cells[row, iconColIndex];
|
||||
string originalIcon = iconCell.Text.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(originalIcon))
|
||||
{
|
||||
emptyCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查Action列是否包含init_spine
|
||||
bool hasInitSpine = false;
|
||||
if (actionColIndex != -1)
|
||||
{
|
||||
var actionCell = worksheet.Cells[row, actionColIndex];
|
||||
string actionValue = actionCell.Text.Trim();
|
||||
if (!string.IsNullOrEmpty(actionValue) && actionValue.Contains("init_spine"))
|
||||
{
|
||||
hasInitSpine = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果包含init_spine,跳过这一行
|
||||
if (hasInitSpine)
|
||||
{
|
||||
spineSkippedCount++;
|
||||
logMessage += $"第{row}行: 跳过(包含init_spine): {originalIcon}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果包含'/',则只保留最后一部分
|
||||
if (originalIcon.Contains("/"))
|
||||
{
|
||||
string newIcon = originalIcon.Substring(originalIcon.LastIndexOf('/') + 1);
|
||||
iconCell.Value = newIcon;
|
||||
|
||||
string sortInfo = "";
|
||||
if (sortIdColIndex != -1)
|
||||
{
|
||||
var sortIdCell = worksheet.Cells[row, sortIdColIndex];
|
||||
sortInfo = $" [SortId={sortIdCell.Text}]";
|
||||
}
|
||||
|
||||
logMessage += $"第{row}行{sortInfo}: {originalIcon} → {newIcon}\n";
|
||||
convertedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
skippedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
package.Save();
|
||||
|
||||
logMessage += $"\n转换完成!\n";
|
||||
logMessage += $"━━━━━━━━━━━━━━━━━━━━━━\n";
|
||||
logMessage += $"✓ 已转换: {convertedCount} 条\n";
|
||||
logMessage += $"• 跳过(无需转换): {skippedCount} 条\n";
|
||||
logMessage += $"• 跳过(init_spine): {spineSkippedCount} 条\n";
|
||||
logMessage += $"• 空值: {emptyCount} 条\n";
|
||||
logMessage += $"━━━━━━━━━━━━━━━━━━━━━━\n";
|
||||
logMessage += $"✓ 文件已保存: {excelPath}\n";
|
||||
|
||||
Debug.Log("DecorateCost表格转换完成!");
|
||||
EditorUtility.DisplayDialog("转换完成",
|
||||
$"Icon路径转换完成!\n\n已转换: {convertedCount} 条\n跳过(无需转换): {skippedCount} 条\n跳过(init_spine): {spineSkippedCount} 条\n空值: {emptyCount} 条\n\n原文件已备份",
|
||||
"确定");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
logMessage += $"\n❌ 转换失败:\n{ex.Message}\n\n{ex.StackTrace}";
|
||||
Debug.LogError($"转换失败: {ex.Message}");
|
||||
EditorUtility.DisplayDialog("转换失败", $"转换过程中出现错误:\n\n{ex.Message}", "确定");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26d566349ea253e4ca0d63d21018f9e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,96 +0,0 @@
|
||||
# DecorateConfigEditor 快速参考
|
||||
|
||||
## 🚫 操作限制
|
||||
|
||||
### AreaId限制
|
||||
- ❌ **不能编辑** AreaId = 1 或 2
|
||||
- ✅ **可以编辑** AreaId ≥ 3 的所有场景
|
||||
- 原因:1和2有特殊处理逻辑
|
||||
|
||||
### 步骤数量
|
||||
- ⚠️ **固定25步**,无法修改
|
||||
- 如需调整,请联系编辑器作者
|
||||
|
||||
---
|
||||
|
||||
## 📋 操作类型速查
|
||||
|
||||
| 操作 | 用途 | UI字段数 | 字段类型 |
|
||||
|-----|------|---------|---------|
|
||||
| **clear** | 隐藏对象 | 动态(+/-) | ObjectField |
|
||||
| **add** | 显示对象 | 动态(+/-) | ObjectField |
|
||||
| **replace** | 替换对象 | 固定2个 | ObjectField × 2 |
|
||||
| **replace_image** | 换图片 | 固定2个 | ObjectField + TextField |
|
||||
| **reset_pos** | 重置位置 | 固定2个 | ObjectField + TextField(x=y) |
|
||||
| **spine** | Spine相关 | 不显示 | 自动保留 |
|
||||
|
||||
---
|
||||
|
||||
## 🔄 常用工作流程
|
||||
|
||||
### 创建新场景
|
||||
1. 点击"创建新场景"
|
||||
2. 输入AreaId(≥3且不存在)
|
||||
3. 编辑步骤配置
|
||||
4. 点击"保存配置"
|
||||
|
||||
### 编辑现有场景
|
||||
1. 设置AreaId(≥3)
|
||||
2. 点击"读取配置"
|
||||
3. 在下方编辑步骤
|
||||
4. 点击"保存配置"
|
||||
|
||||
### 预览效果
|
||||
1. 读取配置后
|
||||
2. 使用"上一步/下一步"按钮
|
||||
3. 或输入步骤号点击"跳转"
|
||||
|
||||
---
|
||||
|
||||
## 💡 快速提示
|
||||
|
||||
- **只读显示**:每个步骤顶部的灰色框显示完整Action字符串
|
||||
- **Spine操作**:完全透明,你看不到但它们会被保留
|
||||
- **拖放编辑**:从Hierarchy拖GameObject到ObjectField
|
||||
- **位置格式**:reset_pos用 `x=y` 格式,如 `-156=-838`
|
||||
- **配置保护**:新建场景不会立即保存,可以先预览
|
||||
|
||||
---
|
||||
|
||||
## ⚡ 键盘快捷操作
|
||||
|
||||
- 使用 **Tab** 在字段间切换
|
||||
- **+/-** 按钮添加/删除ObjectField
|
||||
- **X** 按钮删除整个操作组
|
||||
|
||||
---
|
||||
|
||||
## 🎯 示例配置
|
||||
|
||||
```
|
||||
clear#bg/clearObj/3,bg/clearObj/4@add#bg/addObj/5@replace#bg/clearObj/1,bg/addObj/1@replace_image#bg,BG/s3_bg_2@reset_pos#bg/clearObj/2,-156=-838
|
||||
```
|
||||
|
||||
解读:
|
||||
1. 隐藏 clearObj/3 和 clearObj/4
|
||||
2. 显示 addObj/5
|
||||
3. 用 addObj/1 替换 clearObj/1
|
||||
4. bg换图片为 s3_bg_2
|
||||
5. clearObj/2 移动到 (-156, -838)
|
||||
|
||||
---
|
||||
|
||||
## ❗ 常见错误
|
||||
|
||||
| 错误 | 原因 | 解决方法 |
|
||||
|-----|------|---------|
|
||||
| "AreaId 1和2不支持" | 选择了受限AreaId | 使用AreaId ≥ 3 |
|
||||
| "配置不存在" | AreaId未创建 | 点击"创建新场景" |
|
||||
| "找不到路径" | GameObject路径错误 | 检查Hierarchy结构 |
|
||||
| reset_pos不生效 | 格式错误 | 使用 x=y 格式(=号) |
|
||||
|
||||
---
|
||||
|
||||
## 📞 需要帮助?
|
||||
|
||||
如需修改编辑器功能或遇到特殊需求,请联系编辑器作者。
|
||||
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd5a55ccdd0a4fc4d854b7e0ec9bbbe7
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,236 +0,0 @@
|
||||
# DecorateConfigEditor SO集成升级说明
|
||||
|
||||
## 📋 概述
|
||||
|
||||
已将 `DecorateConfigEditor` 从直接加载图片路径升级为使用 ScriptableObject (SO) 资源系统。
|
||||
|
||||
## 🎯 主要改动
|
||||
|
||||
### 1. **资源加载方式变更**
|
||||
|
||||
#### 旧方式(已废弃)
|
||||
```
|
||||
Icon列:Icon/first/s1_icon_renwu_5
|
||||
加载:从 Assets/GameMain/UI/UISprites/Decorate/ 路径直接加载
|
||||
```
|
||||
|
||||
#### 新方式(当前)
|
||||
```
|
||||
Icon列:s1_icon_renwu_5
|
||||
加载:从 ArtTableSO 中根据 Name 查找对应的 Sprite
|
||||
```
|
||||
|
||||
### 2. **SO资源分类**
|
||||
|
||||
#### DecorateScene(场景资源)
|
||||
- **路径**: `Assets/Art_SubModule/Art_SO/DecorateScene/Scene{AreaId}Resource.asset`
|
||||
- **用途**: 存储 `SortId=0` 的初始化场景物体图片
|
||||
- **命名规则**: Scene1Resource, Scene2Resource, ..., Scene50Resource
|
||||
- **示例**: AreaId=1 → 从 Scene1Resource.asset 中查找
|
||||
|
||||
#### DecorateIcon(图标资源)
|
||||
- **路径**: `Assets/Art_SubModule/Art_SO/DecorateIcon/DecorateIconResource.asset`
|
||||
- **用途**: 存储 `SortId>0` 的步骤装饰图标
|
||||
- **所有步骤图标**: 统一存放在 DecorateIconResource.asset
|
||||
|
||||
### 3. **核心功能修改**
|
||||
|
||||
#### ✅ 已修改的功能
|
||||
|
||||
1. **表格路径转换工具**
|
||||
- 新增:`蹊径 > 转换DecorateCost表格`
|
||||
- 功能:将Icon列完整路径转换为文件名
|
||||
- 自动备份原文件
|
||||
|
||||
2. **配置保存验证**
|
||||
- 保存前验证Icon名称是否存在于对应SO中
|
||||
- 显示详细的验证错误信息
|
||||
- 支持强制保存(不推荐)
|
||||
|
||||
3. **图片预览加载**
|
||||
- 步骤编辑UI的Icon预览
|
||||
- 初始状态编辑UI的Icon预览
|
||||
- 装饰按钮预览
|
||||
|
||||
4. **自动设置Icon**
|
||||
- 从SO中查找匹配的Icon名称
|
||||
- 支持批量设置
|
||||
|
||||
5. **场景物体Action执行**
|
||||
- `init_img`: 从SO加载Sprite
|
||||
- `replace_image`: 从SO加载替换图片
|
||||
|
||||
6. **拖入Sprite处理**
|
||||
- 自动从SO中查找对应Name
|
||||
- 兼容旧路径格式(自动转换)
|
||||
|
||||
## 🚀 使用流程
|
||||
|
||||
### 步骤1: 转换现有表格
|
||||
|
||||
1. 打开Unity编辑器
|
||||
2. 菜单栏选择:`蹊径 > 转换DecorateCost表格`
|
||||
3. 确认Excel路径:`E:\WorkSpace\Docs\config\DecorateCost.xlsx`
|
||||
4. 点击"开始转换"
|
||||
5. 检查转换日志,确认成功
|
||||
|
||||
**转换示例**:
|
||||
```
|
||||
Icon/first/s1_icon_renwu_5 → s1_icon_renwu_5
|
||||
Icon/first/s2_icon_renwu_3 → s2_icon_renwu_3
|
||||
cat/old/old_curtain → old_curtain
|
||||
```
|
||||
|
||||
### 步骤2: 准备SO资源
|
||||
|
||||
#### 确保SO中包含所需资源
|
||||
|
||||
**DecorateScene SO** (初始化场景)
|
||||
```
|
||||
Assets/Art_SubModule/Art_SO/DecorateScene/Scene1Resource.asset
|
||||
└── Items
|
||||
├── Name: "old_curtain" → Sprite: cat/old/old_curtain.png
|
||||
├── Name: "back_box_2" → Sprite: cat/old/back_box_2.png
|
||||
└── Name: "old_gabage" → Sprite: cat/old/old_gabage.png
|
||||
```
|
||||
|
||||
**DecorateIcon SO** (步骤图标)
|
||||
```
|
||||
Assets/Art_SubModule/Art_SO/DecorateIcon/DecorateIconResource.asset
|
||||
└── Items
|
||||
├── Name: "s1_icon_renwu_1" → Sprite: Icon/first/s1_icon_renwu_1.png
|
||||
├── Name: "s1_icon_renwu_2" → Sprite: Icon/first/s1_icon_renwu_2.png
|
||||
└── Name: "s2_icon_renwu_1" → Sprite: Icon/first/s2_icon_renwu_1.png
|
||||
```
|
||||
|
||||
### 步骤3: 使用编辑器
|
||||
|
||||
1. 打开:`蹊径 > 场景建造工具`
|
||||
2. 加载配置(会自动从SO中加载图片)
|
||||
3. 编辑步骤配置
|
||||
4. 保存时自动验证Icon名称是否存在
|
||||
|
||||
## 📝 配置示例
|
||||
|
||||
### DecorateCost.xlsx 表格格式
|
||||
|
||||
| Id | AreaId | SortId | Title | Icon | Pos | Action |
|
||||
|----|--------|--------|-------|------|-----|--------|
|
||||
| 1 | 1 | 0 | show | old_curtain | 150#625 | init_img#bg/clearObj/1 |
|
||||
| 2 | 1 | 1 | 炉火 | s1_icon_renwu_1 | first | clear#bg/clearObj/10 |
|
||||
| 3 | 1 | 2 | 窗户 | s1_icon_renwu_2 | second | add#bg/clearObj/18 |
|
||||
|
||||
### SO配置规则
|
||||
|
||||
```csharp
|
||||
// SortId = 0 → 从 DecorateScene 加载
|
||||
if (row.SortId == 0) {
|
||||
// 查找 Scene{AreaId}Resource.asset
|
||||
// 例如:AreaId=1 → Scene1Resource.asset
|
||||
}
|
||||
|
||||
// SortId > 0 → 从 DecorateIcon 加载
|
||||
if (row.SortId > 0) {
|
||||
// 查找 DecorateIconResource.asset
|
||||
}
|
||||
```
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. Icon名称规范
|
||||
- **必须与SO中Item的Name完全匹配**
|
||||
- 区分大小写
|
||||
- 不包含路径前缀(如 `Icon/first/`)
|
||||
|
||||
### 2. SO资源管理
|
||||
- 定期检查SO中是否包含所有需要的资源
|
||||
- 保持Name的唯一性
|
||||
- Sprite引用不能为空
|
||||
|
||||
### 3. 保存验证
|
||||
- 保存前会检查Icon名称有效性
|
||||
- 无效的Icon会显示详细错误信息
|
||||
- 建议修复后再保存(强制保存可能导致运行时错误)
|
||||
|
||||
### 4. 兼容性
|
||||
- 支持拖入Sprite自动提取Name
|
||||
- 兼容旧路径格式(自动转换为Name)
|
||||
- 旧表格需要先运行转换工具
|
||||
|
||||
## 🔧 故障排查
|
||||
|
||||
### 问题1: 保存时提示"Icon名称在SO中不存在"
|
||||
|
||||
**原因**: Icon名称与SO中的Item Name不匹配
|
||||
|
||||
**解决方案**:
|
||||
1. 检查Icon列的值是否正确
|
||||
2. 打开对应的SO资源(Scene{AreaId}Resource 或 DecorateIconResource)
|
||||
3. 确认Items列表中是否有匹配Name的项
|
||||
4. 修正Icon名称或在SO中添加缺失的Item
|
||||
|
||||
### 问题2: Icon预览显示为空
|
||||
|
||||
**原因**: 无法从SO中加载Sprite
|
||||
|
||||
**解决方案**:
|
||||
1. 检查SO资源是否存在
|
||||
2. 确认Item.Name与Icon名称匹配
|
||||
3. 确认Item.Sprite引用不为空
|
||||
4. 查看Console日志获取详细错误信息
|
||||
|
||||
### 问题3: 自动设置Icon失败
|
||||
|
||||
**原因**: SO中找不到对应的Icon资源
|
||||
|
||||
**解决方案**:
|
||||
1. 确认图标资源已添加到DecorateIconResource.asset
|
||||
2. 确认Name格式:`s{AreaId}_icon_renwu_{StepId}`
|
||||
3. 例如:AreaId=1, Step=5 → Name应为 `s1_icon_renwu_5`
|
||||
|
||||
### 问题4: 拖入Sprite后路径错误
|
||||
|
||||
**原因**: Sprite不在SO中,使用了旧路径提取逻辑
|
||||
|
||||
**解决方案**:
|
||||
1. 确保拖入的Sprite已添加到对应SO的Items中
|
||||
2. 如果是新Sprite,先在SO中添加,设置Name,再拖入编辑器
|
||||
|
||||
## 📚 API参考
|
||||
|
||||
### 新增方法
|
||||
|
||||
```csharp
|
||||
// 加载装饰图标SO
|
||||
ArtTableSO LoadDecorateIconSO()
|
||||
|
||||
// 加载场景资源SO
|
||||
ArtTableSO LoadDecorateSceneSO(int areaId)
|
||||
|
||||
// 从SO中查找Sprite
|
||||
Sprite FindSpriteInSO(string iconName, int areaId, bool isInitScene)
|
||||
|
||||
// 验证Icon名称
|
||||
bool ValidateIconNameInSO(string iconName, int areaId, bool isInitScene, out string errorMsg)
|
||||
|
||||
// 从Icon名称加载Sprite(兼容旧格式)
|
||||
Sprite LoadSpriteFromIconName(string iconNameOrPath, int areaId, bool isInitScene)
|
||||
```
|
||||
|
||||
## 🎉 优势
|
||||
|
||||
1. **统一资源管理**: 所有图片资源集中在SO中管理
|
||||
2. **编辑器友好**: 可视化管理,支持拖拽
|
||||
3. **运行时高效**: 通过Name快速查找,无需路径解析
|
||||
4. **类型安全**: 在保存时验证资源存在性
|
||||
5. **易于维护**: SO结构清晰,便于扩展
|
||||
|
||||
## 📌 版本信息
|
||||
|
||||
- **升级日期**: 2026年1月31日
|
||||
- **影响范围**: DecorateConfigEditor, DecorateCost.xlsx
|
||||
- **兼容性**: 完全向后兼容(需先运行转换工具)
|
||||
|
||||
---
|
||||
|
||||
如有问题,请联系技术支持或查看详细日志。
|
||||
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71927440b54c68d46a8c2410690241cc
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in New Issue
Block a user