chore: sync workspace state

This commit is contained in:
2026-03-29 01:36:53 +08:00
parent eb5de3e3d4
commit e5cb79f3ce
4935 changed files with 35593 additions and 360696 deletions

View File

@@ -1,364 +0,0 @@
# C#脚本系统 Editor 前置缺口
## 1. 目的
本文档只记录 **C# 脚本系统接入 editor 时需要补齐的 editor 侧缺口**
这些内容 **不是脚本模块第一阶段的实现范围**
第一阶段仍以:
- 运行时闭环
- 单元测试闭环
- 最小场景级验证
为主。
本文档的作用是防止后续把 editor 集成需求误混到第一阶段里。
---
## 2. 当前策略
当前策略明确如下:
- 脚本系统第一阶段先不依赖 editor
- editor 只作为后续集成目标
- editor 相关工作拆分为独立 issue
因此,下面所有条目均属于:
- 后续阶段工作
- 或 editor / runtime 边界层工作
---
## 3. Issue 列表
## E-001 Play / Simulate 工作流尚未落地
### 现状
editor 当前已经定义了相关事件,但完整的 Play / Simulate 切换链路仍未形成统一工作流。
### 影响
没有这条链路,脚本系统无法在 editor 中以接近 Unity 的方式运行:
- 无法从编辑态切换到运行态
- 无法创建运行时场景副本
- 无法触发脚本运行时启动与停止
### 需要补齐
- `EditorMode` 状态机
- `Edit / Play / Simulate` 三态切换
- 菜单栏或工具栏中的 Play / Stop / Pause 控件
- 对应的事件派发和恢复流程
### 优先级
高,但属于 editor 集成阶段,不属于脚本第一阶段
---
## E-002 editor 场景与 runtime 场景切换控制未封装
### 现状
当前 scene 管理具备快照能力,但 editor 还没有一套完整的“运行时场景副本控制器”。
### 影响
没有这一层,脚本一旦接入 editor会直接面临以下风险
- Play 过程污染编辑场景
- Stop 后无法恢复编辑态
- 运行时对象状态和 editor 面板状态错乱
### 需要补齐
- editor 场景与 runtime 场景的明确所有权
- Play 前复制
- Stop 后恢复
- 运行时期间禁用部分编辑操作
- 选中对象和层级面板的状态同步策略
### 优先级
---
## E-003 Inspector 缺少 `ScriptComponent` 作者化 UI
### 现状
当前 editor Inspector 还没有脚本组件专用 UI。
### 影响
即使底层脚本系统完成,用户也无法在 editor 中完成以下基础操作:
- 添加脚本组件
- 删除脚本组件
- 选择脚本类
- 查看脚本类名
- 调整脚本组件顺序
### 需要补齐
- Add Component 菜单中的 `ScriptComponent`
- 已挂载脚本组件列表
- 脚本类选择器
- 脚本丢失 / 类不存在 / 程序集未加载的错误态显示
### 优先级
---
## E-004 Inspector 缺少脚本字段编辑能力
### 现状
当前 editor 没有基于脚本字段元数据的动态 Inspector。
### 影响
无法实现 Unity 风格脚本工作流中最关键的一环:
- 在 Inspector 中编辑脚本字段
### 需要补齐
- 字段元数据缓存到 editor 层
- 基础类型字段绘制
- `Vector2/3/4` 字段绘制
- `bool` / `string` / 数值类型编辑
- 字段值回写 `ScriptComponent` 的字段缓存
### 优先级
---
## E-005 C# 项目与程序集管理缺失
### 现状
`Project` 面板目前已经有 `Assets/Scripts` 目录概念,但没有正式的 C# 项目管理机制。
### 影响
用户无法在 editor 中稳定地管理脚本编译输入和输出:
- 没有 `GameScripts.csproj`
- 没有 `ScriptCore` 引用管理
- 没有程序集输出路径约定
### 需要补齐
- 项目初始化时创建脚本工程模板
- 脚本程序集输出目录规范
- `ScriptCore` 引用自动配置
- 脚本工程文件缺失时的恢复策略
### 优先级
中到高
---
## E-006 editor 内缺少脚本编译触发入口
### 现状
当前 editor 没有“编译脚本”入口,也没有编译状态反馈。
### 影响
后续即使 Inspector 可选择脚本,用户也无法在 editor 中完成闭环:
- 修改脚本
- 编译程序集
- 重新加载类列表
### 需要补齐
- 手动编译按钮
- 后续可扩展到自动编译或文件监听
- 编译状态显示
- 成功/失败结果通知
### 优先级
中到高
---
## E-007 Console 面板缺少脚本编译错误与运行时异常接入
### 现状
当前 Console 还没有专门的脚本编译/加载/执行错误通路。
### 影响
脚本系统接入 editor 后,最基本的错误反馈都会缺失:
- 编译错误
- 程序集加载失败
- 类发现失败
- 运行时异常
- 栈信息显示
### 需要补齐
- 编译器 stdout/stderr 采集
- 程序集加载错误显示
- 托管异常栈转发到 Console
- 错误级别区分
- 后续可扩展到点击跳转文件/行号
### 优先级
---
## E-008 脚本类数据库与类缓存刷新机制缺失
### 现状
editor 还没有“当前项目有哪些可挂载脚本类”的缓存层。
### 影响
没有这一层Inspector 无法稳定实现:
- 类下拉列表
- 类是否可挂载的判断
- 类丢失提示
- 程序集重载后的刷新
### 需要补齐
- 脚本程序集扫描结果缓存
- 全限定类名列表
- 类状态标记
- reload 后缓存刷新
### 优先级
---
## E-009 对象引用字段的 editor 交互控件缺失
### 现状
后续脚本字段一旦支持 `GameObject` / 组件引用editor 目前没有相应控件。
### 影响
对象引用字段虽然不属于脚本第一阶段必需项,但属于后续可用性的关键能力。
### 需要补齐
- 场景对象选择器
- 层级面板拖拽赋值
- 失效引用显示
- 类型校验
### 优先级
---
## E-010 脚本程序集重载的 editor UX 缺失
### 现状
editor 当前没有定义“脚本重载时如何影响当前状态”的用户体验规则。
### 影响
后续一旦接入脚本编译与重载,会出现一系列状态问题:
- 当前选中对象是否刷新
- Inspector 是否保留编辑状态
- Play 中是否允许重载
- 重载失败如何回退
### 需要补齐
- Edit 模式重载策略
- Play 模式重载策略
- 失败回退策略
- 用户提示文案与状态反馈
### 优先级
---
## 4. 与 editor 集成直接相关的推荐顺序
建议的 editor 集成顺序如下:
1. `E-001` Play / Simulate 工作流
2. `E-002` runtime scene 切换控制
3. `E-003` `ScriptComponent` 作者化 UI
4. `E-004` 脚本字段 Inspector
5. `E-007` Console 错误接入
6. `E-005` C# 项目与程序集管理
7. `E-006` 脚本编译入口
8. `E-008` 类数据库刷新
9. `E-009` 对象引用字段控件
10. `E-010` 程序集重载 UX
这个顺序的核心原则是:
- 先让脚本能在 editor 中“跑起来”
- 再让脚本能在 editor 中“被作者化”
- 最后再补自动化体验与重载体验
---
## 5. 关联但不归 editor 的前置项
以下事项不是 editor issue但会直接影响后续 editor 集成质量:
- `GameObject UUID` 持久化
- 运行时生命周期规范化
- `Start` 一次性语义
- `SetActive` 驱动 `OnEnable/OnDisable`
- 场景递归更新
- `ScriptComponent` 字段缓存与序列化
这些工作应当在脚本第一阶段或 editor 集成前置阶段优先完成。
---
## 6. 结论
脚本系统第一阶段不应被 editor 当前进度绑定。
正确的推进方式是:
- 先做运行时与单测闭环
- 再按本文档逐项补 editor 集成能力
这样可以避免脚本模块在早期同时背负:
- 运行时实现风险
- editor 工作流风险
- UI 设计风险
- 重载体验风险
从而把复杂度拆开,逐步落地。

View File

@@ -1,144 +0,0 @@
# RHI 模块严重问题OpenGL 后端 RHI 状态不生效
## 问题严重程度
**严重级别**: 🔴 Critical Bug
## 问题定位
`OpenGLPipelineState` 维护了两套状态系统,但它们之间没有关联。
### 两套状态系统
**RHI 抽象层状态** (`OpenGLPipelineState.h:131-133`)
```cpp
RasterizerDesc m_rasterizerDesc;
BlendDesc m_blendDesc;
DepthStencilStateDesc m_depthStencilDesc;
```
**OpenGL 特定状态** (`OpenGLPipelineState.h:141-143`)
```cpp
OpenGLDepthStencilState m_glDepthStencilState;
OpenGLBlendState m_glBlendState;
OpenGLRasterizerState m_glRasterizerState;
```
## 问题详述
### RHI 接口设置的状态只存储不生效
```cpp
// OpenGLPipelineState.cpp:19-21
void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) {
m_rasterizerDesc = state; // ❌ 只存储到 m_rasterizerDesc
}
void OpenGLPipelineState::SetBlendState(const BlendDesc& state) {
m_blendDesc = state; // ❌ 只存储到 m_blendDesc
}
void OpenGLPipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) {
m_depthStencilDesc = state; // ❌ 只存储到 m_depthStencilDesc
}
```
### Apply() 使用的是另一套状态
```cpp
// OpenGLPipelineState.cpp:133-149
void OpenGLPipelineState::ApplyRasterizer() {
if (m_glRasterizerState.cullFaceEnable) { // ✅ 使用的是 m_glRasterizerState
glEnable(GL_CULL_FACE);
glCullFace(static_cast<GLenum>(m_glRasterizerState.cullFace));
// ...
}
}
void OpenGLPipelineState::ApplyBlend() {
if (m_glBlendState.blendEnable) { // ✅ 使用的是 m_glBlendState
glEnable(GL_BLEND);
// ...
}
}
void OpenGLPipelineState::ApplyDepthStencil() {
if (m_glDepthStencilState.depthTestEnable) { // ✅ 使用的是 m_glDepthStencilState
glEnable(GL_DEPTH_TEST);
// ...
}
}
```
## 导致的后果
**通过 RHI 抽象层设置的状态完全不会生效!**
```cpp
// 上层代码
RasterizerDesc raster;
raster.cullMode = 2; // 设置剔除模式
pso->SetRasterizerState(raster); // 通过 RHI 接口设置
// 实际渲染时
pso->Bind(); // 调用 ApplyRasterizer()
// ❌ m_glRasterizerState.cullMode 仍然是默认值,不是设置的值!
```
## 对比 D3D12 后端
D3D12 后端正确地在 `CreateD3D12PSO()` 中使用了 RHI 状态:
```cpp
// D3D12PipelineState.cpp:157-161
desc.RasterizerState.FillMode = static_cast<D3D12_FILL_MODE>(m_rasterizerDesc.fillMode);
desc.RasterizerState.CullMode = static_cast<D3D12_CULL_MODE>(m_rasterizerDesc.cullMode);
// ✅ 直接使用 m_rasterizerDesc
```
## 根本原因
OpenGL 后端有两个 `SetRasterizerState` 重载:
```cpp
// RHI 接口 - 只存储
void SetRasterizerState(const RasterizerDesc& state);
// OpenGL 特定接口 - 会生效
void SetRasterizerState(const OpenGLRasterizerState& state);
```
RHI 接口的实现缺少状态转换逻辑。
## 修复方案
`SetRasterizerState(const RasterizerDesc& state)` 中添加转换逻辑:
```cpp
void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) {
m_rasterizerDesc = state;
// 转换到 OpenGL 状态
m_glRasterizerState.cullFaceEnable = (state.cullMode != 0); // CullMode::None
m_glRasterizerState.cullFace = static_cast<CullMode>(state.cullMode);
m_glRasterizerState.frontFace = static_cast<FrontFace>(state.frontFace);
m_glRasterizerState.polygonMode = static_cast<FillMode>(state.fillMode);
m_glRasterizerState.depthClipEnable = state.depthClipEnable;
// ... 其他字段
}
```
同样需要修复 `SetBlendState``SetDepthStencilState`
## 相关文件
- `engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h`
- `engine/src/RHI/OpenGL/OpenGLPipelineState.cpp`
## 影响范围
1. **所有通过 RHI 抽象层设置的状态都不会生效**
2. **OpenGL 集成测试能工作是因为使用了 OpenGL 特定 API**
3. **上层代码如果使用 RHI 接口,行为会与预期不符**