目录
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 组件(推荐先跑通)
-
点「全部安装」。
-
在场景里新建一个空节点,挂上 demo 组件:
DemoDamage(2D/UI 飘字演示)或DemoWorld3D(3D 飘字演示)。
-
点击运行,即可看到伤害 / 暴击 / 治疗 / 状态提示持续飘出。
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 与常见符号:默认开启。
-
字符集:你要用到的全部字符,直接粘贴进去,只生成输入里的字。
-
实时预览:右侧即时显示打包后的最终图集(真实尺寸、占用率、空闲容量);字符超图集上限或源字体缺字会当场红色提示。
操作步骤:
- 选择字体,输入字符集,调好字号与图集上限。
- 观察右侧预览:
图集 宽×高(上限 N)· 字形 M 个 · 占用 P% · 空闲约 K 字。 - 点「生成并安装 BitmapFont」,写入项目并自动刷新 Assets。
- 运行时在代码里使用:
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/ # 文档