glTF 模型
自 2.2.5从 2.2.5 起,Photon 可以把 glTF 2.0 文件(.glb 和 .gltf)作为 Mesh Source 读取。凡是能用 OBJ 或 JSON 模型的地方都能用 glTF:Model 渲染模式和 Mesh 发射形状都支持。从 2.2.7 起,带骨骼的文件还能播放自带的动画,见动画 glTF 模型。
导入文件
- 在编辑器中打开 Mesh 资源面板。
- 从游戏外把一个或多个
.glb、.gltf文件拖到面板上。.obj和.json模型也可以这样导入。 - 已经位于
<gameDir>/ldlib2/assets/下的文件直接原地使用;其他位置的文件会被复制进ldlib2资源包,编辑器会询问保存路径,默认建议models/<文件名>。
新建的 Mesh 资源使用 glTF 模型 来源。如果文件带骨骼且至少有一段动画,则改用 动画 glTF 模型 来源,拖进来就能直接播放。
要让已有的 Mesh 指向某个文件,把 模型来源 设为 glTF 模型,再点击 选择 glb / gltf 文件。
| 字段 | 默认值 | 描述 |
|---|---|---|
| glTF 位置 | – | 文件对应的资源位置。 |
| 翻转 V | 关 | 垂直翻转 UV(v = 1 - v)。glTF 的 UV 原点本来就和 Minecraft 一样在左上角,除非导出结果上下颠倒,否则保持关闭。 |
Photon 不会监视文件变化。重新导出文件后,点击 重新加载网格。
从 2.2.6.a 起,导出 .fxpack 时会一并打包特效用到的 .glb 和 .gltf 文件,见分发与 FX Pack。
Photon 读取的内容
| 文件部分 | 行为 |
|---|---|
| 容器 | .glb,或者缓冲区以 data: URI 内嵌的 .gltf。引用外部 .bin 文件的 .gltf 会被拒绝,请改为导出 .glb。 |
| 场景 | 只读默认场景。每个节点的变换都会烘焙进顶点。 |
| 图元 | 只读 TRIANGLES。三角带、三角扇、线和点会被跳过。 |
| 顶点数据 | POSITION、NORMAL、TEXCOORD_0 和 TANGENT。没有法线的图元使用平面法线;没有 UV 的图元所有顶点都是 (0, 0)。 |
| 忽略 | 材质、纹理、相机、变形目标(morph target)、顶点色和额外的 UV 组。Mesh 由 Photon 自己的 Material 绘制。 |
顶点位置按导出时的数值原样使用:
- 1 个 glTF 单位等于 1 格方块。Blender 把 1 米导出为 1 个单位。
- Photon 不会居中或缩放 Mesh。文件原点就落在粒子位置上,可以用 Renderer 的
modelPivot调整。 - 不交换坐标轴。glTF 和 Minecraft 都是 Y 轴向上的右手坐标系。
- 在 Model 渲染模式下,粒子大小会缩放 Mesh。大小为
1时按导出尺寸绘制。
顶点切线
自 2.2.5切线空间法线贴图需要每个顶点都带切线。Model 渲染模式为此提供了 tangent 开关,默认关闭。当 Shader Graph 用到 Tangent 或 Bitangent 节点、Transform 节点的 Tangent 空间,或者自定义 Shader 读取切线属性时,请打开它。
- 自带
TANGENT的 glTF 图元沿用文件里的切线。 - OBJ、JSON 模型,以及不带切线的 glTF 图元,会根据 UV 生成切线,并在共享边上做平滑。同一个文件里两种图元混用时,整个 Mesh 都改为生成。
- 该开关需要开启 GPU 实例化。
- 关闭时顶点布局完全不含切线,Tangent / Bitangent 节点以及 Transform 节点的 Tangent 空间都拿不到真实的坐标系。
- Billboard、拖尾、AraTrail 和光束始终带有精确的切线,非实例化的 CPU 路径除外。
Shader 一侧的细节(PHOTON_TANGENT 与属性布局)见顶点格式与 GPU 实例化。
动画 glTF 模型
自 2.2.7
从 2.2.7 起,动画 glTF 模型 来源会在每个使用它的粒子上播放带骨骼 glTF 文件中的一段动画。把带骨骼且至少有一段动画的文件拖进 Mesh 资源面板,就会自动创建这种来源;只含动画的文件和普通模型则导入为 glTF 模型。
字段

| 字段 | 默认值 | 描述 |
|---|---|---|
| glTF 位置、翻转 V | –、关 | 与 glTF 模型来源相同。 |
| 动画(Animation) | (文件中的第一个) | 列出文件本身和动画文件中的动画片段。按名称保存,重新导出时即使片段顺序变了,选择也不会丢。 |
| 速度(Speed) | 1 | 播放速率。2 为两倍速,负数倒放。相位来源为 Lifetime 时,表示粒子一生中播放几遍。 |
| 循环(Loop) | 开 | 播放结束后从头开始。关闭时停在最后一帧。 |
| 动画文件(Animation Files) | 空 | 额外的 .glb 文件,其中的片段会加入列表。见额外的动画文件。 |
| 逐粒子相位(Per-Particle Phase) | 关 | 让每个粒子处在动画的不同位置,而不是全部摆出同一个姿势。 |
| 烘焙帧数(Baked Frames) | 30(2–240) | 仅用于逐粒子相位。烘焙的姿势数量,越多越平滑,占用也越大。 |
| 帧间插值(Interpolate Frames) | 开 | 仅用于逐粒子相位。在相邻烘焙帧之间混合,而不是直接跳帧。每个顶点多一次纹素读取。 |
| 相位来源(Phase From) | Random | 仅用于逐粒子相位。Random:在共享时钟上加一个固定的逐粒子偏移。Lifetime:从出生到死亡播放“速度”遍。 |
面板中还有 选择 glb / gltf 文件 和 重新加载网格 两个按钮。
时钟
动画不跟随 Emitter 自身的时间。
- 在编辑器中,动画跟随时间轴播放头。拖动播放头时姿势随之变化,暂停时保持不动。
- 在世界中,动画跟随关卡的游戏时间。所有特效的所有实例共用这一个时钟,所以特效开始播放时动画并不会从头开始。
游戏时间早已超过任何动画片段的长度,因此在世界中关闭循环的片段会一直停在最后一帧,除非相位来源设为 Lifetime。一次性动画请使用 Lifetime。
共享时钟与逐粒子相位
| 关闭逐粒子相位(共享时钟) | 开启逐粒子相位 | |
|---|---|---|
| 姿势来源 | CPU 每帧蒙皮一次。 | 动画片段烘焙一次,存入姿势表;顶点着色器据此为每个粒子摆姿势。 |
| 粒子 | 全部同步运动。 | 各自处在动画的不同位置。 |
| 每帧开销 | 每种“模型 + 片段 + 速度 + 循环”组合蒙皮一次,所有用到它的 Emitter 共享。 | 烘焙之后没有开销。 |
| 法线 | 跟随形变。 | 与位置一起烘焙,同样跟随形变。 |
切线(tangent 开关) | 跟随形变。 | 不烘焙,保持静止姿势(rest pose)。 |
逐粒子相位在开启和关闭 GPU 实例化时都能工作。
姿势表大小为 (烘焙帧数 + 1) × 顶点数 × 16 字节,上限为 2,000,000 个纹素(32 MiB),按默认 30 帧计算约为 64,000 个顶点。超过上限时 Photon 不会烘焙:模型仍然播放动画,但像关闭逐粒子相位时一样同步播放,日志中会提示一次需要多少纹素。降低烘焙帧数即可回到上限以内。
无论是否开启逐粒子相位,Mesh 预览和发射形状显示的都是共享时钟下的姿势。
额外的动画文件
导出工具常把角色存为一个文件,每段动画各存一个文件。把这些动画文件加入 动画文件 即可:
- 其中的片段按骨骼名称匹配到模型的骨架上。两个文件必须导出自同一套骨骼。
- 只有一段动画的文件以文件名命名,例如
run.glb中的片段名为run。包含多段动画的文件命名为<文件名>/<片段名>。 - 模型中不存在的骨骼对应的通道会被丢弃,日志会报告丢弃的数量。骨骼名称一个都对不上的文件不会添加任何片段。
骨骼支持
- 每个顶点最多 4 个骨骼影响(
JOINTS_0/WEIGHTS_0)。 - 支持
LINEAR、STEP和CUBICSPLINE关键帧插值。 - 变形目标(
weights)通道会被丢弃。 - 没有蒙皮的动画节点(例如螺旋桨、旋转的宝石)同样会动。
发射形状
使用动画来源的 Mesh 形状会在当前共享时钟的姿势上生成粒子,所以生成点会跟着动画移动。采样权重(边长与三角形面积)仍取自静止姿势:被拉长的肢体只分到未拉长时的份额。见 Emission 与 Shape。
实用建议
- 一次性动画(跳跃、花朵绽放):开启逐粒子相位,把相位来源设为 Lifetime。速度为
1时,每个粒子一生中正好播放一遍。速度大于1且关闭循环时,动画提前播完并停在最后一帧。 - 鸟群、虫群:开启逐粒子相位并使用 Random,粒子就不会整齐划一地运动。
- 面数较多的模型:降低烘焙帧数,并保持帧间插值开启。姿势表会随帧数增大。帧数低、片段又长时,不插值会明显卡顿:4 秒的片段只烘焙 30 帧,相当于每秒 7.5 个姿势。
- 带法线贴图的动画模型:使用共享时钟。开启逐粒子相位时,切线会停留在静止姿势。