docs(analysis): 添加 FishDice 框架分析页面
This commit is contained in:
54
analysis/FishDice/design-highlights.html
Normal file
54
analysis/FishDice/design-highlights.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 设计精妙点</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">设计精妙点</span></div>
|
||||
<section class="hero">
|
||||
<h1>框架设计中值得保留的精妙部分</h1>
|
||||
<p class="subtitle">这些亮点都来自源码证据,不是泛泛的架构赞美。它们共同服务一个目标:让 Lucky Dice 的核心闭环可测、可扩展、可追踪。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>亮点列表</h2>
|
||||
<div class="grid-2">
|
||||
<div class="card"><h3>1. Runtime 纯 C#</h3><p><code>noEngineReferences: true</code> 把 Unity 生命周期、场景和资源从核心中剥离,极大降低测试成本。</p></div>
|
||||
<div class="card"><h3>2. 两套骰子语义隔离</h3><p><code>DiceSetType.Normal</code> 和 <code>DiceSetType.Lucky</code> 分开,<code>ComboFactBuilder</code> 明确拒绝 Lucky 结果进入普通组合事实。</p></div>
|
||||
<div class="card"><h3>3. 先事实化再匹配</h3><p><code>ComboFacts</code> 生成 normalized key、ordered key、face count、number sum,避免 matcher 直接读“左骰/右骰”。</p></div>
|
||||
<div class="card"><h3>4. 按类型注册扩展</h3><p>Matcher 按 <code>MatcherType</code>,Action 按 <code>ActionType</code> 注册,扩展点清晰。</p></div>
|
||||
<div class="card"><h3>5. 随机源可注入</h3><p><code>IRandomSource</code> 让 Roll 和 Lucky Dice 权重随机都能用固定序列测试。</p></div>
|
||||
<div class="card"><h3>6. 配置先校验再运行</h3><p><code>LuckyDiceConfigValidator</code> 提前捕获未知 matcher、未知 action、重复 id、坏候选和缺失 target mode。</p></div>
|
||||
<div class="card"><h3>7. Trace 贯穿链路</h3><p><code>RollTrace</code> 用同一个 session 记录决策链,便于复盘线上问题。</p></div>
|
||||
<div class="card"><h3>8. Demo 和核心解耦</h3><p>DemoRunner 和 Controller 只消费核心结果,证明表现层可以替换。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>最关键的架构判断</h2>
|
||||
<div class="note good">框架没有急着做“完整玩法管理器”,而是先把最容易膨胀的部分拆成事实、规则、行为、候选和模式解析。这让第一版虽然小,但变化方向是可控的。</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>为什么这些设计对游戏框架重要</h2>
|
||||
<p>游戏玩法框架最怕两类增长:一类是组合数量增长导致 if/else 爆炸,另一类是表现层倒灌核心导致每次改动画都影响规则。FishDice 当前通过规则配置、Action 分发和纯核心边界,把这两类风险先压住了。</p>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">ComboFactBuilder.cs:14-24</span>:拒绝 Lucky set 和 dice count 不一致。</li>
|
||||
<li><span class="path">ComboFactBuilder.cs:26-36</span>:构建统计事实和 normalized key。</li>
|
||||
<li><span class="path">ComboRuleMatcher.cs:26-45</span>:按优先级匹配并支持 StopAfterMatched。</li>
|
||||
<li><span class="path">DiceRollService.cs:5-16</span>:<code>IRandomSource</code> 抽象。</li>
|
||||
<li><span class="path">LuckyDiceConfigValidator.cs:13-154</span>:配置校验覆盖规则、候选、target mode、注册表。</li>
|
||||
<li><span class="path">LuckyDiceCoreFlowTests.cs:26-63</span>:完整 Lucky Dice 到 target mode 的链路测试。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
76
analysis/FishDice/index.html
Normal file
76
analysis/FishDice/index.html
Normal file
@@ -0,0 +1,76 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 框架分析总览</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar">
|
||||
<div class="brand">FishDice Framework Analysis</div>
|
||||
<div>分析根目录:<span class="path">C:\Users\13999\Documents\Fishdice\FishDice</span></div>
|
||||
</div>
|
||||
|
||||
<section class="hero">
|
||||
<h1>FishDice / LuckyDice 游戏框架分析总览</h1>
|
||||
<p class="subtitle">这份报告分析的是当前仓库中已经落地的 Lucky Dice 玩法内核框架。它不是完整游戏壳,而是一个“纯 C# 可测试核心 + Unity Demo 表现层”的玩法流程框架。</p>
|
||||
<div class="nav-grid">
|
||||
<a class="nav-card" href="structure.html"><strong>结构与分层</strong><span>Runtime、Demo、DemoEditor、Tests 的边界与依赖方向。</span></a>
|
||||
<a class="nav-card" href="lifecycle.html"><strong>流程与生命周期</strong><span>从 Roll 请求到奖励、Lucky Dice、目标玩法入口的完整链路。</span></a>
|
||||
<a class="nav-card" href="module-development.html"><strong>玩法与模块开发</strong><span>规则、Matcher、Action、候选、TargetMode 如何扩展。</span></a>
|
||||
<a class="nav-card" href="resources.html"><strong>资源管理</strong><span>当前资源策略、配置形态、Unity 资源接入缺口。</span></a>
|
||||
<a class="nav-card" href="ui.html"><strong>UI 管理</strong><span>Demo UI 的组织方式,以及框架层尚未拥有的 UI 抽象。</span></a>
|
||||
<a class="nav-card" href="design-highlights.html"><strong>设计精妙点</strong><span>纯核心、注入随机源、配置校验、可观测 Trace 等。</span></a>
|
||||
<a class="nav-card" href="weaknesses.html"><strong>缺点与风险</strong><span>当前框架缺失的系统能力和后续落地风险。</span></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>一句话结论</h2>
|
||||
<div class="note good">FishDice 当前最强的设计点,是把 Lucky Dice 的核心决策链路压成无 UnityEngine 依赖的纯 C# 服务,并用配置、注册表、随机源注入和 Trace 让它可测、可回放、可扩展。</div>
|
||||
<div class="note warning">当前最明显的边界,是它还不是一个完整游戏框架:资源加载、UI 导航、场景生命周期、目标玩法启动器、远端配置与持久化服务都还停留在 Demo 或未来接入层。</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>宏观结构图</h2>
|
||||
<pre>Unity Demo / Scene
|
||||
-> LuckyDiceDemoController
|
||||
-> LuckyDiceDemoRunner
|
||||
-> LuckyDiceRuntimeFactory
|
||||
-> LuckyDiceRollFlowService
|
||||
-> DiceRollService
|
||||
-> ComboFactBuilder
|
||||
-> ComboRuleMatcher
|
||||
-> RollActionDispatcher
|
||||
-> LuckyDiceFlowService
|
||||
-> TargetModeResolver
|
||||
-> RollTrace</pre>
|
||||
<div class="grid-3">
|
||||
<div class="metric"><div class="value">纯 C#</div><div class="label">Runtime asmdef 设置 <code>noEngineReferences: true</code>,核心不依赖 UnityEngine。</div></div>
|
||||
<div class="metric"><div class="value">7 层</div><div class="label">Roll、Facts、Rules、Actions、LuckySelection、TargetMode、Trace。</div></div>
|
||||
<div class="metric"><div class="value">Demo 外挂</div><div class="label">UGUI、场景构建和 Unity 生命周期都在 Demo/DemoEditor 层。</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>如何阅读</h2>
|
||||
<p>先读 <a href="structure.html">结构与分层</a>,理解它为什么是“玩法内核”而不是“完整游戏框架”。再读 <a href="lifecycle.html">生命周期</a>,顺着一次 Roll 的数据流看完整闭环。随后按工作目的进入模块开发、资源、UI、亮点或风险页面。</p>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>关键证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">FishDice/Assets/FishDice/Runtime/FishDice.Runtime.asmdef:13</span> 声明 <code>noEngineReferences: true</code>。</li>
|
||||
<li><span class="path">LuckyDiceRollFlowService.cs:32</span> 是核心流程入口。</li>
|
||||
<li><span class="path">LuckyDiceRuntimeFactory.cs:24-59</span> 统一装配配置、随机源、matcher、executor、服务。</li>
|
||||
<li><span class="path">LuckyDiceDefaultConfig.cs:151-238</span> 定义默认规则、候选和目标模式。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:131-244</span> 运行时构建 Demo UGUI,并只使用内置字体资源。</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="footer">生成目录:<span class="path">analysis/FishDice</span>。所有页面为离线静态 HTML。</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
67
analysis/FishDice/lifecycle.html
Normal file
67
analysis/FishDice/lifecycle.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 流程与生命周期</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">流程与生命周期</span></div>
|
||||
<section class="hero">
|
||||
<h1>一次 Roll 的完整生命周期</h1>
|
||||
<p class="subtitle">框架生命周期不是 Unity 场景级生命周期,而是玩法请求级生命周期:一次 <code>RollFlowRequest</code> 进入核心服务,沿着 Roll、Facts、Rules、Actions、LuckySelection、TargetMode 和 Trace 形成闭环。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>主链路</h2>
|
||||
<pre>RollFlowRequest
|
||||
-> DiceRollService.Roll
|
||||
-> ComboFactBuilder.Build
|
||||
-> ComboRuleMatcher.Match
|
||||
-> RollActionDispatcher.Execute
|
||||
-> LuckyDiceFlowService.Select [只有触发 Lucky Dice 时]
|
||||
-> TargetModeResolver.Resolve [只有选中 Lucky Dice 候选时]
|
||||
-> RollFlowResult + RollTrace</pre>
|
||||
<p><code>LuckyDiceRollFlowService.Execute</code> 是整个核心生命周期的编排点。它创建 <code>RollTrace</code>,执行普通骰子 Roll,把结果转成组合事实,再匹配规则和分发 action。如果 action 结果中包含 <code>LuckyDiceRequestedEffect</code>,才进入 Lucky Dice 选择和目标玩法解析。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>生命周期所有权</h2>
|
||||
<table>
|
||||
<tr><th>阶段</th><th>所有者</th><th>输入</th><th>输出</th></tr>
|
||||
<tr><td>请求校验</td><td><code>LuckyDiceRollFlowService</code></td><td><code>RollFlowRequest</code></td><td>有效 session、dice set、trigger source。</td></tr>
|
||||
<tr><td>骰子产生</td><td><code>DiceRollService</code></td><td><code>DiceSetConfig</code>、随机源</td><td><code>DiceRollResult</code>。</td></tr>
|
||||
<tr><td>事实提取</td><td><code>ComboFactBuilder</code></td><td>普通骰子结果</td><td><code>ComboFacts</code>,含无序 key、计数、点数。</td></tr>
|
||||
<tr><td>规则命中</td><td><code>ComboRuleMatcher</code></td><td>facts、combo rules</td><td>按优先级排列的 <code>ComboRuleMatch</code>。</td></tr>
|
||||
<tr><td>行为执行</td><td><code>RollActionDispatcher</code></td><td>action list、context</td><td><code>RewardEffect</code>、<code>MultiplierEffect</code>、<code>LuckyDiceRequestedEffect</code> 等。</td></tr>
|
||||
<tr><td>特殊骰子选择</td><td><code>LuckyDiceFlowService</code></td><td>候选池、请求上下文、Lucky Dice set</td><td>选中候选、slot count、fallback 类型。</td></tr>
|
||||
<tr><td>目标玩法解析</td><td><code>TargetModeResolver</code></td><td>选中候选、请求、倍率、mode definitions</td><td><code>TargetModeEntry</code> 或失败原因。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Unity Demo 生命周期</h2>
|
||||
<p>Demo 层通过 <code>LuckyDiceDemoController.Awake</code> 构建 UI 并显示初始状态。用户点击按钮后,<code>StartRoll</code> 启动 coroutine,先做普通骰子动画,再调用 <code>LuckyDiceDemoRunner.RunRandom</code> 获取核心结果,并根据结果展示普通奖励、Clover Bonus 或 Lucky Dice 目标玩法。</p>
|
||||
<div class="note warning">这里的 UI 动画不是核心生命周期的一部分。核心已经在 <code>RunRandom</code> 调用时一次性算完,UI 只是消费结果并播放表现。</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>可观测生命周期</h2>
|
||||
<p><code>RollTrace</code> 贯穿同一个 <code>RollSessionId</code>,记录普通骰面、组合 key、命中规则、执行 action、Lucky Dice 候选数量、随机值、选中结果、解析出的模式和最终 outcome。这是定位“为什么进了某个玩法”的主线。</p>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">LuckyDiceRollFlowService.cs:32-103</span>:一次 Roll 的完整编排。</li>
|
||||
<li><span class="path">LuckyDiceFlowService.cs:16-49</span>:Lucky Dice 候选筛选、权重随机、兜底和 slot count。</li>
|
||||
<li><span class="path">TargetModeResolver.cs:9-33</span>:选中结果到目标玩法模式的映射。</li>
|
||||
<li><span class="path">RollTrace.cs:43-115</span>:生命周期关键字段记录。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:30-74</span>:Demo 的 Awake、StartRoll、PlayRollFlow。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
62
analysis/FishDice/module-development.html
Normal file
62
analysis/FishDice/module-development.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 玩法与模块开发</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">玩法与模块开发</span></div>
|
||||
<section class="hero">
|
||||
<h1>从框架设计看玩法、模块、服务和管理器如何拆分</h1>
|
||||
<p class="subtitle">FishDice 的扩展方式不是“给每个组合写一个 if 分支”,而是把变化拆到配置行、Matcher、ActionExecutor、候选定义和 TargetMode 映射里。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>核心开发原则</h2>
|
||||
<div class="grid-2">
|
||||
<div class="card"><h3>组合变化优先改规则配置</h3><p>新增“什么组合触发什么行为”时,优先新增 <code>ComboRuleDefinition</code>。只有现有 matcher 表达不了新语义时,才新增 <code>IComboMatcher</code>。</p></div>
|
||||
<div class="card"><h3>行为变化按 ActionType 扩展</h3><p>新增通用行为时,新增 <code>IRollActionExecutor</code> 并注册到 context。Dispatcher 只知道 ActionType,不知道具体组合 key。</p></div>
|
||||
<div class="card"><h3>特殊玩法入口走候选池</h3><p>Lucky Dice 的结果和目标玩法由 <code>LuckyDiceCandidateDefinition</code> 与 <code>TargetModeDefinition</code> 定义。</p></div>
|
||||
<div class="card"><h3>目标玩法内部不反向污染 Lucky Dice</h3><p>目标玩法模式由 <code>TargetModeResolver</code> 解析,Lucky Dice 选择层只负责选结果和 target key,不关心玩法内部实现。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>新增内容应该放哪里</h2>
|
||||
<table>
|
||||
<tr><th>开发需求</th><th>推荐位置</th><th>实现方式</th><th>测试重点</th></tr>
|
||||
<tr><td>新增普通骰子组合</td><td><code>Config</code></td><td>新增 <code>ComboRuleDefinition</code>,复用已有 matcher 和 action。</td><td>规则命中、优先级、action 顺序。</td></tr>
|
||||
<tr><td>新增组合匹配能力</td><td><code>Rules/Matchers</code></td><td>实现 <code>IComboMatcher</code>,放入 <code>ComboMatcherRegistry</code> 或自定义 validation context。</td><td>MatcherType 唯一、边界输入。</td></tr>
|
||||
<tr><td>新增奖励或业务行为</td><td><code>Actions</code></td><td>实现 <code>IRollActionExecutor</code>,通过 ActionType 注册。</td><td>未注册 action 失败记录、effect 输出。</td></tr>
|
||||
<tr><td>新增 Lucky Dice 结果</td><td><code>Config</code> + 资源层</td><td>新增 candidate 和 target mode,并补图标/展示资源。</td><td>默认候选、权重、source filter、target mode 存在。</td></tr>
|
||||
<tr><td>新增目标玩法模式</td><td><code>TargetMode</code> 接入层</td><td>新增 <code>TargetModeDefinition</code> 或后续扩展 resolver 规则。</td><td>缺失映射失败原因、成功解析 mode key。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>服务和“管理器”的边界</h2>
|
||||
<p>当前 Runtime 里没有传统 Unity 式单例 Manager,而是小服务组合:<code>DiceRollService</code> 做随机 Roll,<code>ComboRuleMatcher</code> 做规则匹配,<code>RollActionDispatcher</code> 做行为分发,<code>LuckyDiceFlowService</code> 做特殊候选选择,<code>TargetModeResolver</code> 做模式解析。</p>
|
||||
<div class="note good">这让“管理器”职责被拆散:没有一个巨大的 LuckyDiceManager 同时管随机、规则、奖励、UI、场景跳转。</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>扩展入口</h2>
|
||||
<p><code>LuckyDiceRuntimeFactory.CreateFlow</code> 支持传入规则、候选和目标模式定义;<code>LuckyDiceConfigValidationContext</code> 支持传入自定义 matcher 与 action executor。测试里已经覆盖“自定义 matcher/action 能被同一 context 用于校验和运行时分发”。</p>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">LuckyDiceDefaultConfig.cs:151-238</span>:默认规则、候选、目标模式定义。</li>
|
||||
<li><span class="path">ComboMatcherRegistry.cs:5-20</span>:默认 matcher 注册表。</li>
|
||||
<li><span class="path">RollActionExecutorRegistry.cs</span>:默认 action executor 注册表。</li>
|
||||
<li><span class="path">LuckyDiceConfigValidationContext.cs:8-30</span>:自定义 matcher/action 的上下文入口。</li>
|
||||
<li><span class="path">LuckyDiceCoreFlowTests.cs:446-487</span>:自定义 matcher/action 走完整 flow。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
63
analysis/FishDice/resources.html
Normal file
63
analysis/FishDice/resources.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 资源管理分析</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">资源管理</span></div>
|
||||
<section class="hero">
|
||||
<h1>资源管理:当前是“配置内建 + Demo 极简资源”,还不是完整资源系统</h1>
|
||||
<p class="subtitle">源码里没有 Addressables、AssetBundle、Prefab 加载器或资源生命周期管理器。核心资源概念主要体现为内建配置数据;Demo UI 只通过 <code>Resources.GetBuiltinResource</code> 取 Unity 内置字体。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>当前资源形态</h2>
|
||||
<table>
|
||||
<tr><th>资源/配置</th><th>当前位置</th><th>管理方式</th><th>评价</th></tr>
|
||||
<tr><td>普通骰子面</td><td><code>LuckyDiceDefaultConfig</code></td><td>硬编码默认集合:2、3、4、5、6、clover。</td><td>适合第一版可测闭环,不适合策划热改。</td></tr>
|
||||
<tr><td>Lucky Dice 结果</td><td><code>LuckyDiceDefaultConfig</code></td><td>硬编码 rocket、thief 和默认 slot count。</td><td>语义清楚,但还缺图标/Prefab 资源绑定。</td></tr>
|
||||
<tr><td>规则表</td><td><code>ComboRuleDefinition</code></td><td>定义行加载为运行时 <code>ComboRule</code>。</td><td>已经具备迁移到 JSON/ScriptableObject 的形状。</td></tr>
|
||||
<tr><td>目标模式映射</td><td><code>TargetModeDefinition</code></td><td>result key + target key -> mode key。</td><td>适合作为玩法启动器的配置入口。</td></tr>
|
||||
<tr><td>Demo 字体</td><td><code>LuckyDiceDemoController</code></td><td><code>Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf")</code>。</td><td>仅 Demo 兜底,不是业务资源系统。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>资源边界判断</h2>
|
||||
<p>当前框架刻意把核心运行时做成纯 C#,所以资源加载不能直接放入 Runtime 核心。真正落地生产时,建议在 Unity 接入层增加“配置提供者”和“表现资源解析器”:</p>
|
||||
<pre>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</pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>后续资源系统建议</h2>
|
||||
<div class="grid-2">
|
||||
<div class="card"><h3>配置资源</h3><p>把 <code>ComboRuleDefinition</code>、<code>LuckyDiceCandidateDefinition</code>、<code>TargetModeDefinition</code> 迁移为 JSON、ScriptableObject 或远端表时,保持先校验再创建 runtime config。</p></div>
|
||||
<div class="card"><h3>表现资源</h3><p>新增一个独立的 Unity 层映射:<code>ResultKey -> icon/prefab/animation</code>,不要让 Runtime 持有 Sprite 或 GameObject。</p></div>
|
||||
<div class="card"><h3>目标玩法资源</h3><p>由 <code>TargetModeEntry</code> 驱动目标玩法 launcher,launcher 再决定加载 scene、panel、prefab 或 addressable。</p></div>
|
||||
<div class="card"><h3>资源失败处理</h3><p>资源加载失败应回到表现层兜底;核心选择结果不应因为图标缺失而改变。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">Packages/manifest.json</span>:项目含 <code>com.unity.modules.assetbundle</code>,但源码未发现实际 AssetBundle/Addressables 使用。</li>
|
||||
<li><span class="path">LuckyDiceDefaultConfig.cs:65-88</span>:普通骰子和 Lucky Dice set 由代码内建。</li>
|
||||
<li><span class="path">LuckyDiceDefaultConfig.cs:151-238</span>:规则、候选和 target mode 默认定义在代码中。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:244</span>:Demo 唯一明确资源读取是内置字体。</li>
|
||||
<li><span class="path">rg Addressables/AssetBundle/LoadAsset</span>:当前 FishDice 源码没有业务资源加载器证据。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
59
analysis/FishDice/structure.html
Normal file
59
analysis/FishDice/structure.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 结构与分层</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">结构与分层</span></div>
|
||||
<section class="hero">
|
||||
<h1>宏观看 FishDice 的结构和分层</h1>
|
||||
<p class="subtitle">当前框架把真正的玩法决策放在 <code>Runtime/LuckyDice</code>,把 Unity 场景、按钮、Canvas、Editor 菜单和演示逻辑隔离在 Demo 层。这是非常明确的“核心域模型先行”结构。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>目录分层</h2>
|
||||
<table>
|
||||
<tr><th>层级</th><th>位置</th><th>职责</th><th>依赖判断</th></tr>
|
||||
<tr><td>Runtime 核心</td><td><span class="path">Assets/FishDice/Runtime/LuckyDice</span></td><td>骰子配置、Roll、组合事实、规则、Action、Lucky Dice 候选、TargetMode、Trace。</td><td>纯 C#,asmdef 不引用 UnityEngine。</td></tr>
|
||||
<tr><td>Demo 表现</td><td><span class="path">Assets/FishDice/Demo</span></td><td>运行核心流程,格式化结果,构建一个可交互 UGUI 演示。</td><td>引用 <code>FishDice.Runtime</code> 和 <code>UnityEngine.UI</code>。</td></tr>
|
||||
<tr><td>DemoEditor</td><td><span class="path">Assets/FishDice/DemoEditor</span></td><td>通过菜单创建 LuckyDiceDemo 场景,并加入 Build Settings。</td><td>依赖 UnityEditor,只服务编辑器构建。</td></tr>
|
||||
<tr><td>Tests</td><td><span class="path">Assets/FishDice/Tests/EditMode/LuckyDice</span></td><td>验证核心链路、配置校验、扩展注册、Demo 输出。</td><td>用固定随机源验证可回放行为。</td></tr>
|
||||
<tr><td>Docs</td><td><span class="path">Docs</span></td><td>需求、规格、ADR、架构蓝图和资源交接资料。</td><td>当前实现与文档目标大体一致,但以源码为准。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>核心内部切分</h2>
|
||||
<div class="flow">
|
||||
<div class="flow-row"><div class="flow-key">Data</div><div class="flow-val">只放不可变或近似不可变的数据结构:<code>DiceFace</code>、<code>DiceRollResult</code>、<code>ComboFacts</code>、<code>RollFlowResult</code>、各种 Effect。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">Config</div><div class="flow-val">默认配置、配置定义行、定义加载、配置校验和错误类型。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">Services</div><div class="flow-val"><code>DiceRollService</code> 和 <code>ComboFactBuilder</code> 处理基础 Roll 与事实提取。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">Rules</div><div class="flow-val"><code>ComboRuleMatcher</code> 按优先级和 MatcherType 匹配规则。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">Actions</div><div class="flow-val"><code>RollActionDispatcher</code> 按 ActionType 分发,避免组合 key 直接绑定方法。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">LuckySelection</div><div class="flow-val"><code>LuckyDiceFlowService</code> 筛选候选、权重随机、兜底和结果槽数量。</div></div>
|
||||
<div class="flow-row"><div class="flow-key">TargetMode</div><div class="flow-val"><code>TargetModeResolver</code> 把选中的 Lucky Dice 结果映射到具体目标玩法模式。</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>依赖方向</h2>
|
||||
<p>依赖方向基本是单向的:Demo 依赖 Runtime,Runtime 内部由 <code>LuckyDiceRollFlowService</code> 编排各个小服务。核心服务只接收结构化输入并返回结构化结果,不调用场景、Canvas、Prefab 或 MonoBehaviour。</p>
|
||||
<div class="note good">这意味着核心玩法可以在 EditMode 测试中直接运行,不需要打开 Unity 场景,也不需要模拟 UI 动画。</div>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">FishDice.Runtime.asmdef:13</span>:Runtime 设置 <code>noEngineReferences: true</code>。</li>
|
||||
<li><span class="path">FishDice.Demo.asmdef:7-16</span>:Demo 引用 <code>FishDice.Runtime</code> 与 <code>UnityEngine.UI</code>。</li>
|
||||
<li><span class="path">LuckyDiceRuntimeFactory.cs:51-58</span>:RuntimeFactory 装配 Roll、Rule、Action、LuckySelection、TargetMode。</li>
|
||||
<li><span class="path">LuckyDiceCoreFlowTests.cs:512-516</span>:测试显式断言 Runtime asmdef 禁止 Engine 引用。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
297
analysis/FishDice/style.css
Normal file
297
analysis/FishDice/style.css
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
64
analysis/FishDice/ui.html
Normal file
64
analysis/FishDice/ui.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice UI 管理分析</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">UI 管理</span></div>
|
||||
<section class="hero">
|
||||
<h1>UI 管理:Demo 是运行时构建 UGUI,核心框架尚未定义 UI 系统</h1>
|
||||
<p class="subtitle">当前 UI 设计思想是“表现层消费核心结果”。核心不依赖 UI;Demo Controller 用 Canvas、Text、Button 手写一个最小可交互界面。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>现有 UI 链路</h2>
|
||||
<pre>LuckyDiceDemoController.Awake
|
||||
-> BuildUi
|
||||
-> ShowReady
|
||||
|
||||
Button.onClick
|
||||
-> StartRoll
|
||||
-> PlayRollFlow coroutine
|
||||
-> LuckyDiceDemoRunner.RunRandom
|
||||
-> ApplyDiceTexts / ShowResult</pre>
|
||||
<p>UI 在点击后播放普通骰子文本轮播,再把核心结果写回 Text。若结果是 Lucky Dice,则显示 3 个 Lucky slot,再展示目标玩法信息。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>UI 设计思想</h2>
|
||||
<table>
|
||||
<tr><th>点</th><th>当前实现</th><th>含义</th></tr>
|
||||
<tr><td>核心和表现分离</td><td>核心先一次性算出 <code>LuckyDiceDemoSnapshot</code>。</td><td>UI 动画不会参与规则、随机或目标模式决策。</td></tr>
|
||||
<tr><td>状态展示集中</td><td><code>ShowReady</code>、<code>ShowResult</code>、<code>SetStatus</code>、<code>ApplyDiceTexts</code>。</td><td>Demo 可读,但还不是可复用 UI 框架。</td></tr>
|
||||
<tr><td>运行时构建界面</td><td><code>BuildUi</code> 代码创建 Canvas、Board、Text、Button。</td><td>方便演示,生产项目应改为 prefab/scene-authored UI。</td></tr>
|
||||
<tr><td>缺少导航系统</td><td>没有 panel stack、modal、screen router、layer manager。</td><td>当前不能直接承担完整游戏 UI 管理。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>生产化建议</h2>
|
||||
<div class="grid-2">
|
||||
<div class="card"><h3>保留核心输出模型</h3><p>继续让核心输出 <code>RollFlowResult</code>、<code>TargetModeEntry</code>、<code>RollTrace</code>,UI 只消费这些结构。</p></div>
|
||||
<div class="card"><h3>拆 Presenter</h3><p>把 Demo 中的格式化和状态展示拆成 Presenter/ViewModel,避免 UI 文本拼接散落在 Controller。</p></div>
|
||||
<div class="card"><h3>Prefab 化</h3><p>把 Canvas、骰子格、结果槽、按钮做成 prefab,运行时只绑定数据和触发动画。</p></div>
|
||||
<div class="card"><h3>建立玩法启动 UI 协议</h3><p><code>EnterTargetModeEffect</code> 或 <code>TargetModeEntry</code> 应交给上层流程/UI router,而不是 Demo Controller 直接决定跳转。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:11</span>:Demo UI 是 <code>MonoBehaviour</code>。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:131-178</span>:运行时创建 Canvas、Board、Text 和 Button。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:46-74</span>:UI coroutine 消费核心结果并播放表现。</li>
|
||||
<li><span class="path">LuckyDiceDemoRunner.cs:40-76</span>:DemoRunner 把核心结果格式化成 snapshot。</li>
|
||||
<li><span class="path">Runtime asmdef</span>:核心不引用 Unity UI。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
58
analysis/FishDice/weaknesses.html
Normal file
58
analysis/FishDice/weaknesses.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>FishDice 缺点与风险</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<div class="topbar"><a href="index.html">← 返回总览</a><span class="brand">缺点与风险</span></div>
|
||||
<section class="hero">
|
||||
<h1>当前框架的缺点、风险和补强方向</h1>
|
||||
<p class="subtitle">FishDice 的核心设计很干净,但它的能力边界也很明显:目前完成的是玩法决策闭环,不是资源、UI、场景、服务和目标玩法全链路框架。</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>主要缺点</h2>
|
||||
<table>
|
||||
<tr><th>问题</th><th>风险</th><th>建议</th></tr>
|
||||
<tr><td>配置仍内建在代码中</td><td>策划无法独立调规则、权重、候选、模式映射;发版成本高。</td><td>把 definition 层迁移到 JSON/ScriptableObject/远端表,但保留现有 validator。</td></tr>
|
||||
<tr><td>没有生产级资源映射</td><td>result key 到图标、动画、prefab、音效的关系尚未定义。</td><td>增加 Unity Integration 层,保持 Runtime 只认 key。</td></tr>
|
||||
<tr><td>UI 只是 Demo</td><td>没有 panel 生命周期、导航、层级、动画完成回调、数据绑定约定。</td><td>建立 LuckyDicePresentation 或 Presenter/ViewModel,再接项目 UI 框架。</td></tr>
|
||||
<tr><td>TargetMode 只解析,不启动</td><td>核心能产出 <code>slap_down_normal</code>,但没有真实玩法启动器。</td><td>补 <code>TargetModeLauncher</code> 接口和 Unity 层实现。</td></tr>
|
||||
<tr><td>Lucky Dice 筛选策略写死在 service 中</td><td>后续 cooldown、tutorial、活动来源、权重策略复杂后,service 会膨胀。</td><td>把 filter 抽成可注册 pipeline,并让 Trace 记录每个 filter 的前后数量。</td></tr>
|
||||
<tr><td>Trace 目前是内存结果,不是日志系统</td><td>线上复盘还缺持久化、埋点、采样和导出协议。</td><td>新增 Trace sink 或 adapter,把核心 trace 转接到日志/埋点系统。</td></tr>
|
||||
<tr><td>异常和失败策略还偏工程化</td><td>部分错误通过 exception 抛出,生产玩法可能需要降级而不是中断。</td><td>区分配置启动期错误、请求错误、运行期可恢复错误。</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>最需要优先补的三件事</h2>
|
||||
<div class="grid-3">
|
||||
<div class="card"><h3>1. 配置外置</h3><p>先让规则、候选、target mode 从外部数据创建,并保留现有校验链。</p></div>
|
||||
<div class="card"><h3>2. 目标玩法启动协议</h3><p>定义 <code>TargetModeEntry</code> 到真实玩法模块的启动、完成、失败回调。</p></div>
|
||||
<div class="card"><h3>3. 表现层资源映射</h3><p>补齐 <code>ResultKey</code> 对应 icon/slot/prefab/动画资源的统一表。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>需要避免的后续走偏</h2>
|
||||
<div class="note danger">不要为了快速接 UI,把 Sprite、Prefab、Canvas、Coroutine 或场景跳转塞回 Runtime。那会破坏当前最有价值的纯核心边界。</div>
|
||||
<div class="note danger">不要把新组合直接写成 <code>if normalizedKey == ...</code> 的业务方法。组合增长应优先走规则配置和 matcher/action 扩展。</div>
|
||||
</section>
|
||||
|
||||
<section class="evidence">
|
||||
<h2>证据</h2>
|
||||
<ul>
|
||||
<li><span class="path">LuckyDiceDefaultConfig.cs:151-238</span>:默认配置仍在代码内。</li>
|
||||
<li><span class="path">LuckyDiceFlowService.cs:21-25</span>:候选筛选条件直接写在 service 内。</li>
|
||||
<li><span class="path">TargetModeResolver.cs:9-33</span>:只解析 target mode,不负责启动真实玩法。</li>
|
||||
<li><span class="path">LuckyDiceDemoController.cs:131-244</span>:UI 是 Demo 代码构建,不是可复用 UI 管理器。</li>
|
||||
<li><span class="path">rg Addressables/AssetBundle/LoadAsset</span>:当前没有资源加载/映射框架证据。</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user