-
Notifications
You must be signed in to change notification settings - Fork 1.6k
ParticleAsset Guide
All assets are known engine types that allow instances to be created at runtime. The "ParticleAsset", like all assets, is derived from a base type of "AssetBase". That means it includes all the fields from that type as well as adding its own fields specific to itself.
The ParticleAsset represents what is often commonly referred to as a particle effect. A ParticleAsset is essentially a container for a "ParticleAssetEmitter".
An emitter is an object that actually emits particles in a configurable manner. An unlimited number of emitters can be created within a ParticleAsset. Emitters cannot "see" each other and therefore cannot alter each others properties. A ParticleAsset can alter its emitters’ properties though by scaling them as a group.
For an ParticleAsset to be valid, it must contain at least one ParticleAssetEmitter.
A ParticleAsset is used in the engine through a "ParticlePlayer".
Exposed Fields: ParticleAssetEmitter
Graph Fields: ParticleAssetEmitter
ParticleAsset and ParticleAssetEmitter API
There are 71 different fields unique to a ParticleAsset which can be used to create and configure a particle effect. This gives you a lot of under-the-hood power to work with but can also quickly lead to feeling overwhelmed. To help avoid this, let's cover some general concepts and terminology about how the particle system in Torque 2D works.
Let's look at a fire effect. We will want two components for this effect: flames and smoke. This means we will create two ParticleAssetEmitters to handle each component separately but they will be contained within one ParticleAsset, so we only have to handle the fire effect as a single object in our game. The basic shell of a ParticleAsset TAML XML file will look like this:
<ParticleAsset
AssetName="Fire">
<ParticleAssetEmitter
EmitterName="Smoke">
</ParticleAssetEmitter>
<ParticleAssetEmitter
EmitterName="Flames">
</ParticleAssetEmitter>
</ParticleAsset>
Obviously this would not display any particles if run in the engine, but it shows the foundation for a particle effect - which we will build upon in the next sections.
A ParticleAsset and its ParticleAssetEmitters are controlled via their fields. These fields are split up into two groups. The first group exposes fields that simply contain values that are on/off, or have one or two values for things such as size. These values cannot be defined to change over time although they can be changed in script dynamically. These fields do things such as setting an emitter into “IntenseParticle” mode or forcing the emitter to track rotation, etc. Continuing with our fire effect example, here is the TAML XML file with some of the "Exposed Fields" defined:
<ParticleAsset
AssetName="Fire" <!-- These are ParticleAsset fields -->
LifeMode="INFINITE">
<ParticleAssetEmitter
EmitterName="Smoke" <!-- These are ParticleAssetEmitter fields -->
EmitterType="LINE"
EmitterSize="0.5 0">
</ParticleAssetEmitter>
<ParticleAssetEmitter
EmitterName="Flames" <!-- These are ParticleAssetEmitter fields -->
EmitterType="LINE"
EmitterSize="1 0">
</ParticleAssetEmitter>
</ParticleAsset>
A detailed description of each field can be found further down in this guide.
The second group, and the more powerful, contains fields which are called "graph fields". A graph field is one which allows its values to be defined to vary over time, automatically in real-time. This is done by using a method called key-framing (a term used in animation). Each graph field allows you to add keys to it. Each key is comprised of a time and a value. Entering multiple keys at various times/values will configure the field to change its output value over a period of time. This is illustrated below:
As you can see, the above graph field has 4 keys defined. Assuming the time is in seconds, we can see that the field's value will change from 0 to 50 over a period of 1 second. If this field controlled the particle size, then the particles would rapidly grow as it aged towards 1 second. The particle system automatically linearly interpolates between the values. When the particle ages beyond 1 second, it would maintain its previous key-value, which in this case is 50; visualizing this, it would be a horizontal line on the above graph extending right from the fourth key. It is important to note that key-times always progress in "forward time". That means that all key-times must be ahead of the previous one and no two keys can contain the same time although they can contain any valid value and repeat that value in multiple keys.
Since a particle editor does not exist right now, there is no visual way to do key-framing. Instead we can manually assign key-times and key-values in our ParticleAsset TAML files. There are two valid ways in XML to format graph fields and their keys:
<SizeXLife>
<Key Time="0" Value="0"/>
<Key Time="0.5" Value="5"/>
<Key Time="0.9" Value="20"/>
<Key Time="1" Value="50"/>
</SizeXLife>
Alternately:
<SizeXLife
Keys="0 0 0.5 5 0.9 20 1 50" />
Here, the numbers represent time/value pairs. They follow after each other, only separated by a space.
Both ways produce the same result, although clearly the first method is easier to read. Also, please note that graph fields need to be bracketed in either
<ParticleAsset.Fields></ParticleAsset.Fields>
or
<ParticleAssetEmitter.Fields></ParticleAssetEmitter.Fields>
tags. The simple fire effect with graph fields looks like this then:
<ParticleAsset
AssetName="Fire" <!-- These are ParticleAsset fields -->
LifeMode="INFINITE">
<ParticleAsset.Fields>
<QuantityScale <!-- This is a ParticleAsset graph field -->
Keys="0 5" />
</ParticleAsset.Fields>
<ParticleAssetEmitter
EmitterName="Smoke" <!-- These are ParticleAssetEmitter fields -->
EmitterType="LINE"
EmitterSize="0.5 0">
<ParticleAssetEmitter.Fields>
<Quantity <!-- This is a ParticleAssetEmitter graph field -->
Keys="0 10" />
</ParticleAssetEmitter.Fields>
</ParticleAssetEmitter>
<ParticleAssetEmitter
EmitterName="Flames" <!-- These are ParticleAssetEmitter fields -->
EmitterType="LINE"
EmitterSize="1 0"
<ParticleAssetEmitter.Fields>
<Quantity <!-- This is a ParticleAssetEmitter graph field -->
Keys="0 20" />
</ParticleAssetEmitter.Fields>
</ParticleAssetEmitter>
</ParticleAsset>
A detailed description of each graph field can be found further down in this guide. Again, this example will not give you an actual fire effect - it is just to show the basic format. If you are curious as to what a real fire effect looks like, there is one included in the main repo: bonfire
There are four types of graph fields: one of which is exclusive to ParticleAsset, the other three to ParticleAssetEmitter. We can define these types as "base", "variation", "life", and "scale". Let's use a real emitter property to explain these types of fields and how they work. For example:
- Spin
- SpinVariation
- SpinLife
- SpinScale
"Spin", without any other word attached to it, is a graph field which is used as a base value. In this case, it would define the base rotation for a particle in degrees/sec. "Spin", and other base types, are only found in a ParticleAssetEmitter.
"SpinVariation" is a graph field which is used as a variation on the base value. In this case, it would define a variance around the base spin. The term variance means that a random value of the range specified would be used. This value is not directly added to the base but sits 'around' the base. A variance of 10 would produce a value in the range -5 to +5. "SpinVariation", and other variation types, are only found in a ParticleAssetEmitter.
"SpinLife" is a graph field which is used to scale the resultant value of the "base" + "variation" in realtime, during the lifetime of the particle. In this case, it would scale the resulting value of "Spin" + "SpinVariation". "SpinLife", and other life types, are only found in a ParticleAssetEmitter.
"SpinScale" is a graph field which only exists in the ParticleAsset and is used to scale the "base" + "variation" used when particles are created. Note that this affects all emitters in the effect! In this case, it would scale the resulting value of "Spin" + "SpinVariation".
So, two of these types act to scale values. The "__Life" type applies scaling during the lifetime of the particle. The "__Scale" type applies scaling only when the particle is emitted (i.e. created). Typically "__Scale" is used to perform effect-wide scaling since it applies to all emitters. Practical examples include needing to render a particle effect in a different resolution camera view - this is where the "__Scale" type can scale your effect up or down. Normally, you will not need "__Scale" when creating a particle effect from scratch though.
Note: Not all emitter properties use all four types! The "Spin" example we used does, but something like "Quantity" only uses the base, variation, and scale types. Which emitter properties use which types are detailed in another section below.
If you are interested in the math behind the particle system, consider the following example. A partial formula for calculating the value used when a particle is emitted is:
Value = (Base ~ Variation) * Scale
So at time = 0, if the base value is 10, the variation is 6 and the scale is 2:
(10 + (-3 to +3)) * 2 which ranges from (10-3)*2 to (10+3)*2 = 14 to 26
Further examples of what happens as a particle effect ages will be shown after we cover the concept of timelines.
Each graph field is comprised of keys which are specified against a timeline, but what is this timeline? The answer depends on whether you’re discussing the effect (ParticleAsset) or the emitter (ParticleAssetEmitter). The quick answer is that timelines come in two varieties. The first timeline is associated with the age of the effect (playing time) and the second timeline is associated with particle-age. These two timelines differ slightly in their definition of time though. Effect-age is specified in absolute-time (in seconds) since the effect started playing whereas particle-age is specified in normalized-time (from 0 to 1).
- Absolute-time (effect age) applies to the "base", "variation" and "scale" types.
- Normalized-time (particle age) applies to the "life" type.
In "Absolute-time", note that the key-times are related to the time from when you start the effect playing. If you restart the effect, the time is also reset and therefore the values picked from the graph change. If the particle effect playing time goes beyond the defined keys in any graph field then the value will stay at the last defined key.
What "Normalized-time" means is that 0 is the start of particle life, 0.5 is halfway through the particle life and 1 is equal to the end of the particle life. You cannot use time outside of the range 0 to 1. This may seem a little strange but the lifetime of particles can be configured separately and using normalized-time means that changing the absolute particle lifetime wouldn’t result in having to change all the key-times. A major advantage!
With this in mind, the final formula for calculating values is:
Value = ((Base ~ Variation) * Scale) * Life
Then we have the following values defined in our ParticleAssetEmitter:
<SizeXLife>
<Key Time="0" Value="1"/>
<Key Time="0.5" Value="2"/>
<Key Time="0.9" Value="5"/>
<Key Time="1" Value="0"/>
</SizeXLife>
Remember we calculated a value range of 14 to 26 in the previous section? Assume they were for particle size and now we factor in the TAML "SizeXLife" values above to it. What we would have defined then is the following:
- Size when particle starts (0.0) would be from 14 to 26
- Size when particle is halfway through its lifetime (0.5) would be 28 to 52
- Size when particle is 9/10ths through its lifetime (0.9) would be 70 to 130
- Size when particle dies (1.0) would be 0
Note that the above doesn’t describe how long the particle lives, just its size over its lifetime.
The ParticleAsset type exposes the following fields in addition to those it inherits. Shown are the equivalent methods available that perform the same action in setting and getting the respective field:
- LifeMode
- setLifeMode(enum)
- getLifeMode()
- Lifetime
- setLifetime(float)
- getLifetime()
The following is a complete description of each of these fields.
There are four modes that control the life of a particle effect. Each mode specifies what happens to the effect after a period of time. The four modes to choose from are: INFINITE, CYCLE, KILL, and STOP. "INFINITE" mode causes the particle effect to last forever. "CYCLE" causes the particle effect to restart playing when its specified "Lifetime" has been reached. The effect will continue repeating forever until explicitly stopped via script or deleted. "KILL" causes the particle effect to be deleted when its specified "Lifetime" has been reached. "STOP" causes the particle effect to stop playing (but not be deleted) when its specified "Lifetime" has been reached.
The default mode is INFINITE.
A floating point number that defines the life of the particle effect (in seconds). This is used according to the "LifeMode" setting. The default value is 0.0 in INFINITE mode, however this should be changed to a number greater than zero when using the other three LifeModes.
The ParticleAsset exposes the following graph fields. Graph fields are always defined as a time/value pair and must be bracketed in TAML XML with:
<ParticleAsset.Fields></ParticleAsset.Fields>
- LifetimeScale
- QuantityScale
- SizeXScale
- SizeYScale
- SpeedScale
- SpinScale
- FixedForceScale
- RandomMotionScale
- AlphaChannelScale
All Scale fields at 0 seconds have a default value of 1 (no scaling). The following is a complete description of each of these fields.
See Lifetime
See Quantity
See SizeX
See SizeY
See Speed
See Spin
See FixedForce
See RandomMotion
See AlphaChannel
The ParticleAssetEmitter type exposes the following fields. Shown are the equivalent methods available that perform the same action in setting and getting the respective field:
- EmitterName
- setEmitterName(string)
- getEmitterName()
- EmitterType
- setEmitterType(enum)
- getEmitterType()
- EmitterOffset
- setEmitterOffset(vector)
- getEmitterOffset()
- EmitterAngle
- setEmitterAngle(float)
- getEmitterAngle()
- EmitterSize
- setEmitterSize(vector)
- getEmitterSize()
- FixedAspect
- setFixedAspect(bool)
- getFixedAspect()
- FixedForceAngle
- setFixedForceAngle(float)
- getFixedForceAngle()
- OrientationType
- setOrientationType(enum)
- getOrientationType()
- KeepAligned
- setKeepAligned(bool)
- getKeepAligned()
- AlignedAngleOffset
- setAlignedAngleOffset(float)
- getAlignedAngleOffset()
- RandomAngleOffset
- setRandomAngleOffset(float)
- getRandomAngleOffset()
- RandomArc
- setRandomArc(float)
- getRandomArc()
- FixedAngleOffset
- setFixedAngleOffset(float)
- getFixedAngleOffset()
- PivotPoint
- setPivotPoint(vector)
- getPivotPoint()
- LinkEmissionRotation
- setLinkEmissionRotation(bool)
- getLinkEmissionRotation()
- IntenseParticles
- setIntenseParticles(bool)
- getIntenseParticles()
- SingleParticle
- setSingleParticle(bool)
- getSingleParticle()
- AttachPositionToEmitter
- setAttachPositionToEmitter(bool)
- getAttachPositionToEmitter()
- AttachRotationToEmitter
- setAttachRotationToEmitter(bool)
- getAttachRotationToEmitter()
- OldestInFront
- setOldestInFront(bool)
- getOldestInFront()
- BlendMode
- setBlendMode(bool)
- getBlendMode()
- SrcBlendFactor
- setSrcBlendFactor(enum)
- getSrcBlendFactor()
- DstBlendFactor
- setDstBlendFactor(enum)
- getDstBlendFactor()
- AlphaTest
- setAlphaTest(float)
- getAlphaTest()
- Image
- setImage(ImageAssetId)
- getImage()
- Frame
- setImageFrame(integer)
- getImageFrame()
- FrameName
- setImageFrameName(string)
- getImageFrameName()
- RandomImageFrame
- setRandomImageFrame(bool)
- getRandomImageFrame()
- Animation
- setAnimation(AnimationAssetId)
- getAnimation()
The following is a complete description of each of these fields.
This is a field for convienience, it is not mandatory to have a name for your emitters. It is helpful to have though in order to make editing TAML files easier, especially when a ParticleAsset contains multiple emitters.
There are six emitter types which control the region in which particles are created: POINT, LINE, BOX, DISK, ELLIPSE, and TORUS. "POINT" creates the particles at the position of the particle player within the scene. "LINE" creates the particles along a line defined by the "EmitterSize" width. "BOX" creates the particles within the bounding box dimensions defined by the field "EmitterSize". "DISK" creates the particles within a disk with radii defined by "EmitterSize". "ELLIPSE" creates the particles on an ellipse with radii defined by "EmitterSize". "TORUS" creates the particles within a torus with the maximum and minimum radii defined by the "EmitterSize" width and height respectively.
This field alters the position (float x, float y) of the emitter relative to the effect or particle player position. When "AttachPositionToEmitter" is true, the offset occurs in emitter space, otherwise the offset is in world space.
This controls the angle of the emitter relative to the effect or ParticlePlayer position.
The size of the emitter is defined here (float width, float height).
This option controls how the particle graph fields "SizeX" and "SizeY" are used. If set to true, the "SizeX" field is used for both the X and Y axis ("SizeY" would be ignored), essentially forcing fixed aspect sized particles. If set to false, "SizeX" and "SizeY" act independently allowing non fixed aspect sized particles.
The default is true.
This controls the angle used for the particle graph field "FixedForce", which provides the ability to apply a constant force to particles.
There are three orientation types which control the orientation of particles when they are created and/or during their lifetime: FIXED, ALIGNED, and RANDOM. Each option has further parameters which can be adjusted using other fields or calls. "FIXED" sets the orientation of the particles along a fixed angle. "ALIGNED" sets the orientation of the particles to the current emission angle. "RANDOM" aligns the particles orientation to a random angle.
The default is FIXED.
Note: this option can only be used when the "OrientationType" is set to "ALIGNED"
When true, this forces the particle to stay aligned to its current direction during its lifetime. This will override any other settings such as "Spin". Adding random motion can cause the direction to change, and this will keep the particle aligned to that new direction. In "ALIGNED" mode, with this option set to false, the alignment is applied when the particle is created.
The default is false.
Note: this option can only be used when the "OrientationType" is set to "ALIGNED"
This allows a fixed angle offset to be added to the alignment function. Because the "ALIGNED" mode orientates the particles such that the initial direction is facing the direction of particle travel - the particle texture used could be orientated in a different direction. This can be changed by rotating the particle with a fixed offset.
Note: this option can only be used when the "OrientationType" is set to "RANDOM"
This uses a floating point number to indicate a fixed angle which the "RandomArc" will be based upon.
Note: this option can only be used when the "OrientationType" is set to "RANDOM"
Assign a floating point number to indicate a random arc range around the "RandomAngleOffset".
Note: this option can only be used when the "OrientationType" is set to "FIXED"
Specify an angle with a floating point number that will initially orientate the particle. Unless "Spin" is used, the particle will stay orientated in this direction. The default is 0.0.
This sets the pivot point used to orientate the particle, which can be useful when the particle is spinning. The offset is defined in local coordinates from the top-left of the texture. "0.5 0.5" would be the center of the particle and "1.0 1.0" is for the bottom-right. Values greater than 1 can be used to create interesting rotational dynamics for particles, especially when they move.
This option will rotate the emission direction to that of the effect. Unlike "AttachRotationToEmitter", which also depends on "AttachPositionToEmitter", this only rotates the emission and not the whole particle system (all particles that are active). Therefore, only the emission direction is rotated. With this option set to true, rotating the effect results in a relative emission rotation as well. Note that all rotations are cummulative; using "AttachRotationToEmitter" and "LinkEmissionRotation" results in the rotations being used together.
Set this option to true to override the blending mode. When active, the particles will render such that their intensity accumulates to white. This can produce a bright or warm glow effects. Note that particles rendered in this mode cannot be seen on a white background. Technically, this option activates blending and uses blending factors of "src=SRC_ALPHA" and "dst=ONE" so this is just a shortcut to a common blending option; obviously the same can be achieved by using the standard blending control.
This option forces the emitter to only create a single particle. The particle is always created as a "POINT" type. It has a speed of zero (doesn't move) and lives infinitely until the effect is stopped. This can be useful when you want to create a single static effect using a single particle. Good for adding corona/glows to effects.
This will attach any particles to the emitter position (which is fixed at the player position). Typically, if an emitter is moving, particles created move independantly. When this option is set to true, they move relative to the emitter. Note that this does not affect the particles "OrientationType".
Note: this option can be used only when "AttachPositionToEmitter" is true
Typically, particles rotate relative to the world such that zero is "up". When this option is active, the particles additionally rotate around the emitter. Note that this does not affect the particles "OrientationType".
Here, the rendering order of particles are controlled. With this option active, the oldest particles are in front with newer particles appearing behind the older ones. With this option inactive, the reverse is true. Note that this option is really only useful when particles are not transparent but completely opaque. Also, there is no performance penalty for either option, e.g. no particle sorting is taking place.
This option controls the blending mode. When true, the source/destination blending factors are used for all particles generated by the emitter. The default for this field is true.
Note: this option can be used only when "BlendMode" is true
This sets the OpenGL source blending factor used. The following blending factors are available to choose from: ZERO, ONE, DST_COLOR, ONE_MINUS_DST_COLOR, SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, and SRC_ALPHA_SATURATE.
The default factor is SRC_ALPHA.
Note: this option can be used only when "BlendMode" is true
This sets the OpenGL destination blending factor used. The following blending factors are available to choose from: ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA.
The default factor is ONE_MINUS_SRC_ALPHA.
When using alpha testing, the alpha channel values determine whether or not areas of the particle are rendered. The "AlphaTest" value is the threshold in the range of 0.0 to 1.0. A negative value will disable alpha testing. For example, giving this field a value of 0.1 will only render areas of the emitter image with an alpha value above 0.1. The graph field "AlphaChannel" can also alter the rendered areas by pushing pixels above or below the "AlphaTest" cutoff threshold.
The default is -1.0 (i.e. disabled).
Specifies the ImageAsset to be used for the emitter. This must be given as a valid ImageAsset ID.
Sets the emitter to use the specified image frame. Make sure your specified ImageAsset is setup for numerical frames when using this field.
Sets the emitter to use the specified image frame name. Make sure your specified ImageAsset is setup for named frames when using this field.
When true, the "Frame" field is disabled and the emitter image frame is randomly chosen from the amount of frames available in the specified ImageAsset. The default is false.
Specifies the AnimationAsset to be used for the emitter. This must be given as a valid AnimationAsset ID.
The ParticleAssetEmitter exposes the following graph fields. Graph fields are always defined as a time/value pair and must be bracketed in TAML XML with:
<ParticleAssetEmitter.Fields></ParticleAssetEmitter.Fields>
- Lifetime
- LifetimeVariation
- Quantity
- QuantityVariation
- SizeX
- SizeXVariation
- SizeXLife
- SizeY
- SizeYVariation
- SizeYLife
- Speed
- SpeedVariation
- SpeedLife
- Spin
- SpinVariation
- SpinLife
- FixedForce
- FixedForceVariation
- FixedForceLife
- RandomMotion
- RandomMotionVariation
- RandomMotionLife
- EmissionForce
- EmissionForceVariation
- EmissionAngle
- EmissionAngleVariation
- EmissionArc
- EmissionArcVariation
- RedChannel
- GreenChannel
- BlueChannel
- AlphaChannel
The following is a complete description of each of these fields.
How long the particle lives in seconds. This defines the normalized time that any of the __Life graph fields work against.
Defaults at 0 seconds - Lifetime: 2, LifetimeVariation: 0
The quantity of particles emitted each second. This value should be kept as small as possible to reduce the performance overhead of the particle effect. It is typically more efficient to produce "bigger" particles than to produce more particles when trying to "fatten up" an effect.
Defaults at 0 seconds - Quantity: 10, QuantityVariation: 0
The X component of size. If the emitter field "FixedAspect" is true then this graph field controls the Y component as well. All sizes are in world units.
Defaults at 0 seconds - SizeX: 2, SizeXVariation: 0, SizeXLife: 1
The Y component of size. If the emitter field "FixedAspect" is true then this graph field is ignored.
Defaults at 0 seconds - SizeY: 2, SizeYVariation: 0, SizeYLife: 1
This field scales the particles velocity. A speed of 1 produces no change to the velocity of the particle. It is very important to understand that "Speed" alone will not produce any movement; the particle must have an initial velocity for "Speed" to be useful. Initial velocity comes from the graph fields "EmissionForce" and/or "FixedForce".
Defaults at 0 seconds - Speed: 10, SpeedVariation: 0, SpeedLife: 1
"Spin" is simply the rotation of the particle and is specified in degree/sec.
Defaults at 0 seconds - Spin: 0, SpinVariation: 0, SpinLife: 1
This controls the magnitude of a fixed, constant force applied to the particles. This can be used to simulate gravity or wind effects. The angle of this force is specified in the emitter field "FixedForceAngle".
Defaults at 0 seconds - FixedForce: 0, FixedForceVariation: 0, FixedForceLife: 1
Controls the magnitude of random motion applied to particles. The magnitude is a variance in world-units. The random motion is omni-directional and is added to the particles position after its velocity calculation meaning that it doesn’t change the particles actual velocity so if it is reduced, the particles velocity stays the same.
Defaults at 0 seconds - RandomMotion: 0, RandomMotionVariation: 0, RandomMotionLife: 1
Controls the particles initial velocity when emitted. This can be changed with “Speed”.
Defaults at 0 seconds - EmissionForce: 5, EmissionForceVariation: 5
Controls the base-angle that the particles will be emitted at (in degrees).
Defaults at 0 seconds - EmissionAngle: 0, EmissionAngleVariation: 0
Controls the arc around the chosen “EmissionAngle” (in degrees).
Defaults at 0 seconds - EmissionArc: 360, EmissionArcVariation: 0
Controls the red channel for the particle color. If the particle texture is white, this controls how much red is applied to the particle.
Default at 0 seconds - RedChannel: 1
Controls the green channel for the particle color. If the particle texture is white, this controls how much green is applied to the particle.
Default at 0 seconds - GreenChannel: 1
Controls the blue channel for the particle color. If the particle texture is white, this controls how much blue is applied to the particle.
Default at 0 seconds - BlueChannel: 1
Controls the alpha channel for the particle color. This essentially controls how transparent the particle is and scales the particle texture itself. A value of 0 makes the particle completely transparent whereas a value of 1 makes the particle opaque. Note that if the particle-texture already has an alpha channel and is already transparent, then a value of 1 will make its transparency the same as the original texture. Essentially, the alpha value here is multiplied by any alpha channel in the texture.
Default at 0 seconds - AlphaChannel: 1
The following methods are available to configure emitters within a ParticleAsset:
- createEmitter()
- addEmitter()
- removeEmitter()
- clearEmitters()
- getEmitterCount()
- getEmitter()
- findEmitter()
- moveEmitter()
The following methods are available to configure graph fields for both ParticleAsset and ParticleAssetEmitter:
- getSelectableFieldCount()
- getSelectableFieldName()
- selectField()
- deselectField()
- getSelectedField()
- setSingleDataKey()
- addDataKey()
- removeDataKey()
- clearDataKeys()
- setDataKeyValue()
- getDataKeyCount()
- getDataKey()
- getMinValue()
- getMaxValue()
- getMinTime()
- getMaxTime()
- getFieldValue()
- setRepeatTime()
- getRepeatTime()
- setValueScale()
- getValueScale()
The following methods are available for use only with a ParticleAssetEmitter:
- getOwner()
Without going into detail on each of these calls as the relevant information can be found in the script-binding files referenced at the top of this document (also in the automatically produced reference documentation), an overview of creating a particle effect in TorqueScript can be shown.
// Create a bare asset.
%effect = new ParticleAsset();
// Configure the basic asset details.
%effect.AssetName = "ForceBubble";
// Create a bare asset emitter.
%emitter = %effect.createEmitter();
// Configure the basic emitter details.
%emitter.EmitterName = "MovingBubbles";
%emitter.Image = "ToyAssets:Particles5";
%emitter.Frame = "1";
// Select the emitter graph fields and populate them with data keys.
%emitter.selectField("Lifetime");
%emitter.addDataKey(0, 5);
%emitter.deselectField();
%emitter.selectField("Quantity");
%emitter.addDataKey(0, 0.2);
%emitter.deselectField();
%emitter.selectField("QuantityVariation");
%emitter.addDataKey(0, 0.1);
%emitter.deselectField();
%emitter.selectField("SizeX");
%emitter.addDataKey(0, 72);
%emitter.deselectField();
%emitter.selectField("SizeXLife");
%emitter.addDataKey(0, 0.3);
%emitter.addDataKey(1, 1);
%emitter.deselectField();
%emitter.selectField("Speed");
%emitter.addDataKey(0, 0);
%emitter.deselectField();
%emitter.selectField("AlphaChannel");
%emitter.addDataKey(0, 0);
%emitter.addDataKey(0.3, 0.2);
%emitter.addDataKey(0.9, 0.1);
%emitter.addDataKey(1, 0);
%emitter.deselectField();
// Assign the asset as private.
%assetId = AssetDatabase.addPrivateAsset(%effect);
// Create a particle player.
%player = new ParticlePlayer();
%player.Particle = %assetId;
// Add the player to the scene.
SandboxScene.add(%player);
It is important to remember that when a ParticleAssetEmitter is created, all of its graph fields are created at the same time and assigned their default values at 0 seconds. In TorqueScript, we are simply selecting the graph fields whose values should be different than those defaults and assigning new data keys.
Using TorqueScript and the exposed fields or methods described in the previous sections, you can programmatically create and configure a ParticleAsset. You can then export this type to a TAML file or even create a TAML file manually and read it into your game at an appropriate time.
If we take the script from the previous section, here is the example ParticleAsset TAML file in XML format:
<ParticleAsset
AssetName="ForceBubble">
<ParticleAssetEmitter
EmitterName="MovingBubbles"
Image="@asset=ToyAssets:Particles5"
Frame="1">
<ParticleAssetEmitter.Fields>
<Quantity>
<Key
Time="0"
Value="0.2" />
</Quantity>
<Lifetime>
<Key
Time="0"
Value="5" />
</Lifetime>
<Speed>
<Key
Time="0"
Value="0" />
</Speed>
<SizeXLife>
<Key
Time="0"
Value="0.3" />
<Key
Time="1"
Value="1" />
</SizeXLife>
<SizeX>
<Key
Time="0"
Value="72" />
</SizeX>
<AlphaChannel>
<Key
Time="0"
Value="0" />
<Key
Time="0.3"
Value="0.2" />
<Key
Time="0.9"
Value="0.1" />
<Key
Time="1"
Value="0" />
</AlphaChannel>
<QuantityVariation>
<Key
Time="0"
Value="0.1" />
</QuantityVariation>
</ParticleAssetEmitter.Fields>
</ParticleAssetEmitter>
</ParticleAsset>
Here is the same example in JSON format:
{
"ParticleAsset": {
"AssetName": "ForceBubble",
"ParticleAssetEmitter[0]": {
"EmitterName": "MovingBubbles",
"Image": "@asset=ToyAssets:Particles5",
"Frame": "1",
"ParticleAssetEmitter.Fields": {
"Quantity[1]": {
"Key[0]": {
"Time": "0",
"Value": "0.2"
}
},
"Lifetime[5]": {
"Key[0]": {
"Time": "0",
"Value": "5"
}
},
"Speed[7]": {
"Key[0]": {
"Time": "0",
"Value": "0"
}
},
"SizeXLife[14]": {
"Key[0]": {
"Time": "0",
"Value": "0.3"
},
"Key[1]": {
"Time": "1",
"Value": "1"
}
},
"SizeX[15]": {
"Key[0]": {
"Time": "0",
"Value": "72"
}
},
"AlphaChannel[23]": {
"Key[0]": {
"Time": "0",
"Value": "0"
},
"Key[1]": {
"Time": "0.3",
"Value": "0.2"
},
"Key[2]": {
"Time": "0.9",
"Value": "0.1"
},
"Key[3]": {
"Time": "1",
"Value": "0"
}
},
"QuantityVariation[24]": {
"Key[0]": {
"Time": "0",
"Value": "0.1"
}
}
}
},
"ParticleAsset.Fields": {}
}
}