From 1edc72db0ce44a9e75c27694be6f6abc07cfaf63 Mon Sep 17 00:00:00 2001 From: "JSD\\13999" <1399945104@qq.com> Date: Thu, 25 Jun 2026 10:46:23 +0800 Subject: [PATCH] =?UTF-8?q?docs(analysis):=20=E6=B7=BB=E5=8A=A0=20FishDice?= =?UTF-8?q?=20=E6=A1=86=E6=9E=B6=E5=88=86=E6=9E=90=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- analysis/FishDice/design-highlights.html | 54 ++++ analysis/FishDice/index.html | 76 ++++++ analysis/FishDice/lifecycle.html | 67 +++++ analysis/FishDice/module-development.html | 62 +++++ analysis/FishDice/resources.html | 63 +++++ analysis/FishDice/structure.html | 59 +++++ analysis/FishDice/style.css | 297 ++++++++++++++++++++++ analysis/FishDice/ui.html | 64 +++++ analysis/FishDice/weaknesses.html | 58 +++++ 9 files changed, 800 insertions(+) create mode 100644 analysis/FishDice/design-highlights.html create mode 100644 analysis/FishDice/index.html create mode 100644 analysis/FishDice/lifecycle.html create mode 100644 analysis/FishDice/module-development.html create mode 100644 analysis/FishDice/resources.html create mode 100644 analysis/FishDice/structure.html create mode 100644 analysis/FishDice/style.css create mode 100644 analysis/FishDice/ui.html create mode 100644 analysis/FishDice/weaknesses.html diff --git a/analysis/FishDice/design-highlights.html b/analysis/FishDice/design-highlights.html new file mode 100644 index 0000000..ba0097d --- /dev/null +++ b/analysis/FishDice/design-highlights.html @@ -0,0 +1,54 @@ + + + + + + FishDice 设计精妙点 + + + +
+
← 返回总览设计精妙点
+
+

框架设计中值得保留的精妙部分

+

这些亮点都来自源码证据,不是泛泛的架构赞美。它们共同服务一个目标:让 Lucky Dice 的核心闭环可测、可扩展、可追踪。

+
+ +
+

亮点列表

+
+

1. Runtime 纯 C#

noEngineReferences: true 把 Unity 生命周期、场景和资源从核心中剥离,极大降低测试成本。

+

2. 两套骰子语义隔离

DiceSetType.NormalDiceSetType.Lucky 分开,ComboFactBuilder 明确拒绝 Lucky 结果进入普通组合事实。

+

3. 先事实化再匹配

ComboFacts 生成 normalized key、ordered key、face count、number sum,避免 matcher 直接读“左骰/右骰”。

+

4. 按类型注册扩展

Matcher 按 MatcherType,Action 按 ActionType 注册,扩展点清晰。

+

5. 随机源可注入

IRandomSource 让 Roll 和 Lucky Dice 权重随机都能用固定序列测试。

+

6. 配置先校验再运行

LuckyDiceConfigValidator 提前捕获未知 matcher、未知 action、重复 id、坏候选和缺失 target mode。

+

7. Trace 贯穿链路

RollTrace 用同一个 session 记录决策链,便于复盘线上问题。

+

8. Demo 和核心解耦

DemoRunner 和 Controller 只消费核心结果,证明表现层可以替换。

+
+
+ +
+

最关键的架构判断

+
框架没有急着做“完整玩法管理器”,而是先把最容易膨胀的部分拆成事实、规则、行为、候选和模式解析。这让第一版虽然小,但变化方向是可控的。
+
+ +
+

为什么这些设计对游戏框架重要

+

游戏玩法框架最怕两类增长:一类是组合数量增长导致 if/else 爆炸,另一类是表现层倒灌核心导致每次改动画都影响规则。FishDice 当前通过规则配置、Action 分发和纯核心边界,把这两类风险先压住了。

+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/index.html b/analysis/FishDice/index.html new file mode 100644 index 0000000..53cd15d --- /dev/null +++ b/analysis/FishDice/index.html @@ -0,0 +1,76 @@ + + + + + + FishDice 框架分析总览 + + + +
+
+
FishDice Framework Analysis
+
分析根目录:C:\Users\13999\Documents\Fishdice\FishDice
+
+ +
+

FishDice / LuckyDice 游戏框架分析总览

+

这份报告分析的是当前仓库中已经落地的 Lucky Dice 玩法内核框架。它不是完整游戏壳,而是一个“纯 C# 可测试核心 + Unity Demo 表现层”的玩法流程框架。

+ +
+ +
+

一句话结论

+
FishDice 当前最强的设计点,是把 Lucky Dice 的核心决策链路压成无 UnityEngine 依赖的纯 C# 服务,并用配置、注册表、随机源注入和 Trace 让它可测、可回放、可扩展。
+
当前最明显的边界,是它还不是一个完整游戏框架:资源加载、UI 导航、场景生命周期、目标玩法启动器、远端配置与持久化服务都还停留在 Demo 或未来接入层。
+
+ +
+

宏观结构图

+
Unity Demo / Scene
+  -> LuckyDiceDemoController
+  -> LuckyDiceDemoRunner
+  -> LuckyDiceRuntimeFactory
+  -> LuckyDiceRollFlowService
+     -> DiceRollService
+     -> ComboFactBuilder
+     -> ComboRuleMatcher
+     -> RollActionDispatcher
+     -> LuckyDiceFlowService
+     -> TargetModeResolver
+     -> RollTrace
+
+
纯 C#
Runtime asmdef 设置 noEngineReferences: true,核心不依赖 UnityEngine。
+
7 层
Roll、Facts、Rules、Actions、LuckySelection、TargetMode、Trace。
+
Demo 外挂
UGUI、场景构建和 Unity 生命周期都在 Demo/DemoEditor 层。
+
+
+ +
+

如何阅读

+

先读 结构与分层,理解它为什么是“玩法内核”而不是“完整游戏框架”。再读 生命周期,顺着一次 Roll 的数据流看完整闭环。随后按工作目的进入模块开发、资源、UI、亮点或风险页面。

+
+ +
+

关键证据

+ +
+ + +
+ + diff --git a/analysis/FishDice/lifecycle.html b/analysis/FishDice/lifecycle.html new file mode 100644 index 0000000..e6785db --- /dev/null +++ b/analysis/FishDice/lifecycle.html @@ -0,0 +1,67 @@ + + + + + + FishDice 流程与生命周期 + + + +
+
← 返回总览流程与生命周期
+
+

一次 Roll 的完整生命周期

+

框架生命周期不是 Unity 场景级生命周期,而是玩法请求级生命周期:一次 RollFlowRequest 进入核心服务,沿着 Roll、Facts、Rules、Actions、LuckySelection、TargetMode 和 Trace 形成闭环。

+
+ +
+

主链路

+
RollFlowRequest
+  -> DiceRollService.Roll
+  -> ComboFactBuilder.Build
+  -> ComboRuleMatcher.Match
+  -> RollActionDispatcher.Execute
+  -> LuckyDiceFlowService.Select       [只有触发 Lucky Dice 时]
+  -> TargetModeResolver.Resolve        [只有选中 Lucky Dice 候选时]
+  -> RollFlowResult + RollTrace
+

LuckyDiceRollFlowService.Execute 是整个核心生命周期的编排点。它创建 RollTrace,执行普通骰子 Roll,把结果转成组合事实,再匹配规则和分发 action。如果 action 结果中包含 LuckyDiceRequestedEffect,才进入 Lucky Dice 选择和目标玩法解析。

+
+ +
+

生命周期所有权

+ + + + + + + + + +
阶段所有者输入输出
请求校验LuckyDiceRollFlowServiceRollFlowRequest有效 session、dice set、trigger source。
骰子产生DiceRollServiceDiceSetConfig、随机源DiceRollResult
事实提取ComboFactBuilder普通骰子结果ComboFacts,含无序 key、计数、点数。
规则命中ComboRuleMatcherfacts、combo rules按优先级排列的 ComboRuleMatch
行为执行RollActionDispatcheraction list、contextRewardEffectMultiplierEffectLuckyDiceRequestedEffect 等。
特殊骰子选择LuckyDiceFlowService候选池、请求上下文、Lucky Dice set选中候选、slot count、fallback 类型。
目标玩法解析TargetModeResolver选中候选、请求、倍率、mode definitionsTargetModeEntry 或失败原因。
+
+ +
+

Unity Demo 生命周期

+

Demo 层通过 LuckyDiceDemoController.Awake 构建 UI 并显示初始状态。用户点击按钮后,StartRoll 启动 coroutine,先做普通骰子动画,再调用 LuckyDiceDemoRunner.RunRandom 获取核心结果,并根据结果展示普通奖励、Clover Bonus 或 Lucky Dice 目标玩法。

+
这里的 UI 动画不是核心生命周期的一部分。核心已经在 RunRandom 调用时一次性算完,UI 只是消费结果并播放表现。
+
+ +
+

可观测生命周期

+

RollTrace 贯穿同一个 RollSessionId,记录普通骰面、组合 key、命中规则、执行 action、Lucky Dice 候选数量、随机值、选中结果、解析出的模式和最终 outcome。这是定位“为什么进了某个玩法”的主线。

+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/module-development.html b/analysis/FishDice/module-development.html new file mode 100644 index 0000000..ac734b3 --- /dev/null +++ b/analysis/FishDice/module-development.html @@ -0,0 +1,62 @@ + + + + + + FishDice 玩法与模块开发 + + + +
+
← 返回总览玩法与模块开发
+
+

从框架设计看玩法、模块、服务和管理器如何拆分

+

FishDice 的扩展方式不是“给每个组合写一个 if 分支”,而是把变化拆到配置行、Matcher、ActionExecutor、候选定义和 TargetMode 映射里。

+
+ +
+

核心开发原则

+
+

组合变化优先改规则配置

新增“什么组合触发什么行为”时,优先新增 ComboRuleDefinition。只有现有 matcher 表达不了新语义时,才新增 IComboMatcher

+

行为变化按 ActionType 扩展

新增通用行为时,新增 IRollActionExecutor 并注册到 context。Dispatcher 只知道 ActionType,不知道具体组合 key。

+

特殊玩法入口走候选池

Lucky Dice 的结果和目标玩法由 LuckyDiceCandidateDefinitionTargetModeDefinition 定义。

+

目标玩法内部不反向污染 Lucky Dice

目标玩法模式由 TargetModeResolver 解析,Lucky Dice 选择层只负责选结果和 target key,不关心玩法内部实现。

+
+
+ +
+

新增内容应该放哪里

+ + + + + + + +
开发需求推荐位置实现方式测试重点
新增普通骰子组合Config新增 ComboRuleDefinition,复用已有 matcher 和 action。规则命中、优先级、action 顺序。
新增组合匹配能力Rules/Matchers实现 IComboMatcher,放入 ComboMatcherRegistry 或自定义 validation context。MatcherType 唯一、边界输入。
新增奖励或业务行为Actions实现 IRollActionExecutor,通过 ActionType 注册。未注册 action 失败记录、effect 输出。
新增 Lucky Dice 结果Config + 资源层新增 candidate 和 target mode,并补图标/展示资源。默认候选、权重、source filter、target mode 存在。
新增目标玩法模式TargetMode 接入层新增 TargetModeDefinition 或后续扩展 resolver 规则。缺失映射失败原因、成功解析 mode key。
+
+ +
+

服务和“管理器”的边界

+

当前 Runtime 里没有传统 Unity 式单例 Manager,而是小服务组合:DiceRollService 做随机 Roll,ComboRuleMatcher 做规则匹配,RollActionDispatcher 做行为分发,LuckyDiceFlowService 做特殊候选选择,TargetModeResolver 做模式解析。

+
这让“管理器”职责被拆散:没有一个巨大的 LuckyDiceManager 同时管随机、规则、奖励、UI、场景跳转。
+
+ +
+

扩展入口

+

LuckyDiceRuntimeFactory.CreateFlow 支持传入规则、候选和目标模式定义;LuckyDiceConfigValidationContext 支持传入自定义 matcher 与 action executor。测试里已经覆盖“自定义 matcher/action 能被同一 context 用于校验和运行时分发”。

+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/resources.html b/analysis/FishDice/resources.html new file mode 100644 index 0000000..5493291 --- /dev/null +++ b/analysis/FishDice/resources.html @@ -0,0 +1,63 @@ + + + + + + FishDice 资源管理分析 + + + +
+
← 返回总览资源管理
+
+

资源管理:当前是“配置内建 + Demo 极简资源”,还不是完整资源系统

+

源码里没有 Addressables、AssetBundle、Prefab 加载器或资源生命周期管理器。核心资源概念主要体现为内建配置数据;Demo UI 只通过 Resources.GetBuiltinResource 取 Unity 内置字体。

+
+ +
+

当前资源形态

+ + + + + + + +
资源/配置当前位置管理方式评价
普通骰子面LuckyDiceDefaultConfig硬编码默认集合:2、3、4、5、6、clover。适合第一版可测闭环,不适合策划热改。
Lucky Dice 结果LuckyDiceDefaultConfig硬编码 rocket、thief 和默认 slot count。语义清楚,但还缺图标/Prefab 资源绑定。
规则表ComboRuleDefinition定义行加载为运行时 ComboRule已经具备迁移到 JSON/ScriptableObject 的形状。
目标模式映射TargetModeDefinitionresult key + target key -> mode key。适合作为玩法启动器的配置入口。
Demo 字体LuckyDiceDemoControllerResources.GetBuiltinResource<Font>("LegacyRuntime.ttf")仅 Demo 兜底,不是业务资源系统。
+
+ +
+

资源边界判断

+

当前框架刻意把核心运行时做成纯 C#,所以资源加载不能直接放入 Runtime 核心。真正落地生产时,建议在 Unity 接入层增加“配置提供者”和“表现资源解析器”:

+
Runtime Core
+  只认识 ResultKey / TargetKey / ModeKey / DiceFace
+
+Unity Integration Layer
+  ResultKey -> Icon Sprite / Animation / Prefab
+  TargetKey + ModeKey -> Scene / Controller / Launcher
+  Remote or Local Config -> ComboRuleDefinition / LuckyDiceCandidateDefinition
+
+ +
+

后续资源系统建议

+
+

配置资源

ComboRuleDefinitionLuckyDiceCandidateDefinitionTargetModeDefinition 迁移为 JSON、ScriptableObject 或远端表时,保持先校验再创建 runtime config。

+

表现资源

新增一个独立的 Unity 层映射:ResultKey -> icon/prefab/animation,不要让 Runtime 持有 Sprite 或 GameObject。

+

目标玩法资源

TargetModeEntry 驱动目标玩法 launcher,launcher 再决定加载 scene、panel、prefab 或 addressable。

+

资源失败处理

资源加载失败应回到表现层兜底;核心选择结果不应因为图标缺失而改变。

+
+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/structure.html b/analysis/FishDice/structure.html new file mode 100644 index 0000000..0ce71ca --- /dev/null +++ b/analysis/FishDice/structure.html @@ -0,0 +1,59 @@ + + + + + + FishDice 结构与分层 + + + +
+
← 返回总览结构与分层
+
+

宏观看 FishDice 的结构和分层

+

当前框架把真正的玩法决策放在 Runtime/LuckyDice,把 Unity 场景、按钮、Canvas、Editor 菜单和演示逻辑隔离在 Demo 层。这是非常明确的“核心域模型先行”结构。

+
+ +
+

目录分层

+ + + + + + + +
层级位置职责依赖判断
Runtime 核心Assets/FishDice/Runtime/LuckyDice骰子配置、Roll、组合事实、规则、Action、Lucky Dice 候选、TargetMode、Trace。纯 C#,asmdef 不引用 UnityEngine。
Demo 表现Assets/FishDice/Demo运行核心流程,格式化结果,构建一个可交互 UGUI 演示。引用 FishDice.RuntimeUnityEngine.UI
DemoEditorAssets/FishDice/DemoEditor通过菜单创建 LuckyDiceDemo 场景,并加入 Build Settings。依赖 UnityEditor,只服务编辑器构建。
TestsAssets/FishDice/Tests/EditMode/LuckyDice验证核心链路、配置校验、扩展注册、Demo 输出。用固定随机源验证可回放行为。
DocsDocs需求、规格、ADR、架构蓝图和资源交接资料。当前实现与文档目标大体一致,但以源码为准。
+
+ +
+

核心内部切分

+
+
Data
只放不可变或近似不可变的数据结构:DiceFaceDiceRollResultComboFactsRollFlowResult、各种 Effect。
+
Config
默认配置、配置定义行、定义加载、配置校验和错误类型。
+
Services
DiceRollServiceComboFactBuilder 处理基础 Roll 与事实提取。
+
Rules
ComboRuleMatcher 按优先级和 MatcherType 匹配规则。
+
Actions
RollActionDispatcher 按 ActionType 分发,避免组合 key 直接绑定方法。
+
LuckySelection
LuckyDiceFlowService 筛选候选、权重随机、兜底和结果槽数量。
+
TargetMode
TargetModeResolver 把选中的 Lucky Dice 结果映射到具体目标玩法模式。
+
+
+ +
+

依赖方向

+

依赖方向基本是单向的:Demo 依赖 Runtime,Runtime 内部由 LuckyDiceRollFlowService 编排各个小服务。核心服务只接收结构化输入并返回结构化结果,不调用场景、Canvas、Prefab 或 MonoBehaviour。

+
这意味着核心玩法可以在 EditMode 测试中直接运行,不需要打开 Unity 场景,也不需要模拟 UI 动画。
+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/style.css b/analysis/FishDice/style.css new file mode 100644 index 0000000..feab670 --- /dev/null +++ b/analysis/FishDice/style.css @@ -0,0 +1,297 @@ +:root { + color-scheme: light; + --ink: #17202a; + --muted: #607080; + --paper: #f7f4ed; + --panel: #fffdf7; + --line: #d9d0bd; + --accent: #b8472a; + --accent-2: #1f6f68; + --accent-3: #315c9a; + --code: #243447; + --soft: #efe7d7; + --warn: #8b4c10; + --bad: #9d2c2f; + --good: #267257; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + background: + linear-gradient(90deg, rgba(23, 32, 42, 0.04) 1px, transparent 1px), + linear-gradient(rgba(23, 32, 42, 0.04) 1px, transparent 1px), + var(--paper); + background-size: 32px 32px; + color: var(--ink); + font-family: "Microsoft YaHei", "Segoe UI", sans-serif; + line-height: 1.7; +} + +a { + color: var(--accent-3); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +.shell { + width: min(1180px, calc(100vw - 40px)); + margin: 0 auto; + padding: 34px 0 56px; +} + +.topbar { + display: flex; + justify-content: space-between; + gap: 18px; + align-items: center; + margin-bottom: 22px; + font-size: 14px; + color: var(--muted); +} + +.brand { + font-weight: 700; + color: var(--accent); + letter-spacing: 0.04em; +} + +.hero { + border: 1px solid var(--line); + background: rgba(255, 253, 247, 0.88); + padding: 34px; + box-shadow: 0 18px 50px rgba(30, 25, 18, 0.08); +} + +h1, +h2, +h3 { + line-height: 1.2; + margin: 0; +} + +h1 { + font-size: clamp(34px, 5vw, 58px); + max-width: 920px; + letter-spacing: 0; +} + +h2 { + font-size: 26px; + margin-top: 40px; + margin-bottom: 14px; + padding-bottom: 10px; + border-bottom: 2px solid var(--line); +} + +h3 { + font-size: 19px; + margin-top: 26px; + margin-bottom: 8px; +} + +.subtitle { + max-width: 860px; + margin: 18px 0 0; + color: var(--muted); + font-size: 17px; +} + +.nav-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); + gap: 12px; + margin-top: 26px; +} + +.nav-card, +.card, +.note, +.evidence, +.metric { + border: 1px solid var(--line); + background: var(--panel); +} + +.nav-card { + min-height: 116px; + padding: 18px; +} + +.nav-card strong { + display: block; + color: var(--accent); + margin-bottom: 7px; +} + +.nav-card span { + color: var(--muted); + font-size: 14px; +} + +.grid-2, +.grid-3 { + display: grid; + gap: 14px; +} + +.grid-2 { + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); +} + +.grid-3 { + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); +} + +.card, +.metric { + padding: 18px; +} + +.metric .value { + font-size: 28px; + font-weight: 800; + color: var(--accent); +} + +.metric .label { + color: var(--muted); + font-size: 14px; +} + +.note { + padding: 16px 18px; + border-left: 5px solid var(--accent-2); + margin: 18px 0; +} + +.warning { + border-left-color: var(--warn); +} + +.danger { + border-left-color: var(--bad); +} + +.good { + border-left-color: var(--good); +} + +table { + width: 100%; + border-collapse: collapse; + margin: 16px 0 26px; + background: var(--panel); + border: 1px solid var(--line); +} + +th, +td { + border-bottom: 1px solid var(--line); + padding: 12px 14px; + text-align: left; + vertical-align: top; +} + +th { + color: var(--accent); + background: var(--soft); + font-weight: 800; +} + +tr:last-child td { + border-bottom: 0; +} + +code, +.path { + font-family: Consolas, "Cascadia Mono", monospace; + color: var(--code); + background: rgba(31, 111, 104, 0.09); + padding: 2px 5px; + border-radius: 3px; +} + +pre { + overflow-x: auto; + padding: 16px; + background: #16202b; + color: #f7f4ed; + border: 1px solid #0f1720; +} + +.flow { + display: grid; + gap: 10px; + margin: 16px 0 24px; +} + +.flow-row { + display: grid; + grid-template-columns: 180px 1fr; + gap: 12px; + align-items: stretch; +} + +.flow-key { + background: var(--accent-2); + color: white; + padding: 12px; + font-weight: 800; +} + +.flow-val { + border: 1px solid var(--line); + background: var(--panel); + padding: 12px; +} + +.evidence { + margin-top: 28px; + padding: 18px; +} + +.evidence ul, +.tight { + margin: 8px 0 0; + padding-left: 20px; +} + +.badge { + display: inline-block; + padding: 3px 8px; + border: 1px solid var(--line); + background: var(--soft); + color: var(--accent); + font-size: 13px; + font-weight: 700; +} + +.footer { + margin-top: 42px; + padding-top: 18px; + border-top: 1px solid var(--line); + color: var(--muted); + font-size: 14px; +} + +@media (max-width: 760px) { + .shell { + width: min(100vw - 24px, 1180px); + padding-top: 20px; + } + + .hero { + padding: 22px; + } + + .flow-row { + grid-template-columns: 1fr; + } +} diff --git a/analysis/FishDice/ui.html b/analysis/FishDice/ui.html new file mode 100644 index 0000000..11a8881 --- /dev/null +++ b/analysis/FishDice/ui.html @@ -0,0 +1,64 @@ + + + + + + FishDice UI 管理分析 + + + +
+
← 返回总览UI 管理
+
+

UI 管理:Demo 是运行时构建 UGUI,核心框架尚未定义 UI 系统

+

当前 UI 设计思想是“表现层消费核心结果”。核心不依赖 UI;Demo Controller 用 Canvas、Text、Button 手写一个最小可交互界面。

+
+ +
+

现有 UI 链路

+
LuckyDiceDemoController.Awake
+  -> BuildUi
+  -> ShowReady
+
+Button.onClick
+  -> StartRoll
+  -> PlayRollFlow coroutine
+  -> LuckyDiceDemoRunner.RunRandom
+  -> ApplyDiceTexts / ShowResult
+

UI 在点击后播放普通骰子文本轮播,再把核心结果写回 Text。若结果是 Lucky Dice,则显示 3 个 Lucky slot,再展示目标玩法信息。

+
+ +
+

UI 设计思想

+ + + + + + +
当前实现含义
核心和表现分离核心先一次性算出 LuckyDiceDemoSnapshotUI 动画不会参与规则、随机或目标模式决策。
状态展示集中ShowReadyShowResultSetStatusApplyDiceTextsDemo 可读,但还不是可复用 UI 框架。
运行时构建界面BuildUi 代码创建 Canvas、Board、Text、Button。方便演示,生产项目应改为 prefab/scene-authored UI。
缺少导航系统没有 panel stack、modal、screen router、layer manager。当前不能直接承担完整游戏 UI 管理。
+
+ +
+

生产化建议

+
+

保留核心输出模型

继续让核心输出 RollFlowResultTargetModeEntryRollTrace,UI 只消费这些结构。

+

拆 Presenter

把 Demo 中的格式化和状态展示拆成 Presenter/ViewModel,避免 UI 文本拼接散落在 Controller。

+

Prefab 化

把 Canvas、骰子格、结果槽、按钮做成 prefab,运行时只绑定数据和触发动画。

+

建立玩法启动 UI 协议

EnterTargetModeEffectTargetModeEntry 应交给上层流程/UI router,而不是 Demo Controller 直接决定跳转。

+
+
+ +
+

证据

+ +
+
+ + diff --git a/analysis/FishDice/weaknesses.html b/analysis/FishDice/weaknesses.html new file mode 100644 index 0000000..1ff0286 --- /dev/null +++ b/analysis/FishDice/weaknesses.html @@ -0,0 +1,58 @@ + + + + + + FishDice 缺点与风险 + + + +
+
← 返回总览缺点与风险
+
+

当前框架的缺点、风险和补强方向

+

FishDice 的核心设计很干净,但它的能力边界也很明显:目前完成的是玩法决策闭环,不是资源、UI、场景、服务和目标玩法全链路框架。

+
+ +
+

主要缺点

+ + + + + + + + + +
问题风险建议
配置仍内建在代码中策划无法独立调规则、权重、候选、模式映射;发版成本高。把 definition 层迁移到 JSON/ScriptableObject/远端表,但保留现有 validator。
没有生产级资源映射result key 到图标、动画、prefab、音效的关系尚未定义。增加 Unity Integration 层,保持 Runtime 只认 key。
UI 只是 Demo没有 panel 生命周期、导航、层级、动画完成回调、数据绑定约定。建立 LuckyDicePresentation 或 Presenter/ViewModel,再接项目 UI 框架。
TargetMode 只解析,不启动核心能产出 slap_down_normal,但没有真实玩法启动器。TargetModeLauncher 接口和 Unity 层实现。
Lucky Dice 筛选策略写死在 service 中后续 cooldown、tutorial、活动来源、权重策略复杂后,service 会膨胀。把 filter 抽成可注册 pipeline,并让 Trace 记录每个 filter 的前后数量。
Trace 目前是内存结果,不是日志系统线上复盘还缺持久化、埋点、采样和导出协议。新增 Trace sink 或 adapter,把核心 trace 转接到日志/埋点系统。
异常和失败策略还偏工程化部分错误通过 exception 抛出,生产玩法可能需要降级而不是中断。区分配置启动期错误、请求错误、运行期可恢复错误。
+
+ +
+

最需要优先补的三件事

+
+

1. 配置外置

先让规则、候选、target mode 从外部数据创建,并保留现有校验链。

+

2. 目标玩法启动协议

定义 TargetModeEntry 到真实玩法模块的启动、完成、失败回调。

+

3. 表现层资源映射

补齐 ResultKey 对应 icon/slot/prefab/动画资源的统一表。

+
+
+ +
+

需要避免的后续走偏

+
不要为了快速接 UI,把 Sprite、Prefab、Canvas、Coroutine 或场景跳转塞回 Runtime。那会破坏当前最有价值的纯核心边界。
+
不要把新组合直接写成 if normalizedKey == ... 的业务方法。组合增长应优先走规则配置和 matcher/action 扩展。
+
+ +
+

证据

+ +
+
+ +