Game.VFXSystem
Assembly:
Namespace: Game.Effects
Type: class
Base: GameSystemBase, IPreDeserialize
Summary:
VFXSystem manages runtime visual-effect instances for Cities: Skylines 2. It enumerates VFX prefabs, creates per-prefab VisualEffect components and GPU-backed instance data textures, and updates instance data via jobs. The system receives source update requests (add/remove/move) through NativeQueue
Fields
-
private static class VFXIDs
Provides cached Shader.PropertyToID integers used to set properties on VisualEffect (WindTexture, MapOffsetScale, Count, InstanceData). -
private struct EffectInfo
Holds per-prefab runtime data: VisualEffect m_VisualEffect
— the created VisualEffect component used to drive the effect.Texture2D m_Texture
— GPU texture used as instance data (width = max instances, height = 3).NativeArray<int> m_Instances
— array mapping instance slot -> enabled effect index (or -1).NativeParallelHashMap<int,int> m_Indices
— mapping enabled effect index -> instance slot.int m_LastCount
— last known active count used to trigger updates.-
bool m_NeedApply
— whether texture.Apply() must be called on the main thread. -
private struct VFXTextureUpdateJob : IJob
Burst-compiled job that writes instance data into the raw texture buffer used by VisualEffect. Fields: NativeArray<float4> m_TextureData
— raw texture data pointer to write floats.[ReadOnly] NativeArray<int> m_Instances
— mapping of slots to enabled indices.[ReadOnly] NativeList<EnabledEffectData> m_EnabledData
— source data for enabled effects.int m_Count
— number of slots to update.-
int m_TextureWidth
— width of the instance texture used for row offsets. The job writes position/intensity, rotation (in radians), and scale rows into the texture. -
private Queue<NativeQueue<VFXUpdateInfo>> m_SourceUpdateQueue
Queue of producer NativeQueues created by callers via GetSourceUpdateData(). Each NativeQueue is consumed and disposed by this system during OnUpdate/PreDeserialize. -
private JobHandle m_SourceUpdateWriter
Combined JobHandle representing writers that produced data into the NativeQueue(s). Completed before consuming queues to guarantee safety. -
private EntityQuery m_VFXPrefabQuery
Query matching VFX prefabs (VFXData) used to initialize EffectInfo entries. -
private PrefabSystem m_PrefabSystem
Cached reference to PrefabSystem for resolving EffectPrefab instances. -
private bool m_Initialized
Flag indicating that initialization (prefab enumeration and EffectInfo allocation) has been performed. -
private EffectInfo[] m_Effects
Array of per-prefab EffectInfo populated during initialization. -
private JobHandle m_TextureUpdate
JobHandle for scheduled VFXTextureUpdateJob(s); combined across prefabs per frame. -
private WindTextureSystem m_WindTextureSystem
Cached reference used to set wind texture on VisualEffect instances. -
private TerrainSystem m_TerrainSystem
Cached reference used to set map offset/scale on VisualEffect instances. -
private EffectControlSystem m_EffectControlSystem
Used to get the enabled effects data and to register a reader dependency for texture updates. -
private RenderingSystem m_RenderingSystem
Used to compute a playRate for VisualEffect playback based on frame timing.
Properties
- None. {{ The VFXSystem exposes no public properties. All runtime state is managed via methods and internal fields. }}
Constructors
public VFXSystem()
Default constructor. The system relies on OnCreate to initialize internal references and data structures.
{{ YOUR_INFO }} Initial setup that depends on world systems occurs in OnCreate rather than the constructor. The constructor only ensures the system instance is created by the ECS world.
Methods
-
public NativeQueue<VFXUpdateInfo> GetSourceUpdateData()
Returns a newly created NativeQueue(Allocator.TempJob) and enqueues it into m_SourceUpdateQueue for the system to consume on the next update. Caller must write to the returned queue from jobs and call AddSourceUpdateWriter to provide writer job handles. -
public void AddSourceUpdateWriter(JobHandle jobHandle)
Combine the provided jobHandle with internal m_SourceUpdateWriter to track writer dependencies. The system completes m_SourceUpdateWriter before reading and disposing the queued NativeQueues. -
[Preserve] protected override void OnCreate() : void
Performs runtime initialization: - creates the m_SourceUpdateQueue,
- sets up m_VFXPrefabQuery,
-
gets references to PrefabSystem, WindTextureSystem, TerrainSystem, EffectControlSystem, and RenderingSystem from the world.
-
private bool Initialize() : bool
Called by OnUpdate to lazily initialize per-prefab EffectInfo when VFX prefabs are present: - enumerates VFX prefab entities and VFXData,
- creates a GameObject+VisualEffect per prefab,
- creates a Texture2D to hold instance data (width = component.m_MaxCount, height = 3, R32G32B32A32_SFloat),
- allocates m_Instances and m_Indices Native containers (Allocator.Persistent),
-
updates VFXData component fields (m_MaxCount, m_Index) and writes them back to the entity. Returns true if initialization was performed, false otherwise.
-
[Preserve] protected override void OnDestroy() : void
Cleans up if initialized: - destroys created Texture2D objects,
- disposes Persistent Native containers (m_Instances, m_Indices),
- clears and disposes any queued NativeQueues via ClearQueue(),
-
calls base.OnDestroy().
-
[Preserve] protected override void OnUpdate() : void
Main frame update: - ensures initialization is done (lazily) or clears queues and early-exits if not ready,
- completes pending texture update jobs and source writers,
- obtains enabled effect data (NativeList
) and its dependency, - consumes producer NativeQueues: waits for writer jobs, processes VFXUpdateInfo entries (Add / Remove / MoveIndex) to maintain instance and indices maps, and updates VisualEffect Count property,
- computes playRate from rendering frameDelta and world delta time and sets VisualEffect properties (playRate, wind texture, map offset/scale),
- prepares VFXTextureUpdateJob for each prefab that needs updating (max of current count and last count),
- schedules jobs and sets m_Effects[i].m_NeedApply so main thread will apply the Texture2D after jobs complete,
- registers the texture update job handle with EffectControlSystem as a reader.
Notes: OnUpdate uses JobHandle.CombineDependencies to safely chain and schedule jobs, and marks when a Texture2D.Apply() must be called on the main thread.
public void PreDeserialize(Context context) : void
Called before deserializing world state:- completes m_TextureUpdate,
- resets VisualEffect Count to 0 and destroys the VisualEffect GameObject instances,
- disposes Native containers and sets m_Initialized=false so the system will reinitialize after deserialization,
-
clears and disposes producer queues.
-
private void ClearQueue() : void
Completes m_SourceUpdateWriter and disposes any remaining NativeQueueitems in m_SourceUpdateQueue. -
public VFXSystem()
Empty public constructor (same as listed in Constructors).
Additional nested types: - VFXTextureUpdateJob.Execute() - For each slot i in m_Count: reads m_Instances[i]; if -1 writes zero intensity; otherwise reads EnabledEffectData (position, rotation, scale, intensity) and writes three float4 rows into m_TextureData (position/intensity, rotation in radians, scale). - This is the burst job that writes per-instance data into the texture buffer used by VisualEffect.
Usage Example
// Example: Producer side - create a queue and write updates from a job
var queue = vfxSystem.GetSourceUpdateData();
// schedule a job that writes VFXUpdateInfo into 'queue' (NativeQueue<VFXUpdateInfo> is thread-safe for writers)
// After scheduling that job, register the writer handle with the system:
vfxSystem.AddSourceUpdateWriter(yourWriterJobHandle);
// Example: consumer is automatic - VFXSystem.OnUpdate() will consume the queue, update instance maps,
// schedule the VFXTextureUpdateJob(s), and call Texture2D.Apply() on the main thread when needed.
// Example: ensure proper cleanup before scene load/deserialization
vfxSystem.PreDeserialize(context); // invoked by game during load sequence
{{ YOUR_INFO }}
Notes and best practices:
- Always call AddSourceUpdateWriter with the JobHandle that writes to the queue so VFXSystem can safely wait for writers before consuming and disposing the queue.
- Returned NativeQueue