INSODIMENSIONStudios
BiomesGuides

Wind Bridge

Configure the AT Wind Manager actor to push one wind value into your own material parameter collections, Niagara effects and wind receivers, and use the shipped foliage wind material.

Wind bridge

The wind bridge is one level actor, AT Wind Manager (AATWindManager). It reads a wind intensity and a wind angle from a source, and writes them to the Material Parameter Collections (MPCs) your foliage materials read. It also calls every actor in the level that implements the ATWindReceiver interface.

Wind source  ->  AT Wind Manager  ->  Mpc Targets (your material parameter collections)
 intensity 0-1                    ->  Receivers   (actors implementing ATWindReceiver, e.g. AT Wind Niagara Actor)
 angle in degrees

Nothing is pre-filled. A new AT Wind Manager has an empty Mpc Targets list, and its default source (Actor Property + MPC Angle) has no weather actor, property name or collection set. Until you configure it, the source reads intensity 0 and angle 0, and nothing is written to any material. The plugin does not know your weather system or your foliage materials. You point the bridge at them.


Set it up

  1. In the Place Actors panel, search for AT Wind Manager and place one in the level. One is enough; it reaches every collection and receiver you give it.
  2. Under Wind → Source, fill in the source. The default is Actor Property + MPC Angle: assign your weather actor, name the float property that holds the wind intensity, and, if your project stores the angle in a Material Parameter Collection, assign that collection and the scalar parameter name. See Actor property source.
  3. Under Wind → Targets, add one element to Mpc Targets per Material Parameter Collection your foliage reads. Set Mpc, then type the parameter names your materials use into the Param fields. Leave a Param field empty to skip it. See Mpc targets.
  4. Press Sync Now on the actor.

The manager also resolves its targets, re-initialises the source, refreshes receivers and pushes the current wind each time the actor is constructed, which includes when you change one of its properties in the editor, and again at Begin Play.

The manager ticks in editor viewports, so the wind updates in the editor as well as in play.

To confirm what it writes, turn on verbose output for the plugin's log category, then press Sync Now:

Log LogAgenticBiomes Verbose

Each push then prints one line in the Output Log. The numbers are an example of the format:

ATWindManager: Intensity=0.50 Angle=90.0 -> 1 MPC targets, 2 receivers

Manager properties

PropertyDefaultNotes
Source (Source)An Actor Property + MPC Angle instanceInstanced object. Pick another source class from the dropdown to swap it.
Mpc Targets (MpcTargets)EmptyOne element per Material Parameter Collection.
Poll Interval (PollInterval)0.1 secondsRange 0.05 to 10. How often the manager reads the source.
Enabled (bEnabled)OnStops the periodic polling when off. Sync Now and the push on construction and Begin Play still run.

Two buttons on the actor:

ButtonWhat it does
Sync Now (SyncNow)Re-resolves the targets, re-initialises the source, reads the source and pushes to every target and receiver now, whatever changed. It does not rebuild the receiver list.
Refresh Receivers (RefreshReceivers)Rebuilds the cached list of actors that implement ATWindReceiver. Press it after you add or remove a receiver. It logs ATWindManager: Cached N wind receivers.

Both are also callable from Blueprints (category Wind).

When the manager pushes

On each poll the manager reads the intensity from the source and compares it with the last value it pushed. It pushes only when the difference is greater than 0.01. The angle is read only at the moment of a push.

  • A wind that changes by 0.01 or less between polls is not pushed.
  • An angle change on its own is not pushed. The new angle arrives the next time the intensity moves by more than 0.01, or when you press Sync Now.
  • The manager clamps intensity to 0 to 1 only when it writes to an MPC target. Receivers get the value exactly as the source returned it.

Mpc targets

Each element of Mpc Targets is a FATWindMpcTarget. A target whose Mpc is empty is skipped. Every Param field that is empty is skipped, so a target only writes what you name.

FieldDefaultMeaning
Label (Label)emptyA name for your own reference in the Details panel. It also appears in log messages.
Mpc (Mpc)noneThe Material Parameter Collection to write to.
Curve Exponent (CurveExponent)1.0Range 0.1 to 5.0. 1.0 is linear; higher values keep calm winds calmer and make storms hit harder.
Strength Param (StrengthParam)noneScalar parameter that receives the strength.
Strength Calm / Strength Storm (StrengthCalm, StrengthStorm)0.0 / 1.0Strength at intensity 0 and at intensity 1.
Speed Param (SpeedParam)noneScalar parameter that receives the speed.
Speed Calm / Speed Storm (SpeedCalm, SpeedStorm)0.0 / 1.0Speed at intensity 0 and at intensity 1.
Weight Param (WeightParam)noneScalar parameter that receives a third value, blended the same way as strength and speed.
Weight Calm / Weight Storm (WeightCalm, WeightStorm)0.0 / 1.0Weight at intensity 0 and at intensity 1.
Direction Scalar Param (DirectionScalarParam)noneScalar parameter that receives the angle as a fraction of a full turn, 0 to 1.
Direction Vector Param (DirectionVectorParam)noneVector parameter that receives the wind direction as a unit vector.
Negate Direction (bNegateDirection)OffFlips the sign of the direction vector, for a collection whose shaders expect the opposite direction.

For each push, the manager computes:

Alpha         = Clamp(Intensity, 0, 1) ^ CurveExponent
Strength      = Lerp(StrengthCalm, StrengthStorm, Alpha)
Speed         = Lerp(SpeedCalm,    SpeedStorm,    Alpha)
Weight        = Lerp(WeightCalm,   WeightStorm,   Alpha)
DirectionScalar = (angle wrapped to 0..360) / 360
DirectionVector = (cos(angle), sin(angle), 0, 0), multiplied by -1 if Negate Direction is on

The angle is in degrees, measured from the world +X axis toward +Y. With a Curve Exponent of 2 and an intensity of 0.5, Alpha is 0.25.

In the direction vector, Z and W are written as 0.

Parameter names must exist

The manager does not check that a parameter exists in the collection. If you type a name the collection does not have, Unreal logs a one-time warning to the Message Log (PIE category):

SetScalarParameterValue called on <collection> with invalid ParameterName '<name>'. This is likely due to a Blueprint error.

The vector variant says SetVectorParameterValue instead. Nothing else tells you the name is wrong, and the foliage does not move.


Actor property source

Actor Property + MPC Angle (UATActorPropertyWindSource) is the source every new manager starts with. It reads the intensity from a property on one of your actors, and the angle from a scalar parameter in one of your collections. It carries no names of its own.

FieldDefaultMeaning
Weather Actor (WeatherActor)noneThe actor that holds the wind intensity. A weak reference, so assign it in the level where it lives.
Weather Mpc (WeatherMpc)noneThe collection that holds the wind angle. Empty means the angle stays 0.
Actor Class Marker (ActorClassMarker)emptyA substring of the weather actor's class name. If Weather Actor is not set, the source searches the level for an actor whose class name contains this text and uses the first match. Empty means do not search.
Intensity Property Name (IntensityPropertyName)noneName of a float or double property on the weather actor. Empty means the intensity stays 0.
Angle Param Name (AngleParamName)noneScalar parameter on Weather Mpc that holds the wind angle in degrees. Empty means the angle stays 0.
Intensity Max (IntensityMax)1.0Minimum 0.01. The raw property value is divided by this, then clamped to 0 to 1. Leave at 1 if the property is already 0 to 1.

Notes:

  • The intensity is Clamp(Raw / Intensity Max, 0, 1). If the actor, the property or the name is missing, it is 0.
  • The angle is read from the collection as it is. It is not converted. It must already be in degrees.
  • Only a float or double property is accepted. Any other type is rejected with a warning.
  • Fields you leave empty are skipped without a message. If you set something that cannot be resolved, the source logs a warning:
Message (category LogAgenticBiomes)Cause
UATActorPropertyWindSource: Could not load WeatherMpc '<path>'; the wind angle stays 0.Weather Mpc is set but cannot be loaded.
UATActorPropertyWindSource: No actor matching class marker '<text>' found. Assign WeatherActor manually.Actor Class Marker matched no actor.
UATActorPropertyWindSource: '<actor>' has no float or double property named '<name>'.Intensity Property Name does not exist on the actor, or has another type.

When the search succeeds it logs UATActorPropertyWindSource: Found weather actor '<name>'.

Do not use the shipped MPC_AT_FoliageWind and its WindDirection parameter as the Weather Mpc angle. That parameter stores a fraction of a turn (0 to 1), not degrees, and it is also what a target typically writes. Use a collection that holds degrees, or write your own source.


Your own source

Wind Source (UATWindSource) is the abstract base for sources. It has three events, all in the Wind Source category:

EventReturnContract
Initialize(WorldContext)noneOne-time setup. Called on construction, Begin Play and every Sync Now. The default does nothing.
ReadIntensity(WorldContext)floatCurrent wind intensity, normalised to 0 to 1. The default returns 0.
ReadAngle(WorldContext)floatCurrent wind angle in degrees, 0 to 360. The default returns 0.

WorldContext is the AT Wind Manager itself, so it can reach the world. ReadIntensity and ReadAngle are const.

The class is Abstract. A concrete subclass that is declared EditInlineNew appears in the Source dropdown. Subclass it in C++ in your own game module, which needs AgenticBiomes in its module dependencies:

#include "ATWindSource.h"
#include "MyWindSource.generated.h"

UCLASS(EditInlineNew, meta = (DisplayName = "My Wind Source"))
class MYGAME_API UMyWindSource : public UATWindSource
{
	GENERATED_BODY()

public:
	virtual float ReadIntensity_Implementation(const UObject* WorldContext) const override;
	virtual float ReadAngle_Implementation(const UObject* WorldContext) const override;
};

UATWindSource is declared BlueprintType but not Blueprintable, and the plugin ships no Blueprint source. Unreal only offers a native class as a Blueprint parent when it is marked Blueprintable, so write a custom source in C++. A Blueprint actor can still implement the receiver interface below.


Receivers

Any actor can follow the wind by implementing the ATWindReceiver interface (IATWindReceiver). It has one event, category Wind:

EventParameters
OnWindChangedIntensity (float), AngleDeg (float, degrees)

The manager calls it on every cached receiver each time it pushes, after it has written the MPC targets. In a Blueprint actor, add ATWindReceiver under Class Settings → Interfaces and implement On Wind Changed.

The manager finds receivers when it is constructed, at Begin Play, and when you press Refresh Receivers. A receiver spawned later is not seen until you call RefreshReceivers. Sync Now does not refresh the list. The list holds weak references, so a destroyed receiver drops out.

AT Wind Niagara Actor

AT Wind Niagara Actor (AATWindNiagaraActor) extends Epic's Niagara Particle System Actor and implements the receiver interface. Use it as the parent class of a Blueprint for a wind-driven effect. It does not tick; it reacts only when the manager pushes.

On each push it sets the actor's yaw to the wind angle, if Rotate To Wind is on, and then writes Niagara float user parameters by name on the actor's Niagara component. A parameter with an empty name is skipped. If the actor has no Niagara component it logs ATWindNiagara [<name>]: No NiagaraComponent found.

PropertyDefaultRangeEffect
Rotate To Wind (bRotateToWind)OnSets the actor's yaw to AngleDeg.
Wind Strength Param (WindStrengthParam)WindStrengthNiagara parameter name. Receives Intensity * Wind Strength Scale.
Storm Strength Param (StormStrengthParam)StormStrengthNiagara parameter name. Receives Intensity * Storm Strength Scale.
Spawn Rate Param (SpawnRateParam)SpawnRateNiagara parameter name. Receives Lerp(Spawn Rate Idle, Spawn Rate Storm, Intensity).
Gravity Param (GravityParam)GravityNiagara parameter name. Receives Lerp(Gravity Idle, Gravity Storm, Intensity).
Wind Strength Scale (WindStrengthScale)10.00 to 100Multiplier for the wind strength parameter.
Storm Strength Scale (StormStrengthScale)0.10 to 10Multiplier for the storm strength parameter.
Spawn Rate Idle (SpawnRateIdle)1500 to 1000Spawn rate at intensity 0.
Spawn Rate Storm (SpawnRateStorm)5000 to 1000Spawn rate at intensity 1.
Gravity Idle (GravityIdle)1.00 to 10Gravity at intensity 0.
Gravity Storm (GravityStorm)0.30 to 10Gravity at intensity 1.

No Niagara system ships for this actor. Create a system with float user parameters whose names match, or rename the Param fields to match your own system.


The foliage wind material

The plugin ships a foliage wind material and its parts under /AgenticBiomes/Materials/Wind/:

AssetWhat it is
M_AT_FoliageWindFoliage master material. Create a Material Instance of it for your own foliage.
MPC_AT_FoliageWindThe Material Parameter Collection M_AT_FoliageWind reads.
MF_AT_GrassWindWind kernel: pivot bend, two travelling noise layers, gust streaks and side sway. Outputs WPO and GustMask.
MF_AT_CharacterPushPushes foliage away from, and presses it down around, a player position.
T_AT_WindNoise, T_AT_GustPattern, T_AT_WhiteLinearDefault noise, gust and neutral textures.

None of the plugin's shipped sample materials use M_AT_FoliageWind, and the manager does not drive MPC_AT_FoliageWind until you add a target for it.

M_AT_FoliageWind is a masked, two-sided foliage material (Two Sided Foliage shading, opacity clip 0.33). It is flagged for instanced static meshes and Nanite. World position offset comes from MF_AT_GrassWind plus the character push.

Prepare the mesh

The bend weight is read from the mesh's vertex colour: it is 1 minus the red channel. Paint red as 1 at the root of the plant and 0 at the tip. A mesh with no vertex colour data reads as white in Unreal, which gives a bend weight of 0, so it will not move until you paint it.

Collection parameters

ParameterDefaultWritten by the manager
WindDirection0.35With Direction Scalar Param. Fraction of a turn, 0 to 1: the material multiplies it by a full turn.
WindStrength0.6With Strength Param.
WindSpeed1.0With Speed Param.
GustStrength0.7No. Set it yourself.
PlayerRadius120No.
PlayerStrength1.0No.
PlayerPosition (vector)0, 0, -1000000No.

WindDirection is a fraction of a turn, the same unit as Direction Scalar Param, so a target needs no conversion. The material does not use a direction vector, so leave Direction Vector Param empty.

A target for this collection looks like this. Pick your own calm and storm values; the manager has none of its own:

FieldValue
MpcMPC_AT_FoliageWind
Strength ParamWindStrength
Speed ParamWindSpeed
Direction Scalar ParamWindDirection
Weight Param, Direction Vector Paramempty

The manager never writes GustStrength. It stays at the value you set in the collection, or whatever your own Blueprint writes.

Character push

MF_AT_CharacterPush reads PlayerPosition, PlayerRadius and PlayerStrength. The default PlayerPosition is far below the world (Z of -1000000), which switches the push off. Nothing in the plugin writes PlayerPosition. To use the push, write the player location to the collection yourself every frame, for example with Set Vector Parameter Value on MPC_AT_FoliageWind, using the player's feet position. The push covers a vertical window from 30 cm below to 200 cm above that position, and its displacement is capped at 60 cm sideways and 45 cm down.

Material instance parameters

GroupParameter (default)
Static switchesEnable Wind (on), Enable Character Push (on), Enable Gust Colour (on)
WindBend (0.45), Noise Scale (1), Gust Scale (1), Gust Speed (6), Sway (0.12), Sway Speed (3); textures Wind Noise (T_AT_WindNoise), Gust Pattern (T_AT_GustPattern)
ColourColor Variation (0.15), Gust Brightness (1.35), Gust Colour Strength (1)
QuixelTexture parameters albedo, normal, roughness, opacity, translucency and displacement, each with a scalar multiplier of the same name (default 1)
  • Bend and Sway scale the bend and the side sway, and Sway Speed sets the rate of the sway.
  • Color Variation darkens each instance by a random amount, up to that fraction.
  • With Enable Gust Colour on, the gust mask, scaled by Gust Colour Strength, drives a brightness change toward Gust Brightness.
  • The displacement texture slot is not connected to anything in the material.
  • Noise Scale, Gust Scale and Gust Speed feed the inputs of the same names on MF_AT_GrassWind.

Limits

  • The bridge does nothing until you configure it: no targets, no weather actor, no property name.
  • It pushes only when the intensity changes by more than 0.01, and it reads the angle only on a push.
  • It does not check that a collection parameter exists.
  • It writes only the parameters you name. GustStrength and the player parameters of MPC_AT_FoliageWind are never written.
  • A receiver added at runtime is not seen until Refresh Receivers.
  • A custom source must be written in C++.
  • No Niagara system ships for AT Wind Niagara Actor.
  • No tool in the agent toolsets edits the wind bridge; use the Details panel.

Troubleshooting

SymptomCause and fix
Nothing movesMpc Targets is empty by default. Add a target, name the parameters your material reads, and press Sync Now.
Targets are set but the wind stays calmThe source reads 0 until Weather Actor (or Actor Class Marker) and Intensity Property Name are set. Check the log for the UATActorPropertyWindSource warnings above.
ATWindManager: Could not resolve MPC '<path>' for target '<label>'The target's Mpc points at an asset that cannot be loaded, for example one that was moved or deleted. Reassign it.
The collection is written but the foliage does not reactA parameter name does not exist in the collection (look for the one-time invalid ParameterName warning in the PIE Message Log), or the material does not read that collection.
The direction does not follow an angle changeThe angle is read only when the intensity moves by more than 0.01. Press Sync Now.
The wind blows the wrong way in your shadersTurn on Negate Direction on the target.
A runtime-spawned receiver does not reactCall Refresh Receivers.
The direction is wrong by a large factorThe source expects degrees. A parameter that stores a 0 to 1 turn gives an angle of at most 1 degree.
A Niagara effect ignores the windThe user parameter names on the effect do not match the Param fields on AT Wind Niagara Actor.

For wider problems, see Troubleshooting. To ask a question, join the Discord.

Next steps

  • Terrain material, the other material system that ships with the plugin.
  • Biome assets, which hold species rows and ground cover. A biome has no wind setting; wind is configured on the bridge.