mcpField
P
particle-system

particle-system

github.com/decentraland创意与媒体4276 次安装今天更新
代码仓库

关于 particle-system

面向 Decentraland SDK7 ParticleSystem 的配置指南,涵盖发射器设置、粒子行为、编辑器调节及实用限制,适用于制作场景特效的创作者。

主要功能

  1. 01点、球体、圆锥和方盒发射器
  2. 02连续发射与爆发发射
  3. 03颜色、尺寸、运动和序列帧控制
  4. 04播放状态与模拟空间设置
  5. 05Creator Hub 检视器使用指南

适用场景

  1. 01创建循环或单次场景特效
  2. 02制作轨迹、降雪、火花或烟花
  3. 03在 Creator Hub 调节粒子发射器
  4. 04将粒子数量控制在场景预算内

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/decentraland/sdk-skills --skill particle-system

安装后在 Claude Code 中输入/particle-system确认已加载。

附带文件references/particle-presets.md

详细介绍

ParticleSystem(SDK7)

从实体发射粒子。每个实体只能有一个 ParticleSystem 组件,并与 Transform 一同附加。无需网格——粒子直接由组件渲染。

规则:Transform.scale 不会缩放粒子

粒子大小仅由 initialSize 和 sizeOverTime(FloatRange)控制。ParticleSystem 还会设置发射器形状的空间尺寸(当形状包含尺寸字段时,例如 Sphere 的 radius、Box 的 size、Cone 的 radius)。这些尺寸不受实体 Transform.scale 影响。增大 Transform.scale 不会让粒子变大。

规则:粒子只会渲染给位于场景地块内的玩家

从场景地块外观看场景的玩家看不到粒子。粒子不属于场景 LOD 轮廓。请将发射器放置在地块范围内。

规则:引擎将粒子总数限制在约 1000 个

引擎会强制执行每个场景的粒子预算;如果所有活动粒子的总数可能超过限制,就会降低所有活动粒子系统的发射率。请为每个系统设置 maxParticles,并优先使用少量效果显著的系统,而不是许多小型系统。

移动端预算(已发布的数据)

移动端客户端公布了明确的数据(文档提交 8139a7f,2026 年 10 月):

软限制硬限制
VFX 发射器(场景中的粒子系统)810
活动粒子25,00050,000

软限制 = 移动端性能面板中显示警告;硬限制 = 场景将无法加载。除场景限制外,移动端还会在运行时将每个发射器的粒子数限制为 5,000 个、每个场景限制为 50,000 个——超过这些上限的配置会被静默调低,因此将 maxParticles 设为高于 5,000 只会浪费预算,不会带来视觉效果。

实用目标:发射器不超过 8 个,每个发射器的 maxParticles 远低于 5,000,并控制同时活动粒子的总数。[未验证:上文“约 1000 个”的桌面端数据与这些移动端数据之间的关系——它们来自不同来源,因此跨平台场景应以较严格的限制作为设计目标。]

完整的移动端限制表以及灯光/粒子相关说明:optimize-scene → 移动端场景限制。移动端支持 ParticleSystem(它不再是兼容性差异)。

规则:预热要求 loop = true

prewarm: true 只有在 loop: true 时才会生效。对于单次播放系统(loop: false),预热会被静默忽略。

规则:faceTravelDirection 会覆盖 billboard

当 faceTravelDirection: true 时,粒子会沿其速度向量定向,并忽略 billboard。用于轨迹/拖尾效果(小行星、子弹、火花)。请显式设置 billboard: false,以免造成混淆。

导入

import { engine, Transform, ParticleSystem } from '@dcl/sdk/ecs'
import {
	PBParticleSystem_BlendMode,
	PBParticleSystem_PlaybackState,
	PBParticleSystem_SimulationSpace,
} from '@dcl/sdk/ecs'
import { Color4, Vector3, Quaternion } from '@dcl/sdk/math'

ParticleSystemBlendMode 和 ParticleSystemPlaybackState 别名也从 @dcl/sdk/ecs 导出,可与带 PB 前缀的名称互换使用。没有 ParticleSystemSimulationSpace 别名——只有 PBParticleSystem_SimulationSpace。为保持一致,请始终优先使用带 PB 前缀的名称。

字段参考

字段类型默认值说明
activebooleantrue控制是否启用新粒子发射。
ratenumber10每秒发射的粒子数(连续发射)。使用 bursts 时设为 0。
maxParticlesnumber1000此系统中同时存活的粒子数量上限。
lifetimenumber5粒子生命周期,单位为秒。
gravitynumber0场景重力的倍率(约为 -9.81 m/s²)。负值表示粒子上升。
additionalForceVector3—每帧施加的恒定力向量(世界空间)。
initialSizeFloatRange{start:1, end:1}生成时的随机尺寸。
sizeOverTimeFloatRange{start:1, end:1}粒子生命周期内从起始值到结束值插值的尺寸。
initialRotationQuaternionidentity生成时的朝向(3D)。
rotationOverTimeQuaternionidentity各轴角速度(四元数转换为等效的 Euler XYZ 弧度/秒)。
faceTravelDirectionbooleanfalse沿速度方向调整朝向。优先于 billboard。
initialColorColorRange{white,white}生成时的随机颜色。
colorOverTimeColorRange{white,white}生命周期内从起始颜色到结束颜色插值。将结束时的 alpha 设为 0 可淡出。
initialVelocitySpeedFloatRange{start:1, end:1}初始速度,单位为 m/s;每个粒子的速度随机生成。
textureTexture白色四边形粒子精灵图。与 Material 纹理使用相同的 Texture 结构。
blendModePBParticleSystem_BlendModePSB_ALPHAPSB_ALPHA | PSB_ADD | PSB_MULTIPLY。
billboardbooleantrue粒子始终面向摄像机。对于具有 3D 朝向的粒子,请禁用此项。
spriteSheet{tilesX, tilesY, framesPerSecond?}—纹理图集帧动画。framesPerSecond 默认为 30。
shapeoneof Point/Sphere/Cone/BoxPoint发射器几何形状 — 见下文。
loopbooleantrue循环发射周期。false 表示仅发射一次。
prewarmbooleanfalse启动时视为已模拟完整个循环。要求 loop: true。
simulationSpacePBParticleSystem_SimulationSpacePSS_LOCALPSS_LOCAL(随实体移动)| PSS_WORLD(生成后保持原位)。
limitVelocity{speed, dampen?}—限制最高速度。dampen 范围为 0–1,默认为 1,表示硬性限制。
playbackStatePBParticleSystem_PlaybackStatePS_PLAYINGPS_PLAYING | PS_PAUSED | PS_STOPPED。
bursts{values: Burst[]}—离散发射事件(见 Bursts)。
FloatRange = { start: number, end: number } — 每个粒子采样一个随机值。
ColorRange = { start: Color4, end: Color4 } — 每个粒子采样一个随机颜色(范围两端的采样彼此独立于其他粒子的随机值)。

发射器形状

使用 ParticleSystem.Shape.* 辅助函数构建 — 切勿手动组装 oneof:

shape: ParticleSystem.Shape.Point()
shape: ParticleSystem.Shape.Sphere({ radius: 1 }) // default radius=1
shape: ParticleSystem.Shape.Cone({ angle: 25, radius: 1 }) // angle = half-angle in degrees
shape: ParticleSystem.Shape.Box({ size: Vector3.create(1, 1, 1) })
  • Point — 从实体原点发射。
  • Sphere — 在 radius 指定的球体内随机取点。
  • Cone — 从底面圆盘发射,并在半角 angle 范围内向外投射。圆锥的默认方向为实体的局部前向;旋转父级 Transform 即可调整发射方向。
  • Box — 在 size 指定的轴对齐方框内随机取点。

若要旋转发射方向(例如让圆锥朝下发射雪花或雨滴),请旋转父实体的 Transform.rotation。例如,圆锥向下飘雪时,可在实体上设置 rotation: Quaternion.fromEulerDegrees(180, 0, 0),或使用任何能翻转圆锥轴的朝向。

爆发

在特定时间发生的离散发射事件。将 rate: 0 设为仅使用爆发,或与 rate > 0 组合以实现连续发射与爆发发射。

bursts: {
	values: [{ time: 0, count: 100, cycles: 1, interval: 0.01, probability: 1.0 }]
}

爆发字段:time(从循环开始计算的秒数)、count(每次爆发的粒子数)、cycles(默认值为 1,0 = 无限循环)、interval(循环间隔秒数,默认值为 0.01)、probability(每次循环触发的概率,范围为 0–1,默认值为 1)。

同一循环中的多次爆发 = 错落点火模式(烟花)。

常见模式

ParticleSystem 定义的组成 — 附加到同时具有 Transform 的实体上:

const emitter = engine.addEntity()
Transform.create(emitter, { position: Vector3.create(8, 1, 8) })
ParticleSystem.create(emitter, {
	rate: 20, // particles per second
	lifetime: 2, // seconds each particle lives
	maxParticles: 100,
	initialSize: { start: 0.1, end: 0.3 }, // FloatRange sampled per particle
	sizeOverTime: { start: 1.0, end: 0.0 }, // shrink to nothing over lifetime
	initialVelocitySpeed: { start: 1, end: 2 },
	colorOverTime: {
		// fade out via alpha = 0 at end
		start: Color4.create(1, 1, 1, 1),
		end: Color4.create(1, 1, 1, 0),
	},
	shape: ParticleSystem.Shape.Point(), // emitter geometry
})

完整的生产级配置请参阅 {baseDir}/references/particle-presets.md — 共 17 个预设:Fire Ember、Magic Aura、Snowfall、Vortex Spiral、Gravity Fountain、Bat Swarm、Tumbling Leaves、Lightning Sparks、Heavy Rain、One-Shot Burst、Asteroid Trail、Purple Swirl、Bee Swarm、Fireworks Loop、Campfire、Flame Wisps、Moving Trail。爆炸/拾取物 VFX(Point/Cone + ADD 火焰、单次 Sphere 爆发)都在其中 — 例如 Fire Ember(预设 1)、One-Shot Burst 爆炸(预设 10)以及循环播放的 Fireworks Loop(预设 14)。

Creator Hub 编辑器集成

Creator Hub 检查器提供专用的 ParticleSystem 面板(已验证源码:ParticleSystemInspector.tsx,支持多实体,已在 EntityInspector.tsx 中注册)。在 Creator Hub 场景中创建和调整粒子效果,推荐使用以下方式:

  1. 在编辑器中为实体添加 ParticleSystem 组件。
  2. 在检查器面板中实时调整所有字段 -- 无需编写代码,也无需重新加载场景。

仅在动态运行时行为需要时使用代码(在 src/ 中调用 ParticleSystem.create/getMutable,或通过 Script 组件):例如通过游戏逻辑切换发射器、将播放/停止绑定到触发器/操作,或在运行时计算配置。

程序化 / 复合组件名称
  • 组件名称:core::ParticleSystem(组件 ID 1217)。
  • shape 是 protobuf oneof,序列化为 {"$case":"sphere","sphere":{"radius":1}}、{"$case":"cone","cone":{"angle":25,"radius":1}}、{"$case":"box","box":{"size":{"x":1,"y":1,"z":1}}} 或 {"$case":"point","point":{}}。
  • texture 是扁平的 Texture(不是 TextureUnion),序列化为 {"src":"assets/Images/spark.png"}。Material 使用的 $case/tex 封装不适用于此处。

播放控制

const ps = ParticleSystem.getMutable(entity)

// Pause emission and freeze existing particles
ps.playbackState = PBParticleSystem_PlaybackState.PS_PAUSED

// Resume
ps.playbackState = PBParticleSystem_PlaybackState.PS_PLAYING

// Stop and clear all live particles
ps.playbackState = PBParticleSystem_PlaybackState.PS_STOPPED

// Disable new emission (existing particles continue to live out their lifetime)
ps.active = false

使用 playbackState = PS_STOPPED 可立即停止。使用 active = false 可平缓结束粒子尾迹。

精灵表动画

纹理图集中的帧按网格排列(从左到右、从上到下)。总帧数 = tilesX * tilesY。

texture: { src: 'assets/Images/flame-sheet.png' },
spriteSheet: { tilesX: 4, tilesY: 3, framesPerSecond: 12 }   // 12 frames, plays at 12fps

测试场景示例使用 4x4(16 帧,蝙蝠群 @24fps)、4x3(12 帧,火焰/焰苗 @10–12fps)和 1x20(20 帧条带,蜜蜂 @30fps)精灵表。

模拟空间(本地与世界)

  • PSS_LOCAL(默认)——粒子随发射器移动。发射器移动时,会带动粒子群一起移动。适合用于移动实体上的光环效果。
  • PSS_WORLD——粒子会停留在生成时的世界空间位置,因此发射器移动时会在身后留下轨迹。

对于由 Tween 驱动的发射器(已在 0,7-particle-system 的“Moving Trail”中验证):PSS_LOCAL 会让粒子群在实体移动时始终附着在实体上;如果希望生成的粒子停留在原地并形成持久轨迹,则切换为 PSS_WORLD。测试场景展示了使用 PSS_LOCAL 的效果——根据你想要的视觉效果选择空间,而非将其视为硬性要求。

纹理字段

texture 字段使用与 Material 相同的 Texture 类型。常见情况(本地文件):

texture: {
	src: 'assets/Images/spark.png'
}

完整的 Texture 格式支持 filterMode/wrapMode,但粒子系统通常只需要 src。粒子上的 Avatar/Video 纹理尚未验证——请使用文件纹理。

注意事项

  • 纹理路径——粒子纹理默认使用 assets/Images/。路径约定与 Material 纹理相同。旧场景可能将纹理放在 assets/scene/Images/ 或 assets/scene/textures/ 下(仍可使用);Creator Hub 资源包中的纹理会放在 assets/asset-packs/,自定义项则放在 assets/custom/——按原路径引用即可。
  • 四元数旋转字段——rotationOverTime 会被解释为各轴的角速度(四元数 → Euler XYZ)。Quaternion.fromEulerDegrees(0, 90, 0) = 绕 Y 轴以 90°/s 旋转。单位四元数 = 不旋转。
  • 即使 simulationSpace = PSS_LOCAL,additionalForce 仍使用世界空间。无论发射器如何旋转,风力/漂移方向都保持不变。
  • limitVelocity.dampen = 1 = 硬性限速(粒子速度不会超过 speed)。较低的值允许速度短暂超过上限,随后再衰减。
  • 在 colorOverTime 末尾将 Color.alpha 设为 0 是淡出粒子的标准方式——不要只依赖 sizeOverTime 以 0 结束。
  • 评估时,爆发会忽略 active = false——active 每帧只检查一次,用于连续发射速率;在爆发时间之后设置该值不会追溯取消爆发。
  • 发射器实体上无需附加网格——添加 MeshRenderer 并无关联;粒子由 ParticleSystem 组件本身渲染。

性能

  • 尽量降低 lifetime * rate;该乘积就是稳定状态下的存活粒子数。
  • 通过 playbackState = PS_STOPPED 或 active = false 禁用视野外的系统。
  • 对于不透明/半透明效果,优先使用 PSB_ALPHA。PSB_ADD 最适合发光/火焰效果(视觉上会叠加),但多层加法混合过度绘制是开销最大的情况。
  • 精灵表开销较低;不支持在单个系统中使用多个纹理(每个系统只能使用一个纹理)。

资源

  • {baseDir}/references/particle-presets.md — 来自 SDK7 测试场景的 17 种即用型预设配置(火焰、魔法、降雪、漩涡、喷泉、群集、火花、雨、爆发、烟花、营火、轨迹)。
  • 在线调节器:ParticleLab.dcl.eth(使用 Decentraland 客户端打开)。

示例场景

  • https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,7-particle-system — 引擎团队的权威示例:上述全部 17 种预设、所有形状(Point/Sphere/Cone/Box)、PSB_ADD/PSB_ALPHA、连续 rate 与 bursts(单次 + 循环烟花)、spriteSheet(4×4/4×3/1×20)、limitVelocity、billboard: false 时的 initialRotation/rotationOverTime、faceTravelDirection、additionalForce,以及展示 simulationSpace 的 Tween 驱动发射器。

评论

支持 Markdown