Energy 模块接入与购买职责
固定源码 b664407a9306272352dd10a1fbe6c82224092e82 的 Assets/DevTools/Modules/FeatureEnergy 声明 com.wenjing.gameplay.feature-energy@1.0.0、Unity 2022.3、UGUI 1.0.0。命名空间为 WenJing.Gameplay.Energy。本文依据已读 C# 描述接口和消费者责任,不提供发布、安装或运行成功的回执,也不包含 prefab/美术资源。
模块提供什么,产品补什么
模块提供购买次数/价格校验、命令与面板状态、UGUI 面板桥接和玩家等级资料模型。消费者提供权威快照、广告结果、付费交易、文本、本地化、反馈、面板关闭与实际资源生命周期。README 明确没有提交产品 adapter。G1
模板 GameFeatures 的 EnergyModel 体力快照/恢复/消耗闭环与本独立 Feature 的 PlayerEnergyModel 不是同一个类型。后者实际维护 PlayerProfileSnapshot 的昵称、头像、等级与经验,并不因为名称包含 Energy 就成为服务器体力账本。G2
准备配置快照
实现 IEnergyPurchaseConfigProvider.GetPurchaseConfig(),将产品当前公开配置和库存/购买快照转换为 EnergyPurchaseConfig。构造字段如下:G3 G4
| 字段 | 来源与意义 |
|---|---|
| MaxFreeAdCount / UsedFreeAdCount | 免费广告额度与已用次数,由产品权威状态提供 |
| FreeEnergyPerAd | 每次免费广告的能量数 |
| MaxPaidBuyCount / UsedPaidBuyCount | 付费购买额度与已用次数 |
| PaidEnergyPerBuy / PaidEnergyUnitPrice | 每次购买量、decimal 单位价格 |
| PaidCurrencyBalance | ulong 当前付费货币余额 |
| PaidCurrencyKey / EnergyItemKey | 命令中使用的产品资源 key;构造时空白分别回落 currency / energy |
快照过期时 service 不会自动向服务器重取。provider 应返回更新后的产品状态;余额与次数不能在 UI 点击后凭本地请求成功先行确认为到账。
剩余次数规则:max ≤ 0 返回 0;used ≤ 0 返回 max;used ≥ max 返回 0,否则 max − used。付费成本对 unitPrice × energyAmount 采用 midpoint-to-even 整数舍入,非正参数/结果为 0,过大乘积饱和到 int.MaxValue。G5
免费校验先检查能量数,再检查剩余次数;付费先检查能量/成本,再查剩余次数,最后查余额。失败值为 InvalidConfig、NoRemainingCount、InsufficientCurrency。规则不是服务器交易、日界线或并发控制实现。
构建 service 并登记 UI adapter
- 构造
EnergyPurchaseService(configProvider, reporter);reporter 为可选IEnergyPurchaseReporter。 - 实现
IEnergyPurchaseUiAdapter:提供 PurchaseService、TextAdapter、RewardAdGateway、PurchaseGateway,并实现ShowMessage(string)和Close(GameObject)。 - 在 UI 组合 root 活跃期间设置
EnergyPurchaseUiBridge.Current。这是静态单登记点,没有每玩家/每场景作用域管理;消费者应明确唯一持有者。 - 使用合法授权且经来源确认的面板资源。README 指向
UXMain/Features/GameMain/Energy/Prefabs/PanelBuyEnergy.prefab;本次没有获取资源内容、验证引用闭包或授予资产使用权。 - 产品收到权威事件后更新 provider,并对仍活跃的面板调用
PanelBuyEnergyLogic.RefreshDisplay()。 - 组合 root 释放时取消消费者自己的产品事件订阅,关闭/释放持有面板,并解除 Current。为避免旧 root 清掉新 root,消费者可按“Current 仍等于本 root 注册的 adapter”判断后清空;这是接入建议,模块没有替消费者实现这种 ownership guard。G1 G6 G7
源码 Panel 的 Awake/OnEnable 绑定按钮并避免重复绑定,OnDestroy 移除;OnEnable 刷新。UIPopupDOTween 虽沿用名称,当前源码只将 target scale 设为 Vector3.one,不依赖或实现第三方 tween 动画。G7 G8
按实际命令 API 发起意图
| API | 已读行为 |
|---|---|
BuildPanelState(textAdapter) | 读取 provider 快照并生成 FreeAd/Paid 两张卡状态,可报告 DisplayBuilt |
TryCreateFreeAdCommand() | 校验免费规则,成功构造 FreeAd 命令;不增加已用次数、不授奖 |
TryCreatePaidCommand() | 校验价格/次数/余额,成功构造 PaidCurrency 命令;不扣币、不发能量 |
RequestFreeAd(IRewardAdGateway) | 先创建命令,再调用 gateway;缺 gateway 返回 MissingRewardAdGateway |
RequestPaidPurchase(IEnergyPurchaseGateway) | 先创建命令,再调用 gateway;缺 gateway 返回 MissingPurchaseGateway |
EnergyPurchaseUiBridge.Submit(kind) | 使用当前 adapter/service/gateway 路由;失败调用 adapter.ShowMessage |
BuyEnergyCommand 包含 Kind、EnergyAmount、PaidCost、PaidCurrencyKey、EnergyItemKey。EnergyGatewayResult 仅有 Success 和 Message;gateway 方法是同步返回,模块没有 Task、回调式授奖状态、请求去重或取消令牌。G3 G9
如果产品 SDK/服务器是异步流程,adapter 必须自行定义“请求已接收”和“权威完成”的含义,处理等待、重复点击、取消/超时与迟到结果。不能把同步 Ok() 当广告实际看完或支付结算成功。报告事件 FreeAdRequested/PaidPurchaseRequested 在创建命令时发出,早于 gateway 实际结果;它们不是到账事件。G9 G10
Panel 点击后立即调用 RefreshDisplay。异步交易尚未更新 provider 时,这次刷新仍使用旧快照;产品后续权威事件还需再刷新。service 本身不持久化次数或余额。G7
文本与按钮状态
IEnergyPurchaseTextAdapter 提供剩余次数、能量数、免费/付费按钮文案及校验消息格式;默认 adapter 为英文 Free、数字和枚举文本。产品可提供本地化实现。G3 G5
面板实际设置 interactable = CanSubmit || KeepButtonEnabled。免费卡的 KeepButtonEnabled 恒为 true;付费卡配置/次数有效时即使余额不足也可保持启用。因此按钮可点不是交易可通过;Submit 的 service 校验仍决定本地请求资格。bridge 失败分支使用 result.Message,源码没有自动将所有失败值转换为 TextAdapter.GetValidationMessage,产品反馈应处理枚举文本和 Missing* 消息。G5 G6 G7
可选的等级资料模型
PlayerEnergyModel 接收 IPlayerLevelConfigProvider 和可选 IPlayerLevelAnalyticsReporter。ApplySnapshot 替换资料;AddExperience 使用下一等级经验阈值,非正阈值停止升级,支持多级提升并饱和累计;PendingLevelUpgrade / TryConsumeLevelUpgrade() 提供一次消费标记。昵称空白、头像非正 ID 被忽略。真实资料持久化和服务器一致性仍属产品。G2
发布与采用仍缺的证据
README 要求 source module 经 module-dashboard 发布、中立消费者经 module-manager 安装精确版本,并有包解析、编译、prefab 完整性、重复 GUID 和聚焦 EditMode 外部证据。本次仅取得源码子集,未取得工具实现、source-to-dist、tarball、实际消费者 PackageCache 或 product adapter,不宣称已发布/消费。测试源存在或 README 写 gate 不等于本次已运行。G1
消费者要补 adapter,应提供实际 config/库存快照 schema、广告与购买请求/完成契约、事务幂等与错误语义、本地化/关闭 API、场景组合 root 和权威事件订阅源码,再由精确消费者 head 的外部工作流提供结果。
固定来源
以下是内部固定来源,需要原仓内网和账号权限,公网读者不能保证可访问。链接保留仓库身份、完整 SHA 和相对路径供定位,不授予访问或资源转用权限;正文已独立说明所需字段与使用边界。
以下均在 gameplay b664407a9306272352dd10a1fbe6c82224092e82:
- G1:README
- G2:PlayerEnergyModel
- G3:EnergyContracts
- G4:EnergyModels
- G5:Rules 与 StateBuilder
- G6:UiBridge
- G7:PanelBuyEnergyLogic
- G8:UIPopupDOTween
- G9:service、Command/Dispatcher
- G10:报告事件