目录

  1. 特性一览
  2. 安装
  3. 快速开始
  4. 坐标空间(2D / 3D / UI)
  5. API 参考
  6. 动画系统
  7. 颜色与默认配色
  8. 渲染模式与默认字体
  9. 限流控制
  10. 位图字体生成(fnt)
  11. 示例与调试
  12. 常见问题(FAQ)

1. 特性一览

  • 跨环境:2D 世界、3D 世界、UI 空间坐标统一投影到 UI 层渲染,一套代码通吃。

  • 低 DrawCall:默认位图字体合批,大量飘字合并为一个 DrawCall。

  • 稳健兜底:启动时自动探测渲染能力,从「位图字体合批」自动降级到「系统字体 Label 池」,任何设备都有字可出。

  • 零 GC:飘字实例全部复用对象池,避免每帧 new,减少垃圾回收卡顿。

  • 预设动画:上浮淡出 / 原地淡出 / 原地弹入 / 上浮回弹 / 上弹回落,面板上直接选。

  • 内置 fnt 生成器:基于 Canvas 栅格化 TTF/OTF,一键生成 .fnt + .png 图集并写入项目,无需 Python 等外部依赖。

  • 默认配色:未指定颜色时按飘字类型自动取值,可整体换肤。


2. 安装

打开插件面板(菜单 → 打开插件面板),顶部有三个安装按钮:

按钮 作用
安装运行时 将运行时脚本写入项目 assets/YYKAFloatText/
安装示例 安装 2D / 3D 演示组件到项目
全部安装 运行时 + 示例 + 默认位图字体一并安装

安装成功后会显示安装的文件数。安装完成后,Cocos Creator 的 Assets 面板会自动刷新,可在资源管理器中看到新增目录:

复制代码
assets/
  YYKAFloatText/            # 运行时脚本 + Demo
  resources/YYKAFloatText/  # 默认位图字体 default.fnt / default.png

若 Assets 面板未自动刷新,可点击资源管理器右上角右键「刷新」手动刷新一次。


3. 快速开始

方式一:使用 Demo 组件(推荐先跑通)

  1. 点「全部安装」。

  2. 在场景里新建一个空节点,挂上 demo 组件:

    • DemoDamage(2D/UI 飘字演示)或 DemoWorld3D(3D 飘字演示)。
  3. 点击运行,即可看到伤害 / 暴击 / 治疗 / 状态提示持续飘出。

Demo 组件的 Inspector 上所有参数(生成频率、数量、字号、上浮高度、动画下拉选择、色板等)都可在运行时实时改。

方式二:代码接入

ts 复制代码
import { _decorator, Component, UITransform, Canvas, Vec3, find, Layers } from 'cc';
import { FloatTextMgr, FloatTextAnim } from './YYKAFloatText/FloatTextMgr';

const { ccclass, property } = _decorator;

@ccclass('MyFloatText')
export class MyFloatText extends Component {
  private mgr: FloatTextMgr;

  onLoad() {
    // 1. 准备一个 UI 承载节点(飘字以它为本地原点渲染)
    const uiRoot = this.createUIRoot();

    // 2. 创建管理器并挂载
    this.mgr = new FloatTextMgr();
    this.mgr.attach(uiRoot);            // 未传字体 → 自动加载默认位图字体

    // 3. 每天在 update 里驱动
    this.scheduleUpdate();
  }

  update(dt: number) {
    this.mgr.update(dt);
  }

  createUIRoot(): Node {
    const n = new Node('FloatTextRoot');
    n.layer = Layers.Enum.UI_2D;
    n.addComponent(UITransform);
    n.addComponent(Canvas);
    this.node.addChild(n);
    return n;
  }
}

然后在你需要飘字的地方调用:

ts 复制代码
// 3D 世界坐标(攻击者头顶)
this.mgr.showDamage(enemyWorldPos, 453, false);   // 普通伤害
this.mgr.showDamage(enemyWorldPos, 999, true);    // 暴击(橙色、更大字号)

// 治疗
this.mgr.showHeal(playerWorldPos, 120);

// 状态提示
this.mgr.showTip(playerWorldPos, '眩晕');

// 通用:指定空间 / 文字 / 动画
this.mgr.showWorld3D(pos, 'MISS', { anim: FloatTextAnim.Pop, size: 30 });
this.mgr.showWorld2D(pos2d, '-50', { color: [255, 60, 60] });
this.mgr.showUI(uiLocalPos, '金币 +100', { anim: FloatTextAnim.ShakeDrop });

4. 坐标空间

插件通过 FloatTextSpace 区分坐标来源,调用时可用 opts.space 指定,未指定用 attach 时的 defaultSpace(默认 World3D)。

枚举值 含义 传入坐标示例
World3D 3D 世界坐标 怪物头顶的 node.worldPosition
World2D 2D 世界坐标 2D 物体图元的 node.worldPosition
UI UI/屏幕空间 已换算到 UI root 下的局部坐标

内部会将该坐标经主相机 worldToScreen 投影为屏幕坐标,再换算成 UI 局部坐标用于渲染。所以 2D / 3D / UI 都能显示在正确的屏幕位置上。

ts 复制代码
import { FloatTextSpace } from './YYKAFloatText/coord/CoordResolver';

// 指定坐标语义
mgr.showWorld3D(pos, '123');
mgr.showUI(uiLocalPos, '你好');

主相机默认取 Camera.main(场景主相机)。若场景第一台相机是 UI 相机导致坐标不准,请用 mgr.setCamera(你的相机) 显式指定。欢迎收敛到 3D 与 2D 主相机的透视/正交投影。


5. API 参考

FloatTextMgr

方法 说明
attach(root, opts?) 挂载到 UI 承载节点,初始化渲染内核并按需加载默认字体
setCamera(camera) 显式绑定投影主相机
update(dt) 每帧驱动(动画推进 + 渲染提交),在组件 update 中调用
showWorld3D(pos, value, opts?) 3D 世界坐标飘字
showWorld2D(pos, value, opts?) 2D 世界坐标飘字
showUI(pos, value, opts?) UI 局部坐标飘字
showDamage(pos, dmg, isCrit) 伤害数字(暴击更高字号+配色)
showHeal(pos, heal) 治疗数字
showTip(pos, text) 状态提示文字
clearAll() / recycleAll() 清空所有活跃飘字
pause() / resume() 暂停 / 继续飘字

FloatTextOptions

ts 复制代码
interface FloatTextOptions {
  space?: 'World3D' | 'World2D' | 'UI'; // 坐标来源语义
  color?: [r, g, b];                    // 文字颜色(默认按类型从 palette 取)
  size?: number;                        // 像素字号(默认 24)
  lifeTime?: number;                    // 存活秒数(默认 1.5)
  floatHeight?: number;                 // 上浮高度(适用于上浮类动画)
  anim?: FloatTextAnim;                 // 预设动画
  scaleCurve?: 'none' | 'bounce';       // 向后兼容参数:'bounce' 等价 anim='rise'
}

FloatTextMgr 属性

属性 默认 说明
maxInstanceCount 300 同时活跃上限,超出直接丢弃
perFrameSpawnLimit 30 单帧最多生成数,防卡顿
palette 见下 默认配色表,可整体换肤
renderMode 只读 当前生效的渲染模式

6. 动画系统

FloatTextAnim 枚举(也是 Demo 面板下拉里的选项):

枚举 字面值 效果
FloatUp float-up 上浮淡出(默认)
Fade fade 原地淡出
Pop pop 原地弹入(过冲后回落)+ 淡出
Rise rise 上浮 + 回弹放大 + 淡出
ShakeDrop shake-drop 上弹(放大)+ 回落 + 滑动下落 + 淡出
ts 复制代码
import { FloatTextAnim } from './YYKAFloatText/FloatTextMgr';

mgr.showUI(pos, '暴击!', {
  anim: FloatTextAnim.Rise,
  size: 40,
  color: [255, 180, 40],
});

shake-drop 为三段时间曲线驱动:先快速弹起到高位(同时放大到约 1.5 倍),再小幅回落到峰高的 80% 处,最后缓缓滑落回原位淡出。曲线定义在 runtime/anim/curves.ts,可自行调整参数(up / frac / riseRatio / dropRatio 等)。


7. 颜色与默认配色

不传 color 时,按飘字类型/palette 取值:

key 默认 RGB 用途
normal [255,255,255] 普通飘字
damage [255,255,255] 伤害
crit [255,180,40] 暴击
heal [80,255,120] 治疗
status [200,200,255] 状态提示

整体换肤:

ts 复制代码
mgr.palette.damage = [255, 80, 80];
mgr.palette.crit = [255, 80, 0];
mgr.palette.heal = [80, 255, 160];

单条覆盖:

ts 复制代码
mgr.showUI(pos, '金币+100', { color: [250, 210, 60] });

位图字体纹理为白色,颜色全部由运行时染色,因此任何颜色都能安全生效,无需额外生成彩色字。


8. 渲染模式与默认字体

插件内置渲染降级链:

复制代码
D(位图字体 Label 合批,DrawCall≈1)  ←→  B(系统字体 Label 池兜底)
  • 有位图字体 → 进入 D 级,合批性能最佳。

  • 无位图字体 → 直接以 B 级系统字体兜底,保证出字。

  • 启动时探测,不在运行中切换。

默认字体:插件面板安装会写入 resources/YYKAFloatText/default.fnt/.png,运行时由 FloatTextMgr 自动 resources.load 加载;加载成功即进入 D 级。若你手动提供字体:

ts 复制代码
// 传入自定义 BitmapFont 资源 → 优先使用该字体
mgr.attach(root, { font: myBitmapFont });

// 或指定默认坐标来源
mgr.attach(root, { defaultSpace: 'UI' });

9. 限流控制

防止瞬时海量飘字拖垮性能:

ts 复制代码
mgr.maxInstanceCount = 500;   // 同时最多 500 个活跃
mgr.perFrameSpawnLimit = 40;  // 单帧最多生成 40 个

超限的请求会被静默丢弃(不报错、不崩),适合弹幕、范围 AOE、连续命中等场景。


10. 位图字体生成

面板「字体生成」区可视化生成 BMFont 图集,支持:

  • 字体:下拉选择(系统字体 + 插件自带字体)。

  • 字号:滑块 16–128(默认 32)。

  • 图集上限:256 / 512 / 1024 / 2048 / 4096(默认 512)。

  • 名称:生成字体名(写入 assets/resources/YYKAFloatText/<名称>.fnt/.png)。

  • 自动补 0-9 与常见符号:默认开启。

  • 字符集:你要用到的全部字符,直接粘贴进去,只生成输入里的字。

  • 实时预览:右侧即时显示打包后的最终图集(真实尺寸、占用率、空闲容量);字符超图集上限或源字体缺字会当场红色提示。

操作步骤:

  1. 选择字体,输入字符集,调好字号与图集上限。
  2. 观察右侧预览:图集 宽×高(上限 N)· 字形 M 个 · 占用 P% · 空闲约 K 字。
  3. 点「生成并安装 BitmapFont」,写入项目并自动刷新 Assets。
  4. 运行时在代码里使用:
ts 复制代码
resources.load('YYKAFloatText/我的字体', BitmapFont, (err, font) => {
  if (err) return;
  mgr.attach(uiRoot, { font });
});

字符集模板内置了常用游戏飘字词(伤害/暴击/命中/眩晕等)、数字、符号、大小写字母,可按需增删。注意:源字体本身缺失的字(如楷书里没有 "霰")无法生成,会明确提示缺失列表。


11. 示例与调试

  • Demo 组件:DemoDamage、DemoWorld3D(挂到场景节点即用),Inspector 提供生成频率、数量、字号、上浮高度、动画下拉选择、颜色板、是否显示状态面板等调试项。

  • 手动把脚本挂到场景节点后,运行即可看到持续的飘字,方便调整动画与配色。


12. 常见问题

Q:为什么我安装后 Assets 里没出现文件?
A:先看顶部状态提示是否「安装成功」。若文件在但列表未刷新,右键 Assets 面板「刷新」;或使用插件「全部安装」。

Q:为什么字出来了但颜色不对 / 是白色?
A:忘传 color 时用默认配色;也可在 mgr.palette 统一换肤。位图字体染色由运行时完成,任何颜色均支持。

Q:3D 场景里坐标偏了 / 点到不对位?
A:确认使用 3D 世界坐标并正确绑定主相机。若场景首台相机是 UI 相机,Camera.main 可能取错,请用 mgr.setCamera(真实主相机) 覆盖。

Q:同时飘很多字会不会卡?
A:已内建对象池(零 GC)+ 合批渲染 + 限流(maxInstanceCount / perFrameSpawnLimit)。若仍卡,优先降低每帧生成上限,或减小字号、提高生命值以控制在低活跃量。

Q:我想换一套动画怎么做?
A:动画曲线集中在 runtime/anim/curves.ts,新增曲线后在 FloatTextMgr 的动画分支里登记即可。


附录:目录结构

复制代码
YYKAFloatText/
  extension/          # 插件(面板 / 主进程 / 打包器)
    dist/panels/      # 面板逻辑
    fonts/            # 插件自带字体(楷书等)
  runtime/            # 运行时源码
    coord/            # CoordResolver 坐标投影
    data/             # FloatTextInstance / FloatTextPool(零 GC 对象池)
    anim/             # curves 动画曲线 / FloatTextAnimator
    render/           # 渲染内核 / 后端(合批 / 系统字体兜底)
    FloatTextMgr.ts   # 对外门面(主 API)
  demos/              # 演示组件
  docs/               # 文档