跳到主要内容

SpellIndicator 目标、位置与生命周期

固定源码 b664407a9306272352dd10a1fbe6c82224092e82 的 FeatureSpellIndicator 声明 com.wenjing.gameplay.feature-spell-indicator@1.0.0、Unity 2022.3。命名空间为 Wenjing.LibGameplay.SpellIndicatorLogic。本文覆盖固定 C# 的接口、几何与生命周期,不提供发布、安装或运行通过证据,也不包含视觉资产。

接入前明确三个实现边界​

  1. SpellIndicatorController.IsWithinEffectiveArea(int, Vector3) 当前直接返回 true,不能用作施法合法性或越界判定。
  2. Show / UpdatePosition 直接向 view 传入位置,不自动调用 clamp。要限制位置,消费者应显式调用 GetClosestEffectiveWorldPosition 或 Rules,并使用返回值显示/结算;显示约束也不替代战斗规则。
  3. view factory 只有 Create 方法,没有 Release/Return。EndDragSession 和切换动态 shape 会对运行时场景对象调用 Destroy,不能直接描述为池化归还闭环。S1 S2 S3

README 提到几何/Controller 测试与可选池化,但以上是当前固定实现实际可见的行为;本次没有执行测试或取得消费者回执。

定义 target、config 和 view 接线​

消费者实现 ISpellIndicatorTargetProvider.TryGetTargetSpec(int indicatorId, out SpellIndicatorTargetSpec),将自己的技能/卡牌标识映射到中立描述,不把产品表或协议传进共享 Runtime。S4

TargetSpecAPI含义
无目标SpellIndicatorTargetSpec.None()结束无效显示绑定
动态圆Dynamic(SpellIndicatorParam.Circle(radius))radius 至少 0.1;圆视图位置与缩放
动态矩形Dynamic(SpellIndicatorParam.Rectangle(width, rotationYDegrees))width 至少 0.1;长度来自 view.RectangleLength,不在 param 中
固定全区FixedArea(Enemy/Friendly)使用对应有效区中心及尺寸;传 None 返回 None 描述

ISpellIndicatorConfigProvider 提供 RestrictDynamicIndicatorsToArea 和 GetEffectiveArea。SpellIndicatorEffectiveArea 含 CenterXZ、SizeXZ、CenterY、HeightY、LineY、LineColor;当前 Controller/规则实际使用中心和 XZ 尺寸,不能推定每个字段都自动驱动线条材质或体积表现。S5

可使用 ScriptableObject SpellIndicatorConfigAsset;其菜单为 Wenjing/Gameplay/Spell Indicator Config。Controller 取配置的优先级为显式 config provider → 序列化 config asset → 默认 provider。默认 enemy/friendly 都为 XZ 40×40、中心 0,限制动态范围标记 true;这些默认值不是产品场地配置。S1 S5

通过 Configure(targetProvider, configProvider, viewFactory) 接线,或分别 SetTargetProvider/SetConfigProvider/SetViewFactory。Controller 的 root 优先使用 _indicatorRoot,否则自身 transform。README 指向模块自有 circle/rectangle/enemy-area/friendly-area 资源;本稿未取得这些资产的权利材料、内容与引用闭包。S6

没有 factory 时,动态显示实例化对应 circle/rectangle prefab;Controller 的固定区 fallback 使用 rectangle prefab。两个 standalone 全区 prefab 可以由消费者独立管理,但 Controller 没有专用的 enemy/friendly prefab 序列化槽。若需不同皮肤,factory 的 CreateFixedAreaView 应按类型提供合适的运行时 rectangle view。S1 S3

一次拖拽的实际调用顺序​

  1. 消费者先取得明确的 target spec、config provider 和矩形长度。矩形长度应来自消费者配置或已知 prefab,不应先显示原始位置来探测自定义 factory 的长度。
  2. 将镜头/屏幕输入转换为世界坐标。模块不做射线、地形、高度或输入系统适配。
  3. 首次显示需要约束时,先调用 SpellIndicatorRules.GetClosestEffectiveWorldPosition(targetSpec, worldPosition, configProvider, rectangleLength),再把返回的位置传给 Show(indicatorId, constrainedPosition)。也可在 Controller 的长度来源已明确时使用 GetClosestEffectiveWorldPosition(indicatorId, worldPosition);其长度取当前 active rectangle,再回落 rectangle prefab,否则为 0。自定义 factory 尚未创建 view 时不能推定 Controller 已知道它的长度,应使用消费者显式长度的 Rules 路径。
  4. Show 获取 target;provider 拒绝或描述为 None 时会隐藏 view 并重置会话。后续每次调用 UpdatePosition 前重复所需位置约束,再传入约束后的位置。UpdatePosition 沿用缓存 target,相同 indicatorId 在一次会话内不会重新读取 provider;配置/目标映射变化时应按产品意图 EndDragSession 后重新开始。无效目标重置后,UpdatePosition 不会重新激活旧目标。
  5. 提交、取消或退出时区分 Hide() 和 EndDragSession()。Hide 只隐藏 view,保留会话和最后位置;后续 UpdatePosition 可再次显示。EndDragSession 清空 ID/spec/最后位置并销毁所持运行时 view。
  6. 消费者场景/Mode 生命周期要明确调用结束。Controller 源码没有自定义 OnDisable/OnDestroy 清理入口,也没有 factory 归还回调;特别是外部 root、对象池和 provider 的生命周期需另外设计。S1

int.MinValue 用作“没有拖拽会话”的内部标记,消费者避免拿它作为正常 indicatorId。

几何和坐标规则​

动态 clamp 在 RestrictDynamicIndicatorsToArea 为 true 时使用 Enemy 区域;不是自动选择 Friendly。Circle 半范围为 radius;旋转矩形 XZ 包围半范围由 width、rectangleLength 和 yaw 的绝对 sin/cos 组合得出。规则将中心限制到“有效区扣除半范围”的区间;当指示器比区间还大,中心落在区间中点,不代表整形状已能容纳。S2

固定目标返回对应区域中心。GetCenterWorld(fallbackY) 仅当 Mathf.Abs(CenterY) > Mathf.Epsilon 时使用 authored 高度,否则使用 fallbackY,所以 0 高度在这个函数中表示回落,不是强制世界 Y=0。S5

Circle view 三轴 scale 均为 radius × ScaleMultiplier,默认 GroundOffsetY=0.02;不能不看实际视觉单位就把传入 radius 当 prefab 直径。Rectangle view 的精确 scale 为 (width * ScaleMultiplier, 1, RectangleLength * ScaleMultiplier),Y 固定为 1,朝向 Quaternion.Euler(0, RotationY, 0)。规则不把视觉 ScaleMultiplier 纳入半范围计算,消费者换皮/缩放时要统一实际视觉单位与战斗几何。S7

TryGetIndicatorWorldPosition(out Vector3) 并不是“是否当前可见”的判定:固定 target 返回区域中心;动态若 active view 的 activeSelf 为 true,返回 view transform(包含 GroundOffsetY),否则可返回最后瞄准位置。Hide 后它仍可能返回 true。IsVisible 只合成各 view 的 activeSelf;父级被停用或没有可见渲染时,仍不能据此保证屏幕可见。权威施法位置由产品确定几何规则和数据源。S1

view factory 与资源责任​

factory 返回具体运行时 view:CreateDynamicView(shape, parent),CreateFixedAreaView(type, parent)。Controller 会改对象名、显示、位置、scale,并在结束/动态换形时销毁 scene-valid 对象。它没有通知 factory 归还,消费者不能仅实现创建就认为池化支持完成。要保持池化,应由 owner 明确释放契约及调用方,或由消费者采用独立 view 生命周期;本稿没有修改这些接口。S1 S3

控制器返回的位置和绿色/蓝色默认区配置都不等于命中、阵营筛选或服务器结算。产品配置、相机转换、场景、资源加载、皮肤和 battle end-to-end 留在消费者。S6

发布与外部验收缺口​

README 指定 module-dashboard 发布、module-manager 消费精确版本,并明确没有 Samples / Samples~ 或示例专用脚本。本次没有实际模块包、打包映射、consumer adapter、prefab/material/sprite 权利资料或中立消费者回执,不把源码测试存在视为已运行。S6

需 gameplay owner 提供同 SHA 的 module source-to-dist、tool 版本/发布 job、消费者安装来源;需消费者提供 camera/input、target/config adapter、factory/释放方案、Mode/scene 接线和精确 head 的外部 battle 证据。对范围判定、自动 clamp 和池化归还的额外保证,必须有实际实现与证据后再更新文稿。

固定来源​

以下是内部固定来源,需要原仓内网和账号权限,公网读者不能保证可访问。链接保留仓库身份、完整 SHA 和相对路径供定位,不授予访问或资源转用权限;正文已独立说明所需字段与使用边界。

以下均在 gameplay b664407a9306272352dd10a1fbe6c82224092e82,模块路径为 Assets/DevTools/Modules/FeatureSpellIndicator:

相关指南​

阅读路径:安装 · 运行时接线 · 架构 · 版本基线 · FAQ