351 lines
12 KiB
Markdown
351 lines
12 KiB
Markdown
# Loxodon Framework Core 分析
|
||
|
||
> 分析对象:<https://github.com/vovgou/loxodon-framework/tree/master/Loxodon.Framework/Assets/LoxodonFramework>
|
||
>
|
||
> 分析日期:2026-06-12
|
||
|
||
## 结论
|
||
|
||
Loxodon Framework 的 Core 本质上是一个 **Unity MVVM + DataBinding 运行时核心**,而不是覆盖完整游戏生命周期的游戏框架内核。
|
||
|
||
它的核心价值集中在:
|
||
|
||
- 用 `Context` 和 `ServiceContainer` 提供全局/局部上下文与轻量服务注册。
|
||
- 用 `BindingServiceBundle` 装配 DataBinding 所需的 Parser、Converter、SourceProxy、TargetProxy、Binder。
|
||
- 用 `ViewModelBase`、`ObservableObject`、Observable Collection 支撑 ViewModel 状态变化。
|
||
- 用 `UIView`、`Window`、`WindowManager` 提供 UI 视图、窗口状态和转场管理。
|
||
- 用 `Messenger`、`Command`、`Async`、`Prefs`、`Localization` 等模块补齐 MVVM UI 开发所需的基础设施。
|
||
|
||
因此,Loxodon 更适合作为 FlowScope 的 **UI / Binding / ServiceBundle 外围模块参考**,不适合作为 FlowScope Kernel 的边界模板。
|
||
|
||
## Core 模块拆解
|
||
|
||
### Context
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Contexts/Context.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Contexts/ApplicationContext.cs>
|
||
|
||
`Context` 维护静态 `ApplicationContext` 和按 key 注册的多个 `Context`,每个 Context 内部有:
|
||
|
||
- `IServiceContainer`
|
||
- 属性字典
|
||
- 可级联查询的 parent context
|
||
|
||
`ApplicationContext` 在 `Context` 基础上补了:
|
||
|
||
- `IMainLoopExecutor`
|
||
- Global Preferences
|
||
- User Preferences
|
||
|
||
这个设计方便应用层快速拿到全局能力,但也说明 Loxodon 的 Core 并不是纯机制内核。它把主线程执行器和 Prefs 这类应用级能力直接放进了全局上下文。
|
||
|
||
### ServiceContainer
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Services/ServiceContainer.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Services/AbstractServiceBundle.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Services/IServiceBundle.cs>
|
||
|
||
`ServiceContainer` 是轻量服务定位器,支持:
|
||
|
||
- 按 `Type` 注册对象或 factory。
|
||
- 按 `string name` 注册对象或 factory。
|
||
- `Resolve<T>()` / `Resolve(string)` 解析服务。
|
||
- `Unregister<T>()` / `Unregister(string)` 注销服务。
|
||
|
||
`ServiceBundle` 是模块装配入口:
|
||
|
||
```csharp
|
||
public interface IServiceBundle
|
||
{
|
||
void Start();
|
||
void Stop();
|
||
}
|
||
```
|
||
|
||
`AbstractServiceBundle` 把容器传给 `OnStart` / `OnStop`,由具体 bundle 负责注册和注销一组服务。
|
||
|
||
这个模式对 FlowScope 有参考价值:模块可以用显式 `Start/Stop` 完成能力注册,避免散落的静态初始化。
|
||
|
||
### Binding
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Binding/BindingServiceBundle.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/tree/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Binding>
|
||
|
||
Binding 是 Loxodon Core 最厚、最核心的部分。
|
||
|
||
`BindingServiceBundle` 会装配:
|
||
|
||
- `PathParser`
|
||
- `ExpressionPathFinder`
|
||
- `ConverterRegistry`
|
||
- `ObjectSourceProxyFactory`
|
||
- `SourceProxyFactory`
|
||
- `TargetProxyFactory`
|
||
- `BindingFactory`
|
||
- `StandardBinder`
|
||
|
||
然后注册:
|
||
|
||
- `IBinder`
|
||
- `IBindingFactory`
|
||
- `IConverterRegistry`
|
||
- `IExpressionPathFinder`
|
||
- `IPathParser`
|
||
- `INodeProxyFactory`
|
||
- `ISourceProxyFactory`
|
||
- `ITargetProxyFactory`
|
||
|
||
这说明 Loxodon 的 Binding 不是简单的反射赋值,而是一条可扩展管线:
|
||
|
||
```text
|
||
BindingDescription
|
||
-> Path / Expression
|
||
-> SourceProxy
|
||
-> Converter
|
||
-> TargetProxy
|
||
-> Binding
|
||
```
|
||
|
||
README 也强调该框架围绕 DataBinding 做了性能优化:减少装箱、降低 GC、通过动态委托或静态织入降低反射成本。
|
||
|
||
### ViewModel / Observable
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/ViewModels/ViewModelBase.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Observables/ObservableObject.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/tree/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Observables>
|
||
|
||
`ViewModelBase` 继承 `ObservableObject`,核心职责是:
|
||
|
||
- 封装属性变更。
|
||
- 触发 `PropertyChanged`。
|
||
- 可选通过 `IMessenger` 广播 `PropertyChangedMessage<T>`。
|
||
|
||
典型路径是:
|
||
|
||
```text
|
||
ViewModel property set
|
||
-> Set<T>
|
||
-> field updated
|
||
-> RaisePropertyChanged
|
||
-> optional Messenger.Publish(PropertyChangedMessage<T>)
|
||
-> Binding updates target UI
|
||
```
|
||
|
||
这是标准 MVVM 的数据驱动 UI 模型。
|
||
|
||
### View / Window
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Views/UIView.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Views/Window.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Views/WindowManager.cs>
|
||
|
||
`UIView` 负责 Unity UI 基础行为:
|
||
|
||
- `RectTransform`
|
||
- `CanvasGroup`
|
||
- `Visibility`
|
||
- Enter / Exit Animation
|
||
- Enable / Disable event
|
||
|
||
`Window` 在 `UIView` 基础上增加:
|
||
|
||
- `WindowType`
|
||
- `windowPriority`
|
||
- `WindowState`
|
||
- activated / dismissed / visibility changed event
|
||
- state broadcast
|
||
|
||
`WindowManager` 管理窗口集合、当前窗口、可见窗口和转场执行。
|
||
|
||
这部分是 UI 框架能力,不是游戏 Feature 生命周期管理。
|
||
|
||
### Messaging / Command / Async / Prefs
|
||
|
||
源码位置:
|
||
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Messaging/Messenger.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Commands/RelayCommand.cs>
|
||
- <https://github.com/vovgou/loxodon-framework/tree/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Asynchronous>
|
||
- <https://github.com/vovgou/loxodon-framework/blob/master/Loxodon.Framework/Assets/LoxodonFramework/Runtime/Framework/Prefs/Preferences.cs>
|
||
|
||
这些模块服务于 MVVM/UI 工程化:
|
||
|
||
- `Messenger`:按消息类型和 channel 做发布订阅。
|
||
- `RelayCommand`:给 UI 事件绑定命令。
|
||
- `AsyncResult` / `ProgressResult` / `CoroutineTask`:把异步、协程、进度结果统一成可等待对象。
|
||
- `Preferences`:默认基于 `PlayerPrefs`,支持全局和用户偏好。
|
||
|
||
这些能力有实用价值,但它们放在 Core 中会让 Core 变厚。对 FlowScope 来说,应当拆成独立模块或适配层,而不是进入 Kernel。
|
||
|
||
## 架构优点
|
||
|
||
### 1. MVVM UI 工程化成熟
|
||
|
||
Binding、ViewModel、Command、Window、Messenger 形成了完整闭环。对于 UI 重、状态同步复杂、需要数据绑定的 Unity 项目,Loxodon 能显著减少手写 UI 刷新代码。
|
||
|
||
### 2. Binding 管线拆得足够细
|
||
|
||
`SourceProxy`、`TargetProxy`、`Converter`、`PathParser`、`Binder` 的拆分使绑定系统具备较强扩展性。不同 UI 系统或不同数据源可以通过 proxy/factory 接入,而不是改主流程。
|
||
|
||
### 3. ServiceBundle 模式简单可控
|
||
|
||
`Start/Stop` 注册/注销一组服务,适合插件化装配。相比全局静态初始化,这种方式更容易表达模块边界。
|
||
|
||
### 4. 有性能意识
|
||
|
||
README 中明确强调减少 value type 装箱、减少 GC、优化绑定性能。这说明 Loxodon 的设计目标不是单纯追求抽象,而是面向 Unity UI 高频更新场景。
|
||
|
||
## 架构局限
|
||
|
||
### 1. Core 边界偏厚
|
||
|
||
`ApplicationContext` 直接提供主线程执行器和 Preferences,`Preferences` 默认落到 `PlayerPrefs`,`Messenger.Default` 也带有全局静态倾向。
|
||
|
||
这些设计让使用更方便,但会让 Core 逐步吸收平台、存储、消息、UI 等应用级能力。
|
||
|
||
### 2. 不是完整游戏框架内核
|
||
|
||
Loxodon Core 没有把以下能力作为主轴:
|
||
|
||
- 游戏 Feature 生命周期
|
||
- 模块启动顺序
|
||
- 资源后端边界
|
||
- 配置表加载边界
|
||
- 存档版本迁移
|
||
- 热更新策略
|
||
- 场景/流程切换策略
|
||
|
||
它的插件生态里有 Addressable、Data、XLua、ILRuntime 等扩展,但 Core 本体的主轴仍然是 MVVM/DataBinding。
|
||
|
||
### 3. 对小团队很省事,对强边界内核有侵蚀风险
|
||
|
||
如果项目目标是快速做 UI 驱动业务,Loxodon 的全局上下文和内置 Prefs 会很方便。
|
||
|
||
但如果目标是 FlowScope 这种机制型内核,直接照搬会让 Kernel 同时承担 UI、Prefs、Messaging、Async、Binding 等职责,边界会变得越来越难控。
|
||
|
||
## 对 FlowScope 的借鉴建议
|
||
|
||
### 可以借鉴
|
||
|
||
1. **ServiceBundle 的模块装配方式**
|
||
|
||
FlowScope 的 P1/P2 模块可以采用类似显式装配模式:
|
||
|
||
```text
|
||
ModuleBundle.Start(container)
|
||
-> register contracts
|
||
-> register default implementations
|
||
-> register adapters
|
||
|
||
ModuleBundle.Stop(container)
|
||
-> unregister contracts
|
||
-> release module-owned state
|
||
```
|
||
|
||
2. **Binding 管线的分层思想**
|
||
|
||
如果 FlowScope 后续需要 UI Binding 或 Editor Binding,可以参考 Loxodon 的拆分:
|
||
|
||
```text
|
||
Source
|
||
Target
|
||
Path
|
||
Converter
|
||
Binder
|
||
BindingContext
|
||
```
|
||
|
||
但这应该作为 UI 扩展模块,而不是 Kernel 机制。
|
||
|
||
3. **ViewModelBase 的属性变更封装**
|
||
|
||
`Set<T>` 模式可以降低 ViewModel 代码重复,也能统一 PropertyChanged 和消息广播策略。
|
||
|
||
4. **Window 状态模型**
|
||
|
||
`Window` / `WindowManager` 对弹窗、页面、转场、可见性和激活状态有参考价值,可用于 FlowScope UI 模块设计。
|
||
|
||
### 不建议照搬
|
||
|
||
1. **不要把 Prefs 放进 Kernel**
|
||
|
||
FlowScope 的 Save / Prefs / PlayerPrefs 应保持在 Save 模块或 Unity Adapter 中。
|
||
|
||
2. **不要把 Messenger 作为 Kernel 默认通信机制**
|
||
|
||
消息总线容易变成隐式耦合通道。Kernel 应保持 Feature 生命周期和 Slot/Policy 机制清晰,事件系统应作为 P1/P2 模块单独设计。
|
||
|
||
3. **不要把 UI Window 放进 Kernel**
|
||
|
||
UI 是 Feature/Module 的外围能力。Kernel 只需要管理 Feature 的启动、替换、停止策略,不应知道 Window 栈。
|
||
|
||
4. **不要用全局 ApplicationContext 承载所有能力**
|
||
|
||
FlowScope 更适合显式 Bootstrap + Container + FeatureContext。全局上下文可以作为上层便利入口,但不应成为 Kernel 的事实中心。
|
||
|
||
## 与 FlowScope Kernel 边界的关系
|
||
|
||
FlowScope 当前更适合保持:
|
||
|
||
```text
|
||
Kernel
|
||
-> Container
|
||
-> AppKernel
|
||
-> StartupPipeline
|
||
-> FeatureHost
|
||
-> FeatureInstance
|
||
-> FeatureContext
|
||
-> FeatureLifetime
|
||
-> FeatureSlot
|
||
-> FeaturePolicy
|
||
```
|
||
|
||
Loxodon 的能力更适合放在:
|
||
|
||
```text
|
||
FlowScope.UI
|
||
-> ViewModel
|
||
-> Binding
|
||
-> Window / Panel
|
||
-> Command
|
||
|
||
FlowScope.Events
|
||
-> Messenger / EventBus
|
||
|
||
FlowScope.Save.Unity
|
||
-> PlayerPrefs adapter
|
||
|
||
FlowScope.Runtime.Extensions
|
||
-> ServiceBundle helpers
|
||
```
|
||
|
||
换句话说,Loxodon 对 FlowScope 的启发是:**外围模块可以做厚,Kernel 必须保持薄。**
|
||
|
||
## 最终判断
|
||
|
||
Loxodon Framework 的 Core 是一个成熟的 Unity MVVM/UI 运行时。它适合解决 UI 数据绑定、ViewModel 状态传播、窗口管理和 UI 事件命令化问题。
|
||
|
||
但它不是 FlowScope Kernel 的直接模板。对 FlowScope 来说,最值得吸收的是:
|
||
|
||
- `ServiceBundle` 式模块装配。
|
||
- Binding 管线拆分方式。
|
||
- ViewModel 属性变更封装。
|
||
- Window 状态管理经验。
|
||
|
||
最需要避免的是:
|
||
|
||
- 把 Prefs、UI、Messaging、Binding 一起塞进 Core。
|
||
- 用全局上下文替代显式生命周期。
|
||
- 让 Kernel 从机制层滑向应用便利层。
|
||
|