粒子模块
脚本入口: eve.Particles()
用代码或 JSON 创建发射器,配置运动、颜色、寿命并进行更新和渲染。
基本用法
绑定到动态骨骼
粒子仍是 2D。支持多种运行时骨骼源;每帧 particles.update 会自动 syncAttach。
| 源 | API | 说明 |
|---|---|---|
3D AnimPose | attachToBone / attachToBoneByName | 骨骼世界坐标经 plane(xy/xz/yz)与 scale 投影 |
| 2D Spine | attachToSpineBone / attachToSpineBoneByName | 像素空间;scale 仍生效,plane 忽略 |
IK Skeleton2D | attachToSkeleton2D | FABRIK 链骨位置(像素/世界单位 × scale) |
IK Skeleton3D | attachToSkeleton3D | 3D 骨位置经 plane+scale 投影 |
Spine(2D)示例:
IK 2D/3D 示例:
detach() 解除绑定;getAttachKind() 返回 "anim" / "spine" / "ik2d" / "ik3d" / "none";也可手动 syncAttach()。
蒙皮表面发射(人物皮肤粒子)
从 CPU 蒙皮后的顶点采样发射位置,适合身体表面的火花、灰尘、能量层:
脚本侧也可主动刷新蒙皮缓存:skin.updateSkinnedPositions(pose),再用 getSkinnedPositionX/Y/Z(i) 读取。
外观增强:混合模式、序列帧与生命周期曲线
发射器支持加法混合、精灵表序列帧动画、多段颜色渐变与大小/旋转曲线,均可通过 JSON 或脚本配置。
JSON 等价配置:
说明:
blendMode:"alpha"(默认)/"additive"/"opaque"。加法混合适合火焰、火花、魔法等自发光效果。flipbook:hframes/vframes为精灵表行列数;frameRate为每秒帧数(0 = 静止第一帧);frameRandomStart(0~1)随机化起始帧。colorOverLifetime/sizeOverLifetime/rotationOverLifetime为按归一化寿命采样的多段渐变/曲线;不配置时回退到colorStart/colorEnd与sizes的两端线性插值。rotationOverLifetime单位为度,叠加在初始旋转与自旋之上。
发射控制与受力增强
发射器支持定时爆发、预热、重力/阻尼/限速、速度曲线、继承速度与本地/世界仿真空间:
JSON 等价配置:
说明:
bursts:按发射器运行时间触发的爆发(数组元素为{time, count}或[time, count]),每个爆发只触发一次。prewarm:start()时按 1/60 步长预模拟,让循环效果在首帧就是满的。gravity每步作为加速度叠加;damping为每秒速度衰减比例(0~1);limitVelocity为速度上限(0 = 不限);velocityOverLifetime为速度倍率曲线。inheritVelocity(0~1)把发射器当前移动速度按比例附加到新粒子;simulationSpace: "local"时粒子随发射器平移(默认"world")。noise为 CPU 值噪声湍流(强度/频率/时间流速),适合烟雾、火焰的自然扰动。maxDeltaTime限制单帧模拟步长,防止卡顿后的粒子爆炸。
碰撞与子发射器
JSON:collision: {mode, radius, restitution, lifetimeLoss}、collisionBounds: {enabled, minX, minY, maxX, maxY}、worldCollision: true。子发射器目前通过脚本 addSubEmitter(target, trigger, inherit) 关联(trigger 为 "birth" / "death" / "collision")。
拖尾:setRenderMode("stretched", factor) 或 JSON renderMode: "stretched" + stretch,粒子沿速度方向拉伸成彗星/流光。
健壮性:overflowMode("drop" 默认 / "pause" 暂停发射直到有空位 / "warn" 日志提示);setMaxDeltaTime 限制单帧步长;带相机的发射器在屏幕外且无存活粒子时会跳过模拟。
力场、自定义 Shader 与粒子灯光
JSON:forceFields: [{x, y, radius, strength, falloff}];lights: {enabled, max, radius, intensity, color: [r,g,b]}。粒子灯光由 ParticleLightSystem(随 particles.update 自动调用)维护一盏 Light2D 池,位置与最前面的存活粒子同步。
GPU 加速模拟
setGpuSimulation(true) 或 JSON "gpuSimulation": true 可为单个发射器开启 GPU 模拟:每粒子的运动积分(重力、阻尼、限速、径向/切向加速度、速度帧、噪声湍流、旋转、序列帧推进、寿命衰减)在计算着色器中执行,生成与回收、碰撞、子发射器仍由 CPU 处理。不可用(无 GPU 设备/计算管线失败)时自动回退到 CPU 模拟,行为保持一致。
实现说明:粒子状态以 16 个 float/粒子存放在 SSBO(ParticleGpuKernel.h),每帧 upload → dispatch(64 线程/组)→ readback 后走原有渲染路径;渲染仍是 CPU 批量四边形,因此收益集中在把每粒子物理计算移到 GPU。该模式下暂不参与 GPU 的项:力场、噪声外的 CPU 专属逻辑仍在 CPU 侧生效(碰撞等)。GLSL 内核可通过 glslc 单独编译验证(ParticleGpuKernel.h 内注释含布局说明)。
对象关系与调用时机
Particles 管理 Emitter 及配置、模拟、渲染系统;Emitter 持有容量、发射配置与运行状态。模块 update 统一推进所有 emitter(含骨骼绑定同步与蒙皮表面采样),render 按 layer 提交。
帧序建议:动画 computeWorld → particles.update(dt) → particles.render(gfx)。
目标导向指南
从 JSON 创建火焰
配置 buffer、发射率、寿命、速度、颜色和 autoReload,调用 newEmitterFromFile();设置位置后 start()。模块统一 update(dt) 和 render(gfx),无需逐粒子操作。
制作一次性爆炸
创建容量足够的 emitter,设置有限 emitter life 和较高瞬时发射率,停止循环;播放结束后检查 active 状态并回收。预览时用 preset 起步,再逐项覆盖参数。
角色手上的拖尾 / 皮肤光晕
动画更新并 computeWorld 后,用 attachToBoneByName 绑定肢体,或用 setSkinSource 从蒙皮表面发射;setAttachScale / setSkinScale 把模型单位映射到像素空间。
常见问题
- buffer 太小导致高发射率粒子被覆盖。
- 只 render 不 update,粒子静止。
- 无限 emitter 离开场景后未 stop/回收。
- 骨骼绑定后位置不对:检查是否先更新姿态(
pose.computeWorld(sk)/spine.updateWorldTransform()/ IKforwardKinematics/solve),以及plane/scale是否匹配相机投影。 - 蒙皮表面无粒子:确认
setSkinSource与hasBones网格,且过滤器未把候选顶点剔光。
API 快查
下列方法名来自当前 Squirrel 绑定;同一模块创建的辅助对象(例如 World、Body、Source)的方法也列在这里。
addBurst()、addColorStop()、addForceField()、addRotationCurvePoint()、addSizeCurvePoint()、addSubEmitter()、addVelocityCurvePoint()、applyConfig()、applyPreset()、attachToBone()、attachToBoneByName()、attachToSkeleton2D()、attachToSkeleton3D()、attachToSpineBone()、attachToSpineBoneByName()、clearBursts()、clearColorGradient()、clearForceFields()、clearRotationCurve()、clearSizeCurve()、clearSkinSource()、clearSubEmitters()、clearVelocityCurve()、detach()、emit()、emitFromSkin()、getAttachBone()、getAttachKind()、getAutoReload()、getBlendMode()、getBufferSize()、getConfigPath()、getCount()、getDirection()、getGpuSimulation()、getLightsEnabled()、getPrewarmSeconds()、getShader()getEmissionAreaType()、getEmissionAreaX()、getEmissionAreaY()、getEmissionRate()、getEmitterCount()、getEmitterLifetime()、getLayer()、getName()getParticleHeight()、getParticleLifetimeMax()、getParticleLifetimeMin()、getParticleWidth()、getSizeVariation()、getSpread()、getX()、getY()hasSkinSource()、isActive()、isAttached()、isPaused()、isStopped()、isVisible()、loadConfig()、moveTo()、newEmitter()、newEmitterFromFile()pause()、pollConfigs()、reloadConfig()、render()、reset()、setAttachOffset()、setAttachPlane()、setAttachScale()、setAutoReload()、setCamera()、setCanvas()setBlendMode()、setCollision()、setCollisionBounds()、setColorEnd()、setColorStart()、setDamping()、setDirection()、setEmissionArea()、setEmissionRate()、setEmitterLife()、setEmitterLifetime()、setEmitterTime()、setFlipbook()、setGpuSimulation()、setGravity()、setInheritVelocity()、setLights()、setLimitVelocity()、setMaxDeltaTime()、setNoise()、setOverflowMode()、setPrewarm()、setRenderMode()、setShader()、setSimulationSpace()、setWorldCollision()setFollowBoneRotation()、setLayer()、setLinearAcceleration()、setParticleLife()、setParticleLifetime()、setParticleSize()、setPosition()、setRadialAcceleration()、setSizeVariation()setSizes()、setSkinBoneFilter()、setSkinBoneFilterByName()、setSkinPlane()、setSkinScale()、setSkinSource()、setSpeed()、setSpin()、setSpread()、setStartRotation()、setTangentialAcceleration()、setTexture()、setVisible()、start()stop()、syncAttach()、update()
使用要点
- 模块对象和它创建的资源对象应保存在全局或实体状态中,不要在每帧重复创建。
- 带
update(dt)的系统应在eve_update调用;绘制方法应在eve_render调用。 - 参数约束、默认值和返回类型以对应模块头文件及
addFunc绑定为准;本文 API 快查与当前源码同步生成。
源码: src/modules/particles/ 相关测试: test/particles.cpp、test/particles_attach_skin.cpp、test/particles_dynamic_bones.cpp、test/particles_attach_more.cpp、test/particles_attach_extra.cpp。