ParticleSystem简易指南
粒子系统基本使用方法
新建一个ParticleEmitter实例(粒子发射器)并使用ApplyEmitterModule、ApplyParticleSpawn和ApplyParticleModule方法设置发射器与粒子的具体行为。
//示例,并不完整,只是为了展示方法和模块该怎么写
emitter.ApplyEmitterModule(new SetEmitterLife(emitter, setLife - 20, false));
emitter.ApplyParticleSpawn(new BurstSpawnerModule(emitter, 260));
emitter.ApplyParticleModule(new AddElement(emitter, new Particle.SpriteInitParam("Futile_White", "FlatLight", alpha: 0.5f)));
(一般可能用到的)字段
ParticleEmitter.pos(Vector2)
发射器的中心位置,如果设置movetype为Relative则粒子的运动以该位置为原点
ParticleEmitter.vel(Vector2)
发射器的速度,似乎如果把发射器绑定到有物理行为的物体上时就会对它赋值
ParticleEmitter.room(Room)
发射器所在的房间
方法与Module
ApplyEmitterModule
控制发射器的行为(主要为控制发射器生命周期),默认包含以下两个module:
SetEmitterLife
(ParticleEmitter emitter, int life, bool loop, bool killOnFinish = true)
设置发射器的寿命,通过计时器来自动重置或清除发射器
emitter:目标发射器实例
life:目标发射器的寿命,每次更新(一个逻辑帧即0.025s)时减少
loop:是否循环。如果为True则当life=0时重置life的值
killOnFinish:是否在结束时清除,默认为True。如果为True则当life=0时执行Die方法
BindEmitterToPhysicalObject
(ParticleEmitter emitter, PhysicalObject physicalObject, int chunk = 0, bool dieOnNoRoomOrNull = true)
将发射器绑定到有物理性质的物体上,发射器在初始化和更新时将会尝试同步该物体的位置和速度,而且如果找不到该物体或该物体房间为空则清除发射器
emitter:目标发射器实例
physicalObject:目标物体实例
chunk:如果物体有多个节段则决定绑定到哪一段,默认为0
dieOnNoRoomOrNull:如果无房间或为空则清除(似乎并没有用到?目前只要房间和物体中任何一个找不到就Die)
当然也可以不使用这两个Module,手动给Emitter的速度和位置赋值也是可以的,可以用Die方法强制清除发射器
ApplyParticleSpawn
控制粒子生成的模式,默认包含以下两个module:
RateSpawnerModule
(ParticleEmitter emitter, int maxParticleCount, int ratePerSec)
按一定的频率连续生成粒子,直到达到最大值
emitter:目标发射器实例
maxParticleCount:该发射器在一个生命周期中能累计产生的最大粒子数
rateParSec:粒子生成速率
BurstSpawnerModule
(ParticleEmitter emitter, int count)
在初始化时一次性生成指定数量的粒子
emitter:目标发射器实例
count:生成的粒子数
同上,你大概可以不用这些Module 而是自己调用ParticleEmitter的SpawnParticle()方法让它以你喜欢的方式生成粒子
ApplyParticleModule
控制粒子的具体行为,默认包含以下模块:
/初始化/
这些Module负责控制粒子的初始化行为(指定初始状态的速度/大小/外观等),可以自己选取并组合。有些对同一属性赋值的Module不可叠加并且会按顺序覆盖之前的设定。也可以自己编写新的Module以实现更丰富的效果。
AddElement
(ParticleEmitter emitter, params Particle.SpriteInitParam[] spriteInitParam)
为粒子添加外观元素(可以多次添加)
emitter:目标发射器实例
spriteInitParam:粒子的sprite渲染初始化 实际格式应为:
(string element, string shader, int layer = 8, float alpha = 1f, float scale = 1f, Color? constCol = null)
element:贴图名称
shader:使用的着色器(mod开发群里提供了RW内置贴图和着色器预览)
layer:渲染层,默认为8
alpha:不透明度,默认为1
scale:缩放比例,默认为1
SetMoveType
(ParticleEmitter emitter, Particle.MoveType moveType)
设置粒子的运动参考系
emitter:目标发射器实例
moveType:如果为Realtive,则计算粒子坐标以发射器为参考系,如果为Global则使用世界坐标系
SetConstVelociy
(ParticleEmitter emitter, Vector2 vel)
指定粒子的初始速度为固定值
emitter:目标发射器实例
vel:速度
SetRandomVelocity
(ParticleEmitter emitter, Vector2 a, Vector2 b,bool isDir = true)
使用两个向量随机指定粒子的初始方向和速度
emitter:目标发射器实例
a:指定x速度和y速度的一个值
b:指定x速度和y速度的另一个值
isDir:决定初始速度的计算方式
如果为true,则对a和b的角度进行随机插值后转化为单位向量(作为方向) ,再乘以一个a和b的绝对值之间随机选取的值(作为速度),实际生成a与b夹角范围内的大小介于a和b之间的向量。
如果为false,直接取a.x和b.x之间的随机数为x,a.y和b.y之间的随机数为y,然后合成向量
SetSphericalVelocity
(ParticleEmitter emitter, float vA, float vB)
粒子飞向任何方向的可能性相等,速度为介于vA和vB之间的随机值
emitter:目标发射器实例
vA:速度的最大值或最小值
vB:速度的最小值或最大值
SetVelociyFromEmitter
(ParticleEmitter emitter, float t)
基于发射器的速度设置粒子的初始速度
emitter:目标发射器实例
t:速度倍率
SetRandomRotation
(ParticleEmitter emitter, float rotationA, float rotationB)
随机化粒子的初始旋转
emitter:目标发射器实例
a,b:粒子旋转的取值范围(单位似乎是角度)
SetRandomScale
(ParticleEmitter emitter, float a, float b)
随机化粒子的初始大小
emitter:目标发射器实例
a,b:粒子比例的取值范围(实际是产生(a,a)和(b,b)两个二维向量来控制大小以保证粒子图像等比例缩放)
SetRandomPos
(ParticleEmitter emitter, float rad)
粒子的生成位置分散在以发射器为中心 rad范围内的圆形区域中,且越靠近中心密度越高
emitter:目标发射器实例
rad:半径
SetRandomLife
(ParticleEmitter emitter, int a, int b)
随机化粒子寿命
emitter:目标发射器实例
a,b:粒子的存在时长(单位为逻辑帧),会取a与b之间的随机值
SetConstColor
ParticleEmitter emitter, Color color)
设置固定的粒子起始颜色
emitter:目标发射器实例
color:颜色
SetRandomColor
(ParticleEmitter emitter, float hueA, float hueB, float saturation, float lightness)
设置带有随机色相的初始粒子颜色
emitter:目标发射器实例
hueA:色相A
hueB:色相B
saturation:饱和度
lightness:明度
/更新/
这些Module负责控制粒子更新时的行为(生命周期中颜色、外观和运动状态的变化),也可以视情况自由组合使用或自行编写新的Module
ConstantAcc
(ParticleEmitter emitter, Vector2 acc)
粒子的速度会均匀增加
emitter:目标发射器实例(...这个 真的有必要每次都说一遍吗)
acc:加速度
Gravity
(ParticleEmitter emitter, float g)
粒子受重力影响
emitter:目标发射器实例
g:重力大小
(各种各样的)OverLife
(emitter,(particle,particle.lifeparam) =>{return})
指定粒子的某一属性在整个生命周期内变化,用法都差不多。
emitter:目标发射器实例
particle:目标粒子实例
particle.lifeparam:目标粒子的生命周期(已经存在的时间与最大寿命的比值,范围0f-1f)
//示例
//建立新的发射器实例
emitter = new ParticleEmitter(room);
/*
省略了发射器行为、粒子生成模式和粒子初始化的设置
*/
//对于发射器实例emitter所产生的每一个粒子实例p以及该粒子的生命周期l,这两个被提供用于在大括号内计算并返回(return)一个float类型的值作为粒子的不透明度
emitter.ApplyParticleModule(new AlphaOverLife(emitter,
(p, l) =>
{
if (l < 0.2f)
{
return l * 5f;
}
else if (l > 0.8f)
{
return 1f - (l - 0.8f) * 5f;
}
return 1f;
}));
VelocityOverLife:返回类型为Vector2(速度)
PositionOverLife:返回类型为Vector2(位置)
RotationOverLife:返回类型为float(旋转角度)
AlphaOverLife:返回类型为float,范围在0f-1f之间(透明度)
SimpleParticlePhysic
(ParticleEmitter emitter, bool bounce, bool die, float velDamping = 0.8f)
粒子物理模拟
emitter:目标发射器实例
bounce:是否在触碰实体物块时反弹
die:是否在触及实体物块时消失
(如果die为true则会覆盖bounce的效果,如果bounce和die都为false则粒子会在触及实体物块后停止运动)
velDamping:运动阻尼大小
/渲染/
这些Module负责控制粒子的渲染。
-如果你只需要正常显示粒子的外观,则不需要手动指定渲染器。未指定渲染器时,会自动使用默认渲染器的默认设置。
-如果你不需要显示粒子但需要使用粒子的拖尾效果,则需要指定尾迹渲染器。这时候将不会自动使用默认渲染器 因此实际生效的只有尾迹渲染器。
-如果你需要同时显示粒子本身和拖尾效果,则需要手动指定默认渲染器和尾迹渲染器,以保证两个渲染器都正常工作。
DefaultDrawer
(ParticleEmitter emitter, int[] renderElementIndexs)
默认的渲染器,用于显示粒子本身。如果不指定渲染器则会自动使用默认渲染器的默认设置
//默认设置
//注意这边有个自动换行 实际上最好写在一行内
emitter.ApplyParticleModule(new DefaultDrawer(emitter, new int[1] { 0 }));
//如果需要手动指定默认渲染器,建议直接套用默认设置,否则可能会引起不可预测的后果
TrailDrawer
(ParticleEmitter emitter, int index, int trailCount = 10)
尾迹渲染器,仅用于显示尾迹效果,仅在手动指定渲染器时启用。
emitter:emitter:目标发射器实例
index:尾迹节段索引,暂时不建议设为1意外的任何值
trailCount:尾迹总段数,会直接影响尾迹的长度,默认为10
尾迹渲染器的具体设置需要在语句后的大括号内进行,类似于上面那些“OverLife”。
提供了六个可被赋值的变量用于控制尾迹的外观:
gradient和colorOverLife
控制尾迹的颜色,两者的返回值都为Color类型,且两者中必须有且只有一个被指定。gradient提供尾迹某一节的索引i与尾迹的总节数a来单独为每一节计算颜色,而colorOverLife通过粒子的生命周期l来计算颜色,颜色将会应用于整条尾迹
width和widthModifyOverLife
控制尾迹的宽度,两者的返回值都为float类型,且必须指定width,两者效果可叠加。width提供尾迹某一节的索引i与尾迹的总节数a来单独为每一节计算宽度,而widthModifyOverLife通过粒子粒子的生命周期l来计算整条尾迹的宽度倍率,结果以乘积方式叠加
alpha和alphaModifyOverLife
用于控制尾迹的不透明度,两者的返回值都为float类型,且必须指定alpha,两者效果可叠加。alpha提供尾迹某一节的索引i与尾迹的总节数a来单独为每一节计算不透明度,而alphaModifyOverLife通过粒子的生命周期l来计算整条尾迹的不透明度倍率,结果以乘积方式叠加
gradient/width/alpha提供粒子p、尾迹某一节的索引i、尾迹的总节数a。
colorOverLife/widthModifyOverLife/alphaModifyOverLife提供粒子p、粒子的生命周期l。
//示例,来自ClusterBombBuff.cs
//小 心 自 动 换 行
emitter.ApplyParticleModule(new TrailDrawer(emitter, 1, 20)
{
alpha = (p, i, a) => 1f - i / (float)a,
alphaModifyOverLife = (p, l) => 1f - l,
gradient = (p, i, a) => Color.Lerp(Color.white, p.setColor, i / (float)a),
width = (p, i, a) => (1f - i / (float)a) * p.setScaleXY.x * 0.1f
});